Commit Diff


commit - 481340ccf7f2ae08e260a374ffaad5a430cc3f57
commit + 5cd2ebb1798e7ee9e1656e7bda590e0790558cd5
blob - 600f2c50a791865471365b60ac5950499f2ecb24
blob + 6b945d131b5f4e03e7a4028d7233d758c3a40b4b
--- pages.c
+++ pages.c
@@ -45,10 +45,14 @@ const char *about_new =
 	"Id dolore aperiam voluptatem libero eaque omnis rerum nulla. Ullam sit voluptate accusamus molestiae enim minus. Fugit sequi quam dignissimos. Odio inventore vel sed. Voluptatem aut magni dignissimos."
 	;
 
+/* XXX: keep in sync with telescope.c:/^normalize_code/ */
 const char *err_pages[70] = {
 	[CANNOT_FETCH]		= "# Couldn't load the page\n",
 	[TOO_MUCH_REDIRECTS]	= "# Too much redirects\n",
+	[MALFORMED_RESPONSE]	= "# Got a malformed response\n",
 
+	[10] = "# Input required\n",
+	[11] = "# Input required\n",
 	[40] = "# Temporary failure\n",
 	[41] = "# Server unavailable\n",
 	[42] = "# CGI error\n",
blob - 4fe903ae320e7036cdfea34342a5ae4e04c06447
blob + 6df001b5456b94ad62d8d599ff1b3ecc122f242d
--- telescope.c
+++ telescope.c
@@ -86,33 +86,48 @@ handle_imsg_check_cert(struct imsg *imsg, size_t datal
 	imsg_flush(ibuf);
 }
 
+static inline int
+normalize_code(int n)
+{
+	if (n < 20) {
+		if (n == 10 || n == 11)
+			return n;
+		return 10;
+	} else if (n < 30) {
+		return 20;
+	} else if (n < 40) {
+		if (n == 30 || n == 31)
+			return n;
+		return 30;
+	} else if (n < 50) {
+		if (n <= 44)
+			return n;
+		return 40;
+	} else if (n < 60) {
+		if (n <= 53 || n == 59)
+			return n;
+		return 50;
+	} else if (n < 70) {
+		if (n <= 62)
+			return n;
+		return 60;
+	} else
+		return MALFORMED_RESPONSE;
+}
+
 static void
 handle_imsg_got_code(struct imsg *imsg, size_t datalen)
 {
-	const char	*errpage;
 	struct tab	*tab;
 
 	tab = tab_by_id(imsg->hdr.peerid);
 
 	if (sizeof(tab->code) != datalen)
 		die();
-	memcpy(&tab->code, imsg->data, sizeof(tab->code));
 
-        if (tab->code < 20) {
-		if (tab->code != 10 && tab->code != 11)
-			tab->code = 10;
-	} else if (tab->code < 30)
-		tab->code = 20;
-	else if (tab->code < 40)
-		tab->code = 30;
-	else if (tab->code < 50)
-		tab->code = 40;
-	else if (tab->code < 60)
-		tab->code = 50;
-	else
-		tab->code = 60;
-
-	if (tab->code != 30)
+	memcpy(&tab->code, imsg->data, sizeof(tab->code));
+	tab->code = normalize_code(tab->code);
+	if (tab->code != 30 && tab->code != 31)
 		tab->redirect_count = 0;
 }
 
@@ -125,35 +140,31 @@ handle_imsg_got_meta(struct imsg *imsg, size_t datalen
 
 	if (sizeof(tab->meta) <= datalen)
 		die();
+
 	memcpy(tab->meta, imsg->data, datalen);
 
-	if (tab->code != 30)
-		tab->redirect_count = 0;
-
-	if (tab->code == 20) {
-		/* TODO: parse the MIME type */
+	if (tab->code < 10) {	/* internal errors */
+		load_page_from_str(tab, err_pages[tab->code]);
+	} else if (tab->code < 20) {	/* 1x */
+		load_page_from_str(tab, err_pages[tab->code]);
+		ui_require_input(tab, tab->code == 11);
+	} else if (tab->code == 20) {
+		/* TODO: parse mime type */
 		gemtext_initparser(&tab->page);
 		imsg_compose(ibuf, IMSG_PROCEED, tab->id, 0, -1, NULL, 0);
 		imsg_flush(ibuf);
-		return;
-	}
-
-	if (tab->code == 30) {
+	} else if (tab->code < 40) { /* 3x */
 		tab->redirect_count++;
 
 		/* TODO: make customizable? */
 		if (tab->redirect_count > 5) {
 			load_page_from_str(tab,
 			    err_pages[TOO_MUCH_REDIRECTS]);
-			return;
-		}
-
-		load_url(tab, tab->meta);
-		return;
+		} else
+			load_url(tab, tab->meta);
+	} else { /* 4x, 5x & 6x */
+		load_page_from_str(tab, err_pages[tab->code]);
 	}
-
-	/* 4x, 5x or 6x */
-	load_page_from_str(tab, err_pages[tab->code]);
 }
 
 static void
blob - f4c658d59575f21d0f4a690189336e0a5b8833f9
blob + 9c5befa4fe3de4b7ab1ceb6ccf2bd8b5970d02e8
--- telescope.h
+++ telescope.h
@@ -124,6 +124,7 @@ extern const char	*about_new;
 
 #define CANNOT_FETCH		0
 #define TOO_MUCH_REDIRECTS	1
+#define MALFORMED_RESPONSE	2
 extern const char	*err_pages[70];
 
 /* telescope.c */
@@ -136,6 +137,7 @@ void		 stop_tab(struct tab*);
 int		 ui_init(void);
 void		 ui_on_tab_loaded(struct tab*);
 void		 ui_on_tab_refresh(struct tab*);
+void		 ui_require_input(struct tab*, int);
 void		 ui_end(void);
 
 /* util.c */
blob - 348b1d7722e39c463da898258334d5f696cc5011
blob + 9084aee50dda572cdeb80779074c97356803eec2
--- ui.c
+++ ui.c
@@ -100,6 +100,8 @@ static void		 cmd_tab_close(struct tab*);
 static void		 cmd_tab_new(struct tab*);
 static void		 cmd_tab_next(struct tab*);
 static void		 cmd_tab_previous(struct tab*);
+static void		 cmd_load_url(struct tab*);
+static void		 cmd_load_current_url(struct tab*);
 
 static void		 global_key_unbound(void);
 
@@ -112,9 +114,15 @@ static void		 cmd_mini_kill_line(struct tab*);
 static void		 cmd_mini_abort();
 static void		 cmd_mini_complete_and_exit();
 
+static void		 minibuffer_self_insert(void);
 static void		 eecmd_self_insert(void);
 static void		 eecmd_select(void);
+static void		 ir_self_insert(void);
+static void		 ir_select(void);
+static void		 lu_self_insert(void);
+static void		 lu_select(void);
 
+
 static struct line	*nth_line(struct tab*, size_t);
 static struct tab	*current_tab(void);
 static void		 dispatch_stdio(int, short, void*);
@@ -136,6 +144,7 @@ static void		 stop_loading_anim(struct tab*);
 static void		 load_url_in_tab(struct tab*, const char*);
 static void		 enter_minibuffer(void(*)(void), void(*)(void), void(*)(void));
 static void		 exit_minibuffer(void);
+static void		 switch_to_tab(struct tab*);
 static void		 new_tab(void);
 
 static struct { int meta, key; } thiskey;
@@ -217,7 +226,7 @@ static struct {
 
 	char	 buf[1025];
 	size_t	 off, len;
-	char	 prompt[16];
+	char	 prompt[32];
 	void	 (*donefn)(void);
 	void	 (*abortfn)(void);
 } ministate;
@@ -332,6 +341,8 @@ load_default_keys(void)
 	global_set_key("C-x C-c",	cmd_kill_telescope);
 
 	global_set_key("M-x",		cmd_execute_extended_command);
+	global_set_key("C-x C-f",	cmd_load_url);
+	global_set_key("C-x M-f",	cmd_load_current_url);
 
 	global_set_key("C-x t 0",	cmd_tab_close);
 	global_set_key("C-x t 2",	cmd_tab_new);
@@ -617,9 +628,26 @@ cmd_tab_previous(struct tab *tab)
 	if ((t = TAILQ_PREV(tab, tabshead, tabs)) == NULL)
 		t = TAILQ_LAST(&tabshead, tabshead);
 	t->flags |= TAB_CURRENT;
+}
+
+static void
+cmd_load_url(struct tab *tab)
+{
+	enter_minibuffer(lu_self_insert, lu_select, exit_minibuffer);
+	strlcpy(ministate.prompt, "Load URL: ", sizeof(ministate.prompt));
 }
 
 static void
