commit 65c4966563d067115fc09f5e5c8c43a917b1cf03 from: Omar Polo date: Tue Jan 23 19:18:01 2024 UTC rework the history management It was a huge pile of spaghetti with useless utility functions and lots of code reaching into the "data structure" (if you can call it so) to do stuff. Instead, provide a "module" with a clean interface and noone reaching in the insides. commit - 91ef5ab4100ad6f754a0945d4ec468a52626ac63 commit + 65c4966563d067115fc09f5e5c8c43a917b1cf03 blob - bd2d752329a0e9cc48def01631b34b2561c5d131 blob + 6432f67d4568e5bd4e10fda23d48d6c2a7bff393 --- cmd.c +++ cmd.c @@ -22,6 +22,7 @@ #include "compl.h" #include "defaults.h" +#include "hist.h" #include "mcache.h" #include "minibuffer.h" #include "session.h" @@ -326,7 +327,7 @@ cmd_push_button_new_tab(struct buffer *buffer) if (vl == NULL || vl->parent->type != LINE_LINK) return; - new_tab(vl->parent->alt, current_tab->hist_cur->h, current_tab); + new_tab(vl->parent->alt, hist_cur(current_tab->hist), current_tab); } void @@ -429,7 +430,7 @@ cmd_execute_extended_command(struct buffer *buffer) GUARD_RECURSIVE_MINIBUFFER(); enter_minibuffer(sensible_self_insert, eecmd_select, exit_minibuffer, - &eecmd_history, compl_eecmd, NULL, 1); + eecmd_history, compl_eecmd, NULL, 1); len = sizeof(ministate.prompt); strlcpy(ministate.prompt, "", len); @@ -560,7 +561,7 @@ cmd_load_url(struct buffer *buffer) GUARD_RECURSIVE_MINIBUFFER(); enter_minibuffer(sensible_self_insert, lu_select, exit_minibuffer, - &lu_history, compl_lu, NULL, 0); + lu_history, compl_lu, NULL, 0); strlcpy(ministate.prompt, "Load URL: ", sizeof(ministate.prompt)); } @@ -570,16 +571,16 @@ cmd_load_current_url(struct buffer *buffer) GUARD_RECURSIVE_MINIBUFFER(); enter_minibuffer(sensible_self_insert, lu_select, exit_minibuffer, - &lu_history, compl_lu, NULL, 0); + lu_history, compl_lu, NULL, 0); strlcpy(ministate.prompt, "Load URL: ", sizeof(ministate.prompt)); - strlcpy(ministate.buf, current_tab->hist_cur->h, sizeof(ministate.buf)); + strlcpy(ministate.buf, hist_cur(current_tab->hist), sizeof(ministate.buf)); ministate.buffer.cpoff = utf8_cplen(ministate.buf); } void cmd_reload_page(struct buffer *buffer) { - load_url_in_tab(current_tab, current_tab->hist_cur->h, NULL, + load_url_in_tab(current_tab, hist_cur(current_tab->hist), NULL, LU_MODE_NOHIST|LU_MODE_NOCACHE); } @@ -591,7 +592,8 @@ cmd_bookmark_page(struct buffer *buffer) enter_minibuffer(sensible_self_insert, bp_select, exit_minibuffer, NULL, NULL, NULL, 0); strlcpy(ministate.prompt, "Bookmark URL: ", sizeof(ministate.prompt)); - strlcpy(ministate.buf, current_tab->hist_cur->h, sizeof(ministate.buf)); + strlcpy(ministate.buf, hist_cur(current_tab->hist), + sizeof(ministate.buf)); ministate.buffer.cpoff = utf8_cplen(ministate.buf); } @@ -783,7 +785,7 @@ cmd_mini_complete_and_exit(struct buffer *buffer) if (!in_minibuffer) return; - if (ministate.compl.must_select && ministate.hist_cur == NULL) { + if (ministate.compl.must_select && ministate.hist == NULL) { vl = ministate.compl.buffer.current_line; if (vl == NULL || vl->parent->flags & L_HIDDEN || vl->parent->type == LINE_COMPL) { @@ -799,49 +801,47 @@ cmd_mini_complete_and_exit(struct buffer *buffer) void cmd_mini_previous_history_element(struct buffer *buffer) { - if (ministate.history == NULL) { + char *text; + + if (ministate.hist == NULL) { message("No history"); return; } - if (ministate.hist_cur == NULL || - (ministate.hist_cur = TAILQ_PREV(ministate.hist_cur, mhisthead, entries)) == NULL) { - ministate.hist_cur = TAILQ_LAST(&ministate.history->head, mhisthead); - ministate.hist_off = ministate.history->len - 1; - if (ministate.hist_cur == NULL) - message("No prev history item"); - } else { - ministate.hist_off--; + if (hist_prev(ministate.hist) == NULL) { + message("No prev history item"); + return; } - if (ministate.hist_cur != NULL) { - buffer->current_line->parent->line = ministate.hist_cur->h; - recompute_completions(0); - } + ministate.editing = 0; + + /* XXX the minibuffer line is never modified so this is fine */ + text = (char *)hist_cur(ministate.hist); + buffer->current_line->parent->line = text; + recompute_completions(0); } void cmd_mini_next_history_element(struct buffer *buffer) { - if (ministate.history == NULL) { + char *text; + + if (ministate.hist == NULL) { message("No history"); return; } - if (ministate.hist_cur == NULL || - (ministate.hist_cur = TAILQ_NEXT(ministate.hist_cur, entries)) == NULL) { - ministate.hist_cur = TAILQ_FIRST(&ministate.history->head); - ministate.hist_off = 0; - if (ministate.hist_cur == NULL) - message("No next history item"); - } else { - ministate.hist_off++; + if (hist_next(ministate.hist) == NULL) { + message("No next history item"); + return; } - if (ministate.hist_cur != NULL) { - buffer->current_line->parent->line = ministate.hist_cur->h; - recompute_completions(0); - } + ministate.editing = 0; + + /* XXX the minibuffer line is never modified so this is fine */ + text = (char *)hist_cur(ministate.hist); + buffer->current_line->parent->line = text; + recompute_completions(0); } void @@ -1047,7 +1047,7 @@ cmd_write_buffer(struct buffer *buffer) return; } - url = current_tab->hist_cur->h; + url = hist_cur(current_tab->hist); if ((f = strrchr(url, '/')) != NULL) f++; @@ -1077,8 +1077,7 @@ cmd_home(struct buffer *buffer) tilde[1] != '\0' && tilde[1] != '/') { if ((t = strchr(tilde, '/')) != NULL) *++t = '\0'; - load_url_in_tab(current_tab, path, current_tab->hist_cur->h, - LU_MODE_NOCACHE); + load_url_in_tab(current_tab, path, NULL, LU_MODE_NOCACHE); } else cmd_root(buffer); } @@ -1086,13 +1085,11 @@ cmd_home(struct buffer *buffer) void cmd_root(struct buffer *buffer) { - load_url_in_tab(current_tab, "/", current_tab->hist_cur->h, - LU_MODE_NOCACHE); + load_url_in_tab(current_tab, "/", NULL, LU_MODE_NOCACHE); } void cmd_up(struct buffer *buffer) { - load_url_in_tab(current_tab, "..", current_tab->hist_cur->h, - LU_MODE_NOCACHE); + load_url_in_tab(current_tab, "..", NULL, LU_MODE_NOCACHE); } blob - 27e9f1421a74a09bb2f79e3182a628e354849c82 blob + f6243324b8c79bb4caa3af734dd71f9c490da953 --- compl.c +++ compl.c @@ -19,6 +19,7 @@ #include #include "compl.h" +#include "hist.h" #include "telescope.h" #include "session.h" @@ -76,8 +77,8 @@ compl_ts(void **data, void **ret, const char **descr) *ret = *tab; if (*(*tab)->buffer.page.title == '\0') - return (*tab)->hist_cur->h; - *descr = (*tab)->hist_cur->h; + return hist_cur((*tab)->hist); + *descr = hist_cur((*tab)->hist); return (*tab)->buffer.page.title; } blob - 90134a3d3e22fe68c2682313af3261d7b079d628 blob + c6eacfeded1e19b1e77d86523fac935cf8080f72 --- hist.c +++ hist.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Omar Polo + * Copyright (c) 2021, 2024 Omar Polo * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -17,64 +17,266 @@ #include "compat.h" #include +#include -#include "telescope.h" +#include "hist.h" +struct hist { + TAILQ_HEAD(mhist, hist_item) head; + int flags; + size_t size; + ssize_t off; + struct hist_item *cur; +}; + +struct hist_item { + char *str; + size_t line_off; + size_t current_off; + TAILQ_ENTRY(hist_item) entries; +}; + +struct hist * +hist_new(int flags) +{ + struct hist *hist; + + if ((hist = calloc(1, sizeof(*hist))) == NULL) + return (NULL); + + TAILQ_INIT(&hist->head); + hist->flags = flags; + hist->off = -1; + return (hist); +} + void -hist_clear(struct histhead *head) +hist_free(struct hist *hist) { - struct hist *h, *th; + if (hist == NULL) + return; - TAILQ_FOREACH_SAFE(h, &head->head, entries, th) { - TAILQ_REMOVE(&head->head, h, entries); + hist_erase(hist); + free(hist); +} + +static void +hist_erase_from(struct hist *hist, struct hist_item *h) +{ + struct hist_item *next; + + while (h != NULL) { + next = TAILQ_NEXT(h, entries); + + hist->size--; + TAILQ_REMOVE(&hist->head, h, entries); + free(h->str); free(h); + h = next; } - head->len = 0; } void -hist_clear_forward(struct histhead *head, struct hist *h) +hist_erase(struct hist *hist) { - struct hist *i; + hist_erase_from(hist, TAILQ_FIRST(&hist->head)); - if (h == NULL) - return; + hist->size = 0; + hist->off = -1; + hist->cur = NULL; +} - while ((i = TAILQ_NEXT(h, entries)) != NULL) { - TAILQ_REMOVE(&head->head, i, entries); - free(i); - head->len--; +size_t +hist_size(struct hist *hist) +{ + return (hist->size); +} + +size_t +hist_off(struct hist *hist) +{ + if (hist->off == -1) + return (0); + return (hist->off); +} + +const char * +hist_cur(struct hist *hist) +{ + if (hist->cur == NULL) + return (NULL); + return (hist->cur->str); +} + +int +hist_cur_offs(struct hist *hist, size_t *line, size_t *curr) +{ + *line = 0; + *curr = 0; + + if (hist->cur == NULL) + return (-1); + + *line = hist->cur->line_off; + *curr = hist->cur->current_off; + return (0); +} + +int +hist_set_cur(struct hist *hist, const char *str) +{ + char *d; + + if (hist->cur == NULL) + return (-1); + + if ((d = strdup(str)) == NULL) + return (-1); + + free(hist->cur->str); + hist->cur->str = d; + return (0); +} + +int +hist_set_offs(struct hist *hist, size_t line, size_t curr) +{ + if (hist->cur == NULL) + return (-1); + + hist->cur->line_off = line; + hist->cur->current_off = line; + return (0); +} + +const char * +hist_nth(struct hist *hist, size_t n) +{ + size_t i; + struct hist_item *h; + + i = 0; + TAILQ_FOREACH(h, &hist->head, entries) { + if (i++ == n) + return (h->str); } + return (NULL); +} - TAILQ_REMOVE(&head->head, h, entries); - free(h); - head->len--; +const char * +hist_prev(struct hist *hist) +{ + struct hist_item *h; + int wrap = hist->flags & HIST_WRAP; + + if (hist->cur == NULL && !wrap) + return (NULL); + + if (hist->cur == NULL || + (h = TAILQ_PREV(hist->cur, mhist, entries)) == NULL) { + if (!wrap || (h = TAILQ_LAST(&hist->head, mhist)) == NULL) + return (NULL); + hist->off = hist->size - 1; + } else + hist->off--; + + hist->cur = h; + return (h->str); } -void -hist_push(struct histhead *head, struct hist *h) +const char * +hist_next(struct hist *hist) { - head->len++; - TAILQ_INSERT_TAIL(&head->head, h, entries); + struct hist_item *h; + int wrap = hist->flags & HIST_WRAP; + + if (hist->cur == NULL && !wrap) + return (NULL); + + if (hist->cur == NULL || + (h = TAILQ_NEXT(hist->cur, entries)) == NULL) { + if (!wrap || (h = TAILQ_FIRST(&hist->head)) == NULL) + return (NULL); + hist->off = 0; + } else + hist->off++; + + hist->cur = h; + return (h->str); } void -hist_add_before(struct histhead *head, struct hist *curr, struct hist *h) +hist_seek_start(struct hist *hist) { - head->len++; - TAILQ_INSERT_BEFORE(curr, h, entries); + hist->off = -1; + hist->cur = NULL; } -struct hist * -hist_pop(struct histhead *head) +int +hist_push(struct hist *hist, const char *str) { - struct hist *h, *p; + struct hist_item *h; - if ((h = TAILQ_LAST(&head->head, mhisthead)) == NULL) - return NULL; - if ((p = TAILQ_PREV(h, mhisthead, entries)) == NULL) - return NULL; + if ((h = calloc(1, sizeof(*h))) == NULL) + return (-1); - hist_clear_forward(head, h); - return p; + if ((h->str = strdup(str)) == NULL) { + free(h); + return (-1); + } + + if (hist->cur != NULL) + hist_erase_from(hist, TAILQ_NEXT(hist->cur, entries)); + hist->cur = h; + hist->off++; + hist->size++; + TAILQ_INSERT_TAIL(&hist->head, h, entries); + return (0); } + +int +hist_prepend(struct hist *hist, const char *str) +{ + struct hist_item *h; + + if (hist->cur == NULL) + return (-1); + + if ((h = calloc(1, sizeof(*h))) == NULL) + return (-1); + + if ((h->str = strdup(str)) == NULL) { + free(h); + return (-1); + } + + hist->size++; + hist->off++; + TAILQ_INSERT_BEFORE(hist->cur, h, entries); + return (0); +} + +int +hist_append(struct hist *hist, const char *str) +{ + struct hist_item *h; + + /* + * Not sure. The minibuffer needs to append even when there + * are no items. + */ + if (hist->cur == NULL && !(hist->flags & HIST_WRAP)) + return (-1); + + if ((h = calloc(1, sizeof(*h))) == NULL) + return (-1); + + if ((h->str = strdup(str)) == NULL) { + free(h); + return (-1); + } + + hist->size++; + TAILQ_INSERT_TAIL(&hist->head, h, entries); + return (0); +} blob - e19d2936f5dbf647c825d2caa8bbb9d6cd7bd4ef blob + d993896dd79343bae46a2ba6dc48362c4b802c8a --- include/minibuffer.h +++ include/minibuffer.h @@ -36,10 +36,11 @@ */ typedef const char *(complfn)(void **, void **, const char **); -extern struct histhead eecmd_history, - ir_history, - lu_history, - read_history; +struct hist; +extern struct hist *eecmd_history; +extern struct hist *ir_history; +extern struct hist *lu_history; +extern struct hist *read_history; struct ministate { char *curmesg; @@ -53,9 +54,8 @@ struct ministate { struct vline vline; struct buffer buffer; - struct histhead *history; - struct hist *hist_cur; - size_t hist_off; + struct hist *hist; + int editing; struct { struct buffer buffer; @@ -86,7 +86,7 @@ void swiper_select(void); void toc_select(void); void enter_minibuffer(void(*)(void), void(*)(void), void(*)(void), - struct histhead *, complfn *, void *, int); + struct hist *, complfn *, void *, int); void exit_minibuffer(void); void yornp(const char *, void (*)(int, struct tab *), struct tab *); blob - 19ae69e25c10857032952eea8589d154d52115ee blob + acb3a2423988a8d005fdc3feb99dc4e6348683c0 --- include/telescope.h +++ include/telescope.h @@ -173,17 +173,6 @@ struct tofu_entry { int verified; }; -struct histhead { - TAILQ_HEAD(mhisthead, hist) head; - size_t len; -}; -struct hist { - char h[1025]; - size_t line_off; - size_t current_off; - TAILQ_ENTRY(hist) entries; -}; - struct buffer { struct parser page; @@ -206,6 +195,8 @@ struct buffer { #define TAB_LAZY 0x8 /* to lazy load tabs */ #define NEW_TAB_URL "about:new" + +struct hist; TAILQ_HEAD(tabshead, tab); extern struct tabshead tabshead; @@ -219,9 +210,7 @@ struct tab { enum trust_state trust; struct proxy *proxy; struct iri iri; - struct histhead hist; - struct hist *hist_cur; - size_t hist_off; + struct hist *hist; char *last_input_url; int code; @@ -284,13 +273,6 @@ struct download *download_by_id(uint32_t); /* help.c */ void recompute_help(void); -/* hist.c */ -void hist_clear(struct histhead *); -void hist_clear_forward(struct histhead*, struct hist*); -void hist_push(struct histhead*, struct hist*); -void hist_add_before(struct histhead *, struct hist *, struct hist *); -struct hist *hist_pop(struct histhead *); - /* mime.c */ int setup_parser_for(struct tab*); blob - /dev/null blob + fdd02ec1da20a65b7c9f591451086fd6afcc58df (mode 644) --- /dev/null +++ hist.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2021, 2024 Omar Polo + * + * 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. + */ + +struct hist; + +#define HIST_LINEAR 0x0 +#define HIST_WRAP 0x1 + +struct hist *hist_new(int); +void hist_free(struct hist *); +void hist_erase(struct hist *); + +size_t hist_size(struct hist *); +size_t hist_off(struct hist *); + +const char *hist_cur(struct hist *); +int hist_cur_offs(struct hist *, size_t *, size_t *); + +int hist_set_cur(struct hist *, const char *); +int hist_set_offs(struct hist *, size_t, size_t); + +const char *hist_nth(struct hist *, size_t); +const char *hist_prev(struct hist *); +const char *hist_next(struct hist *); + +void hist_seek_start(struct hist *); + +int hist_push(struct hist *, const char *); +int hist_prepend(struct hist *, const char *); +int hist_append(struct hist *, const char *); + blob - 15ad787db716874d579217b8bfb8b4c61a5a9890 blob + eb297a3141dc42fac25f1b19d59ee31bb68367d7 --- mcache.c +++ mcache.c @@ -21,6 +21,7 @@ #include #include "telescope.h" +#include "hist.h" #include "mcache.h" #include "parser.h" #include "utils.h" @@ -99,7 +100,7 @@ mcache_tab(struct tab *tab) const char *url; FILE *fp; - url = tab->hist_cur->h; + url = hist_cur(tab->hist); l = strlen(url); len = sizeof(*e) + l + 1; blob - 3505c26ce050a82be817c9bde5ad177be56dc650 blob + ad7a389c7d41f9219d2c68bb3d40e02b30ded2c1 --- minibuffer.c +++ minibuffer.c @@ -23,6 +23,7 @@ #include #include "fs.h" +#include "hist.h" #include "iri.h" #include "minibuffer.h" #include "session.h" @@ -51,11 +52,10 @@ static struct tab *yornp_data; static void (*read_cb)(const char*, struct tab *); static struct tab *read_data; -/* XXX: don't forget to init these in minibuffer_init */ -struct histhead eecmd_history, - ir_history, - lu_history, - read_history; +struct hist *eecmd_history; +struct hist *ir_history; +struct hist *lu_history; +struct hist *read_history; struct ministate ministate; @@ -103,8 +103,8 @@ recompute_completions(int add) if (in_minibuffer != MB_COMPREAD) return; - if (ministate.hist_cur != NULL) - text = ministate.hist_cur->h; + if (!ministate.editing) + text = hist_cur(ministate.hist); else text = ministate.buf; @@ -176,8 +176,8 @@ minibuffer_compl_text(void) { struct vline *vl; - if (ministate.hist_cur != NULL) - return ministate.hist_cur->h; + if (!ministate.editing) + return hist_cur(ministate.hist); vl = ministate.compl.buffer.current_line; if (vl == NULL || vl->parent->flags & L_HIDDEN || @@ -189,20 +189,10 @@ minibuffer_compl_text(void) static void minibuffer_hist_save_entry(void) { - struct hist *hist; - const char *t; - - if (ministate.history == NULL) + if (ministate.hist == NULL) return; - if ((hist = calloc(1, sizeof(*hist))) == NULL) - abort(); - - t = minibuffer_compl_text(); - strlcpy(hist->h, t, sizeof(hist->h)); - - TAILQ_INSERT_TAIL(&ministate.history->head, hist, entries); - ministate.history->len++; + hist_append(ministate.hist, minibuffer_compl_text()); } /* @@ -213,11 +203,12 @@ minibuffer_hist_save_entry(void) void minibuffer_taint_hist(void) { - if (ministate.hist_cur == NULL) + if (ministate.editing) return; - strlcpy(ministate.buf, ministate.hist_cur->h, sizeof(ministate.buf)); - ministate.hist_cur = NULL; + ministate.editing = 1; + strlcpy(ministate.buf, hist_cur(ministate.hist), + sizeof(ministate.buf)); ministate.buffer.current_line->parent->line = ministate.buf; } @@ -285,7 +276,7 @@ ir_select_gemini(void) minibuffer_hist_save_entry(); - if (iri_parse(NULL, tab->hist_cur->h, &iri) == -1) + if (iri_parse(NULL, hist_cur(tab->hist), &iri) == -1) goto err; if (iri_setquery(&iri, minibuffer_compl_text()) == -1) goto err; @@ -332,7 +323,7 @@ lu_select(void) char url[GEMINI_URL_LEN+1]; minibuffer_hist_save_entry(); - humanify_url(minibuffer_compl_text(), current_tab->hist_cur->h, + humanify_url(minibuffer_compl_text(), hist_cur(current_tab->hist), url, sizeof(url)); exit_minibuffer(); @@ -514,7 +505,7 @@ populate_compl_buffer(complfn *fn, void *data) void enter_minibuffer(void (*self_insert_fn)(void), void (*donefn)(void), - void (*abortfn)(void), struct histhead *hist, + void (*abortfn)(void), struct hist *hist, complfn *complfn, void *compldata, int must_select) { ministate.compl.must_select = must_select; @@ -540,9 +531,10 @@ enter_minibuffer(void (*self_insert_fn)(void), void (* ministate.buffer.cpoff = 0; strlcpy(ministate.buf, "", sizeof(ministate.prompt)); - ministate.history = hist; - ministate.hist_cur = NULL; - ministate.hist_off = 0; + ministate.editing = 1; + ministate.hist = hist; + if (ministate.hist) + hist_seek_start(ministate.hist); } void @@ -591,7 +583,7 @@ minibuffer_read(const char *prompt, void (*fn)(const c read_cb = fn; read_data = data; enter_minibuffer(read_self_insert, read_select, read_abort, - &read_history, NULL, NULL, 0); + read_history, NULL, NULL, 0); len = sizeof(ministate.prompt); strlcpy(ministate.prompt, prompt, len); @@ -641,10 +633,11 @@ message(const char *fmt, ...) void minibuffer_init(void) { - TAILQ_INIT(&eecmd_history.head); - TAILQ_INIT(&ir_history.head); - TAILQ_INIT(&lu_history.head); - TAILQ_INIT(&read_history.head); + if ((eecmd_history = hist_new(HIST_WRAP)) == NULL || + (ir_history = hist_new(HIST_WRAP)) == NULL || + (lu_history = hist_new(HIST_WRAP)) == NULL || + (read_history = hist_new(HIST_WRAP)) == NULL) + err(1, "hist_new"); TAILQ_INIT(&ministate.compl.buffer.head); TAILQ_INIT(&ministate.compl.buffer.page.head); blob - 202790522d830e1e67c26e02f7719f0c893744b2 blob + 792a676e94ed7fc9dbe717a6bbc97d808856896f --- parser/parser.c +++ parser/parser.c @@ -19,6 +19,7 @@ #include #include +#include "hist.h" #include "parser.h" #include "telescope.h" @@ -70,7 +71,7 @@ parser_free(struct tab *tab) * heuristic: see if there is a "tilde user" and use that as * page title, using the full domain name as fallback. */ - if ((tilde = strstr(tab->hist_cur->h, "/~")) != NULL) { + if ((tilde = strstr(hist_cur(tab->hist), "/~")) != NULL) { strlcpy(tab->buffer.page.title, tilde+1, sizeof(tab->buffer.page.title)); blob - 21d12efffa439e96ca4a468420ba5df14a0d8507 blob + c17f3b88353b860490d35ebc7d8832291d82c0fb --- session.c +++ session.c @@ -27,6 +27,7 @@ #include "defaults.h" #include "fs.h" +#include "hist.h" #include "minibuffer.h" #include "session.h" #include "ui.h" @@ -42,7 +43,8 @@ switch_to_tab(struct tab *tab) tab->flags &= ~TAB_URGENT; if (operating && tab->flags & TAB_LAZY) - load_url_in_tab(tab, tab->hist_cur->h, NULL, LU_MODE_NOHIST); + load_url_in_tab(tab, hist_cur(tab->hist), NULL, + LU_MODE_NOHIST); } unsigned int @@ -66,7 +68,12 @@ new_tab(const char *url, const char *base, struct tab return NULL; } - TAILQ_INIT(&tab->hist.head); + if ((tab->hist = hist_new(HIST_LINEAR)) == NULL) { + free(tab); + event_loopbreak(); + return NULL; + } + TAILQ_INIT(&tab->buffer.head); TAILQ_INIT(&tab->buffer.page.head); evtimer_set(&tab->loadingev, NULL, NULL); @@ -152,7 +159,7 @@ void free_tab(struct tab *tab) { TAILQ_REMOVE(&ktabshead, tab, tabs); - hist_clear(&tab->hist); + hist_free(tab->hist); free(tab); } @@ -165,13 +172,12 @@ stop_tab(struct tab *tab) static inline void savetab(FILE *fp, struct tab *tab, int killed) { - struct hist *h; + size_t i, size, cur; size_t top_line, current_line; - int future; get_scroll_position(tab, &top_line, ¤t_line); - fprintf(fp, "%s ", tab->hist_cur->h); + fprintf(fp, "%s ", hist_cur(tab->hist)); if (tab == current_tab) fprintf(fp, "current,"); if (killed) @@ -180,14 +186,13 @@ savetab(FILE *fp, struct tab *tab, int killed) fprintf(fp, "top=%zu,cur=%zu %s\n", top_line, current_line, tab->buffer.page.title); - future = 0; - TAILQ_FOREACH(h, &tab->hist.head, entries) { - if (h == tab->hist_cur) { - future = 1; + cur = hist_off(tab->hist); + size = hist_size(tab->hist); + for (i = 0; i < size; ++i) { + if (i == cur) continue; - } - - fprintf(fp, "%s %s\n", future ? ">" : "<", h->h); + fprintf(fp, "%s %s\n", i > cur ? ">" : "<", + hist_nth(tab->hist, i)); } } @@ -589,8 +594,7 @@ parse_tab_line(char *line, struct tab **ct) if ((tab = new_tab(uri, NULL, NULL)) == NULL) err(1, "new_tab"); - tab->hist_cur->line_off = tline; - tab->hist_cur->current_off = cline; + hist_set_offs(tab->hist, tline, cline); strlcpy(tab->buffer.page.title, title, sizeof(tab->buffer.page.title)); if (current) @@ -605,7 +609,6 @@ static void load_tabs(void) { struct tab *tab = NULL, *ct = NULL; - struct hist *h; FILE *session; size_t lineno = 0, linesize = 0; ssize_t linelen; @@ -632,14 +635,10 @@ load_tabs(void) } uri++; - if ((h = calloc(1, sizeof(*h))) == NULL) - err(1, "calloc"); - strlcpy(h->h, uri, sizeof(h->h)); - if (*line == '>') /* future hist */ - hist_push(&tab->hist, h); + hist_append(tab->hist, uri); else - hist_add_before(&tab->hist, tab->hist_cur, h); + hist_prepend(tab->hist, uri); } else tab = parse_tab_line(line, &ct); } blob - beb58f6449ac23f84e91a9788a99ee68f61b3806 blob + 5be7a5c39e9ff36b14dce25662daf2b6bab164cd --- telescope.c +++ telescope.c @@ -33,6 +33,7 @@ #include "control.h" #include "defaults.h" #include "fs.h" +#include "hist.h" #include "iri.h" #include "mcache.h" #include "minibuffer.h" @@ -191,7 +192,7 @@ handle_imsg_err(struct imsg *imsg, size_t datalen) page[datalen-1] = '\0'; if (asprintf(&page, "# Error loading %s\n\n> %s\n", - tab->hist_cur->h, page) == -1) + hist_cur(tab->hist), page) == -1) die(); load_page_from_str(tab, page); free(page); @@ -392,24 +393,21 @@ handle_imsg_got_meta(struct imsg *imsg, size_t datalen load_page_from_str(tab, err_pages[tab->code]); } else if (tab->code < 20) { /* 1x */ free(tab->last_input_url); - tab->last_input_url = strdup(tab->hist_cur->h); + tab->last_input_url = strdup(hist_cur(tab->hist)); if (tab->last_input_url == NULL) die(); load_page_from_str(tab, err_pages[tab->code]); ui_require_input(tab, tab->code == 11, ir_select_gemini); } else if (tab->code == 20) { - history_add(tab->hist_cur->h); + history_add(hist_cur(tab->hist)); if (setup_parser_for(tab)) { ui_send_net(IMSG_PROCEED, tab->id, NULL, 0); } else if (safe_mode) { load_page_from_str(tab, err_pages[UNKNOWN_TYPE_OR_CSET]); } else { - struct hist *h; - - if ((h = hist_pop(&tab->hist)) != NULL) - tab->hist_cur = h; + hist_prev(tab->hist); snprintf(buf, sizeof(buf), "Can't display \"%s\", save it?", tab->meta); ui_yornp(buf, handle_maybe_save_page, tab); @@ -422,7 +420,7 @@ handle_imsg_got_meta(struct imsg *imsg, size_t datalen load_page_from_str(tab, err_pages[TOO_MUCH_REDIRECTS]); } else - do_load_url(tab, tab->meta, tab->hist_cur->h, + do_load_url(tab, tab->meta, hist_cur(tab->hist), LU_MODE_NOCACHE); } else { /* 4x, 5x & 6x */ load_page_from_str(tab, err_pages[tab->code]); @@ -509,6 +507,7 @@ handle_imsg_eof(struct imsg *imsg, size_t datalen) { struct tab *tab = NULL; struct download *d = NULL; + const char *h; if ((tab = tab_by_id(imsg->hdr.peerid)) == NULL && (d = download_by_id(imsg->hdr.peerid)) == NULL) @@ -517,8 +516,9 @@ handle_imsg_eof(struct imsg *imsg, size_t datalen) if (tab != NULL) { if (!parser_free(tab)) die(); - if (!strncmp(tab->hist_cur->h, "gemini://", 9) || - !strncmp(tab->hist_cur->h, "gopher://", 9)) + h = hist_cur(tab->hist); + if (!strncmp(h, "gemini://", 9) || + !strncmp(h, "gopher://", 9)) mcache_tab(tab); ui_on_tab_refresh(tab); ui_on_tab_loaded(tab); @@ -594,7 +594,7 @@ load_gemini_url(struct tab *tab, const char *url) strlcpy(req.host, tab->iri.iri_host, sizeof(req.host)); strlcpy(req.port, tab->iri.iri_portstr, sizeof(req.port)); - make_request(tab, &req, PROTO_GEMINI, tab->hist_cur->h); + make_request(tab, &req, PROTO_GEMINI, hist_cur(tab->hist)); } static inline const char * @@ -679,7 +679,7 @@ load_via_proxy(struct tab *tab, const char *url, struc tab->proxy = p; - make_request(tab, &req, p->proto, tab->hist_cur->h); + make_request(tab, &req, p->proto, hist_cur(tab->hist)); } static void @@ -746,6 +746,7 @@ do_load_url(struct tab *tab, const char *url, const ch struct proxy *proxy; int nocache = mode & LU_MODE_NOCACHE; char *t; + char buf[1025]; tab->proxy = NULL; tab->trust = TS_UNKNOWN; @@ -754,15 +755,16 @@ do_load_url(struct tab *tab, const char *url, const ch if (asprintf(&t, "# error loading %s\n>%s\n", url, "Can't parse the IRI") == -1) die(); - strlcpy(tab->hist_cur->h, url, sizeof(tab->hist_cur->h)); + hist_set_cur(tab->hist, url); load_page_from_str(tab, t); free(t); return; } - iri_unparse(&tab->iri, tab->hist_cur->h, sizeof(tab->hist_cur->h)); + iri_unparse(&tab->iri, buf, sizeof(buf)); + hist_set_cur(tab->hist, buf); - if (!nocache && mcache_lookup(tab->hist_cur->h, tab)) { + if (!nocache && mcache_lookup(buf, tab)) { ui_on_tab_refresh(tab); ui_on_tab_loaded(tab); return; @@ -775,7 +777,7 @@ do_load_url(struct tab *tab, const char *url, const ch p->port != NULL) iri_setport(&tab->iri, p->port); - p->loadfn(tab, tab->hist_cur->h); + p->loadfn(tab, buf); return; } } @@ -797,34 +799,26 @@ do_load_url(struct tab *tab, const char *url, const ch void load_url(struct tab *tab, const char *url, const char *base, int mode) { + size_t line_off, curr_off; int lazy = tab->flags & TAB_LAZY; - int nohist = mode & LU_MODE_NOHIST; + int dohist = !(mode & LU_MODE_NOHIST); if (operating && lazy) { tab->flags ^= TAB_LAZY; lazy = 0; - } else if (tab->hist_cur != NULL) - get_scroll_position(tab, &tab->hist_cur->line_off, - &tab->hist_cur->current_off); + } else if (hist_size(tab->hist) != 0) { + get_scroll_position(tab, &line_off, &curr_off); + hist_set_offs(tab->hist, line_off, curr_off); + } - if (!nohist && (!lazy || tab->hist_cur == NULL)) { - if (tab->hist_cur != NULL) - hist_clear_forward(&tab->hist, - TAILQ_NEXT(tab->hist_cur, entries)); - - if ((tab->hist_cur = calloc(1, sizeof(*tab->hist_cur))) - == NULL) { + if (dohist) { + if (hist_push(tab->hist, url) == -1) { event_loopbreak(); return; } strlcpy(tab->buffer.page.title, url, sizeof(tab->buffer.page.title)); - hist_push(&tab->hist, tab->hist_cur); - - if (lazy) - strlcpy(tab->hist_cur->h, url, - sizeof(tab->hist_cur->h)); } if (!lazy) @@ -840,7 +834,7 @@ load_url_in_tab(struct tab *tab, const char *url, cons } if (base == NULL) - base = tab->hist_cur->h; + base = hist_cur(tab->hist); load_url(tab, url, base, mode); } @@ -848,24 +842,22 @@ load_url_in_tab(struct tab *tab, const char *url, cons int load_previous_page(struct tab *tab) { - struct hist *h; + const char *h; - if ((h = TAILQ_PREV(tab->hist_cur, mhisthead, entries)) == NULL) + if ((h = hist_prev(tab->hist)) == NULL) return 0; - tab->hist_cur = h; - do_load_url(tab, h->h, NULL, LU_MODE_NONE); + do_load_url(tab, h, NULL, LU_MODE_NONE); return 1; } int load_next_page(struct tab *tab) { - struct hist *h; + const char *h; - if ((h = TAILQ_NEXT(tab->hist_cur, entries)) == NULL) + if ((h = hist_next(tab->hist)) == NULL) return 0; - tab->hist_cur = h; - do_load_url(tab, h->h, NULL, LU_MODE_NONE); + do_load_url(tab, h, NULL, LU_MODE_NONE); return 1; } blob - 83bff426c3fc53cb1f21828c824714bebc25e481 blob + 795da31d0de4937c1a245d5b3064bb1420919f2a --- ui.c +++ ui.c @@ -42,6 +42,7 @@ #include #include "defaults.h" +#include "hist.h" #include "minibuffer.h" #include "session.h" #include "telescope.h" @@ -649,7 +650,7 @@ redraw_tabline(void) current = tab == current_tab; if (*(title = tab->buffer.page.title) == '\0') - title = tab->hist_cur->h; + title = hist_cur(tab->hist); if (tab->flags & TAB_URGENT) strlcpy(buf, "!", sizeof(buf)); @@ -865,7 +866,7 @@ redraw_modeline(struct tab *tab) wprintw(modeline, "%zu/%zu %s ", buffer->line_off + buffer->curs_y, buffer->line_max, - tab->hist_cur->h); + hist_cur(tab->hist)); getyx(modeline, y, x); getmaxyx(modeline, max_y, max_x); @@ -932,16 +933,16 @@ do_redraw_minibuffer(void) cmplbuf->line_max); wprintw(echoarea, "%s", ministate.prompt); - if (ministate.hist_cur != NULL) + if (!ministate.editing) wprintw(echoarea, "(%zu/%zu) ", - ministate.hist_off + 1, - ministate.history->len); + hist_off(ministate.hist) + 1, + hist_size(ministate.hist)); getyx(echoarea, off_y, off_x); - start = ministate.hist_cur != NULL - ? ministate.hist_cur->h - : ministate.buf; + start = ministate.buf; + if (!ministate.editing) + start = hist_cur(ministate.hist); line = buffer->current_line->parent->line + buffer->current_line->from; c = utf8_nth(line, buffer->cpoff); while (utf8_swidth_between(start, c) > (size_t)COLS/2) { @@ -1229,13 +1230,15 @@ ui_main_loop(void) void ui_on_tab_loaded(struct tab *tab) { + size_t line_off, curr_off; + stop_loading_anim(tab); - message("Loaded %s", tab->hist_cur->h); + message("Loaded %s", hist_cur(tab->hist)); - if (tab->hist_cur->current_off != 0 && + hist_cur_offs(tab->hist, &line_off, &curr_off); + if (curr_off != 0 && tab->buffer.current_line == TAILQ_FIRST(&tab->buffer.head)) { - set_scroll_position(tab, tab->hist_cur->line_off, - tab->hist_cur->current_off); + set_scroll_position(tab, line_off, curr_off); redraw_tab(tab); return; } @@ -1326,7 +1329,7 @@ ui_require_input(struct tab *tab, int hide, void (*fn) switch_to_tab(tab); enter_minibuffer(sensible_self_insert, fn, exit_minibuffer, - &ir_history, NULL, NULL, 0); + ir_history, NULL, NULL, 0); strlcpy(ministate.prompt, "Input required: ", sizeof(ministate.prompt)); redraw_tab(tab);