summary refs log tree commit diff
path: root/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'main.c')
-rw-r--r--main.c121
1 files changed, 94 insertions, 27 deletions
diff --git a/main.c b/main.c
index 65de555..c2c9575 100644
--- a/main.c
+++ b/main.c
@@ -29,16 +29,44 @@ struct {
 } text;
 
 struct doc {
-	struct doc *prev, *next;
 	struct {
 		size_t ofs, len, idx;
 	} txt;
 };
 
 #define DOC_MAX 32
-struct doc docv[DOC_MAX];
+struct doc docv[DOC_MAX] = {
+	{
+		.txt = {
+			.ofs = 0,
+			.len = 0,
+			.idx = 0
+		}
+	}
+};
 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(text.buf, text.buf + docv[0].txt.len, text.n - docv[0].txt.len);
+		memmove(&docv[0], &docv[1], docn * sizeof(struct doc));
+		docv[0].txt.ofs = 0;
+		for (int i = 1; i < docn; i++) {
+			docv[i].txt.idx = docv[i - 1].txt.ofs + (docv[i].txt.idx - docv[i].txt.ofs);
+			docv[i].txt.ofs = docv[i - 1].txt.ofs + docv[i - 1].txt.len;
+		}
+		if (docn > 0 && doci >= docn) doci = docn - 1;
+	}
+}
+
 int doc_new(void) {
 	if (doci < docn) {
 		text.n = docv[doci].txt.ofs;
@@ -52,15 +80,20 @@ int doc_new(void) {
 	return 0;
 }
 
-int doc_add(char *buf, size_t n) {
+int doc_add(const char *buf, size_t n) {
 	if (text.n + n > TXT_BUF_SIZE) {
 		return -1;
 	}
 	memcpy(&text.buf[text.n], buf, n);
+	docv[doci].txt.len += n;
 	text.n += n;
 	return 0;
 }
 
+int doc_adds(const char *s) {
+	return doc_add(s, strlen(s));
+}
+
 void doc_prev(void) {
 	if (doci > 0) doci--;
 }
@@ -69,6 +102,29 @@ void doc_next(void) {
 	if (doci < docn) doci++;
 }
 
+void doc_back_line(void) {
+	if (doci >= docn) return;
+	struct doc *d = &docv[doci];
+	size_t i = d->txt.idx;
+	while (i > 0 && text.buf[d->txt.idx] != '\n') i--;
+	if (i > 0) i--;
+	while (i > 0 && text.buf[d->txt.idx] != '\n') i--;
+	if (i > 0) i++;
+	d->txt.idx = i;
+}
+
+void doc_print_line(void) {
+	if (doci >= docn) return;
+	struct doc *d = &docv[doci];
+	size_t i = d->txt.idx;
+	size_t n = d->txt.ofs + d->txt.len;
+	while (i < n && text.buf[d->txt.idx] != '\n') {
+		putchar(text.buf[i++]);
+	}
+	if (i < n) i++;
+	d->txt.idx = i;
+}
+
 /* pagination */
 
 size_t pg_lines() {
@@ -76,27 +132,21 @@ size_t pg_lines() {
 }
 
 int pg_down(const char *_) {
-	if (doci >= docn) return -1;
 	size_t lines = pg_lines();
-	size_t i = docv[doci].txt.idx;
-	size_t end = docv[doci].txt.ofs + docv[doci].txt.len;
-	while (lines > 0 && i < end) {
-		putchar(text.buf[i]);
-		if (text.buf[i] == '\n') lines--;
-		i++;
-	}
+	while (lines--) doc_print_line();
 	return 0;
 }
 
 int pg_up(const char *_) {
-	if (doci >= docn) return -1;
 	size_t lines = pg_lines() << 1;
-	size_t i = docv[doci].txt.idx;
-	while (lines > 0 && i > 0) {
-		putchar(text.buf[i]);
-		if (text.buf[i] == '\n') lines--;
-		i--;
-	}
+	while (lines--) doc_back_line();
+	pg_down(_);
+	return 0;
+}
+
+int pg_redraw(const char *_) {
+	size_t lines = pg_lines();
+	while (lines--) doc_back_line();
 	pg_down(_);
 	return 0;
 }
@@ -107,17 +157,17 @@ int pg_up(const char *_) {
 #define PATH_MAX 255
 
 enum doc_type {
+	TYPE_UNKNOWN,
 	TYPE_GOPHERDOC,
 	TYPE_GEMTEXT,
 	TYPE_PLAIN,
-	TYPE_UNKNOWN
 };
 
 enum protocol {
+	PROT_UNKNOWN,
 	PROT_FILE,
 	PROT_GOPHER,
 	PROT_GEMINI,
-	PROT_UNKNOWN,
 };
 
 struct addr {
@@ -128,15 +178,24 @@ struct addr {
 	enum doc_type type;
 };
 
-int url_to_addr(const char *url, struct addr *adr) {
-	char *colon = strchr(url, ':');
-	adr->prot = PROT_UNKNOWN;
-	if (colon) {
-	}
-	return -1;
+int url_to_addr(const char *url, struct addr *adr, enum protocol prot_default) {
+	adr->prot = prot_default;
+	adr->type = TYPE_PLAIN;
+	adr->host_len = 0;
+	size_t n = strlen(url);
+	if (n > PATH_MAX) return -1;
+	adr->path_len = n;
+	memcpy(adr->path, url, n);
+	return 0;
 }
 
 int nav_to(const char *url) {
+	struct addr a;
+	static enum protocol prot_default = PROT_FILE; /* change to gopher later */
+	if (url_to_addr(url, &a, prot_default)) {
+		return -1;
+	}
+	prot_default = a.prot;
 	return 0;
 }
 
@@ -151,10 +210,16 @@ struct cmd {
 	int (*fn)(const char *);
 };
 
+int addtxt(const char *s) {
+	return doc_add(s, strlen(s)) || doc_add("\n", 1);
+}
+
 struct cmd cmd_tbl[] = {
 	{ 'g', nav_to },
 	{ '\n', pg_down },
-	{ '\b', pg_up },
+	{ 'b', pg_up },
+	{ 'r', pg_redraw },
+	{ 'a', addtxt },
 	{ 'q', quit }
 };
 
@@ -194,6 +259,8 @@ int cmd_get(char *buf, size_t n) {
 int main(void) {
 	char cmd_buf[1024];
 	running = 1;
+	doc_new();
+	doc_adds("Press ? for help.\n");
 	while (running && cmd_get(cmd_buf, sizeof cmd_buf)) {
 		cmd_do(cmd_buf);
 	}