about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJune McEnroe <june@causal.agency>2018-09-12 22:55:02 -0400
committerJune McEnroe <june@causal.agency>2018-09-12 22:55:02 -0400
commitb36a1347022965fdbe1b61298dc6a05be2d2a34d (patch)
treeb758829545252a09cac25ac7e89774faa36ae186
parentFactor out IRC formatting parsing (diff)
downloadcatgirl-b36a1347022965fdbe1b61298dc6a05be2d2a34d.tar.gz
catgirl-b36a1347022965fdbe1b61298dc6a05be2d2a34d.zip
Use formatParse split to position input cursor
-rw-r--r--chat.h11
-rw-r--r--edit.c11
-rw-r--r--format.c8
-rw-r--r--ui.c50
4 files changed, 41 insertions, 39 deletions
diff --git a/chat.h b/chat.h
index 50f5c87..6295ce6 100644
--- a/chat.h
+++ b/chat.h
@@ -86,15 +86,12 @@ enum {
 struct Format {
 	const wchar_t *str;
 	size_t len;
-	bool bold;
-	bool italic;
-	bool underline;
-	bool reverse;
-	int fg;
-	int bg;
+	bool split;
+	bool bold, italic, underline, reverse;
+	int fg, bg;
 };
 void formatReset(struct Format *format);
-bool formatParse(struct Format *format, const wchar_t *stop);
+bool formatParse(struct Format *format, const wchar_t *split);
 
 void handle(char *line);
 void input(struct Tag tag, char *line);
diff --git a/edit.c b/edit.c
index 5aca61f..38ee843 100644
--- a/edit.c
+++ b/edit.c
@@ -33,17 +33,10 @@ static struct {
 	.end = line.buf,
 };
 
-// XXX: editTail must always be called after editHead.
-static wchar_t tail;
 const wchar_t *editHead(void) {
-	tail = *line.ptr;
-	*line.ptr = L'\0';
 	return line.buf;
 }
 const wchar_t *editTail(void) {
-	if (tail) *line.ptr = tail;
-	*line.end = L'\0';
-	tail = L'\0';
 	return line.ptr;
 }
 
@@ -180,10 +173,12 @@ void edit(struct Tag tag, enum Edit op, wchar_t ch) {
 
 		break; case EditKillBackWord: reject(); killBackWord();
 		break; case EditKillForeWord: reject(); killForeWord();
-		break; case EditKillLine:      reject(); line.end = line.ptr;
+		break; case EditKillLine:     reject(); line.end = line.ptr;
 
 		break; case EditComplete: complete(tag);
 
 		break; case EditEnter: accept(); enter(tag);
 	}
+
+	*line.end = L'\0';
 }
diff --git a/format.c b/format.c
index 800388b..30b287e 100644
--- a/format.c
+++ b/format.c
@@ -64,10 +64,11 @@ static const wchar_t Stops[] = {
 	L'\0',
 };
 
