summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--buf.c28
-rw-r--r--buf.h15
-rw-r--r--design.txt5
-rw-r--r--doc.c157
-rw-r--r--doc.h27
-rw-r--r--main.c45
-rw-r--r--nav.c62
-rw-r--r--nav.h19
-rw-r--r--parse.c17
-rw-r--r--parse.h9
10 files changed, 189 insertions, 195 deletions
diff --git a/buf.c b/buf.c
new file mode 100644
index 0000000..dd93116
--- /dev/null
+++ b/buf.c
@@ -0,0 +1,28 @@
+#include <stdlib.h>
+#include "buf.h"
+#include "err.h"
+
+void buf_init(struct buf *b, size_t n) {
+	b->buf = calloc(1, n);
+	if (!b->buf) {
+		efatal("buf_init");
+	}
+	b->cap = n;
+	b->sz = 0;
+}
+
+void buf_grow(struct buf *b, size_t n) {
+	size_t sz = b->sz + n;
+	size_t c = b->cap;
+	if (sz > c) {
+		while (sz > c) c <<= 1;
+		char *p = realloc(b->buf, c);
+		if (!p) efatal("buf_grow");
+		b->buf = p;
+		b->cap = c;
+	}
+}
+
+void buf_free(struct buf *b) {
+	free(b->buf);
+}
diff --git a/buf.h b/buf.h
new file mode 100644
index 0000000..fdf0c52
--- /dev/null
+++ b/buf.h
@@ -0,0 +1,15 @@
+#ifndef BUF_H
+#define BUF_H
+
+#include <stddef.h>
+
+struct buf {
+	size_t sz, cap;
+	char *buf;
+};
+
+void buf_init(struct buf *, size_t);
+void buf_grow(struct buf *, size_t);
+void buf_free(struct buf *);
+
+#endif
diff --git a/design.txt b/design.txt
index 84fa2f0..e884d76 100644
--- a/design.txt
+++ b/design.txt
@@ -2,3 +2,8 @@
  WORM'S LINE BROWSER
 =====================
 Design Considerations
+
+LINE HEADER
++---------------------+---------+--------+---------+
+| dist to prev header | link nr | length | text... |
++---------------------+---------+--------+---------+
diff --git a/doc.c b/doc.c
index 3478f8b..658315c 100644
--- a/doc.c
+++ b/doc.c
@@ -5,139 +5,48 @@
 #include "doc.h"
 #include "err.h"
 
