summary refs log tree commit diff
diff options
context:
space:
mode:
authorJune McEnroe <june@causal.agency>2018-06-05 15:47:11 -0400
committerJune McEnroe <june@causal.agency>2018-06-05 15:47:11 -0400
commita7eb76606f0cda9d74478e545605358986e52d5a (patch)
tree7ce6b9f23b51fdb68bc985ec6699f5d9fa31d567
parentCurse edi (diff)
downloadsrc-a7eb76606f0cda9d74478e545605358986e52d5a.tar.gz
src-a7eb76606f0cda9d74478e545605358986e52d5a.zip
Implement bidirectional iterators in edi
Also I'm calling them vecs now. No one can stop me.
Diffstat (limited to '')
-rw-r--r--bin/edi.c185
1 files changed, 97 insertions, 88 deletions
diff --git a/bin/edi.c b/bin/edi.c
index ecb19c30..f78b668e 100644
--- a/bin/edi.c
+++ b/bin/edi.c
@@ -24,11 +24,10 @@
 #include <stdlib.h>
 #include <string.h>
 #include <sysexits.h>
-#include <wchar.h>
+#include <unistd.h>
 
 static struct Span {
-	size_t at;
-	size_t to;
+	size_t at, to;
 } Span(size_t at, size_t to) {
 	return (struct Span) { at, to };
 }
@@ -46,27 +45,27 @@ static bool spanTailIn(struct Span a, struct Span b) {
 	return a.to > b.at && a.to < b.to;
 }
 
