Commit Diff


commit - 14071a5adaa0065fdf58a2662f4a905113bbf7bd
commit + 1fce2e758fce1ba5d600301bb2b5fae29578adbc
blob - f9700485e6e51e0685df1b85448c1dacebc0f557
blob + b87d975b158b12520b075074fe6260776d2db0d8
--- Makefile.am
+++ Makefile.am
@@ -31,6 +31,8 @@ telescope_SOURCES =	cmd.c			\
 			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
@@ -23,6 +23,7 @@
 #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
@@ -21,6 +21,7 @@
 #include <string.h>
 
 #include "minibuffer.h"
+#include "session.h"
 #include "ui.h"
 #include "utf8.h"
 
blob - 5e81c69e04676a27822b4ad6e9d48670eb4646e8
blob + acfc0ecc4abaf7a75f65981ed7a488ac8f50c617
--- parser.c
+++ parser.c
@@ -16,10 +16,28 @@
 
 #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
@@ -22,6 +22,8 @@
 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
@@ -0,0 +1,248 @@
+/*
+ * 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
@@ -30,6 +30,7 @@
 #include "defaults.h"
 #include "minibuffer.h"
 #include "parser.h"
+#include "session.h"
 #include "telescope.h"
 #include "ui.h"
 
@@ -45,12 +46,10 @@ static const char *opts = "Cc:hnT:v";
 /*
  * 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);
 
@@ -108,7 +107,6 @@ static void		 handle_imsg_bookmark_ok(struct imsg*, si
 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 *);
@@ -120,12 +118,7 @@ static int		 make_request(struct tab *, struct get_req
 			     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;
@@ -569,20 +562,6 @@ handle_dispatch_imsg(int fd, short ev, void *d)
 
 	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
@@ -939,225 +918,15 @@ load_next_page(struct tab *tab)
 	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)
 {
@@ -1195,7 +964,7 @@ start_child(enum telescope_process p, const char *argv
 	err(1, "execvp(%s)", argv0);
 }
 
-static int
+int
 ui_send_net(int type, uint32_t peerid, const void *data,
     uint16_t datalen)
 {
@@ -1203,7 +972,7 @@ ui_send_net(int type, uint32_t peerid, const void *dat
 	    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,
@@ -1338,7 +1107,7 @@ main(int argc, char * const *argv)
 	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
@@ -0,0 +1,35 @@
+/*
+ * 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
@@ -320,19 +320,16 @@ void		 sandbox_ui_process(void);
 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
@@ -43,6 +43,7 @@
 
 #include "defaults.h"
 #include "minibuffer.h"
+#include "session.h"
 #include "telescope.h"
 #include "ui.h"
 #include "utf8.h"