Commit Diff


commit - 259cf35adb2f60cfcb4f26887963e1a74c649fb0
commit + a2728733634103e8460cf0d47c151e2642e7cbc4
blob - 404b74f78085a21d19c3147c8fa36f7d7ee4408f
blob + f3e0670e15637b074bd0df5d34a8387ac88fe3c1
--- .gitignore
+++ .gitignore
@@ -19,7 +19,9 @@ ylwrap
 *.o
 cmd.gen.c
 parse.c
+pages.c
 telescope
+pagebundler
 compile_flags.txt
 telescope-*.tar.gz
 emoji-matcher.c
blob - 01b89b660157942791f9862ef9caa2014895ef6d
blob + b274f2ae06880c9ae2a50799b693ed1c5cf6df1e
--- Makefile.am
+++ Makefile.am
@@ -41,10 +41,13 @@ telescope_SOURCES =	cmd.c		\
 telescope_SOURCES +=	phos/phos.h	\
 			phos/phos_uri.c
 
-BUILT_SOURCES =		cmd.gen.c compile_flags.txt emoji-matcher.c
+noinst_PROGRAMS =	pagebundler
+pagebundler_SOURCES =	pagebundler.c
 
-CLEANFILES =		cmd.gen.c compile_flags.txt emoji-matcher.c
+BUILT_SOURCES =		cmd.gen.c compile_flags.txt emoji-matcher.c pages.c
 
+CLEANFILES =		cmd.gen.c compile_flags.txt emoji-matcher.c pages.c
+
 LDADD =			$(LIBOBJS)
 
 EXTRA_DIST =		ChangeLog LICENSE README.md data/emoji.txt
@@ -59,3 +62,15 @@ emoji-matcher.c: $(srcdir)/data/emoji.txt $(srcdir)/ge
 
 compile_flags.txt:
 	printf "%s\n" ${CFLAGS} > compile_flags.txt
+
+PAGES =	pages/about_about.gmi	\
+	pages/about_blank.gmi	\
+	pages/about_help.gmi	\
+	pages/about_new.gmi
+pages.c: pagebundler $(srcdir)/pages.h ${PAGES}
+	echo > $@
+	echo "#include \"pages.h\"" >> $@
+	./pagebundler -f $(srcdir)/pages/about_about.gmi -v about_about >> $@
+	./pagebundler -f $(srcdir)/pages/about_blank.gmi -v about_blank >> $@
+	./pagebundler -f $(srcdir)/pages/about_help.gmi  -v about_help  >> $@
+	./pagebundler -f $(srcdir)/pages/about_new.gmi   -v about_new   >> $@
blob - 4df0dd10b376c1bfe218ffbe6e8303a7031d389c
blob + 6d64a46064b519b0d218231adbf4449385bb9496
--- fs.c
+++ fs.c
@@ -35,7 +35,7 @@
 
 static void		 die(void) __attribute__((__noreturn__));
 static void		 serve_bookmarks(uint32_t);
-static void		 send_page(struct imsg *, const char *);
+static void		 send_page(struct imsg *, const uint8_t *, size_t);
 static void		 handle_get(struct imsg*, size_t);
 static void		 handle_quit(struct imsg*, size_t);
 static void		 handle_bookmark_page(struct imsg*, size_t);
@@ -107,38 +107,49 @@ serve_bookmarks(uint32_t peerid)
 }
 
 static void