-static struct Seg {
+static struct Vec {
 	char *ptr;
 	size_t len;
-} Seg(char *ptr, size_t len) {
-	return (struct Seg) { ptr, len };
+} Vec(char *ptr, size_t len) {
+	return (struct Vec) { ptr, len };
 }
 
-static struct Seg segHead(struct Seg seg, size_t at) {
-	return Seg(seg.ptr, at);
+static struct Vec vecHead(struct Vec vec, size_t at) {
+	return Vec(vec.ptr, at);
 }
-static struct Seg segTail(struct Seg seg, size_t at) {
-	return Seg(seg.ptr + at, seg.len - at);
+static struct Vec vecTail(struct Vec vec, size_t at) {
+	return Vec(vec.ptr + at, vec.len - at);
 }
 
 static struct Table {
-	struct Table *next;
-	struct Table *prev;
+	struct Table *next, *prev;
+	struct Span span;
 	size_t len;
-	struct Seg seg[];
+	struct Vec vec[];
 } *Table(size_t cap) {
-	size_t size = sizeof(struct Table) + cap * sizeof(struct Seg);
+	size_t size = sizeof(struct Table) + cap * sizeof(struct Vec);
 	struct Table *table = malloc(size);
 	if (!table) err(EX_OSERR, "malloc");
 	memset(table, 0, size);
@@ -74,51 +73,51 @@ static struct Table {
 }
 
 static struct TableIter {
-	size_t len;
-	struct Seg *seg;
+	size_t next, prev;
+	struct Vec *vec;
 	struct Span span;
 } TableIter(struct Table *table) {
-	if (table->len) {
-		return (struct TableIter) {
-			table->len,
-			&table->seg[0],
-			Span(0, table->seg[0].len),
-		};
-	} else {
-		return (struct TableIter) { 0, NULL, Span(0, 0) };
-	}
+	if (!table->len) return (struct TableIter) { 0, 0, NULL, Span(0, 0) };
+	return (struct TableIter) {
+		table->len, 0,
+		&table->vec[0],
+		Span(0, table->vec[0].len),
+	};
 }
-
 static void tableNext(struct TableIter *it) {
-	it->len--;
-	it->seg++;
-	it->span = Span(it->span.to, it->span.to + it->seg->len);
+	it->next--;
+	it->prev++;
+	if (it->next) {
+		it->vec++;
+		it->span = Span(it->span.to, it->span.to + it->vec->len);
+	}
 }
-
-static struct Seg *tableAt(struct Table *table, size_t at) {
-	for (struct TableIter it = TableIter(table); it.len; tableNext(&it)) {
-		if (it.span.at == at) return it.seg;
+static void tablePrev(struct TableIter *it) {
+	it->next++;
+	it->prev--;
+	if (it->prev) {
+		it->vec--;
+		it->span = Span(it->span.at - it->vec->len, it->span.at);
 	}
-	return NULL;
 }
 
-static struct Table *tableInsert(struct Table *prev, size_t at, struct Seg seg) {
+static struct Table *tableInsert(struct Table *prev, size_t at, struct Vec vec) {
 	struct Table *next = Table(prev->len + 2);
 	if (!prev->len) {
-		next->seg[next->len++] = seg;
+		next->vec[next->len++] = vec;
 		return next;
 	}
-	struct Span span = Span(at, at + seg.len);
-	for (struct TableIter it = TableIter(prev); it.len; tableNext(&it)) {
+	struct Span span = Span(at, at + vec.len);
+	for (struct TableIter it = TableIter(prev); it.next; tableNext(&it)) {
 		if (it.span.at == at) {
-			next->seg[next->len++] = seg;
-			next->seg[next->len++] = *it.seg;
+			next->vec[next->len++] = vec;
+			next->vec[next->len++] = *it.vec;
 		} else if (spanHeadIn(span, it.span)) {
-			next->seg[next->len++] = segHead(*it.seg, at - it.span.at);
-			next->seg[next->len++] = seg;
-			next->seg[next->len++] = segTail(*it.seg, at - it.span.at);
+			next->vec[next->len++] = vecHead(*it.vec, at - it.span.at);
+			next->vec[next->len++] = vec;
+			next->vec[next->len++] = vecTail(*it.vec, at - it.span.at);
 		} else {
-			next->seg[next->len++] = *it.seg;
+			next->vec[next->len++] = *it.vec;
 		}
 	}
 	return next;
@@ -126,51 +125,58 @@ static struct Table *tableInsert(struct Table *prev, size_t at, struct Seg seg)
 
 static struct Table *tableDelete(struct Table *prev, struct Span span) {
 	struct Table *next = Table(prev->len + 1);
-	for (struct TableIter it = TableIter(prev); it.len; tableNext(&it)) {
+	for (struct TableIter it = TableIter(prev); it.next; tableNext(&it)) {
 		if (spanIn(it.span, span) || spanEqual(it.span, span)) {
 			// drop
 		} else if (spanIn(span, it.span)) {
-			next->seg[next->len++] = segHead(*it.seg, span.at - it.span.at);
-			next->seg[next->len++] = segTail(*it.seg, span.to - it.span.at);
+			next->vec[next->len++] = vecHead(*it.vec, span.at - it.span.at);
+			next->vec[next->len++] = vecTail(*it.vec, span.to - it.span.at);
 		} else if (spanHeadIn(span, it.span)) {
-			next->seg[next->len++] = segHead(*it.seg, span.at - it.span.at);
+			next->vec[next->len++] = vecHead(*it.vec, span.at - it.span.at);
 		} else if (spanTailIn(span, it.span)) {
-			next->seg[next->len++] = segTail(*it.seg, span.to - it.span.at);
+			next->vec[next->len++] = vecTail(*it.vec, span.to - it.span.at);
 		} else {
-			next->seg[next->len++] = *it.seg;
+			next->vec[next->len++] = *it.vec;
 		}
 	}
 	return next;
 }
 
-static struct CharIter {
-	struct TableIter in;
-	struct Seg seg;
-	size_t at;
-	wchar_t ch;
+static struct VecIter {
+	size_t next, prev;
+	char *ptr;
 	int len;
-} CharIter(struct Table *table, size_t at) {
-	struct TableIter in;
-	for (in = TableIter(table); in.len; tableNext(&in)) {
-		if (at >= in.span.at && at < in.span.to) break;
-	}
-	struct CharIter it = { in, segTail(*in.seg, at - in.span.at), at, 0, 0 };
-	it.len = mbtowc(&it.ch, it.seg.ptr, it.seg.len);
-	if (it.len < 0) err(EX_DATAERR, "mbtowc");
+	wchar_t ch;
+} VecIter(struct Vec vec, size_t at) {
+	struct VecIter it = {
+		vec.len - at, at,
+		vec.ptr + at,
+		0, 0,
+	};
+	it.len = mbtowc(&it.ch, it.ptr, it.next);
+	if (it.len < 0) errx(EX_DATAERR, "mbtowc");
 	return it;
 }
-
-static void charNext(struct CharIter *it) {
-	it->seg.ptr += it->len;
-	it->seg.len -= it->len;
-	it->at += it->len;
-	if (!it->seg.len && it->in.len) {
-		tableNext(&it->in);
-		it->seg = *it->in.seg;
-		it->at = it->in.span.at;
+static void vecNext(struct VecIter *it) {
+	it->next -= it->len;
+	it->prev += it->len;
+	if (it->next) {
+		it->ptr += it->len;
+		it->len = mbtowc(&it->ch, it->ptr, it->next);
+		if (it->len < 0) errx(EX_DATAERR, "mbtowc");
+	}
+}
+static void vecPrev(struct VecIter *it) {
+	it->next += it->len;
+	it->prev -= it->len;
+	if (it->prev) {
+		for (int n = 1; n < MB_CUR_MAX; ++n) {
+			it->len = mbtowc(&it->ch, it->ptr - n, n);
+			if (it->len > 0) break;
+		}
+		if (it->len < 0) errx(EX_DATAERR, "mbtowc");
+		it->ptr -= it->len;
 	}
-	it->len = mbtowc(&it->ch, it->seg.ptr, it->seg.len);
-	if (it->len < 0) err(EX_DATAERR, "mbtowc");
 }
 
 static void curse(void) {
@@ -189,28 +195,31 @@ static void curseChar(wchar_t ch, attr_t attr, short color) {
 	add_wch(&cc);
 }
 
-static void draw(struct Table *table, size_t at, struct Span cursor) {
+static void draw(struct Table *table) {
 	move(0, 0);
-	int y, x;
-	for (struct CharIter it = CharIter(table, at); it.seg.len; charNext(&it)) {
-		if (it.at == cursor.at) getyx(stdscr, y, x);
-		attr_t attr = A_NORMAL;
-		if (it.at >= cursor.at && it.at < cursor.to) attr = A_REVERSE;
-		curseChar(it.ch, attr, 0);
+	struct VecIter it;
+	for (it = VecIter(table->vec[0], 0); it.next; vecNext(&it)) {
+		curseChar(it.ch, A_NORMAL, 0);
+	}
+	for (; it.prev; vecPrev(&it)) {
+		curseChar(it.ch, A_NORMAL, 0);
+	}
+	for (; it.next; vecNext(&it)) {
+		curseChar(it.ch, A_NORMAL, 0);
 	}
-	move(y, x);
 }
 
 int main() {
 	struct Table *table = Table(0);
-	table = tableInsert(table, 0, Seg("Hello, world!\nGoodbye, world!\n", 30));
-	table = tableDelete(table, Span(1, 5));
-	table = tableInsert(table, 1, Seg("owdy", 4));
-	table = tableDelete(table, Span(3, 6));
-	table = tableInsert(table, 3, Seg(" do", 3));
+	table = tableInsert(table, 0, Vec("«…»", 7));
+	//table = tableInsert(table, 0, Vec("Hello, world!\nGoodbye, world!\n", 30));
+	//table = tableDelete(table, Span(1, 5));
+	//table = tableInsert(table, 1, Vec("owdy", 4));
+	//table = tableDelete(table, Span(3, 6));
+	//table = tableInsert(table, 3, Vec(" Ω", 3));
 
 	curse();
-	draw(table, 0, Span(1, 3));
+	draw(table);
 	getch();
 	endwin();
 }