# HG changeset patch # User Matti Hamalainen # Date 1338541211 -10800 # Node ID ca88945d8eda054ec73be50d818f450e19c9523f # Parent 78447d70f9d30354cebd49ecfe6998f15705a35f Begin work on integrating the removal of ncurses "windowing" and transition to internally managing the screen as whole. diff -r 78447d70f9d3 -r ca88945d8eda main.c --- a/main.c Fri Jun 01 06:11:11 2012 +0300 +++ b/main.c Fri Jun 01 12:00:11 2012 +0300 @@ -248,8 +248,8 @@ if (!optDaemon && (flags & LOG_WINDOW)) { nn_window_t *tmp = (win != NULL) ? win : nnwin_main_window(); - if (flags & LOG_STAMP) nnwin_print_buf(tmp, tmpStr); - nnwin_print_buf(tmp, buf); + if (flags & LOG_STAMP) nnwin_print(tmp, tmpStr); + nnwin_print(tmp, buf); } th_free(buf); @@ -1345,8 +1345,7 @@ BOOL argsOK, isError = FALSE, exitProg = FALSE, colorSet = FALSE, - insertMode = TRUE, - firstUpdate = TRUE; + insertMode = TRUE; time_t prevTime; char *tmpStr; nn_editbuf_t *editBuf = nn_editbuf_new(NN_TMPBUF_SIZE); @@ -1487,14 +1486,15 @@ goto err_exit; if (cursesInit) - nnwin_update_statusline(optUserName, optUserColor); + { + nnwin_update(TRUE, NULL, optUserName, optUserColor); + } // Check if we have username and password if (cursesInit && (optUserName == NULL || optPassword == NULL)) { - nnwin_print(editWin, "You can avoid this prompt by issuing '/save' after logging in.\n"); - optUserName = nnwin_prompt_requester(editWin, "NN username: ", FALSE); - optPassword = nnwin_prompt_requester(editWin, "NN password: ", TRUE); + optUserName = nnwin_prompt_requester("You can avoid this prompt by issuing '/save' after logging in.\nNN username: ", FALSE); + optPassword = nnwin_prompt_requester("NN password: ", TRUE); } if (optUserName == NULL || optPassword == NULL) @@ -1584,8 +1584,7 @@ nn_editbuf_clear(editBuf); // First update of screen - nnwin_update_editbuf(editBuf); - nnwin_update_statusline(optUserName, optUserColor); + nnwin_update(TRUE, editBuf, optUserName, optUserColor); printMsg(NULL, "%s v%s - %s\n", th_prog_name, th_prog_version, th_prog_fullname); printMsg(NULL, "%s\n", th_prog_author); @@ -1749,12 +1748,7 @@ resize_term(0, 0); erase(); timeout(SET_DELAY); - - if (!nnwin_init_windows()) - { - errorMsg("Error resizing curses chatWindows\n"); - isError = TRUE; - } + nnwin_reset(); update = updateMain = TRUE; break; #endif @@ -1954,16 +1948,7 @@ } while (c != ERR && !exitProg && ++cnt < 10); - nnwin_update_main(updateMain); - - if (update || firstUpdate) - { - // Update edit line - nnwin_update_statusline(optUserName, optUserColor); - nnwin_update_editbuf(editBuf); - firstUpdate = FALSE; // a nasty hack ... - } - + nnwin_update(FALSE, editBuf, optUserName, optUserColor); } // cursesInit if (++updateCount > 10) @@ -1983,8 +1968,7 @@ nn_conn_send_msg_v(conn, optUserNameEnc, "%%2FSetFontColor%%20%%2Dcolor%%20%06X", optUserColor); } - nnwin_update_statusline(optUserName, optUserColor); - nnwin_update_editbuf(editBuf); + nnwin_update(FALSE, editBuf, optUserName, optUserColor); updateCount = 0; } diff -r 78447d70f9d3 -r ca88945d8eda ui.c --- a/ui.c Fri Jun 01 06:11:11 2012 +0300 +++ b/ui.c Fri Jun 01 12:00:11 2012 +0300 @@ -6,14 +6,14 @@ #include "util.h" #include "ui.h" +#define STATUS_YPOS 0 + nn_window_t *chatWindows[SET_MAX_WINDOWS], *currWin = NULL; BOOL cursesInit = FALSE; -int cursorVisible = ERR; -WINDOW *mainWin = NULL, - *statusWin = NULL, - *editWin = NULL; +int cursorVisible = ERR, + scrWidth, scrHeight; static nn_window_t *nn_window_new(const char *id) @@ -63,16 +63,19 @@ BOOL nnwin_init(int delay) { + // Sanity check the terminal size if (LINES < 0 || LINES > 1000) LINES = 24; if (COLS < 0 || COLS > 1000) COLS = 80; + // Initialize (n)curses library and terminal settings initscr(); raw(); keypad(stdscr, TRUE); noecho(); meta(stdscr, TRUE); timeout(delay); - cursorVisible = curs_set(0); + scrollok(stdscr, FALSE); + cursorVisible = curs_set(1); if (has_colors()) { @@ -97,9 +100,7 @@ } cursesInit = TRUE; - - if (!nnwin_init_windows()) - return FALSE; + nnwin_reset(); #ifdef PDCURSES PDC_set_title("NNChat v" NN_VERSION); @@ -125,14 +126,18 @@ if (cursorVisible != ERR) curs_set(cursorVisible); - nnwin_close_windows(); - endwin(); THMSG(1, "NCurses deinitialized.\n"); } } +void nnwin_reset(void) +{ + getmaxyx(stdscr, scrHeight, scrWidth); +} + + nn_window_t *nnwin_find(const char *id) { int i; @@ -179,140 +184,33 @@ if (win == NULL) return; for (i = 1; i < SET_MAX_WINDOWS; i++) + { if (chatWindows[i] == win) { chatWindows[i] = NULL; nn_window_free(win); return; } -} - - -void nnwin_update_statusline(char *optUserName, int optUserColor) -{ - char tmpStr[128]; - int i; - - if (statusWin == NULL) return; - - str_get_timestamp(tmpStr, sizeof(tmpStr), "%H:%M:%S"); - - wbkgdset(statusWin, COLOR_PAIR(10)); - werase(statusWin); - - wattrset(statusWin, A_BOLD | COLOR_PAIR(11)); - mvwaddstr(statusWin, 0, 1, tmpStr); - - wattrset(statusWin, A_BOLD | COLOR_PAIR(13)); - waddstr(statusWin, " | "); - wattrset(statusWin, A_BOLD | COLOR_PAIR(16)); - waddstr(statusWin, optUserName); - wattrset(statusWin, A_BOLD | COLOR_PAIR(13)); - - wattrset(statusWin, A_BOLD | COLOR_PAIR(13)); - waddstr(statusWin, " | "); - wattrset(statusWin, A_BOLD | COLOR_PAIR(11)); - snprintf(tmpStr, sizeof(tmpStr), "#%06x", optUserColor); - waddstr(statusWin, tmpStr); - - wattrset(statusWin, A_BOLD | COLOR_PAIR(13)); - waddstr(statusWin, " | WIN: "); - snprintf(tmpStr, sizeof(tmpStr), "%d: %s / %d", - currWin->num + 1, - currWin->id != NULL ? currWin->id : "MAIN", - currWin->pos); - waddstr(statusWin, tmpStr); - - wattrset(statusWin, A_BOLD | COLOR_PAIR(13)); - waddstr(statusWin, " | "); - wattrset(statusWin, A_BOLD | COLOR_PAIR(11)); - - for (i = 0; i < SET_MAX_WINDOWS; i++) - { - if (chatWindows[i] != NULL && chatWindows[i]->dirty) - { - snprintf(tmpStr, sizeof(tmpStr), "%d ", i + 1); - waddstr(statusWin, tmpStr); - } } - - wrefresh(statusWin); } -void nnwin_update_editbuf(nn_editbuf_t *buf) -{ - char *tmp; - if (editWin == NULL || buf == NULL || !buf->dirty) - return; - - buf->dirty = FALSE; - buf->data[buf->len] = 0; - tmp = nn_username_decode(th_strdup(buf->data)); - - werase(editWin); - - wattrset(editWin, A_NORMAL); +#define QPUTCH(ch) th_vputch(&(win->line->buf), &(win->line->bufsize), &(win->line->len), ch) - if (buf->pos < buf->len) - { - waddnstr(editWin, tmp, buf->pos); - wattrset(editWin, A_REVERSE); - waddch(editWin, tmp[buf->pos]); - wattrset(editWin, A_NORMAL); - waddnstr(editWin, tmp + buf->pos + 1, buf->len - buf->pos - 1); - } - else - { - waddnstr(editWin, tmp, buf->len); - wattrset(editWin, A_REVERSE); - waddch(editWin, ' '); - wattrset(editWin, A_NORMAL); - } - wrefresh(editWin); - th_free(tmp); -} - - -int nnwin_print(WINDOW *win, const char *fmt) +int nnwin_print(nn_window_t *win, const char *fmt) { const char *s = fmt; int col = 0; - + while (*s) { - if (*s == '½') - { - s++; - if (*s == '½') - { - waddch(win, ((unsigned char) *s) | col); - s++; - } - else - { - memcpy(&col, s, sizeof(int)); - s += sizeof(int); - } - } - else + if (win->line == NULL) { - waddch(win, ((unsigned char) *s) | col); - s++; + win->line = th_calloc(1, sizeof(nn_line_t)); + if (win->line == NULL) + return -15; } - } - return 0; -} - -#define QPUTCH(ch) th_vputch(&(win->buf), &(win->bufsize), &(win->len), ch) - -int nnwin_print_buf(nn_window_t *win, const char *fmt) -{ - const char *s = fmt; - int col = 0; - while (*s) - { if (*s == '½') { s++; @@ -320,7 +218,7 @@ { QPUTCH(*s); QPUTCH(*s); - win->chlen++; + win->line->chlen++; } else { @@ -340,26 +238,24 @@ QPUTCH('½'); - if (!th_growbuf(&(win->buf), &(win->bufsize), &(win->len), sizeof(int))) + if (!th_growbuf(&(win->line->buf), &(win->line->bufsize), &(win->line->len), sizeof(int))) return -2; - memcpy(win->buf + win->len, &col, sizeof(int)); - win->len += sizeof(int); + memcpy(win->line->buf + win->line->len, &col, sizeof(int)); + win->line->len += sizeof(int); } } else if (*s == '\n') { - QPUTCH('\n'); QPUTCH(0); - th_ringbuf_add(win->data, win->buf); - win->buf = NULL; - win->chlen = 0; + th_ringbuf_add(win->data, win->line); + win->line = NULL; win->dirty = TRUE; } else if (*s != '\r') { QPUTCH((unsigned char) *s == 255 ? ' ' : *s); - win->chlen++; + win->line->chlen++; } s++; @@ -369,86 +265,150 @@ } -char *nnwin_prompt_requester(WINDOW *win, const char *info, BOOL allowEmpty) +char *nnwin_prompt_requester(const char *info, BOOL allowEmpty) { char tmpBuf[512], *ptr; - size_t pos; int curSave = curs_set(1); echo(); - waddstr(win, info); - wgetnstr(win, tmpBuf, sizeof(tmpBuf) - 1); + waddstr(stdscr, info); + wgetnstr(stdscr, tmpBuf, sizeof(tmpBuf) - 1); noecho(); if (curSave != ERR) curs_set(curSave); - for (pos = strlen(tmpBuf) - 1; pos > 0 && th_isspace(tmpBuf[pos]); pos--) - tmpBuf[pos] = 0; - + str_trim_right(tmpBuf); ptr = str_trim_left(tmpBuf); - if (allowEmpty || strlen(ptr) > 0) + if (allowEmpty || ptr[0]) return th_strdup(ptr); else return NULL; } -BOOL nnwin_update_main(BOOL force) +void nnwin_update(BOOL force, nn_editbuf_t *ebuf, char *optUserName, int optUserColor) { - int h, offs; - qringbuf_t *buf; - - // Check pointers - if (mainWin == NULL || currWin == NULL) - return FALSE; - + if (force) + { + wattrset(stdscr, A_NORMAL); + wbkgdset(stdscr, COLOR_PAIR(0)); + werase(stdscr); + } + // Check if update is forced or if the window is dirty - if (!force && !currWin->dirty) - return FALSE; + if (currWin != NULL && (force || currWin->dirty)) + { + int h = scrHeight - 5, y, offs; + qringbuf_t *buf = currWin->data; - // Compute how many lines from backbuffer fit on the screen - buf = currWin->data; - h = getmaxy(mainWin); + wattrset(stdscr, A_NORMAL); + wbkgdset(stdscr, COLOR_PAIR(0)); + wmove(stdscr, 0, 0); + + for (y = 0, offs = buf->size - h - currWin->pos; offs >= 0 && offs < buf->size - currWin->pos && offs < buf->size && y < h; offs++) + { + int col = 0; + nn_line_t *line = buf->data[offs]; + if (line == NULL) + continue; - // Clear and redraw window - werase(mainWin); - scrollok(mainWin, 1); - for (offs = buf->size - h - currWin->pos; offs >= 0 && offs < buf->size - currWin->pos && offs < buf->size; offs++) - { - if (buf->data[offs] != NULL) - nnwin_print(mainWin, buf->data[offs]); + while (*s && y < h) + { + if (*s == '½') + { + s++; + if (*s == '½') + { + waddch(stdscr, ((unsigned char) *s) | col); + s++; + } + else + { + memcpy(&col, s, sizeof(int)); + s += sizeof(int); + } + } + else + { + waddch(stdscr, ((unsigned char) *s) | col); + s++; + } + y = getcury(stdscr); + } + } + + currWin->dirty = FALSE; } - currWin->dirty = FALSE; - wrefresh(mainWin); - return TRUE; -} + { + // Statusline + char tmpStr[128]; + int i; + + str_get_timestamp(tmpStr, sizeof(tmpStr), "%H:%M:%S"); + wmove(stdscr, scrHeight - 4, 0); + wbkgdset(stdscr, COLOR_PAIR(10)); + wclrtoeol(stdscr); + + wattrset(stdscr, A_BOLD | COLOR_PAIR(11)); + mvwaddstr(stdscr, scrHeight - 4, 1, tmpStr); -void nnwin_close_windows(void) -{ - if (mainWin) delwin(mainWin); - if (statusWin) delwin(statusWin); - if (editWin) delwin(editWin); -} + wattrset(stdscr, A_BOLD | COLOR_PAIR(13)); + waddstr(stdscr, " | "); + wattrset(stdscr, A_BOLD | COLOR_PAIR(16)); + waddstr(stdscr, optUserName); + wattrset(stdscr, A_BOLD | COLOR_PAIR(13)); + wattrset(stdscr, A_BOLD | COLOR_PAIR(13)); + waddstr(stdscr, " | "); + wattrset(stdscr, A_BOLD | COLOR_PAIR(11)); + snprintf(tmpStr, sizeof(tmpStr), "#%06x", optUserColor); + waddstr(stdscr, tmpStr); + + wattrset(stdscr, A_BOLD | COLOR_PAIR(13)); + waddstr(stdscr, " | WIN: "); + snprintf(tmpStr, sizeof(tmpStr), "%d: %s / %d", + currWin->num + 1, + currWin->id != NULL ? currWin->id : "MAIN", + currWin->pos); + waddstr(stdscr, tmpStr); -BOOL nnwin_init_windows(void) -{ - int w, h; + wattrset(stdscr, A_BOLD | COLOR_PAIR(13)); + waddstr(stdscr, " | "); + wattrset(stdscr, A_BOLD | COLOR_PAIR(11)); - getmaxyx(stdscr, h, w); - - nnwin_close_windows(); + for (i = 0; i < SET_MAX_WINDOWS; i++) + { + if (chatWindows[i] != NULL && chatWindows[i]->dirty) + { + snprintf(tmpStr, sizeof(tmpStr), "%d ", i + 1); + waddstr(stdscr, tmpStr); + } + } + } - mainWin = subwin(stdscr, h - 4, w, 0, 0); - statusWin = subwin(stdscr, 1, w, h - 4, 0); - editWin = subwin(stdscr, 3, w, h - 3, 0); + if (ebuf != NULL) + // && (force || ebuf->dirty)) + { + int yoffs = ebuf->pos / scrWidth, + xoffs = ebuf->pos % scrWidth; + char *tmp; + + ebuf->dirty = FALSE; + ebuf->data[ebuf->len] = 0; + tmp = nn_username_decode(th_strdup(ebuf->data)); - if (mainWin == NULL || statusWin == NULL || editWin == NULL) - return FALSE; + wmove(stdscr, scrHeight - 3, 0); + wattrset(stdscr, A_NORMAL); + wbkgdset(stdscr, COLOR_PAIR(0)); + waddnstr(stdscr, tmp, ebuf->len); + wmove(stdscr, scrHeight - 3 + yoffs, xoffs); - return TRUE; + th_free(tmp); + } + + wrefresh(stdscr); } diff -r 78447d70f9d3 -r ca88945d8eda ui.h --- a/ui.h Fri Jun 01 06:11:11 2012 +0300 +++ b/ui.h Fri Jun 01 12:00:11 2012 +0300 @@ -19,47 +19,48 @@ #include "th_string.h" -#define SET_MAX_WINDOWS (32) +#define SET_MAX_WINDOWS (32) #define NN_BACKBUF_LEN (512) // Backbuffer size (in lines) + +typedef struct +{ + char *buf; + size_t chlen, len, bufsize; +} nn_line_t; + + typedef struct { qringbuf_t *data; // "Backbuffer" data for this window int pos; // Current position in the window, 0 = real time BOOL dirty; + int num; char *id; // Chatter ID, NULL = main window - int num; // Window number - char *buf; - size_t len, bufsize; - size_t chlen; + nn_line_t *line; } nn_window_t; extern nn_window_t *currWin; extern BOOL cursesInit; -extern WINDOW *mainWin, *statusWin, *editWin; -BOOL nnwin_init(int delay); -void nnwin_shutdown(); +BOOL nnwin_init(int delay); +void nnwin_shutdown(); +void nnwin_reset(void); -BOOL nnwin_init_windows(void); -void nnwin_close_windows(void); +void nnwin_update(BOOL force, nn_editbuf_t *ebuf, char *optUserName, int optUserColor); -nn_window_t *nnwin_main_window(); -nn_window_t *nnwin_get(const int index); -nn_window_t *nnwin_find(const char *id); - -BOOL nnwin_open(const char *name, BOOL curwin); -void nnwin_close(nn_window_t *win); +nn_window_t * nnwin_main_window(); +nn_window_t * nnwin_get(const int index); +nn_window_t * nnwin_find(const char *id); +void nnwin_set_current(nn_window_t *); -void nnwin_update_statusline(char *optUserName, int optUserColor); -void nnwin_update_editbuf(nn_editbuf_t *buf); -int nnwin_print(WINDOW *win, const char *fmt); -int nnwin_print_buf(nn_window_t *win, const char *fmt); -char * nnwin_prompt_requester(WINDOW *win, const char *info, BOOL allowEmpty); -BOOL nnwin_update_main(BOOL force); +BOOL nnwin_open(const char *name, BOOL curwin); +void nnwin_close(nn_window_t *win); +int nnwin_print(nn_window_t *win, const char *fmt); +char * nnwin_prompt_requester(const char *info, BOOL allowEmpty); #endif