Implement scrolling!

weechat-hashes
C. McEnroe 2020-02-09 08:52:17 -05:00
parent 8ce6d4c377
commit 8451543b98
1 changed files with 33 additions and 11 deletions

44
ui.c
View File

@ -367,13 +367,22 @@ static void statusUpdate(void) {
fflush(stdout); fflush(stdout);
} }
static void unmark(void) { static void unmark(struct Window *window) {
windows.active->heat = Cold; if (window->scroll < BufferCap) return;
windows.active->unread = 0; window->heat = Cold;
windows.active->mark = false; window->unread = 0;
window->mark = false;
statusUpdate(); 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) { static int wordWidth(const char *str) {
size_t len = strcspn(str, " "); size_t len = strcspn(str, " ");
int width = 0; int width = 0;
@ -388,11 +397,12 @@ static int wordWidth(const char *str) {
return width; return width;
} }
static void wordWrap(WINDOW *win, const char *str) { static int wordWrap(WINDOW *win, const char *str) {
int y, x, width; int y, x, width;
getmaxyx(win, y, width); getmaxyx(win, y, width);
size_t len; size_t len;
int lines = 0;
int align = 0; int align = 0;
struct Style style = Reset; struct Style style = Reset;
while (*str) { while (*str) {
@ -409,6 +419,7 @@ static void wordWrap(WINDOW *win, const char *str) {
getyx(win, y, x); getyx(win, y, x);
const char *word = &str[strspn(str, " ")]; const char *word = &str[strspn(str, " ")];
if (width - x - 1 <= wordWidth(word)) { if (width - x - 1 <= wordWidth(word)) {
lines++;
waddch(win, '\n'); waddch(win, '\n');
getyx(win, y, x); getyx(win, y, x);
wmove(win, y, align); wmove(win, y, align);
@ -432,6 +443,7 @@ static void wordWrap(WINDOW *win, const char *str) {
waddnstr(win, str, len); waddnstr(win, str, len);
str += len; str += len;
} }
return lines;
} }
void uiWrite(size_t id, enum Heat heat, const time_t *src, const char *str) { 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)); time_t clock = (src ? *src : time(NULL));
bufferPush(&window->buffer, clock, str); bufferPush(&window->buffer, clock, str);
int lines = 1;
waddch(window->pad, '\n'); waddch(window->pad, '\n');
if (window->mark && heat > Cold) { if (window->mark && heat > Cold) {
if (!window->unread++) { if (!window->unread++) {
lines++;
waddch(window->pad, '\n'); waddch(window->pad, '\n');
} }
window->heat = heat; window->heat = heat;
statusUpdate(); statusUpdate();
} }
wordWrap(window->pad, str); lines += wordWrap(window->pad, str);
if (window->scroll < BufferCap) {
windowScroll(window, -lines);
}
if (heat > Warm) beep(); if (heat > Warm) beep();
} }
@ -573,7 +590,7 @@ static void windowShow(struct Window *window) {
windows.active = window; windows.active = window;
windows.other->mark = true; windows.other->mark = true;
inputUpdate(); inputUpdate();
unmark(); unmark(windows.active);
} }
void uiShowID(size_t id) { void uiShowID(size_t id) {
@ -645,11 +662,12 @@ static void showAuto(void) {
} }
static void keyCode(int code) { static void keyCode(int code) {
size_t id = windows.active->id; struct Window *window = windows.active;
size_t id = window->id;
switch (code) { switch (code) {
break; case KEY_RESIZE: resize(); break; case KEY_RESIZE: resize();
break; case KeyFocusIn: unmark(); break; case KeyFocusIn: unmark(window);
break; case KeyFocusOut: windows.active->mark = true; break; case KeyFocusOut: window->mark = true;
break; case KeyPasteOn:; // TODO break; case KeyPasteOn:; // TODO
break; case KeyPasteOff:; // TODO break; case KeyPasteOff:; // TODO
@ -659,15 +677,19 @@ static void keyCode(int code) {
break; case KeyMetaB: edit(id, EditPrevWord, 0); break; case KeyMetaB: edit(id, EditPrevWord, 0);
break; case KeyMetaD: edit(id, EditDeleteNextWord, 0); break; case KeyMetaD: edit(id, EditDeleteNextWord, 0);
break; case KeyMetaF: edit(id, EditNextWord, 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_BACKSPACE: edit(id, EditDeletePrev, 0);
break; case KEY_DC: edit(id, EditDeleteNext, 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_END: edit(id, EditTail, 0);
break; case KEY_ENTER: edit(id, EditEnter, 0); break; case KEY_ENTER: edit(id, EditEnter, 0);
break; case KEY_HOME: edit(id, EditHead, 0); break; case KEY_HOME: edit(id, EditHead, 0);
break; case KEY_LEFT: edit(id, EditPrev, 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_RIGHT: edit(id, EditNext, 0);
break; case KEY_UP: windowScroll(window, -1);
break; default: { break; default: {
if (code >= KeyMeta0 && code <= KeyMeta9) { if (code >= KeyMeta0 && code <= KeyMeta9) {