-send_page(struct imsg *imsg, const char *page)
+send_page(struct imsg *imsg, const uint8_t *page, size_t len)
 {
-	fs_send_ui(IMSG_BUF, imsg->hdr.peerid, -1, page, strlen(page));
+	fs_send_ui(IMSG_BUF, imsg->hdr.peerid, -1, page, len);
 	fs_send_ui(IMSG_EOF, imsg->hdr.peerid, -1, NULL, 0);
 }
 
 static void
 handle_get(struct imsg *imsg, size_t datalen)
 {
-	char		*data;
-	const char	*p;
+	const char	*data, *p;
+	size_t		 i;
+	struct page {
+		const char	*name;
+		void		(*handle)(uint32_t);
+		const uint8_t	*data;
+		size_t		 len;
+	} pages[] = {
+		{"about:about",		NULL,	about_about,	about_about_len},
+		{"about:blank",		NULL,	about_blank,	about_blank_len},
+		{"about:bookmarks",	serve_bookmarks, 0,	0},
+		{"about:help",		NULL,	about_help,	about_help_len},
+		{"about:new",		NULL,	about_new,	about_new_len},
+	};
 
 	data = imsg->data;
 
 	if (data[datalen-1] != '\0')
 		die();
 
-	if (!strcmp(data, "about:about")) {
-		send_page(imsg, about_about);
-	} else if (!strcmp(data, "about:blank")) {
-		send_page(imsg, about_blank);
-	} else if (!strcmp(data, "about:bookmarks")) {
-		serve_bookmarks(imsg->hdr.peerid);
-	} else if (!strcmp(data, "about:help")) {
-		send_page(imsg, about_help);
-	} else if (!strcmp(data, "about:new")) {
-		send_page(imsg, about_new);
-	} else {
-		p = "# not found!\n";
-		fs_send_ui(IMSG_BUF, imsg->hdr.peerid, -1, p, strlen(p));
-		fs_send_ui(IMSG_EOF, imsg->hdr.peerid, -1, NULL, 0);
+	for (i = 0; i < sizeof(pages)/sizeof(pages[0]); ++i) {
+		if (strcmp(data, pages[i].name) != 0)
+			continue;
+
+		if (pages[i].handle != NULL)
+			pages[i].handle(imsg->hdr.peerid);
+		else
+			send_page(imsg, pages[i].data, pages[i].len);
+		return;
 	}
+
+	p = "# not found!\n";
+	fs_send_ui(IMSG_BUF, imsg->hdr.peerid, -1, p, strlen(p));
+	fs_send_ui(IMSG_EOF, imsg->hdr.peerid, -1, NULL, 0);
 }
 
 static void
blob - /dev/null
blob + 526d709b3461b25c83937a54b1d04cda8d872ddb (mode 644)
--- /dev/null
+++ pagebundler.c
@@ -0,0 +1,91 @@
+/*
+ * 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.
+ */
+
+/*
+ * pagebundler converts the given file into a valid C program that can
+ * be compiled.  The generated code provides a variable that holds the
+ * original file.
+ *
+ * Usage: pagebundler -f file -v varname > outfile
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+
+const char *file;
+const char *varname;
+
+int
+main(int argc, char **argv)
+{
+	size_t len, r, i;
+	int ch;
+	FILE *f;
+	uint8_t buf[64];
+
+	while ((ch = getopt(argc, argv, "f:v:")) != -1) {
+		switch (ch) {
+		case 'f':
+			file = optarg;
+			break;
+		case 'v':
+			varname = optarg;
+			break;
+		default:
+			fprintf(stderr, "%s: wrong usage\n",
+			    argv[0]);
+			return 1;
+		}
+	}
+
+	if (file == NULL || varname == NULL) {
+		fprintf(stderr, "%s: wrong usage\n", argv[0]);
+		return 1;
+	}
+
+	if ((f = fopen(file, "r")) == NULL) {
+		fprintf(stderr, "%s: can't open %s: %s",
+		    argv[0], file, strerror(errno));
+	}
+
+        printf("const uint8_t %s[] = {\n", varname);
+
+	len = 0;
+        for (;;) {
+		r = fread(buf, 1, sizeof(buf), f);
+		len += r;
+
+		printf("\t");
+		for (i = 0; i < r; ++i) {
+			printf("0x%x, ", buf[i]);
+		}
+		printf("\n");
+
+		if (r != sizeof(buf))
+			break;
+	}
+
+	len++;
+	printf("\t0x00\n");
+	printf("}; /* %s */\n", varname);
+
+	printf("size_t %s_len = %zu;\n", varname, len);
+
+	fclose(f);
+	return 0;
+}
blob - b6ea65930d862fa2044bc2dc882577f033db053a
blob + 8cb3d52c2d64e22430c0bdb4be644b1eb50d9dd8
--- pages.h
+++ pages.h
@@ -17,9 +17,19 @@
 #ifndef PAGES_H
 #define PAGES_H
 
-extern const char	*about_about;
-extern const char	*about_blank;
-extern const char	*about_help;
-extern const char	*about_new;
+#include <stddef.h>
+#include <stdint.h>
 