-bool formatParse(struct Format *format, const wchar_t *stop) {
+bool formatParse(struct Format *format, const wchar_t *split) {
 	format->str += format->len;
 	if (!format->str[0]) return false;
 
+	const wchar_t *init = format->str;
 	switch (format->str[0]) {
 		break; case IRCBold:      format->str++; format->bold ^= true;
 		break; case IRCItalic:    format->str++; format->italic ^= true;
@@ -76,14 +77,15 @@ bool formatParse(struct Format *format, const wchar_t *stop) {
 		break; case IRCColor:     format->str++; parseColor(format);
 		break; case IRCReset:     format->str++; formatReset(format);
 	}
+	format->split = (split >= init && split <= format->str);
 
 	if (format->str[0] == L' ') {
 		format->len = 1 + wcscspn(&format->str[1], Stops);
 	} else {
 		format->len = wcscspn(format->str, Stops);
 	}
-	if (stop && stop > format->str && stop < &format->str[format->len]) {
-		format->len = stop - format->str;
+	if (split > format->str && split < &format->str[format->len]) {
+		format->len = split - format->str;
 	}
 	return true;
 }
diff --git a/ui.c b/ui.c
index 90a75af..72fed6a 100644
--- a/ui.c
+++ b/ui.c
@@ -239,10 +239,25 @@ static const short IRCColors[] = {
 	[IRCLightGray]  = 0 + COLOR_WHITE,
 };
 
-static int addIRC(WINDOW *win, const wchar_t *str) {
-	int lines = 0;
+static void addFormat(WINDOW *win, const struct Format *format) {
+	attr_t attr = A_NORMAL;
+	if (format->bold)      attr |= A_BOLD;
+	if (format->italic)    attr |= A_ITALIC;
+	if (format->underline) attr |= A_UNDERLINE;
+	if (format->reverse)   attr |= A_REVERSE;
+
+	short pair = -1;
+	if (format->fg >= 0) pair = IRCColors[format->fg];
+	if (format->bg >= 0) pair |= IRCColors[format->bg] << 4;
+
+	wattr_set(win, attr | attr8(pair), 1 + pair8(pair), NULL);
+	waddnwstr(win, format->str, format->len);
+}
+
+static int addWrap(WINDOW *win, const wchar_t *str) {
 	struct Format format = { .str = str };
 	formatReset(&format);
+	int lines = 0;
 	while (formatParse(&format, NULL)) {
 		int _, x, xMax;
 		getyx(win, _, x);
@@ -255,19 +270,7 @@ static int addIRC(WINDOW *win, const wchar_t *str) {
 			waddch(win, '\n');
 			lines++;
 		}
-
-		attr_t attr = A_NORMAL;
-		if (format.bold)      attr |= A_BOLD;
-		if (format.italic)    attr |= A_ITALIC;
-		if (format.underline) attr |= A_UNDERLINE;
-		if (format.reverse)   attr |= A_REVERSE;
-
-		short pair = -1;
-		if (format.fg >= 0) pair = IRCColors[format.fg];
-		if (format.bg >= 0) pair |= IRCColors[format.bg] << 4;
-
-		wattr_set(win, attr | attr8(pair), 1 + pair8(pair), NULL);
-		waddnwstr(win, format.str, format.len);
+		addFormat(win, &format);
 	}
 	return lines;
 }
@@ -293,7 +296,7 @@ static void uiStatus(void) {
 		if (len < 0) err(EX_OSERR, "aswprintf");
 		if (view->unread == 1) str[unread] = L'\0';
 
-		addIRC(ui.status, count ? str : &str[1]);
+		addWrap(ui.status, count ? str : &str[1]);
 		free(str);
 		count++;
 	}
@@ -360,7 +363,7 @@ void uiTopic(struct Tag tag, const char *topic) {
 	wchar_t *wcs = ambstowcs(topic);
 	if (!wcs) err(EX_DATAERR, "ambstowcs");
 	wmove(view->topic, 0, 0);
-	addIRC(view->topic, wcs);
+	addWrap(view->topic, wcs);
 	wclrtoeol(view->topic);
 	free(wcs);
 }
@@ -380,7 +383,7 @@ void uiLog(struct Tag tag, enum UIHeat heat, const wchar_t *line) {
 		}
 		uiStatus();
 	}
-	lines += addIRC(view->log, line);
+	lines += addWrap(view->log, line);
 	if (view->scroll != LogLines) view->scroll -= lines;
 }
 
@@ -545,9 +548,14 @@ void uiRead(void) {
 
 	int y, x;
 	wmove(ui.input, 0, 0);
-	addIRC(ui.input, editHead());
-	getyx(ui.input, y, x);
-	addIRC(ui.input, editTail());
+
+	struct Format format = { .str = editHead() };
+	formatReset(&format);
+	while (formatParse(&format, editTail())) {
+		if (format.split) getyx(ui.input, y, x);
+		addFormat(ui.input, &format);
+	}
+
 	wclrtoeol(ui.input);
 	wmove(ui.input, y, x);
 }