+cmd_load_current_url(struct tab *tab)
+{
+	enter_minibuffer(lu_self_insert, lu_select, exit_minibuffer);
+	strlcpy(ministate.prompt, "Load URL: ", sizeof(ministate.prompt));
+	strlcpy(ministate.buf, tab->urlstr, sizeof(ministate.buf));
+	ministate.off = strlen(tab->urlstr);
+	ministate.len = ministate.off;
+}
+
+static void
 global_key_unbound(void)
 {
 	message("%s is undefined", keybuf);
@@ -688,14 +716,8 @@ cmd_mini_complete_and_exit(struct tab *tab)
 }
 
 static void
-eecmd_self_insert(void)
+minibuffer_self_insert(void)
 {
-	if (thiskey.meta || isspace(thiskey.key) ||
-	    !isgraph(thiskey.key)) {
-		global_key_unbound();
-		return;
-	}
-
 	if (ministate.len == sizeof(ministate.buf) -1)
 		return;
 
@@ -710,10 +732,65 @@ eecmd_self_insert(void)
 }
 
 static void
+eecmd_self_insert(void)
+{
+	if (thiskey.meta || isspace(thiskey.key) ||
+	    !isgraph(thiskey.key)) {
+		global_key_unbound();
+		return;
+	}
+
+	minibuffer_self_insert();
+}
+
+static void
 eecmd_select(void)
 {
 	exit_minibuffer();
 	message("TODO: try to execute %s", ministate.buf);
+}
+
+static void
+ir_self_insert(void)
+{
+	minibuffer_self_insert();
+}
+
+static void
+ir_select(void)
+{
+	char		 buf[1025] = {0};
+	struct url	 url;
+	struct tab	*tab;
+
+	tab = current_tab();
+
+	exit_minibuffer();
+
+	/* a bit ugly but... */
+	memcpy(&url, &tab->url, sizeof(tab->url));
+	url_set_query(&url, ministate.buf);
+	url_unparse(&url, buf, sizeof(buf));
+	load_url_in_tab(tab, buf);
+}
+
+static void
+lu_self_insert(void)
+{
+	if (thiskey.meta || isspace(thiskey.key) ||
+	    !isgraph(thiskey.key)) {
+		global_key_unbound();
+		return;
+	}
+
+	minibuffer_self_insert();
+}
+
+static void
+lu_select(void)
+{
+	exit_minibuffer();
+	load_url_in_tab(current_tab(), ministate.buf);
 }
 
 static struct line *
