summary refs log tree commit diff
diff options
context:
space:
mode:
authorJune McEnroe <june@causal.agency>2018-09-05 17:10:26 -0400
committerJune McEnroe <june@causal.agency>2018-09-05 17:10:26 -0400
commit0cf067315de4960522df360f8e1b2b04a23db7f0 (patch)
tree1d656c3196660e62df297e7edbfe5073ce6147d4
parentUse PascalCase for constants (diff)
downloadcatgirl-0cf067315de4960522df360f8e1b2b04a23db7f0.tar.gz
catgirl-0cf067315de4960522df360f8e1b2b04a23db7f0.zip
Preserve scroll position when new lines appear
Diffstat (limited to '')
-rw-r--r--ui.c21
1 files changed, 15 insertions, 6 deletions
diff --git a/ui.c b/ui.c
index 8d13ea5..879fea3 100644
--- a/ui.c
+++ b/ui.c
@@ -131,7 +131,7 @@ static struct View *viewTag(struct Tag tag) {
 	view->log = newpad(LogLines, COLS);
 	wsetscrreg(view->log, 0, lastLogLine());
 	scrollok(view->log, true);
-	wmove(view->log, lastLogLine() - logHeight(view) + 2, 0);
+	wmove(view->log, lastLogLine(), 0);
 	view->scroll = LogLines;
 	view->mark = true;
 
@@ -266,7 +266,7 @@ static const wchar_t *parseColor(short *pair, const wchar_t *str) {
 	return str;
 }
 
-static void wordWrap(WINDOW *win, const wchar_t *str) {
+static int wordWrap(WINDOW *win, const wchar_t *str) {
 	size_t len = wcscspn(str, L" ");
 	size_t width = 1;
 	for (size_t i = 0; i < len; ++i) {
@@ -279,8 +279,10 @@ static void wordWrap(WINDOW *win, const wchar_t *str) {
 
 	if (width >= (size_t)(xMax - x)) {
 		waddch(win, '\n');
+		return 1;
 	} else {
 		waddch(win, ' ');
+		return 0;
 	}
 }
 
@@ -295,9 +297,10 @@ static const wchar_t IRCCodes[] = {
 	L'\0',
 };
 
-static void addIRC(WINDOW *win, const wchar_t *str) {
+static int addIRC(WINDOW *win, const wchar_t *str) {
 	attr_t attr = A_NORMAL;
 	short pair = -1;
+	int lines = 0;
 	for (;;) {
 		size_t cc = wcscspn(str, IRCCodes);
 		wattr_set(win, attr | attr8(pair), 1 + pair8(pair), NULL);
@@ -306,7 +309,7 @@ static void addIRC(WINDOW *win, const wchar_t *str) {
 
 		str = &str[cc];
 		switch (*str++) {
-			break; case L' ':          wordWrap(win, str);
+			break; case L' ':         lines += wordWrap(win, str);
 			break; case IRCBold:      attr ^= A_BOLD;
 			break; case IRCItalic:    attr ^= A_ITALIC;
 			break; case IRCUnderline: attr ^= A_UNDERLINE;
@@ -315,6 +318,7 @@ static void addIRC(WINDOW *win, const wchar_t *str) {
 			break; case IRCReset:     attr = A_NORMAL; pair = -1;
 		}
 	}
+	return lines;
 }
 
 static void uiStatus(void) {
@@ -412,16 +416,21 @@ void uiTopic(struct Tag tag, const char *topic) {
 
 void uiLog(struct Tag tag, enum UIHeat heat, const wchar_t *line) {
 	struct View *view = viewTag(tag);
+	int lines = 1;
 	waddch(view->log, '\n');
 	if (view->mark && heat > UICold) {
-		if (!view->unread++) waddch(view->log, '\n');
+		if (!view->unread++) {
+			lines++;
+			waddch(view->log, '\n');
+		}
 		if (heat > UIWarm) {
 			view->hot = true;
 			beep(); // TODO: Notification.
 		}
 		uiStatus();
 	}
-	addIRC(view->log, line);
+	lines += addIRC(view->log, line);
+	if (view->scroll != LogLines) view->scroll -= lines;
 }
 
 void uiFmt(struct Tag tag, enum UIHeat heat, const wchar_t *format, ...) {
022-02-19Factor out window management to window.cJune McEnroe 2022-02-19Enable -Wmissing-prototypesJune McEnroe In other words, warn when a function is missing static. I don't see why this isn't in -Wextra. 2022-02-19Fix edit.[ch] license notice additional permissionsJune McEnroe 2022-02-19Run line editing testsJune McEnroe I know, it feels wrong. 2022-02-18Implement new line editing "library"June McEnroe Losing tab complete and text macros, for now. This new implementation works on an instance of a struct and does not interact with the rest of catgirl, making it possible to copy into another project. Unlike existing line editing libraries, this one is entirely abstract and can be rendered externally. My goal with this library is to be able to implement vi mode. Since it operates on struct instances rather than globals, it might also be possible to give catgirl separate line editing buffers for each window, which would be a nice UX improvement. 2022-02-18Simplify cursor positioning in inputJune McEnroe Do some extra work by adding the portion before the cursor to the input window twice, but simplify the interaction with the split point. This fixes the awkward behaviour when moving the cursor across colour codes where the code would be partially interpreted up to the cursor. 2022-02-18Fix M-f orderingJune McEnroe 2022-02-12Move sandman build to scripts/MakefileJune McEnroe 2022-02-12Use compat_readpassphrase.c on LinuxJune McEnroe 2022-02-12Copy RPP defines from oconfigureJune McEnroe