commit - 14071a5adaa0065fdf58a2662f4a905113bbf7bd
commit + 1fce2e758fce1ba5d600301bb2b5fae29578adbc
blob - f9700485e6e51e0685df1b85448c1dacebc0f557
blob + b87d975b158b12520b075074fe6260776d2db0d8
--- Makefile.am
+++ Makefile.am
parser_textpatch.c \
parser_textplain.c \
sandbox.c \
+ session.c \
+ session.h \
telescope.c \
telescope.h \
tofu.c \
blob - a9e7f413497fdf626deef837e1d7742ff240d69f
blob + 0c1616c92912ba90abe1c57a6cc4b027ddc46e44
--- cmd.c
+++ cmd.c
#include "compl.h"
#include "defaults.h"
#include "minibuffer.h"
+#include "session.h"
#include "telescope.h"
#include "ui.h"
#include "utf8.h"
blob - e9d7d6511c8937cf42d4049494201e702d9e2c62
blob + ec8779a1d316069a5d20451ba8150655023d4aff
--- minibuffer.c
+++ minibuffer.c
#include <string.h>
#include "minibuffer.h"
+#include "session.h"
#include "ui.h"
#include "utf8.h"
blob - 5e81c69e04676a27822b4ad6e9d48670eb4646e8
blob + acfc0ecc4abaf7a75f65981ed7a488ac8f50c617
--- parser.c
+++ parser.c
#include "parser.h"
#include "telescope.h"
+#include "ui.h"
#include <stdlib.h>
#include <string.h>
+/*
+ * Load a text/gemini page given the string page. Always returns 0.
+ */
+int
+load_page_from_str(struct tab *tab, const char *page)
+{
+ erase_buffer(&tab->buffer);
+ parser_init(tab, gemtext_initparser);
+ if (!tab->buffer.page.parse(&tab->buffer.page, page, strlen(page)))
+ abort();
+ if (!tab->buffer.page.free(&tab->buffer.page))
+ abort();
+ ui_on_tab_refresh(tab);
+ ui_on_tab_loaded(tab);
+ return 0;
+}
+
void
parser_init(struct tab *tab, parserfn fn)
{
blob - d1ef5e24490de37385e3d9fdc808aa2a598d8925
blob + 63be7ce5d280b6dd51d837b3fc21ca0132203642
--- parser.h
+++ parser.h
typedef void (*parserfn)(struct parser *);
/* parser.c */
+int load_page_from_str(struct tab *, const char *);
+
void parser_init(struct tab *, parserfn);
int parser_parse(struct tab *, const char *, size_t);
int parser_free(struct tab *);
blob - /dev/null
blob + 08d58942f01ce15982085bfa616d7f140af5a211 (mode 644)
--- /dev/null
+++ session.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 "compat.h"
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "defaults.h"
+#include "minibuffer.h"
+#include "parser.h"
+#include "session.h"
+#include "ui.h"
+
+static struct event autosaveev;
+
+void
+switch_to_tab(struct tab *tab)
+{
+ current_tab = tab;
+ tab->flags &= ~TAB_URGENT;
+
+ if (operating && tab->flags & TAB_LAZY)
+ load_url_in_tab(tab, tab->hist_cur->h, NULL, 0);
+}
+
+unsigned int
+tab_new_id(void)
+{
+ static uint32_t tab_counter;
+
+ return tab_counter++;
+}
+
+struct tab *
+new_tab(const char *url, const char *base, struct tab *after)
+{
+ struct tab *tab;
+
+ autosave_hook();
+
+ if ((tab = calloc(1, sizeof(*tab))) == NULL) {
+ event_loopbreak();
+ return NULL;
+ }
+ tab->fd = -1;
+
+ TAILQ_INIT(&tab->hist.head);
+
+ TAILQ_INIT(&tab->buffer.head);
+ TAILQ_INIT(&tab->buffer.page.head);
+
+ tab->id = tab_new_id();
+ if (!operating)
+ tab->flags |= TAB_LAZY;
+ switch_to_tab(tab);
+
+ if (after != NULL)
+ TAILQ_INSERT_AFTER(&tabshead, after, tab, tabs);
+ else
+ TAILQ_INSERT_TAIL(&tabshead, tab, tabs);
+
+ load_url_in_tab(tab, url, base, 0);
+ return tab;
+}
+
+/*
+ * Free every resource linked to the tab, including the tab itself.
+ * Removes the tab from the tablist, but doesn't update the
+ * current_tab though.
+ */
+void
+free_tab(struct tab *tab)
+{
+ stop_tab(tab);
+
+ autosave_hook();
+
+ if (evtimer_pending(&tab->loadingev, NULL))
+ evtimer_del(&tab->loadingev);
+
+ TAILQ_REMOVE(&tabshead, tab, tabs);
+ free(tab);
+}
+
+void
+stop_tab(struct tab *tab)
+{
+ ui_send_net(IMSG_STOP, tab->id, NULL, 0);
+
+ if (tab->fd != -1) {
+ close(tab->fd);
+ tab->fd = -1;
+ free(tab->path);
+ tab->path = NULL;
+ load_page_from_str(tab, "Stopped.\n");
+ }
+}
+
+
+void
+save_session(void)
+{
+ struct tab *tab;
+ char *t;
+ int flags;
+
+ ui_send_fs(IMSG_SESSION_START, 0, NULL, 0);
+
+ TAILQ_FOREACH(tab, &tabshead, tabs) {
+ flags = tab->flags;
+ if (tab == current_tab)
+ flags |= TAB_CURRENT;
+
+ t = tab->hist_cur->h;
+ ui_send_fs(IMSG_SESSION_TAB, flags, t, strlen(t)+1);
+
+ t = tab->buffer.page.title;
+ ui_send_fs(IMSG_SESSION_TAB_TITLE, 0, t, strlen(t)+1);
+ }
+
+ ui_send_fs(IMSG_SESSION_END, 0, NULL, 0);
+}
+
+/*
+ * Parse a line of the session file. The format is:
+ *
+ * URL [flags,...] [title]\n
+ */
+static void
+parse_session_line(char *line, const char **title, uint32_t *flags)
+{
+ char *s, *t, *ap;
+
+ *title = "";
+ *flags = 0;
+ if ((s = strchr(line, ' ')) == NULL)
+ return;
+
+ *s++ = '\0';
+
+ if ((t = strchr(s, ' ')) != NULL) {
+ *t++ = '\0';
+ *title = t;
+ }
+
+ while ((ap = strsep(&s, ",")) != NULL) {
+ if (*ap == '\0')
+ ;
+ else if (!strcmp(ap, "current"))
+ *flags |= TAB_CURRENT;
+ else
+ message("unknown tab flag: %s", ap);
+ }
+}
+
+void
+load_last_session(void)
+{
+ const char *title;
+ char *nl, *line = NULL;
+ uint32_t flags;
+ size_t linesize = 0;
+ ssize_t linelen;
+ FILE *session;
+ struct tab *tab, *curr = NULL;
+
+ if ((session = fopen(session_file, "r")) == NULL) {
+ /* first time? */
+ new_tab("about:new", NULL, NULL);
+ switch_to_tab(new_tab("about:help", NULL, NULL));
+ return;
+ }
+
+ while ((linelen = getline(&line, &linesize, session)) != -1) {
+ if ((nl = strchr(line, '\n')) != NULL)
+ *nl = '\0';
+ parse_session_line(line, &title, &flags);
+ if ((tab = new_tab(line, NULL, NULL)) == NULL)
+ err(1, "new_tab");
+ strlcpy(tab->buffer.page.title, title,
+ sizeof(tab->buffer.page.title));
+ if (flags & TAB_CURRENT)
+ curr = tab;
+ }
+
+ if (ferror(session))
+ message("error reading %s: %s",
+ session_file, strerror(errno));
+ fclose(session);
+ free(line);
+
+ if (curr != NULL)
+ switch_to_tab(curr);
+
+ if (last_time_crashed())
+ switch_to_tab(new_tab("about:crash", NULL, NULL));
+
+ return;
+}
+
+void
+autosave_init(void)
+{
+ evtimer_set(&autosaveev, autosave_timer, NULL);
+}
+
+void
+autosave_timer(int fd, short event, void *data)
+{
+ save_session();
+}
+
+/*
+ * Function to be called in "interesting" places where we may want to
+ * schedule an autosave (like on new tab or before loading an url.)
+ */
+void
+autosave_hook(void)
+{
+ struct timeval tv;
+
+ if (autosave <= 0)
+ return;
+
+ if (!evtimer_pending(&autosaveev, NULL)) {
+ tv.tv_sec = autosave;
+ tv.tv_usec = 0;
+
+ evtimer_add(&autosaveev, &tv);
+ }
+}
blob - a3369803052b9b1054d382f1d6e4c8c5f05f72bc
blob + 70f1484960a8f53f3329a21fa25dbdf04545b672
--- telescope.c
+++ telescope.c
#include "defaults.h"
#include "minibuffer.h"
#include "parser.h"
+#include "session.h"
#include "telescope.h"
#include "ui.h"
/*
* Used to know when we're finished loading.
*/
-static int operating;
+int operating;
static struct imsgev *iev_fs, *iev_net;
-static struct event autosaveev;
-
struct tabshead tabshead = TAILQ_HEAD_INITIALIZER(tabshead);
struct proxylist proxies = TAILQ_HEAD_INITIALIZER(proxies);
static void handle_imsg_save_cert_ok(struct imsg*, size_t);
static void handle_imsg_update_cert_ok(struct imsg *, size_t);
static void handle_dispatch_imsg(int, short, void*);
-static int load_page_from_str(struct tab*, const char*);
static int load_about_url(struct tab*, const char*);
static int load_file_url(struct tab *, const char *);
static int load_finger_url(struct tab *, const char *);
const char *);
static int make_fs_request(struct tab *, int, const char *);
static int do_load_url(struct tab*, const char *, const char *);
-static void autosave_timer(int, short, void *);
-static void parse_session_line(char *, const char **, uint32_t *);
-static void load_last_session(void);
static pid_t start_child(enum telescope_process, const char *, int);
-static int ui_send_net(int, uint32_t, const void *, uint16_t);
-static int ui_send_fs(int, uint32_t, const void *, uint16_t);
static struct proto {
const char *schema;
if (dispatch_imsg(iev, ev, handlers, sizeof(handlers)) == -1)
err(1, "connection closed");
-}
-
-static int
-load_page_from_str(struct tab *tab, const char *page)
-{
- erase_buffer(&tab->buffer);
- parser_init(tab, gemtext_initparser);
- if (!tab->buffer.page.parse(&tab->buffer.page, page, strlen(page)))
- die();
- if (!tab->buffer.page.free(&tab->buffer.page))
- die();
- ui_on_tab_refresh(tab);
- ui_on_tab_loaded(tab);
- return 0;
}
static int
tab->hist_cur = h;
do_load_url(tab, h->h, NULL);
return 1;
-}
-
-void
-switch_to_tab(struct tab *tab)
-{
- current_tab = tab;
- tab->flags &= ~TAB_URGENT;
-
- if (operating && tab->flags & TAB_LAZY)
- load_url_in_tab(tab, tab->hist_cur->h, NULL, 0);
-}
-
-unsigned int
-tab_new_id(void)
-{
- static uint32_t tab_counter;
-
- return tab_counter++;
-}
-
-struct tab *
-new_tab(const char *url, const char *base, struct tab *after)
-{
- struct tab *tab;
-
- autosave_hook();
-
- if ((tab = calloc(1, sizeof(*tab))) == NULL) {
- event_loopbreak();
- return NULL;
- }
- tab->fd = -1;
-
- TAILQ_INIT(&tab->hist.head);
-
- TAILQ_INIT(&tab->buffer.head);
- TAILQ_INIT(&tab->buffer.page.head);
-
- tab->id = tab_new_id();
- if (!operating)
- tab->flags |= TAB_LAZY;
- switch_to_tab(tab);
-
- if (after != NULL)
- TAILQ_INSERT_AFTER(&tabshead, after, tab, tabs);
- else
- TAILQ_INSERT_TAIL(&tabshead, tab, tabs);
-
- load_url_in_tab(tab, url, base, 0);
- return tab;
}
-/*
- * Free every resource linked to the tab, including the tab itself.
- * Removes the tab from the tablist, but doesn't update the
- * current_tab though.
- */
void
-free_tab(struct tab *tab)
-{
- stop_tab(tab);
-
- autosave_hook();
-
- if (evtimer_pending(&tab->loadingev, NULL))
- evtimer_del(&tab->loadingev);
-
- TAILQ_REMOVE(&tabshead, tab, tabs);
- free(tab);
-}
-
-void
-stop_tab(struct tab *tab)
-{
- ui_send_net(IMSG_STOP, tab->id, NULL, 0);
-
- if (tab->fd != -1) {
- close(tab->fd);
- tab->fd = -1;
- free(tab->path);
- tab->path = NULL;
- load_page_from_str(tab, "Stopped.\n");
- }
-}
-
-void
add_to_bookmarks(const char *str)
{
ui_send_fs(IMSG_BOOKMARK_PAGE, 0,
str, strlen(str)+1);
}
-void
-save_session(void)
-{
- struct tab *tab;
- char *t;
- int flags;
-
- ui_send_fs(IMSG_SESSION_START, 0, NULL, 0);
-
- TAILQ_FOREACH(tab, &tabshead, tabs) {
- flags = tab->flags;
- if (tab == current_tab)
- flags |= TAB_CURRENT;
-
- t = tab->hist_cur->h;
- ui_send_fs(IMSG_SESSION_TAB, flags, t, strlen(t)+1);
-
- t = tab->buffer.page.title;
- ui_send_fs(IMSG_SESSION_TAB_TITLE, 0, t, strlen(t)+1);
- }
-
- ui_send_fs(IMSG_SESSION_END, 0, NULL, 0);
-}
-
-static void
-autosave_timer(int fd, short event, void *data)
-{
- save_session();
-}
-
-/*
- * Function to be called in "interesting" places where we may want to
- * schedule an autosave (like on new tab or before loading an url.)
- */
-void
-autosave_hook(void)
-{
- struct timeval tv;
-
- if (autosave <= 0)
- return;
-
- if (!evtimer_pending(&autosaveev, NULL)) {
- tv.tv_sec = autosave;
- tv.tv_usec = 0;
-
- evtimer_add(&autosaveev, &tv);
- }
-}
-
-/*
- * Parse a line of the session file. The format is:
- *
- * URL [flags,...] [title]\n
- */
-static void
-parse_session_line(char *line, const char **title, uint32_t *flags)
-{
- char *s, *t, *ap;
-
- *title = "";
- *flags = 0;
- if ((s = strchr(line, ' ')) == NULL)
- return;
-
- *s++ = '\0';
-
- if ((t = strchr(s, ' ')) != NULL) {
- *t++ = '\0';
- *title = t;
- }
-
- while ((ap = strsep(&s, ",")) != NULL) {
- if (*ap == '\0')
- ;
- else if (!strcmp(ap, "current"))
- *flags |= TAB_CURRENT;
- else
- message("unknown tab flag: %s", ap);
- }
-}
-
-static void
-load_last_session(void)
-{
- const char *title;
- char *nl, *line = NULL;
- uint32_t flags;
- size_t linesize = 0;
- ssize_t linelen;
- FILE *session;
- struct tab *tab, *curr = NULL;
-
- if ((session = fopen(session_file, "r")) == NULL) {
- /* first time? */
- new_tab("about:new", NULL, NULL);
- switch_to_tab(new_tab("about:help", NULL, NULL));
- return;
- }
-
- while ((linelen = getline(&line, &linesize, session)) != -1) {
- if ((nl = strchr(line, '\n')) != NULL)
- *nl = '\0';
- parse_session_line(line, &title, &flags);
- if ((tab = new_tab(line, NULL, NULL)) == NULL)
- err(1, "new_tab");
- strlcpy(tab->buffer.page.title, title,
- sizeof(tab->buffer.page.title));
- if (flags & TAB_CURRENT)
- curr = tab;
- }
-
- if (ferror(session))
- message("error reading %s: %s",
- session_file, strerror(errno));
- fclose(session);
- free(line);
-
- if (curr != NULL)
- switch_to_tab(curr);
-
- if (last_time_crashed())
- switch_to_tab(new_tab("about:crash", NULL, NULL));
-
- return;
-}
-
static pid_t
start_child(enum telescope_process p, const char *argv0, int fd)
{
err(1, "execvp(%s)", argv0);
}
-static int
+int
ui_send_net(int type, uint32_t peerid, const void *data,
uint16_t datalen)
{
datalen);
}
-static int
+int
ui_send_fs(int type, uint32_t peerid, const void *data, uint16_t datalen)
{
return imsg_compose_event(iev_fs, type, peerid, 0, -1, data,
event_init();
/* Setup event handler for the autosave */
- evtimer_set(&autosaveev, autosave_timer, NULL);
+ autosave_init();
/* Setup event handlers for pipes to fs/net */
iev_fs->events = EV_READ;
blob - /dev/null
blob + 6a43fea1188a6278ccb9176a6d5229214b5aef23 (mode 644)
--- /dev/null
+++ session.h
+/*
+ * 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.
+ */
+
+#ifndef SESSION_H
+#define SESSION_H
+
+#include "telescope.h"
+
+void switch_to_tab(struct tab *);
+unsigned int tab_new_id(void);
+struct tab *new_tab(const char *, const char *base, struct tab *);
+void free_tab(struct tab *);
+void stop_tab(struct tab*);
+
+void save_session(void);
+void load_last_session(void);
+
+void autosave_init(void);
+void autosave_timer(int, short, void *);
+void autosave_hook(void);
+
+#endif
blob - 0d27078306404e67cb153ed72bd19478b4d061c0
blob + a11df120af6df0245b79aa4a40723dd9a031bbaa
--- telescope.h
+++ telescope.h
void sandbox_fs_process(void);
/* telescope.c */
+extern int operating;
+
void gopher_send_search_req(struct tab *, const char *);
void load_url(struct tab *, const char *, const char *, int);
void load_url_in_tab(struct tab *, const char *, const char *, int);
int load_previous_page(struct tab*);
int load_next_page(struct tab*);
-void switch_to_tab(struct tab *);
-unsigned int tab_new_id(void);
-struct tab *new_tab(const char *, const char *base, struct tab *);
-void free_tab(struct tab *);
-void stop_tab(struct tab*);
void add_to_bookmarks(const char*);
-void save_session(void);
-void autosave_hook(void);
+int ui_send_net(int, uint32_t, const void *, uint16_t);
+int ui_send_fs(int, uint32_t, const void *, uint16_t);
/* tofu.c */
void tofu_init(struct ohash*, unsigned int, ptrdiff_t);
blob - 74418030e8c0876058277924bc327014757d0d5d
blob + bed65fdfaaa525e0fc3697c0fed86952b81a3de3
--- ui.c
+++ ui.c
#include "defaults.h"
#include "minibuffer.h"
+#include "session.h"
#include "telescope.h"
#include "ui.h"
#include "utf8.h"