changeset 501:ca88945d8eda

Begin work on integrating the removal of ncurses "windowing" and transition to internally managing the screen as whole.
author Matti Hamalainen <ccr@tnsp.org>
date Fri, 01 Jun 2012 12:00:11 +0300
parents 78447d70f9d3
children 52da406caf54
files main.c ui.c ui.h
diffstat 3 files changed, 179 insertions(+), 234 deletions(-) [+]
line wrap: on
line diff
--- 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;
         }
 
--- 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);
 }
--- 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