commit - 3148eeac0e951ab7d1818680e65b366276d484bd
commit + 2051e6535ed850f2676a2ef1353b58943369eee8
blob - ad9d7c241a992e0548e4aa80c463f112d0aec7c5
blob + 9b6cc8523d58871663b3a93f05e6daf88a10f206
--- Makefile.am
+++ Makefile.am
compat/*.[ch] \
gemini.c \
gemtext.c \
+ hist.c \
keymap.c \
mime.c \
pages.c \
blob - /dev/null
blob + 1426ef08f888dba8cf9c25dc9c0c17736aa96666 (mode 644)
--- /dev/null
+++ hist.c
+/*
+ * Copyright (c) 2021 Omar Polo <op@omarpolo.com>
+ *
+ * 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 "telescope.h"
+
+#include <stdlib.h>
+
+void
+hist_clear_forward(struct histhead *head, struct hist *h)
+{
+ if (h == NULL)
+ return;
+ hist_clear_forward(head, TAILQ_NEXT(h, entries));
+ TAILQ_REMOVE(&head->head, h, entries);
+ free(h);
+}
+
+void
+hist_push(struct histhead *head, struct hist *h)
+{
+ head->len++;
+ if (TAILQ_EMPTY(&head->head))
+ TAILQ_INSERT_HEAD(&head->head, h, entries);
+ else
+ TAILQ_INSERT_TAIL(&head->head, h, entries);
+}
blob - 5a7d85f8cd585912bde5e691d7b840b2837fa8d0
blob + 1cfaeef114ef2fdd2b03e11a08ad16dbf39b8bd5
--- telescope.c
+++ telescope.c
static struct imsgbuf *netibuf;
-static void handle_imsg_err(struct imsg*, size_t);
-static void handle_imsg_check_cert(struct imsg*, size_t);
-static void handle_imsg_got_code(struct imsg*, size_t);
-static void handle_imsg_got_meta(struct imsg*, size_t);
-static void handle_imsg_buf(struct imsg*, size_t);
-static void handle_imsg_eof(struct imsg*, size_t);
+static void die(void) __attribute__((__noreturn__));
+static struct tab *tab_by_id(uint32_t);
+static void handle_imsg_err(struct imsg*, size_t);
+static void handle_imsg_check_cert(struct imsg*, size_t);
+static void handle_imsg_got_code(struct imsg*, size_t);
+static void handle_imsg_got_meta(struct imsg*, size_t);
+static void handle_imsg_buf(struct imsg*, size_t);
+static void handle_imsg_eof(struct imsg*, size_t);
+static void dispatch_imsg(int, short, void*);
+static void load_page_from_str(struct tab*, const char*);
+static void do_load_url(struct tab*, const char*);
-static void load_page_from_str(struct tab*, const char*);
-
static imsg_handlerfn *handlers[] = {
[IMSG_ERR] = handle_imsg_err,
[IMSG_CHECK_CERT] = handle_imsg_check_cert,
page[datalen-1] = '\0';
if (asprintf(&page, "# Error loading %s\n\n> %s\n",
- tab->urlstr, page) == -1)
+ tab->hist_cur->h, page) == -1)
die();
load_page_from_str(tab, page);
free(page);
load_page_from_str(tab,
err_pages[TOO_MUCH_REDIRECTS]);
} else
- load_url(tab, tab->meta);
+ do_load_url(tab, tab->meta);
} else { /* 4x, 5x & 6x */
load_page_from_str(tab, err_pages[tab->code]);
}
void
load_about_url(struct tab *tab, const char *url)
{
- char *m;
+ char *m;
+ size_t len;
- memset(tab->urlstr, 0, sizeof(tab->urlstr));
+
memset(&tab->url, 0, sizeof(tab->url));
m = strchr(url, ':');
strlcpy(tab->url.scheme, "about", sizeof(tab->url.scheme));
strlcpy(tab->url.path, m+1, sizeof(tab->url.path));
- strlcpy(tab->urlstr, url, sizeof(tab->urlstr));
+ len = sizeof(tab->hist_cur->h)-1;
+ strlcpy(tab->hist_cur->h, url, len);
if (!strcmp(url, "about:new"))
load_page_from_str(tab, about_new);
{
const char *err;
char *p;
+ size_t len;
if (has_prefix(url, "gemini:")) {
if (!url_parse(url, &tab->url, &err))
goto err;
}
- url_unparse(&tab->url, tab->urlstr, sizeof(tab->urlstr));
+ len = sizeof(tab->hist_cur->h)-1;
+ url_unparse(&tab->url, tab->hist_cur->h, len);
imsg_compose(netibuf, IMSG_GET, tab->id, 0, -1,
- tab->urlstr, strlen(tab->urlstr)+1);
+ tab->hist_cur->h, len+1);
imsg_flush(netibuf);
return;
if (asprintf(&p, "#error loading %s\n>%s\n",
url, err) == -1)
die();
- strlcpy(tab->urlstr, url, sizeof(tab->urlstr));
+ strlcpy(tab->hist_cur->h, url, len);
load_page_from_str(tab, p);
free(p);
}
-void
-load_url(struct tab *tab, const char *url)
+static void
+do_load_url(struct tab *tab, const char *url)
{
struct proto *p;
}
void
+load_url(struct tab *tab, const char *url)
+{
+ 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) {
+ event_loopbreak();
+ return;
+ }
+ hist_push(&tab->hist, tab->hist_cur);
+ do_load_url(tab, url);
+}
+
+int
+load_previous_page(struct tab *tab)
+{
+ struct hist *h;
+
+ if ((h = TAILQ_PREV(tab->hist_cur, mhisthead, entries)) == NULL)
+ return 0;
+ tab->hist_cur = h;
+ do_load_url(tab, h->h);
+ return 1;
+}
+
+int
+load_next_page(struct tab *tab)
+{
+ struct hist *h;
+
+ if ((h = TAILQ_NEXT(tab->hist_cur, entries)) == NULL)
+ return 0;
+ tab->hist_cur = h;
+ do_load_url(tab, h->h);
+ return 1;
+}
+
+void
stop_tab(struct tab *tab)
{
imsg_compose(netibuf, IMSG_STOP, tab->id, 0, -1, NULL, 0);
blob - 891c0885d00a6245148faa47e09ae776f3e55035
blob + 1dc9501e5f5d65f38cb6543a81ff7be791058e24
--- telescope.h
+++ telescope.h
uint32_t id;
uint32_t flags;
- char urlstr[GEMINI_URL_LEN];
struct url url;
+ struct histhead hist;
+ struct hist *hist_cur;
+ size_t hist_off;
int code;
char meta[GEMINI_URL_LEN];
/* gemtext.c */
void gemtext_initparser(struct parser*);
+/* hist.c */
+void hist_clear_forward(struct histhead*, struct hist*);
+void hist_push(struct histhead*, struct hist*);
+
/* keymap.c */
int kbd(const char*);
const char *unkbd(int);
void load_about_url(struct tab*, const char*);
void load_gemini_url(struct tab*, const char*);
void load_url(struct tab*, const char*);
+int load_previous_page(struct tab*);
+int load_next_page(struct tab*);
void stop_tab(struct tab*);
/* textplain.c */
blob - 21f55e4d4b132b1b04f8ac77fabb7abf908cbf47
blob + 6ebc6bca2a03a899c1eec92c38cb34250c8e8cf7
--- ui.c
+++ ui.c
static void cmd_kill_telescope(struct tab*);
static void cmd_push_button(struct tab*);
static void cmd_push_button_new_tab(struct tab*);
+static void cmd_previous_page(struct tab*);
+static void cmd_next_page(struct tab*);
static void cmd_clear_minibuf(struct tab*);
static void cmd_execute_extended_command(struct tab*);
static void cmd_tab_close(struct tab*);
global_set_key("M-<", cmd_beginning_of_buffer);
global_set_key("M->", cmd_end_of_buffer);
+ global_set_key("C-M-b", cmd_previous_page);
+ global_set_key("C-M-f", cmd_next_page);
+
/* vi/vi-like */
global_set_key("k", cmd_previous_line);
global_set_key("j", cmd_next_line);
global_set_key("g g", cmd_beginning_of_buffer);
global_set_key("G", cmd_end_of_buffer);
+ global_set_key("H", cmd_previous_page);
+ global_set_key("L", cmd_next_page);
+
/* tmp */
global_set_key("q", cmd_kill_telescope);
global_set_key("<prior>", cmd_scroll_up);
global_set_key("<next>", cmd_scroll_down);
+ global_set_key("M-<left>", cmd_previous_page);
+ global_set_key("M-<right>", cmd_next_page);
+
/* "ncurses standard" */
global_set_key("C-l", cmd_redraw);
t = new_tab();
memcpy(&t->url, &tab->url, sizeof(tab->url));
- memcpy(&t->urlstr, &tab->urlstr, sizeof(tab->urlstr));
load_url_in_tab(t, l->alt);
+}
+
+static void
+cmd_previous_page(struct tab *tab)
+{
+ if (!load_previous_page(tab))
+ message("No previous page");
+}
+
+static void
+cmd_next_page(struct tab *tab)
+{
+ if (!load_next_page(tab))
+ message("No next page");
}
static void
enter_minibuffer(lu_self_insert, lu_select, exit_minibuffer,
&lu_history);
strlcpy(ministate.prompt, "Load URL: ", sizeof(ministate.prompt));
- strlcpy(ministate.buf, tab->urlstr, sizeof(ministate.buf));
- ministate.off = strlen(tab->urlstr);
+ strlcpy(ministate.buf, tab->hist_cur->h, sizeof(ministate.buf));
+ ministate.off = strlen(tab->hist_cur->h);
ministate.len = ministate.off;
}
current = tab->flags & TAB_CURRENT;
if (*(title = tab->page.title) == '\0')
- title = tab->urlstr;
+ title = tab->hist_cur->h;
if (current)
wattron(tabline, A_UNDERLINE);
wprintw(modeline, "%d/%d %s ",
tab->s->line_off + tab->s->curs_y,
tab->s->line_max,
- tab->urlstr);
+ tab->hist_cur->h);
getyx(modeline, y, x);
getmaxyx(modeline, max_y, max_x);
if ((tab = calloc(1, sizeof(*tab))) == NULL)
goto err;
+ TAILQ_INIT(&tab->hist.head);
+
if ((tab->s = calloc(1, sizeof(*t->s))) == NULL)
goto err;
ui_on_tab_loaded(struct tab *tab)
{
stop_loading_anim(tab);
- message("Loaded %s", tab->urlstr);
+ message("Loaded %s", tab->hist_cur->h);
}
void