@@ -1326,6 +1403,18 @@ exit_minibuffer(void)
 }
 
 static void
+switch_to_tab(struct tab *tab)
+{
+	struct tab	*t;
+
+	TAILQ_FOREACH(t, &tabshead, tabs) {
+		t->flags &= ~TAB_CURRENT;
+	}
+
+	tab->flags |= TAB_CURRENT;
+}
+
+static void
 new_tab(void)
 {
 	struct tab	*tab, *t;
@@ -1338,12 +1427,9 @@ new_tab(void)
 		goto err;
 
 	TAILQ_INIT(&tab->s->head);
-	TAILQ_FOREACH(t, &tabshead, tabs) {
-		t->flags &= ~TAB_CURRENT;
-	}
 
 	tab->id = tab_counter++;
-	tab->flags = TAB_CURRENT;
+	switch_to_tab(tab);
 
 	if (TAILQ_EMPTY(&tabshead))
 		TAILQ_INSERT_HEAD(&tabshead, tab, tabs);
@@ -1427,6 +1513,18 @@ ui_on_tab_refresh(struct tab *tab)
 }
 
 void
+ui_require_input(struct tab *tab, int hide)
+{
+	/* TODO: hard-switching to another tab is ugly */
+	switch_to_tab(tab);
+
+	enter_minibuffer(ir_self_insert, ir_select, exit_minibuffer);
+	strlcpy(ministate.prompt, "Input required: ",
+	    sizeof(ministate.prompt));
+	redraw_tab(tab);
+}
+
+void
 ui_end(void)
 {
 	endwin();
blob - 05ca88cc830beebab8aa1f335938a5c3c2e2fdfc
blob + 0400a0d9ca7426bcd82ebe78db300108c62f3e59
--- url.c
+++ url.c
@@ -480,6 +480,14 @@ url_resolve_from(struct url *url, const char *str, con
 
 	*i = '\0';
 	strlcat(url->path, str, sizeof(url->path));
+	return 1;
+}
+
+int
+url_set_query(struct url *url, const char *query)
+{
+	/* TODO: pct-encode! */
+	memcpy(&url->query, query, strlen(query)+1);
 	return 1;
 }
 
@@ -497,7 +505,7 @@ url_unparse(struct url *url, char *buf, size_t len)
 
 	if (*url->path != '\0')
 		strlcat(buf, url->path, len);
-	if (*url->query != '?') {
+	if (*url->query != '\0') {
 		strlcat(buf, "?", len);
 		strlcat(buf, url->query, len);
 	}
blob - c7c4733788fda0b3bae0891f1541559eca62bae1
blob + 9faa9b4461810bd37a108c882ed890be35667b27
--- url.h
+++ url.h
@@ -31,4 +31,5 @@ struct url {
 
 int		 url_parse(const char*, struct url*, const char**);
 int		 url_resolve_from(struct url*, const char*, const char**);
+int		 url_set_query(struct url*, const char*);
 void		 url_unparse(struct url*, char*, size_t);