Question

I'm trying to create a simple application that uses a scrollok()-enabled window for text as an example application but I'm having difficulty getting my windows to line up properly. The application's layout should be something along the lines of this:

       (Not to Scale)
+------------------------+
|                        |
|        80x22           |
| scrollok() text dump   |
|                        |
|                        |
+*80x1: Status Bar ******+
= 80x1: Input Bar        +

The issue: I figured out that I need to refresh the windows in the correct order. wrefresh(text) first, wrefresh(status) second and finally wrefresh(input) last. The scrollok()-enabled window functions until you get right down to the last line of text. Then it clobbers my status bar: it disappears forever.

If I shorten the scrollok()-enabled window it does not line up to the status bar properly and there is always an extra blank line of text on the terminal window. I'm looking for suggestions on how to make the scroll window line up to the status bar while at the same not make it disappear completely.

The code:

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <curses.h>

int main(int argc, char **argv)
{
    int ch;
    char buf[256];

    initscr();
    keypad(stdscr, TRUE);
    nonl();
    cbreak();
    noecho();

    /* Various windows we need to keep track of. */
    WINDOW *status;
    WINDOW *input;
    WINDOW *text;

    /* We need to always be aware of the zie of the terminal */
    int row;
    int col;
    getmaxyx(stdscr, row, col);

    /*
     * If we have color support, turn it on.
     */
    if (has_colors())
    {
        start_color();

        /* 
         * Standard <X> on BLACK.
         */
        init_pair(1, COLOR_RED,     COLOR_BLACK);
        init_pair(2, COLOR_GREEN,   COLOR_BLACK);
        init_pair(3, COLOR_YELLOW,  COLOR_BLACK);
        init_pair(4, COLOR_BLUE,    COLOR_BLACK);
        init_pair(5, COLOR_CYAN,    COLOR_BLACK);
        init_pair(6, COLOR_MAGENTA, COLOR_BLACK);
        init_pair(7, COLOR_WHITE,   COLOR_BLACK);

        /* Pair 8 is the color of our status bar */
        init_pair(8, COLOR_WHITE,   COLOR_BLUE);
    }

    /* Paint the text scrollable */
    text = newwin(row - 1, col, 0, 0);
    scrollok(text, TRUE);

    /* Paint the status bar */
    status = newwin(1, col, row - 2, 0);
    wbkgd(status, COLOR_PAIR(8));       
    wprintw(status, "%ix%i", col, row);

    /* Paint the input window */
    input = newwin(1, col, row, 0);
    keypad(input, TRUE);
    wmove(input, 0, 0);

    /* Refresh all windows */
    refresh();
    wrefresh(text);
    wrefresh(status);
    wrefresh(input);

    for (;;)
    {
                ch = wgetch(input);
        switch(ch)
        {
        case KEY_UP:
        case KEY_DOWN:
            break;
        case KEY_LEFT:
            getyx(input, row, col);
            wmove(input, row, col -1); 
            wrefresh(input);
            break;
        case KEY_RIGHT:
            getyx(input, row, col);
            wmove(input, row, col +1); 
            wrefresh(input);
            break;
        case 8:     /* same as KEY_BACKSPACE */
        case 127:   /* delete */
        case KEY_BACKSPACE:
            getyx(input, row, col);
            wmove(input, row, col -1); 
            wdelch(input);
            wrefresh(input);
            break;
        case '\r':
        case '\n':
        case KEY_SEND:
        case KEY_ENTER:
            memset(buf, 0, 256);
            getyx(input, row, col);
            wmove(input, 0, 0);
            /* TODO: Plz2rethink */
            winnstr(input, buf, col);
            wclrtoeol(input);
            wprintw(text, "%s\n", buf);
            wrefresh(text);
            wrefresh(input);
            break;
        default:
            waddch(input, ch);
            wrefresh(input);
            break;
        }
    }

    endwin();
    printf("DEBUG: BUF: %s\n", buf);
    exit(0);
}
Was it helpful?

Solution

In your diagram, you want 2 rows for the status and input and therest for text, but the code has

text = newwin(row - 1, col, 0, 0);

Using all but 1 line, so the status line gets overwritten. It should be

text = newwin(row - 2, col, 0, 0);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top