diff options
author | Stevan Andjelkovic <stevan.andjelkovic@strath.ac.uk> | 2012-01-02 17:57:33 +0100 |
---|---|---|
committer | Stevan Andjelkovic <stevan.andjelkovic@strath.ac.uk> | 2012-01-02 17:57:33 +0100 |
commit | c1ac3eb45e9211189581d99398016821649ac644 (patch) | |
tree | 2b5dd4417eefab2c568b94fc054d32c3aeb3a974 | |
parent | 5b1812e85743e196c281d70483ef646aa53ef489 (diff) | |
download | xombrero-c1ac3eb45e9211189581d99398016821649ac644.tar.gz |
Add history.c and completion.c...
... and move history and completion related functions to them. ok marco@
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | completion.c | 98 | ||||
-rw-r--r-- | freebsd/Makefile | 7 | ||||
-rw-r--r-- | history.c | 239 | ||||
-rw-r--r-- | xxxterm.c | 293 | ||||
-rw-r--r-- | xxxterm.h | 15 |
6 files changed, 359 insertions, 295 deletions
diff --git a/Makefile b/Makefile index cda17c2..f447ea2 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,7 @@ PROG=xxxterm MAN=xxxterm.1 SRCS= cookie.c inspector.c marco.c about.c whitelist.c settings.c inputfocus.c -SRCS+= xxxterm.c +SRCS+= history.c completion.c xxxterm.c CFLAGS+= -O2 -Wall -Wno-format-extra-args -Wunused CFLAGS+= -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -Wno-sign-compare DEBUG= -ggdb3 diff --git a/completion.c b/completion.c new file mode 100644 index 0000000..09f3b6c --- /dev/null +++ b/completion.c @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2010, 2011 Marco Peereboom <marco@peereboom.us> + * Copyright (c) 2011 Stevan Andjelkovic <stevan@student.chalmers.se> + * Copyright (c) 2010, 2011 Edd Barrett <vext01@gmail.com> + * Copyright (c) 2011 Todd T. Fries <todd@fries.net> + * Copyright (c) 2011 Raphael Graf <r@undefined.ch> + * Copyright (c) 2011 Michal Mazurek <akfaew@jasminek.net> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "xxxterm.h" + +gboolean +completion_select_cb(GtkEntryCompletion *widget, GtkTreeModel *model, + GtkTreeIter *iter, struct tab *t) +{ + gchar *value; + + gtk_tree_model_get(model, iter, 0, &value, -1); + load_uri(t, value); + g_free(value); + + return (FALSE); +} + +gboolean +completion_hover_cb(GtkEntryCompletion *widget, GtkTreeModel *model, + GtkTreeIter *iter, struct tab *t) +{ + gchar *value; + + gtk_tree_model_get(model, iter, 0, &value, -1); + gtk_entry_set_text(GTK_ENTRY(t->uri_entry), value); + gtk_editable_set_position(GTK_EDITABLE(t->uri_entry), -1); + g_free(value); + + return (TRUE); +} + +void +completion_add_uri(const gchar *uri) +{ + GtkTreeIter iter; + + /* add uri to list_store */ + gtk_list_store_append(completion_model, &iter); + gtk_list_store_set(completion_model, &iter, 0, uri, -1); +} + +gboolean +completion_match(GtkEntryCompletion *completion, const gchar *key, + GtkTreeIter *iter, gpointer user_data) +{ + gchar *value; + gboolean match = FALSE; + + gtk_tree_model_get(GTK_TREE_MODEL(completion_model), iter, 0, &value, + -1); + + if (value == NULL) + return FALSE; + + match = match_uri(value, key); + + g_free(value); + return (match); +} + +void +completion_add(struct tab *t) +{ + /* enable completion for tab */ + t->completion = gtk_entry_completion_new(); + gtk_entry_completion_set_text_column(t->completion, 0); + gtk_entry_set_completion(GTK_ENTRY(t->uri_entry), t->completion); + gtk_entry_completion_set_model(t->completion, + GTK_TREE_MODEL(completion_model)); + gtk_entry_completion_set_match_func(t->completion, completion_match, + NULL, NULL); + gtk_entry_completion_set_minimum_key_length(t->completion, 1); + gtk_entry_completion_set_inline_selection(t->completion, TRUE); + g_signal_connect(G_OBJECT (t->completion), "match-selected", + G_CALLBACK(completion_select_cb), t); + g_signal_connect(G_OBJECT (t->completion), "cursor-on-match", + G_CALLBACK(completion_hover_cb), t); +} + diff --git a/freebsd/Makefile b/freebsd/Makefile index a088b83..8834693 100644 --- a/freebsd/Makefile +++ b/freebsd/Makefile @@ -35,9 +35,14 @@ cookie.o: ../cookie.o inputfocus.o: ../inputfocus.o +history.o: ../history.o + +completion.o: ../completion.o + ../xxxterm.o: ../javascript.h -xxxterm: xxxterm.o freebsd.o marco.o about.o inspector.o whitelist.o settings.o cookie.o +xxxterm: xxxterm.o freebsd.o marco.o about.o inspector.o whitelist.o settings.o \ + cookie.o history.o completion.o $(CC) $(LDFLAGS) -o $@ *.o $+ $(LDADD) install: all diff --git a/history.c b/history.c new file mode 100644 index 0000000..5ded110 --- /dev/null +++ b/history.c @@ -0,0 +1,239 @@ +/* + * Copyright (c) 2010, 2011 Marco Peereboom <marco@peereboom.us> + * Copyright (c) 2011 Stevan Andjelkovic <stevan@student.chalmers.se> + * Copyright (c) 2010, 2011 Edd Barrett <vext01@gmail.com> + * Copyright (c) 2011 Todd T. Fries <todd@fries.net> + * Copyright (c) 2011 Raphael Graf <r@undefined.ch> + * Copyright (c) 2011 Michal Mazurek <akfaew@jasminek.net> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "xxxterm.h" + +#define XT_HISTORY_FILE ("history") +#define XT_MAX_HL_PURGE_COUNT (1000) /* Purge the history for every + * MAX_HL_PURGE_COUNT items inserted into + * history and delete all items older + * than MAX_HISTORY_AGE. */ +#define XT_MAX_HISTORY_AGE (60.0 * 60.0 * 24 * 14) /* 14 days */ + +int +purge_history(void) +{ + struct history *h, *next; + double age = 0.0; + + DNPRINTF(XT_D_HISTORY, "%s: hl_purge_count = %d (%d is max)\n", + __func__, hl_purge_count, XT_MAX_HL_PURGE_COUNT); + + if (hl_purge_count == XT_MAX_HL_PURGE_COUNT) { + hl_purge_count = 0; + + for (h = RB_MIN(history_list, &hl); h != NULL; h = next) { + + next = RB_NEXT(history_list, &hl, h); + + age = difftime(time(NULL), h->time); + + if (age > XT_MAX_HISTORY_AGE) { + DNPRINTF(XT_D_HISTORY, "%s: removing %s (age %.1f)\n", + __func__, h->uri, age); + + RB_REMOVE(history_list, &hl, h); + g_free(h->uri); + g_free(h->title); + g_free(h); + } else { + DNPRINTF(XT_D_HISTORY, "%s: keeping %s (age %.1f)\n", + __func__, h->uri, age); + } + } + } + + return (0); +} + +int +insert_history_item(const gchar *uri, const gchar *title, time_t time) +{ + struct history *h; + + if (!(uri && strlen(uri) && title && strlen(title))) + return (1); + + h = g_malloc(sizeof(struct history)); + h->uri = g_strdup(uri); + h->title = g_strdup(title); + h->time = time; + + DNPRINTF(XT_D_HISTORY, "%s: adding %s\n", __func__, h->uri); + + RB_INSERT(history_list, &hl, h); + completion_add_uri(h->uri); + hl_purge_count++; + + purge_history(); + update_history_tabs(NULL); + + return (0); +} + +int +restore_global_history(void) +{ + char file[PATH_MAX]; + FILE *f; + gchar *uri, *title, *stime, *err = NULL; + time_t time; + struct tm tm; + const char delim[3] = {'\\', '\\', '\0'}; + + snprintf(file, sizeof file, "%s/%s", work_dir, XT_HISTORY_FILE); + + if ((f = fopen(file, "r")) == NULL) { + warnx("%s: fopen", __func__); + return (1); + } + + for (;;) { + if ((uri = fparseln(f, NULL, NULL, delim, 0)) == NULL) + if (feof(f) || ferror(f)) + break; + + if ((title = fparseln(f, NULL, NULL, delim, 0)) == NULL) + if (feof(f) || ferror(f)) { + err = "broken history file (title)"; + goto done; + } + + if ((stime = fparseln(f, NULL, NULL, delim, 0)) == NULL) + if (feof(f) || ferror(f)) { + err = "broken history file (time)"; + goto done; + } + + if (strptime(stime, "%a %b %d %H:%M:%S %Y", &tm) == NULL) { + err = "strptime failed to parse time"; + goto done; + } + + time = mktime(&tm); + + if (insert_history_item(uri, title, time)) { + err = "failed to insert item"; + goto done; + } + + free(uri); + free(title); + free(stime); + uri = NULL; + title = NULL; + stime = NULL; + } + +done: + if (err && strlen(err)) { + warnx("%s: %s\n", __func__, err); + free(uri); + free(title); + free(stime); + + return (1); + } + + return (0); +} + +int +save_global_history_to_disk(struct tab *t) +{ + char file[PATH_MAX]; + FILE *f; + struct history *h; + + snprintf(file, sizeof file, "%s/%s", work_dir, XT_HISTORY_FILE); + + if ((f = fopen(file, "w")) == NULL) { + show_oops(t, "%s: global history file: %s", + __func__, strerror(errno)); + return (1); + } + + RB_FOREACH_REVERSE(h, history_list, &hl) { + if (h->uri && h->title && h->time) + fprintf(f, "%s\n%s\n%s", h->uri, h->title, + ctime(&h->time)); + } + + fclose(f); + + return (0); +} + +/* Marshall the internal record of visited URIs into a Javascript hash table in + * string form. */ +char * +color_visited_helper(void) +{ + char *s = NULL; + struct history *h; + + RB_FOREACH_REVERSE(h, history_list, &hl) { + if (s == NULL) + s = g_strdup_printf("'%s':'dummy'", h->uri); + else + s = g_strjoin(",", s, + g_strdup_printf("'%s':'dummy'", h->uri), NULL); + } + + s = g_strdup_printf("{%s}", s); + + DNPRINTF(XT_D_VISITED, "%s: s = %s\n", __func__, s); + + return (s); +} + +int +color_visited(struct tab *t, char *visited) +{ + char *s; + + if (t == NULL || visited == NULL) { + show_oops(NULL, "%s: invalid parameters", __func__); + return (1); + } + + /* Create a string representing an annonymous Javascript function, which + * takes a hash table of visited URIs as an argument, goes through the + * links at the current web page and colors them if they indeed been + * visited. + */ + s = g_strconcat( + "(function(visitedUris) {", + " for (var i = 0; i < document.links.length; i++)", + " if (visitedUris[document.links[i].href])", + " document.links[i].style.color = 'purple';", + "})", + /* Apply the annonymous function to the hash table containing + * visited URIs. */ + g_strdup_printf("(%s);", visited), + NULL); + + run_script(t, s); + g_free(s); + g_free(visited); + + return (0); +} diff --git a/xxxterm.c b/xxxterm.c index d1bb3fb..c396e5e 100644 --- a/xxxterm.c +++ b/xxxterm.c @@ -90,18 +90,12 @@ TAILQ_HEAD(command_list, command_entry); #define XT_SAVED_TABS_FILE ("main_session") #define XT_RESTART_TABS_FILE ("restart_tabs") #define XT_SOCKET_FILE ("socket") -#define XT_HISTORY_FILE ("history") #define XT_SAVE_SESSION_ID ("SESSION_NAME=") #define XT_SEARCH_FILE ("search_history") #define XT_COMMAND_FILE ("command_history") #define XT_DLMAN_REFRESH "10" #define XT_MAX_URL_LENGTH (4096) /* 1 page is atomic, don't make bigger */ #define XT_MAX_UNDO_CLOSE_TAB (32) -#define XT_MAX_HL_PURGE_COUNT (1000) /* Purge the history for every - * MAX_HL_PURGE_COUNT items inserted into - * history and delete all items older - * than MAX_HISTORY_AGE. */ -#define XT_MAX_HISTORY_AGE (60.0 * 60.0 * 24 * 14) /* 14 days */ #define XT_RESERVED_CHARS "$&+,/:;=?@ \"<>#%%{}|^~[]`" #define XT_PRINT_EXTRA_MARGIN 10 #define XT_URL_REGEX ("^[[:blank:]]*[^[:blank:]]*([[:alnum:]-]+\\.)+[[:alnum:]-][^[:blank:]]*[[:blank:]]*$") @@ -267,8 +261,6 @@ int next_download_id = 1; void xxx_dir(char *); int icon_size_map(int); -void completion_add(struct tab *); -void completion_add_uri(const gchar *); void history_delete(struct command_list *l, int *counter) @@ -1090,160 +1082,6 @@ userstyle(struct tab *t, struct karg *args) } int -purge_history(void) -{ - struct history *h, *next; - double age = 0.0; - - DNPRINTF(XT_D_HISTORY, "%s: hl_purge_count = %d (%d is max)\n", - __func__, hl_purge_count, XT_MAX_HL_PURGE_COUNT); - - if (hl_purge_count == XT_MAX_HL_PURGE_COUNT) { - hl_purge_count = 0; - - for (h = RB_MIN(history_list, &hl); h != NULL; h = next) { - - next = RB_NEXT(history_list, &hl, h); - - age = difftime(time(NULL), h->time); - - if (age > XT_MAX_HISTORY_AGE) { - DNPRINTF(XT_D_HISTORY, "%s: removing %s (age %.1f)\n", - __func__, h->uri, age); - - RB_REMOVE(history_list, &hl, h); - g_free(h->uri); - g_free(h->title); - g_free(h); - } else { - DNPRINTF(XT_D_HISTORY, "%s: keeping %s (age %.1f)\n", - __func__, h->uri, age); - } - } - } - - return (0); -} - -int -insert_history_item(const gchar *uri, const gchar *title, time_t time) -{ - struct history *h; - - if (!(uri && strlen(uri) && title && strlen(title))) - return (1); - - h = g_malloc(sizeof(struct history)); - h->uri = g_strdup(uri); - h->title = g_strdup(title); - h->time = time; - - DNPRINTF(XT_D_HISTORY, "%s: adding %s\n", __func__, h->uri); - - RB_INSERT(history_list, &hl, h); - completion_add_uri(h->uri); - hl_purge_count++; - - purge_history(); - update_history_tabs(NULL); - - return (0); -} - -int -restore_global_history(void) -{ - char file[PATH_MAX]; - FILE *f; - gchar *uri, *title, *stime, *err = NULL; - time_t time; - struct tm tm; - const char delim[3] = {'\\', '\\', '\0'}; - - snprintf(file, sizeof file, "%s/%s", work_dir, XT_HISTORY_FILE); - - if ((f = fopen(file, "r")) == NULL) { - warnx("%s: fopen", __func__); - return (1); - } - - for (;;) { - if ((uri = fparseln(f, NULL, NULL, delim, 0)) == NULL) - if (feof(f) || ferror(f)) - break; - - if ((title = fparseln(f, NULL, NULL, delim, 0)) == NULL) - if (feof(f) || ferror(f)) { - err = "broken history file (title)"; - goto done; - } - - if ((stime = fparseln(f, NULL, NULL, delim, 0)) == NULL) - if (feof(f) || ferror(f)) { - err = "broken history file (time)"; - goto done; - } - - if (strptime(stime, "%a %b %d %H:%M:%S %Y", &tm) == NULL) { - err = "strptime failed to parse time"; - goto done; - } - - time = mktime(&tm); - - if (insert_history_item(uri, title, time)) { - err = "failed to insert item"; - goto done; - } - - free(uri); - free(title); - free(stime); - uri = NULL; - title = NULL; - stime = NULL; - } - -done: - if (err && strlen(err)) { - warnx("%s: %s\n", __func__, err); - free(uri); - free(title); - free(stime); - - return (1); - } - - return (0); -} - -int -save_global_history_to_disk(struct tab *t) -{ - char file[PATH_MAX]; - FILE *f; - struct history *h; - - snprintf(file, sizeof file, "%s/%s", work_dir, XT_HISTORY_FILE); - - if ((f = fopen(file, "w")) == NULL) { - show_oops(t, "%s: global history file: %s", - __func__, strerror(errno)); - return (1); - } - - RB_FOREACH_REVERSE(h, history_list, &hl) { - if (h->uri && h->title && h->time) - fprintf(f, "%s\n%s\n%s", h->uri, h->title, - ctime(&h->time)); - } - - fclose(f); - - return (0); -} - -int quit(struct tab *t, struct karg *args) { if (save_global_history) @@ -1425,62 +1263,6 @@ save_tabs_and_quit(struct tab *t, struct karg *args) return (1); } -/* Marshall the internal record of visited URIs into a Javascript hash table in - * string form. */ -char * -color_visited_helper(void) -{ - char *s = NULL; - struct history *h; - - RB_FOREACH_REVERSE(h, history_list, &hl) { - if (s == NULL) - s = g_strdup_printf("'%s':'dummy'", h->uri); - else - s = g_strjoin(",", s, - g_strdup_printf("'%s':'dummy'", h->uri), NULL); - } - - s = g_strdup_printf("{%s}", s); - - DNPRINTF(XT_D_VISITED, "%s: s = %s\n", __func__, s); - - return (s); -} - -int -color_visited(struct tab *t, char *visited) -{ - char *s; - - if (t == NULL || visited == NULL) { - show_oops(NULL, "%s: invalid parameters", __func__); - return (1); - } - - /* Create a string representing an annonymous Javascript function, which - * takes a hash table of visited URIs as an argument, goes through the - * links at the current web page and colors them if they indeed been - * visited. - */ - s = g_strconcat( - "(function(visitedUris) {", - " for (var i = 0; i < document.links.length; i++)", - " if (visitedUris[document.links[i].href])", - " document.links[i].style.color = 'purple';", - "})", - /* Apply the annonymous function to the hash table containing - * visited URIs. */ - g_strdup_printf("(%s);", visited), - NULL); - - run_script(t, s); - g_free(s); - g_free(visited); - - return (0); -} - int run_page_script(struct tab *t, struct karg *args) { @@ -7286,81 +7068,6 @@ done: return (-1); } -gboolean -completion_select_cb(GtkEntryCompletion *widget, GtkTreeModel *model, - GtkTreeIter *iter, struct tab *t) -{ - gchar *value; - - gtk_tree_model_get(model, iter, 0, &value, -1); - load_uri(t, value); - g_free(value); - - return (FALSE); -} - -gboolean -completion_hover_cb(GtkEntryCompletion *widget, GtkTreeModel *model, - GtkTreeIter *iter, struct tab *t) -{ - gchar *value; - - gtk_tree_model_get(model, iter, 0, &value, -1); - gtk_entry_set_text(GTK_ENTRY(t->uri_entry), value); - gtk_editable_set_position(GTK_EDITABLE(t->uri_entry), -1); - g_free(value); - - return (TRUE); -} - -void -completion_add_uri(const gchar *uri) -{ - GtkTreeIter iter; - - /* add uri to list_store */ - gtk_list_store_append(completion_model, &iter); - gtk_list_store_set(completion_model, &iter, 0, uri, -1); -} - -gboolean -completion_match(GtkEntryCompletion *completion, const gchar *key, - GtkTreeIter *iter, gpointer user_data) -{ - gchar *value; - gboolean match = FALSE; - - gtk_tree_model_get(GTK_TREE_MODEL(completion_model), iter, 0, &value, - -1); - - if (value == NULL) - return FALSE; - - match = match_uri(value, key); - - g_free(value); - return (match); -} - -void -completion_add(struct tab *t) -{ - /* enable completion for tab */ - t->completion = gtk_entry_completion_new(); - gtk_entry_completion_set_text_column(t->completion, 0); - gtk_entry_set_completion(GTK_ENTRY(t->uri_entry), t->completion); - gtk_entry_completion_set_model(t->completion, - GTK_TREE_MODEL(completion_model)); - gtk_entry_completion_set_match_func(t->completion, completion_match, - NULL, NULL); - gtk_entry_completion_set_minimum_key_length(t->completion, 1); - gtk_entry_completion_set_inline_selection(t->completion, TRUE); - g_signal_connect(G_OBJECT (t->completion), "match-selected", - G_CALLBACK(completion_select_cb), t); - g_signal_connect(G_OBJECT (t->completion), "cursor-on-match", - G_CALLBACK(completion_hover_cb), t); -} - void xxx_dir(char *dir) { diff --git a/xxxterm.h b/xxxterm.h index e510bc4..b32d967 100644 --- a/xxxterm.h +++ b/xxxterm.h @@ -275,6 +275,8 @@ void show_oops(struct tab *, const char *, ...); gchar *get_html_page(gchar *, gchar *, gchar *, bool); const gchar *get_uri(struct tab *); const gchar *get_title(struct tab *, bool); +void load_uri(struct tab *t, gchar *uri); +gboolean match_uri(const gchar *uri, const gchar *key); void load_webkit_string(struct tab *, const char *, gchar *); void button_set_stockid(GtkWidget *, char *); @@ -285,6 +287,17 @@ int remove_cookie_domain(int); void print_cookie(char *msg, SoupCookie *); void setup_cookies(void); +/* history */ +int insert_history_item(const gchar *uri, const gchar *title, time_t time); +int save_global_history_to_disk(struct tab *t); +int restore_global_history(void); +char *color_visited_helper(void); +int color_visited(struct tab *t, char *visited); + +/* completion */ +void completion_add(struct tab *); +void completion_add_uri(const gchar *uri); + /* proxy */ #define XT_PRXY_SHOW (1<<0) #define XT_PRXY_TOGGLE (1<<1) @@ -567,10 +580,12 @@ extern SoupCookieJar *s_cookiejar; extern SoupCookieJar *p_cookiejar; extern SoupSession *session; extern GtkNotebook *notebook; +extern GtkListStore *completion_model; extern void (*_soup_cookie_jar_add_cookie)(SoupCookieJar *, SoupCookie *); extern struct history_list hl; +extern int hl_purge_count; extern struct download_list downloads; extern struct tab_list tabs; extern struct about_type about_list[]; |