Commit Diff


commit - 43a1b8d081bd3c444b70d0f1a0da23dd598c4749
commit + 4d3785b1daec2139c584305f088d4eedce580920
blob - e2e901d20a6c83134747f66d74dd1cfbf22595cb
blob + fd41dd34ee49a80387c977619c17039f358dffcf
--- telescope.c
+++ telescope.c
@@ -14,6 +14,12 @@
 struct event		 imsgev;
 struct tabshead		 tabshead;
 
+struct proto protos[] = {
+	{ "gemini:",	load_gemini_url },
+	{ "about:",	load_about_url },
+	{ NULL, NULL },
+};
+
 static struct imsgbuf	*ibuf;
 
 static void	handle_imsg_err(struct imsg*, size_t);
@@ -65,7 +71,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->url, page) == -1)
+	    tab->urlstr, page) == -1)
 		die();
 	load_page_from_str(tab, page);
 	free(page);
@@ -218,49 +224,67 @@ load_page_from_str(struct tab *tab, const char *page)
 }
 
 void
-load_url(struct tab *tab, const char *url)
+load_about_url(struct tab *tab, const char *url)
 {
-	/* TODO: parsing the url here is a bit ugly.  maybe store it
-	 * in the struct tab? */
-	struct url	 u;
-	const char	*err;
-	char		*page;
+	char *m;
 
-	if (!strcmp(url, "about:new")) {
-		strlcpy(tab->url, url, sizeof(tab->url));
+	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));
+
+	if (!strcmp(url, "about:new"))
 		load_page_from_str(tab, about_new);
-		return;
-	}
+	else
+		load_page_from_str(tab, "# not found\n");
+}
 