-/* text */
-
-static struct {
-	char *buf;
-	size_t len, cap;
-} txt;
-
-void txt_init(void) {
-	txt.buf = malloc(1);
-	if (!txt.buf) efatal("txt_init");
-	txt.buf[0] = 0;
-	txt.len = 0;
-	txt.cap = 1;
-}
-
-void txt_fini(void) {
-	free(txt.buf);
-}
-
-void txt_grow(size_t n) {
-	size_t cap = txt.cap;
-	size_t len = txt.len + n;
-	if (cap < len) {
-		while (cap < len) cap <<= 1;
-		char *s = realloc(txt.buf, cap);
-		if (!s) efatal("txt_grow");
-		txt.cap = cap;
-		txt.buf = s;
-	}
-}
-
-/* docs */
-
-struct doc {
-	size_t ofs, len, idx;
-};
-
-#define DOC_MAX 32
-
-static struct doc docv[DOC_MAX] = {
-	{
-		 
-		.ofs = 0,
+void doc_init(struct doc *d) {
+	buf_init(&d->txt, sizeof(struct doc_line));
+	buf_init(&d->lnk, 1);
+	d->txt.sz = sizeof(struct doc_line);
+	*(struct doc_line *)d->txt.buf = (struct doc_line) {
+		.prev = 0,
+		.link = DOC_LINK_NONE,
 		.len = 0,
-		.idx = 0
-	}
-};
-
-static size_t docn = 0, doci = 0;
-
-void doc_pop(void) {
-	if (docn > 0) {
-		docn--;
-		if (doci > 0) doci--;
-	}
-}
-
-void doc_shift(void) {
-	if (docn > 0) {
-		docn--;
-		memmove(txt.buf, txt.buf + docv[0].len, txt.len - docv[0].len);
-		memmove(&docv[0], &docv[1], docn * sizeof(struct doc));
-		docv[0].ofs = 0;
-		for (int i = 1; i < docn; i++) {
-			docv[i].idx = docv[i - 1].ofs + (docv[i].idx - docv[i].ofs);
-			docv[i].ofs = docv[i - 1].ofs + docv[i - 1].len;
-		}
-		if (docn > 0 && doci >= docn) doci = docn - 1;
-	}
-}
-
-void doc_new(void) {
-	while (docn >= DOC_MAX) {
-		doc_shift();
-	}
-	if (doci < docn) {
-		txt.len = docv[doci].ofs;
-		docn = doci;
-	}
-	memset(&docv[docn], 0, sizeof(struct doc));
-	docv[docn].ofs = txt.len;
-	docv[docn].idx = txt.len;
-	doci = docn++;
-}
-
-void doc_add(const char *buf, size_t n) {
-	txt_grow(n);
-	memcpy(&txt.buf[txt.len], buf, n);
-	txt.len += n;
-	docv[doci].len += n;
-}
-
-void doc_adds(const char *s) {
-	doc_add(s, strlen(s));
-}
-
-void doc_prev(void) {
-	if (doci > 0) doci--;
+	};
+	d->latest = 0;
 }
 
-void doc_next(void) {
-	if (doci < docn) doci++;
+void doc_fini(struct doc *d) {
+	buf_free(&d->txt);
+	buf_free(&d->lnk);
 }
 
-void doc_back_line(void) {
-	if (doci >= docn) return;
-	struct doc *d = &docv[doci];
-	size_t i = d->idx;
-	while (i > 0 && txt.buf[d->idx] != '\n') i--;
-	if (i > 0) i--;
-	while (i > 0 && txt.buf[d->idx] != '\n') i--;
-	if (i > 0) i++;
-	d->idx = i;
+void doc_new_line(struct doc *d) {
+	size_t here = d->latest, there = d->txt.sz;
+	buf_grow(&d->txt, sizeof(struct doc_line));
+	*(struct doc_line *)&d->txt.buf[there] = (struct doc_line) {
+		.prev = there - here,
+		.link = DOC_LINK_NONE,
+		.len = 0
+	};
+	d->txt.sz += sizeof(struct doc_line);
+	d->latest = there;
 }
 
-void doc_print_line(void) {
-	if (doci >= docn) return;
-	struct doc *d = &docv[doci];
-	size_t i = d->idx;
-	size_t n = d->ofs + d->len;
-	while (i < n && txt.buf[d->idx] != '\n') {
-		putchar(txt.buf[i++]);
-	}
-	if (i < n) i++;
-	d->idx = i;
+void doc_add_line(struct doc *d, const char *s) {
+	doc_add_text(d, s);
+	doc_new_line(d);
 }
 
-void doc_init(void) {
-	txt_init();
-	doc_new();
-	doc_adds("Type ? for command help.\n");
+void doc_add_text(struct doc *d, const char *s) {
+	doc_add_textn(d, s, strlen(s));
 }
 
-void doc_fini(void) {
-	txt_fini();
+void doc_add_textn(struct doc *d, const char *s, size_t n) {
+	buf_grow(&d->txt, n);
+	memcpy(&d->txt.buf[d->txt.sz], s, n);
+	struct doc_line *dl = (struct doc_line *)&d->txt.buf[d->latest];
+	d->txt.sz += n;
+	dl->len += n;
 }
diff --git a/doc.h b/doc.h
index 3c5dfcc..5e9c18c 100644
--- a/doc.h
+++ b/doc.h
@@ -1,6 +1,8 @@
 #ifndef DOC_H
 #define DOC_H
 
+#include "buf.h"
+
 enum doc_type {
 	TYPE_UNKNOWN,
 	TYPE_GOPHERDOC,
@@ -8,17 +10,24 @@ enum doc_type {
 	TYPE_PLAIN,
 };
 
-void doc_new(void);
-void doc_prev(void);
-void doc_next(void);
+#define DOC_LINK_NONE 0xffff
+
+struct doc_line {
+	unsigned short prev, link, len;
+	char txt[];
+};
 
-void doc_add(const char *, size_t);
-void doc_adds(const char *);
+struct doc {
+	struct buf txt, lnk;
+	size_t latest;
+};
 
-void doc_back_line(void);
-void doc_print_line(void);
+void doc_init(struct doc *);
+void doc_fini(struct doc *);
 
-void doc_init(void);
-void doc_fini(void);
+void doc_new_line(struct doc *);
+void doc_add_line(struct doc *, const char *);
+void doc_add_text(struct doc *, const char *);
+void doc_add_textn(struct doc *, const char *, size_t);
 
 #endif
diff --git a/main.c b/main.c
index adc488a..64343bc 100644
--- a/main.c
+++ b/main.c
@@ -7,30 +7,10 @@
 #include "doc.h"
 #include "net.h"
 #include "err.h"
+#include "nav.h"
 
 /* pagination */
 
-size_t pg_lines() {
-	return 24;
-}
-
-void pg_down(void) {
-	size_t lines = pg_lines();
-	while (lines--) doc_print_line();
-}
-
-void pg_up(void) {
-	size_t lines = pg_lines() << 1;
-	while (lines--) doc_back_line();
-	pg_down();
-}
-
-void pg_redraw(void) {
-	size_t lines = pg_lines();
-	while (lines--) doc_back_line();
-	pg_down();
-}
-
 /* navigation */
 
 int nav_to(const char *url) {
@@ -56,7 +36,7 @@ struct cmd {
 
 /* cmd is mutated when trimming strings
  * returns whether to quit */
-int cmd_do(char *cmd) {
+int cmd_do(char *cmd, struct nav_state *ns) {
 	switch (*cmd) {
 	case 'q':
 		puts("goodbye!");
@@ -74,13 +54,13 @@ int cmd_do(char *cmd) {
 		}
 		break;
 	case 'b':
-		pg_up();
+		nav_pg_up(ns);
 		break;
 	case '\0':
-		pg_down();
+		nav_pg_down(ns);
 		break;
 	case 'r':
-		pg_redraw();
+		nav_redraw(ns);
 		break;
 	case 'g':
 		if (nav_to(cmd + 1)) perr("navigation failure");
@@ -108,23 +88,16 @@ int cmd_get(char *buf, size_t n) {
 	return !!fgets(buf, n, stdin);
 }
 
-void init(void) {
-	doc_init();
-}
-
-void fini(void) {
-	doc_fini();
-}
-
 int main(void) {
+	struct nav_state ns;
 	char cmd_buf[1024];
-	init();
-	atexit(fini);
+	nav_init(&ns);
 	while (cmd_get(cmd_buf, sizeof cmd_buf)) {
 		cmd_trim(cmd_buf, sizeof cmd_buf);
-		if (cmd_do(cmd_buf)) {
+		if (cmd_do(cmd_buf, &ns)) {
 			break;
 		}
 	}
+	nav_fini(&ns);
 	return 0;
 }
diff --git a/nav.c b/nav.c
new file mode 100644
index 0000000..82cf71a
--- /dev/null
+++ b/nav.c
@@ -0,0 +1,62 @@
+#include <string.h>
+#include <stdio.h>
+#include "nav.h"
+
+void nav_init(struct nav_state *ns) {
+	memset(ns, 0, sizeof *ns);
+	ns->histc = 1;
+	doc_init(&ns->histv[0]);
+	doc_add_text(&ns->histv[0], "Type ? for command help.");
+}
+
+void nav_fini(struct nav_state *ns) {
+	for (size_t i = 0; i < ns->histc; i++) {
+		doc_fini(&ns->histv[i]);
+	}
+}
+
+size_t pg_lines(void) {
+	return 24;
+}
+
+struct doc_line *nav_cur_line(struct nav_state *ns) {
+	return (struct doc_line *)&ns->histv[ns->cur_doc].txt.buf[ns->cur_ofs[ns->cur_doc]];
+}
+
+int nav_line_up(struct nav_state *ns) {
+	if (ns->cur_ofs[ns->cur_doc] > 0) {
+		ns->cur_ofs[ns->cur_doc] -= nav_cur_line(ns)->prev; 
+		return 1;
+	} else {
+		return 0;
+	}
+}
+
+int nav_line_down(struct nav_state *ns) {
+	struct doc_line *l = nav_cur_line(ns);
+	if (ns->cur_ofs[ns->cur_doc] + sizeof(struct doc_line) + l->len < ns->histv[ns->cur_doc].txt.sz) {
+		ns->cur_ofs[ns->cur_doc] += l->len + sizeof(struct doc_line); 
+		return 1;
+	} else {
+		return 0;
+	}
+}
+
+void nav_pg_up(struct nav_state *ns) {
+	size_t lines = pg_lines() << 1;
+	while (lines-- && nav_line_up(ns));
+	nav_pg_down(ns);
+}
+
+void nav_pg_down(struct nav_state *ns) {
+	size_t lines = pg_lines();
+	while (lines--) {
+		struct doc_line *l = nav_cur_line(ns);
+		fwrite(l->txt, 1, l->len, stdout);
+		putchar('\n');
+		if (!nav_line_down(ns)) break;
+	}
+}
+
+void nav_redraw(struct nav_state *ns) {
+}
diff --git a/nav.h b/nav.h
new file mode 100644
index 0000000..baefba9
--- /dev/null
+++ b/nav.h
@@ -0,0 +1,19 @@
+#ifndef NAV_H
+#define NAV_H
+
+#include "doc.h"
+#define HIST_MAX 32
+
+struct nav_state {
+	size_t histc, cur_doc;
+	struct doc histv[HIST_MAX];
+	size_t cur_ofs[HIST_MAX];
+};
+
+void nav_init(struct nav_state *ns);
+void nav_fini(struct nav_state *ns);
+void nav_pg_up(struct nav_state *ns);
+void nav_pg_down(struct nav_state *ns);
+void nav_redraw(struct nav_state *ns);
+
+#endif
diff --git a/parse.c b/parse.c
deleted file mode 100644
index 8061257..0000000
--- a/parse.c
+++ /dev/null
@@ -1,17 +0,0 @@
-#include "parse.h"
-
-int parse_doc(enum doc_type doct, int (*line_get)(char **, size_t *)) {
-	char *s;
-	size_t n;
-	switch (doct) {
-	case TYPE_PLAIN:
-		doc_new();
-		while (line_get(&s, &n)) {
-			doc_add(s, n);
-			doc_add("\n", 1);
-		}
-		return 0;
-	default:
-		return -1;
-	}
-}
diff --git a/parse.h b/parse.h
deleted file mode 100644
index 1267b3c..0000000
--- a/parse.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef PARSE_H
-#define PARSE_H
-
-#include <stddef.h>
-#include "doc.h"
-
-int parse_doc(enum doc_type doct, int (*line_get)(char **, size_t *));
-
-#endif