+extern const uint8_t	 about_about[];
+extern size_t		 about_about_len;
+
+extern const uint8_t	 about_blank[];
+extern size_t		 about_blank_len;
+
+extern const uint8_t	 about_help[];
+extern size_t		 about_help_len;
+
+extern const uint8_t	 about_new[];
+extern size_t		 about_new_len;
+
 #endif
blob - /dev/null
blob + 76248ea864545416f85a989901c3f10b271bb22f (mode 644)
--- /dev/null
+++ pages/about_about.gmi
@@ -0,0 +1,9 @@
+# About pages
+
+Telescope has a number of “special” built-in pages:
+
+=> about:about
+=> about:blanks
+=> about:bookmarks
+=> about:help
+=> about:new
blob - /dev/null
blob + e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 (mode 644)
blob - /dev/null
blob + 694e7a4b045dafed5be51b176abd278f10fa685f (mode 644)
--- /dev/null
+++ pages/about_help.gmi
@@ -0,0 +1,66 @@
+# Help
+
+Welcome to Telescope!
+
+Use the arrow keys, page up/down, hjkl or C-{b,f,n,p} to move the cursor and read the page.
+
+Use > to enter an URL, B and F (uppercase) to navigate backward and forward in the history, [ and ] to move between tabs.  C-t (control + t) opens a new tab and C-w (control + w) closes it.
+
+This page is always available as
+> $ telescope about:help
+
+## What is Gemini?
+
+Gemini is a new internet protocol which:
+
+* is heavier than gopher
+* is lighter than the web
+* will not replace either
+* strives for maximum power to weight ratio
+* takes user privacy very seriously
+
+=> gemini://gemini.circumlunar.space Project Gemini Homepage
+
+> Tip: press tab and shift-tab to jump between links
+
+> Tip: move the cursor over a link and press M-RET (alt + enter) to open it in another tab.  Then use [ and ] (or ‘g t’ and ‘g T’) to switch between tabs.
+
+## What is Telescope?
+
+Telescope is a Gemini browser written for fun, as hobbystic project in my free time.  As such, it lacks tons of features available in others, more mature Gemini browsers, but it also has some unique ones.
+
+The UI is strongly inspired from Emacs and w3m, so it’s possible to notice various familiar concepts, such as the minibuffer or the tab line.  Care has been taken to make it as familiar as possible for vi and “CUA” users too.
+
+=> gemini://telescope.omarpolo.com Telescope Project Homepage
+
+Telescope is documented carefully, so please refer to the manpage to know more about all the available keybindings, the format and location of the configuration file and more:
+
+> man telescope
+
+## Appearance
+
+Telescope is fully customizable.  The default configuration file is
+
+> ~/.telescope/config
+
+If your terminal emulator doesn’t have problems with UTF-8 glyphs, try to load Telescope with the following configuration:
+
+```Example of configuration file with some pretty defaults
+set hide-pre-closing-line = 1
+
+style line.pre.start {
+	prefix "─── " "    "
+}
+
+style line.item {
+	prefix " • " "   "
+}
+
+style line.link {
+	prefix "→ " "  "
+}
+
+style line.quote {
+	prefix " ┃ "
+}
+```
blob - /dev/null
blob + 4c7d7e3202d4d5b9b6027194aee8412511e3fce8 (mode 644)
--- /dev/null
+++ pages/about_new.gmi
@@ -0,0 +1,18 @@
+```Ascii art of the word “Telescope”
+ _______         __
+|_     _|.-----.|  |.-----.-----.----.-----.-----.-----.
+  |   |  |  -__||  ||  -__|__ --|  __|  _  |  _  |  -__|
+  |___|  |_____||__||_____|_____|____|_____|   __|_____|
+                                           |__|
+```
+
+=> gemini://gemini.circumlunar.space/docs	Gemini documentation
+=> gemini://gemini.circumlunar.space/software	Gemini software
+=> gemini://geminispace.info			Search Engine (geminispace.info)
+
+Version ${VERSION}
+Bug reports to: telescope@omarpolo.com
+
+=> gemini://telescope.omarpolo.com		Telescope project page
+=> about:help					Help
+=> about:about					Internal pages