summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ui.c44
1 files changed, 33 insertions, 11 deletions
diff --git a/ui.c b/ui.c
index 33d6a15..b4a2dee 100644
--- a/ui.c
+++ b/ui.c
@@ -367,13 +367,22 @@ static void statusUpdate(void) {
fflush(stdout);
}
-static void unmark(void) {
- windows.active->heat = Cold;
- windows.active->unread = 0;
- windows.active->mark = false;
+static void unmark(struct Window *window) {
+ if (window->scroll < BufferCap) return;
+ window->heat = Cold;
+ window->unread = 0;
+ window->mark = false;
statusUpdate();
}
+static void windowScroll(struct Window *window, int n) {
+ if (window->scroll == BufferCap) window->mark = true;
+ window->scroll += n;
+ if (window->scroll < WINDOW_LINES) window->scroll = WINDOW_LINES;
+ if (window->scroll > BufferCap) window->scroll = BufferCap;
+ if (window->scroll == BufferCap) unmark(window);
+}
+
static int wordWidth(const char *str) {
size_t len = strcspn(str, " ");
int width = 0;
@@ -388,11 +397,12 @@ static int wordWidth(const char *str) {
return width;
}
-static void wordWrap(WINDOW *win, const char *str) {
+static int wordWrap(WINDOW *win, const char *str) {
int y, x, width;
getmaxyx(win, y, width);
size_t len;
+ int lines = 0;
int align = 0;
struct Style style = Reset;
while (*str) {
@@ -409,6 +419,7 @@ static void wordWrap(WINDOW *win, const char *str) {
getyx(win, y, x);
const char *word = &str[strspn(str, " ")];
if (width - x - 1 <= wordWidth(word)) {
+ lines++;
waddch(win, '\n');
getyx(win, y, x);
wmove(win, y, align);
@@ -432,6 +443,7 @@ static void wordWrap(WINDOW *win, const char *str) {
waddnstr(win, str, len);
str += len;
}
+ return lines;
}
void uiWrite(size_t id, enum Heat heat, const time_t *src, const char *str) {
@@ -439,15 +451,20 @@ void uiWrite(size_t id, enum Heat heat, const time_t *src, const char *str) {
time_t clock = (src ? *src : time(NULL));
bufferPush(&window->buffer, clock, str);
+ int lines = 1;
waddch(window->pad, '\n');
if (window->mark && heat > Cold) {
if (!window->unread++) {
+ lines++;
waddch(window->pad, '\n');
}
window->heat = heat;
statusUpdate();
}
- wordWrap(window->pad, str);
+ lines += wordWrap(window->pad, str);
+ if (window->scroll < BufferCap) {
+ windowScroll(window, -lines);
+ }
if (heat > Warm) beep();
}
@@ -573,7 +590,7 @@ static void windowShow(struct Window *window) {
windows.active = window;
windows.other->mark = true;
inputUpdate();
- unmark();
+ unmark(windows.active);
}
void uiShowID(size_t id) {
@@ -645,11 +662,12 @@ static void showAuto(void) {
}
static void keyCode(int code) {
- size_t id = windows.active->id;
+ struct Window *window = windows.active;
+ size_t id = window->id;
switch (code) {
break; case KEY_RESIZE: resize();
- break; case KeyFocusIn: unmark();
- break; case KeyFocusOut: windows.active->mark = true;
+ break; case KeyFocusIn: unmark(window);
+ break; case KeyFocusOut: window->mark = true;
break; case KeyPasteOn:; // TODO
break; case KeyPasteOff:; // TODO
@@ -659,15 +677,19 @@ static void keyCode(int code) {
break; case KeyMetaB: edit(id, EditPrevWord, 0);
break; case KeyMetaD: edit(id, EditDeleteNextWord, 0);
break; case KeyMetaF: edit(id, EditNextWord, 0);
- break; case KeyMetaM: waddch(windows.active->pad, '\n');
+ break; case KeyMetaM: waddch(window->pad, '\n');
break; case KEY_BACKSPACE: edit(id, EditDeletePrev, 0);
break; case KEY_DC: edit(id, EditDeleteNext, 0);
+ break; case KEY_DOWN: windowScroll(window, +1);
break; case KEY_END: edit(id, EditTail, 0);
break; case KEY_ENTER: edit(id, EditEnter, 0);
break; case KEY_HOME: edit(id, EditHead, 0);
break; case KEY_LEFT: edit(id, EditPrev, 0);
+ break; case KEY_NPAGE: windowScroll(window, +(WINDOW_LINES - 2));
+ break; case KEY_PPAGE: windowScroll(window, -(WINDOW_LINES - 2));
break; case KEY_RIGHT: edit(id, EditNext, 0);
+ break; case KEY_UP: windowScroll(window, -1);
break; default: {
if (code >= KeyMeta0 && code <= KeyMeta9) {