viking

webkit based web browser for Enlightenment
Log | Files | Refs | LICENSE

commit da3ec8f4f3408d50f29d5430883939a3f0ff4cff
parent a61a1d406b4fc9655b385938830ab92faa45698b
Author: Kyle Milz <kmilz@ucalgary.ca>
Date:   Sun, 14 Oct 2012 16:35:03 -0600

re-implement tab completion

implement rudimentary command and history completion. still needs a few
things (highlighting of current suggestion, other bugs).

rip out the old completion.

Diffstat:
Msrc/commands.c | 364+++++++++++++++++++++++++------------------------------------------------------
1 file changed, 114 insertions(+), 250 deletions(-)

diff --git a/src/commands.c b/src/commands.c @@ -8,270 +8,134 @@ #include "commands.h" #include "utilities.h" -static unsigned int scrollstep = 40; /* cursor difference in pixel */ -static unsigned int pagingkeep = 40; /* pixels kept when paging */ +// static unsigned int scrollstep = 40; /* cursor difference in pixel */ +// static unsigned int pagingkeep = 40; /* pixels kept when paging */ -void fill_suggline(char * suggline, const char * command, const char *fill_with); -Evas_Object * fill_eventbox(const char * completion_line); +Eina_Bool +complete(const Arg *arg, void *data) +{ + Window_Data *wd = data; + const char *match; + Eina_List *l; + size_t len; + int i; + Evas_Object *label; + + /* make this function re-entrant */ + static Eina_List *matches = NULL; + static const char *prefix; + static int current = -1, n; + static Eina_List *widgets = NULL; + + printf("complete()\n"); + + match = elm_entry_entry_get(wd->url); + len = strlen(match); + + if ((len == 0 || match[0] != ':') && arg->i != HideCompletion) + return EINA_TRUE; + + if (prefix) { + printf("\tprefix found, current = %i, num matches = %i\n", current, eina_list_count(matches)); + if (arg->i != HideCompletion && widgets && current != -1 && !strcmp(&match[0], + eina_list_nth(matches, current))) { + elm_object_style_set(eina_list_nth(widgets, current), "normal"); + current = (n + current + (arg->i == DirectionPrev ? -1 : 1)) % n; + if ((arg->i == DirectionNext && current == 0) + || (arg->i == DirectionPrev && current == n - 1)) + current = -1; + } else { + eina_list_free(widgets); + eina_list_free(matches); + eina_stringshare_del(prefix); + elm_box_clear(wd->event_box); + widgets = NULL; + matches = NULL; + prefix = NULL; + n = 0; + current = -1; + if (arg->i == HideCompletion) + return EINA_TRUE; + } + } else if (arg->i == HideCompletion) + return EINA_TRUE; + if (!widgets) { + prefix = eina_stringshare_add(match); -void fill_suggline(char * suggline, const char * command, const char *fill_with) { - memset(suggline, 0, 512); - strncpy(suggline, command, 512); - strncat(suggline, " ", 1); - strncat(suggline, fill_with, 512 - strlen(suggline) - 1); -} + if (strchr(match, ' ') == NULL) { + for (i = 0; i < LENGTH(commands); i++) + if (strncmp(commands[i].cmd, match + 1, len - 1) == 0) { + Eina_Strbuf *buf = eina_strbuf_new(); + eina_strbuf_append_printf(buf, ":%s", commands[i].cmd); + matches = eina_list_append(matches, eina_strbuf_string_get(buf)); + } + } -Evas_Object *fill_eventbox(const char * completion_line) -{ - /* - GtkBox * row; - Evas_Object *row_eventbox, *el; - GdkColor color; - char *markup, *markup_tmp; - - row = GTK_BOX(gtk_hbox_new(FALSE, 0)); - row_eventbox = gtk_event_box_new(); - gdk_color_parse(completionbgcolor[0], &color); - gtk_widget_modify_bg(row_eventbox, GTK_STATE_NORMAL, &color); - el = gtk_label_new(NULL); - markup_tmp = g_markup_escape_text(completion_line, strlen(completion_line)); - markup = g_strconcat("<span font=\"", completionfont[0], "\" color=\"", completioncolor[0], "\">", - markup_tmp, "</span>", NULL); - gtk_label_set_markup(GTK_LABEL(el), markup); - g_free(markup_tmp); - g_free(markup); - gtk_misc_set_alignment(GTK_MISC(el), 0, 0); - gtk_box_pack_start(row, el, TRUE, TRUE, 2); - gtk_container_add(GTK_CONTAINER(row_eventbox), GTK_WIDGET(row)); - return row_eventbox; - */ - return NULL; -} + char **tokens = eina_str_split(match, " ", 2); + if (tokens && (strncmp(tokens[0], ":open", 5) == 0 || + strncmp(tokens[0], ":tabopen", 8) == 0)) { + /* :open history completion */ + void *hash_data; + Eina_Iterator *it = eina_hash_iterator_tuple_new(hist_items_hash_get(wd->app->history)); + + while (eina_iterator_next(it, &hash_data)) { + Eina_Hash_Tuple *t = hash_data; + Eina_Strbuf *buf = eina_strbuf_new(); + Hist_Item *hist_item = t->data; + const char *url = hist_item_url_get(hist_item); + if (strncmp(url, tokens[1], strlen(tokens[1])) == 0) { + eina_strbuf_append_printf(buf, "%s %s", tokens[0], url); + matches = eina_list_append(matches, eina_strbuf_string_get(buf)); + } + } + } + else if (tokens && strncmp(tokens[0], ":set", 5) == 0) { + printf("\t:set not implemented yet\n"); + } -Eina_Bool -complete(const Arg *arg, void *data) -{ -#if 0 - char *p, *s, *markup, *entry, *searchfor, command[32] = "", suggline[512] = "", **suggurls; - char *str; - size_t listlen, len, cmdlen; - int i, spacepos; - Listelement *elementlist = NULL, *elementpointer; - Eina_Bool highlight = FALSE; - // GtkBox *row; - // GtkWidget *row_eventbox, *el; - // GtkBox *_table; - // GdkColor color; - // static GtkWidget *table, *top_border; - Evas_Object *row, *row_eventbox, *el, *_table; - Evas_Object *table, *top_border; - static char *prefix; - static char **suggestions; - static Evas_Object **widgets; - static int n = 0, m, current = -1; - Window_Data *ad = data; + n = eina_list_count(matches); + printf("\tfound %i matches for %s\n", n, match); - str = elm_entry_entry_get(ad->url); - // str = (char*)gtk_entry_get_text(GTK_ENTRY(inputbox)); - len = strlen(str); + EINA_LIST_FOREACH(matches, l, match) { - /* Get the length of the list of commands for completion. We need this to - * malloc/realloc correctly. - */ - listlen = LENGTH(commands); + printf("\tbuilding label for match %s\n", match); - if ((len == 0 || str[0] != ':') && arg->i != HideCompletion) - return TRUE; - /* - if (prefix) { - if (arg->i != HideCompletion && widgets && current != -1 && !strcmp(&str[1], suggestions[current])) { - gdk_color_parse(completionbgcolor[0], &color); - gtk_widget_modify_bg(widgets[current], GTK_STATE_NORMAL, &color); - current = (n + current + (arg->i == DirectionPrev ? -1 : 1)) % n; - if ((arg->i == DirectionNext && current == 0) - || (arg->i == DirectionPrev && current == n - 1)) - current = -1; - } else { - free(widgets); - free(suggestions); - free(prefix); - gtk_widget_destroy(GTK_WIDGET(table)); - gtk_widget_destroy(GTK_WIDGET(top_border)); - table = NULL; - widgets = NULL; - suggestions = NULL; - prefix = NULL; - n = 0; - current = -1; - if (arg->i == HideCompletion) - return TRUE; - } - } else if (arg->i == HideCompletion) - return TRUE; - */ - if (!widgets) { - prefix = strdup(str); - // widgets = malloc(sizeof(GtkWidget*) * listlen); - widgets = malloc(sizeof(Evas_Object*) * listlen); - suggestions = malloc(sizeof(char*) * listlen); - top_border = gtk_event_box_new(); - gtk_widget_set_size_request(GTK_WIDGET(top_border), 0, 1); - - // gdk_color_parse(completioncolor[2], &color); - // gtk_widget_modify_bg(top_border, GTK_STATE_NORMAL, &color); - elm_bg_color_set(top_border, completioncolor[2][0], completioncolor[2][1], completioncolor[2][2]); - - table = gtk_event_box_new(); - gdk_color_parse(completionbgcolor[0], &color); - _table = GTK_BOX(gtk_vbox_new(FALSE, 0)); - highlight = len > 1; - if (strchr(str, ' ') == NULL) { - /* command completion */ - listlen = LENGTH(commands); - for (i = 0; i < listlen; i++) { - if (commands[i].cmd == NULL) - break; - cmdlen = strlen(commands[i].cmd); - if (!highlight || (n < MAX_LIST_SIZE && len - 1 <= cmdlen && !strncmp(&str[1], commands[i].cmd, len - 1))) { - p = s = malloc(sizeof(char*) * (highlight ? sizeof(COMPLETION_TAG_OPEN) + sizeof(COMPLETION_TAG_CLOSE) - 1 : 1) + cmdlen); - if (highlight) { - memcpy(p, COMPLETION_TAG_OPEN, sizeof(COMPLETION_TAG_OPEN) - 1); - memcpy((p += sizeof(COMPLETION_TAG_OPEN) - 1), &str[1], len - 1); - memcpy((p += len - 1), COMPLETION_TAG_CLOSE, sizeof(COMPLETION_TAG_CLOSE) - 1); - p += sizeof(COMPLETION_TAG_CLOSE) - 1; - } - memcpy(p, &commands[i].cmd[len - 1], cmdlen - len + 2); - row = GTK_BOX(gtk_hbox_new(FALSE, 0)); - row_eventbox = gtk_event_box_new(); - gtk_widget_modify_bg(row_eventbox, GTK_STATE_NORMAL, &color); - el = gtk_label_new(NULL); - markup = g_strconcat("<span font=\"", completionfont[0], "\" color=\"", completioncolor[0], "\">", s, "</span>", NULL); - free(s); - gtk_label_set_markup(GTK_LABEL(el), markup); - g_free(markup); - gtk_misc_set_alignment(GTK_MISC(el), 0, 0); - gtk_box_pack_start(row, el, TRUE, TRUE, 2); - gtk_container_add(GTK_CONTAINER(row_eventbox), GTK_WIDGET(row)); - gtk_box_pack_start(_table, GTK_WIDGET(row_eventbox), FALSE, FALSE, 0); - suggestions[n] = commands[i].cmd; - widgets[n++] = row_eventbox; - } - } - } else { - entry = (char *)malloc(512 * sizeof(char)); - if (entry == NULL) { - return FALSE; - } - memset(entry, 0, 512); - suggurls = malloc(sizeof(char*) * listlen); - if (suggurls == NULL) { - return FALSE; - } - spacepos = strcspn(str, " "); - searchfor = (str + spacepos + 1); - strncpy(command, (str + 1), spacepos - 1); - if (strlen(command) == 3 && strncmp(command, "set", 3) == 0) { - /* browser settings */ - listlen = LENGTH(browsersettings); - for (i = 0; i < listlen; i++) { - if (n < MAX_LIST_SIZE && strstr(browsersettings[i].name, searchfor) != NULL) { - /* match */ - fill_suggline(suggline, command, browsersettings[i].name); - /* FIXME(HP): This memory is never freed */ - suggurls[n] = (char *)malloc(sizeof(char) * 512 + 1); - strncpy(suggurls[n], suggline, 512); - suggestions[n] = suggurls[n]; - row_eventbox = fill_eventbox(suggline); - gtk_box_pack_start(_table, GTK_WIDGET(row_eventbox), FALSE, FALSE, 0); - widgets[n++] = row_eventbox; - } + label = elm_label_add(wd->win); + evas_object_size_hint_align_set(label, 0.0, EVAS_HINT_FILL); + elm_object_text_set(label, match); + elm_box_pack_end(wd->event_box, label); + evas_object_show(label); - } - } else if (strlen(command) == 2 && strncmp(command, "qt", 2) == 0) { - /* completion on tags */ - spacepos = strcspn(str, " "); - searchfor = (str + spacepos + 1); - elementlist = complete_list(searchfor, 1, elementlist); - } else { - /* URL completion: bookmarks */ - elementlist = complete_list(searchfor, 0, elementlist); - m = count_list(elementlist); - if (m < MAX_LIST_SIZE) { - /* URL completion: history */ - elementlist = complete_list(searchfor, 2, elementlist); - } - } - elementpointer = elementlist; - while (elementpointer != NULL) { - fill_suggline(suggline, command, elementpointer->element); - /* FIXME(HP): This memory is never freed */ - suggurls[n] = (char *)malloc(sizeof(char) * 512 + 1); - strncpy(suggurls[n], suggline, 512); - suggestions[n] = suggurls[n]; - row_eventbox = fill_eventbox(suggline); - gtk_box_pack_start(_table, GTK_WIDGET(row_eventbox), FALSE, FALSE, 0); - widgets[n++] = row_eventbox; - elementpointer = elementpointer->next; - if (n >= MAX_LIST_SIZE) - break; - } - free_list(elementlist); - if (suggurls != NULL) { - free(suggurls); - suggurls = NULL; - } - if (entry != NULL) { - free(entry); - entry = NULL; - } - } - /* TA: FIXME - this needs rethinking entirely. */ - { - GtkWidget **widgets_temp = realloc(widgets, sizeof(*widgets) * n); - if (widgets_temp == NULL && widgets == NULL) { - fprintf(stderr, "Couldn't realloc() widgets\n"); - exit(1); - } - widgets = widgets_temp; - char **suggestions_temp = realloc(suggestions, sizeof(*suggestions) * n); - if (suggestions_temp == NULL && suggestions == NULL) { - fprintf(stderr, "Couldn't realloc() suggestions\n"); - exit(1); - } - suggestions = suggestions_temp; - } - if (!n) { - gdk_color_parse(completionbgcolor[1], &color); - gtk_widget_modify_bg(table, GTK_STATE_NORMAL, &color); - el = gtk_label_new(NULL); - gtk_misc_set_alignment(GTK_MISC(el), 0, 0); - markup = g_strconcat("<span font=\"", completionfont[1], "\" color=\"", completioncolor[1], "\">No Completions</span>", NULL); - gtk_label_set_markup(GTK_LABEL(el), markup); - g_free(markup); - gtk_box_pack_start(_table, GTK_WIDGET(el), FALSE, FALSE, 0); - } - gtk_box_pack_start(box, GTK_WIDGET(top_border), FALSE, FALSE, 0); - gtk_container_add(GTK_CONTAINER(table), GTK_WIDGET(_table)); - gtk_box_pack_start(box, GTK_WIDGET(table), FALSE, FALSE, 0); - gtk_widget_show_all(GTK_WIDGET(window)); - if (!n) - return TRUE; + widgets = eina_list_append(widgets, label); + } + + if (!n) { + label = elm_label_add(wd->win); + evas_object_size_hint_align_set(label, 0.0, EVAS_HINT_FILL); + elm_object_text_set(label, "No Completions"); + elm_box_pack_end(wd->event_box, label); + evas_object_show(label); + } + + evas_object_show(wd->event_box); + if (!n) + return EINA_TRUE; current = arg->i == DirectionPrev ? n - 1 : 0; - } + } + if (current != -1) { - gdk_color_parse(completionbgcolor[2], &color); - gtk_widget_modify_bg(GTK_WIDGET(widgets[current]), GTK_STATE_NORMAL, &color); - s = g_strconcat(":", suggestions[current], NULL); - gtk_entry_set_text(GTK_ENTRY(inputbox), s); - g_free(s); + Eina_Strbuf *suggestion = eina_strbuf_new(); + eina_strbuf_append_printf(suggestion, "%s", (char*)eina_list_nth(matches, current)); + elm_entry_entry_set(wd->url, eina_strbuf_string_get(suggestion)); + elm_object_style_set(eina_list_nth(matches, current), "highlighted"); } else - gtk_entry_set_text(GTK_ENTRY(inputbox), prefix); - gtk_editable_set_position(GTK_EDITABLE(inputbox), -1); -#endif - return TRUE; + elm_entry_entry_set(wd->url, prefix); + elm_entry_cursor_end_set(wd->url); + + return EINA_TRUE; } Eina_Bool