-	if (has_prefix(tab->url, "about:")) {
-		strlcpy(tab->url, url, sizeof(tab->url));
-	} else {
-		if (!url_parse(tab->url, &u, &err))
-			goto err;
+void
+load_gemini_url(struct tab *tab, const char *url)
+{
+	const char	*err;
+	char		*p;
 
-		if (!url_resolve_from(&u, url, &err))
+	if (has_prefix(url, "gemini:")) {
+		if (!url_parse(url, &tab->url, &err))
 			goto err;
-
-		/* TODO: this is nowhere good enough */
-		strlcpy(tab->url, u.scheme, sizeof(tab->url));
-		strlcat(tab->url, "://", sizeof(tab->url));
-		strlcat(tab->url, u.host, sizeof(tab->url));
-		strlcat(tab->url, "/", sizeof(tab->url));
-		strlcat(tab->url, u.path, sizeof(tab->url));
+	} else {
+		if (!url_resolve_from(&tab->url, url, &err))
+			goto err;
 	}
 
-	imsg_compose(ibuf, IMSG_GET, tab->id, 0, -1, url, strlen(url)+1);
+	url_unparse(&tab->url, tab->urlstr, sizeof(tab->urlstr));
+	imsg_compose(ibuf, IMSG_GET, tab->id, 0, -1,
+	    tab->urlstr, strlen(tab->urlstr)+1);
 	imsg_flush(ibuf);
 	return;
 
 err:
-	if (asprintf(&page, "# error resolving %s from %s\n\n> %s\n",
-	    url, tab->url, err) == -1)
+	if (asprintf(&p, "#error loading %s\n>%s\n",
+	    url, err) == -1)
 		die();
-	load_page_from_str(tab, page);
-	free(page);
+	strlcpy(tab->urlstr, url, sizeof(tab->urlstr));
+	load_page_from_str(tab, p);
+	free(p);
 }
 
+void
+load_url(struct tab *tab, const char *url)
+{
+	struct proto *p;
+
+	for (p = protos; p->schema != NULL; ++p) {
+		if (has_prefix(url, p->schema)) {
+			p->loadfn(tab, url);
+			return;
+		}
+	}
+
+	protos[0].loadfn(tab, url);
+}
+
 int
 main(void)
 {
blob - 72bda1bf3350c40fa7c7fe8783237bab8dcd518e
blob + 2ca8fdf2b69ebaf2803317f281603af31265e97e
--- telescope.h
+++ telescope.h
@@ -88,7 +88,8 @@ struct tab {
 	uint32_t		 id;
 	uint32_t		 flags;
 
-	char			 url[GEMINI_URL_LEN];
+	char			 urlstr[GEMINI_URL_LEN];
+	struct url		 url;
 
 	int			 code;
 	char			 meta[GEMINI_URL_LEN];
@@ -97,6 +98,19 @@ struct tab {
 	struct ui_state		*s;
 };
 
+struct proto {
+	const char	*schema;
+
+	/* should load the given url in the tab.  Optionally, it may
+	 * consider the given url as relative to the one already
+	 * present in tab.  It must set tab->urlstr to a serialized
+	 * human-friendly URL. */
+	void		 (*loadfn)(struct tab*, const char*);
+};
+
+/* the first is also the fallback one */
+extern struct proto protos[];
+
 extern struct event		 imsgev;
 
 /* gemini.c */
@@ -113,6 +127,8 @@ extern const char	*about_new;
 extern const char	*err_pages[70];
 
 /* telescope.c */
+void		 load_about_url(struct tab*, const char*);
+void		 load_gemini_url(struct tab*, const char*);
 void		 load_url(struct tab*, const char*);
 
 /* ui.c */
blob - 677e97baffdaf0ed7c0c09de4391105af007b7c3
blob + 1a96ed6f7968f22cf4440e7204dc8b8617a67c33
--- ui.c
+++ ui.c
@@ -675,7 +675,7 @@ redraw_modeline(struct tab *tab)
 	wmove(modeline, 0, 0);
 
 	wprintw(modeline, "-%c %s %s ",
-	    spin[tab->s->loading_anim_step], mode, tab->url);
+	    spin[tab->s->loading_anim_step], mode, tab->urlstr);
 	getyx(modeline, y, x);
 	getmaxyx(modeline, max_y, max_x);
 
@@ -871,7 +871,7 @@ void
 ui_on_tab_loaded(struct tab *tab)
 {
 	stop_loading_anim(tab);
-	message("Loaded %s", tab->url);
+	message("Loaded %s", tab->urlstr);
 }
 
 void
blob - b7d99055862723b1ee6e5a9e62cc963169110af0
blob + 05ca88cc830beebab8aa1f335938a5c3c2e2fdfc
--- url.c
+++ url.c
@@ -481,4 +481,24 @@ url_resolve_from(struct url *url, const char *str, con
 	*i = '\0';
 	strlcat(url->path, str, sizeof(url->path));
 	return 1;
+}
+
+void
+url_unparse(struct url *url, char *buf, size_t len)
+{
+	strlcpy(buf, url->scheme, len);
+	strlcat(buf, "://", len);
+	strlcat(buf, url->host, len);
+
+	if (*url->path == '\0' && *url->query == '\0')
+		return;
+
+	strlcat(buf, "/", len);
+
+	if (*url->path != '\0')
+		strlcat(buf, url->path, len);
+	if (*url->query != '?') {
+		strlcat(buf, "?", len);
+		strlcat(buf, url->query, len);
+	}
 }
blob - 1da297cb09c85ac346bf9128b7838afb3ccb901a
blob + c7c4733788fda0b3bae0891f1541559eca62bae1
--- url.h
+++ url.h
@@ -15,6 +15,7 @@
  */
 
 #include <netdb.h>
+#include <stddef.h>
 
 #define GEMINI_URL_LEN 1024
 
@@ -30,3 +31,4 @@ struct url {
 
 int		 url_parse(const char*, struct url*, const char**);
 int		 url_resolve_from(struct url*, const char*, const char**);
+void		 url_unparse(struct url*, char*, size_t);