Dylan Forsyth
Dylan Forsyth

Reputation: 57

Overwriting a Window

I'm making a program with ncurses that splits the screen into two windows. The top screen can accept input, and by pressing '#' it will move all the text down the the bottom window and wipe the top window. In my code I'm trying to use copywin() to replace the bottom window, but it will not paste the wording in the second window. This is what I have...

#include <ncurses.h>

int main(int argc, char *argv[])
{
// Declare variables for windows and sizes
WINDOW *top_win, *bottom_win;
int maxx, maxy, halfy, flag = 0, ch;

// Start curses
initscr();
noecho();
refresh();

// get the max x's and y's
getmaxyx(stdscr, maxy, maxx);
halfy = maxy >> 1;

// Start color
start_color();
init_pair(1, COLOR_BLACK, COLOR_WHITE);
init_pair(2, COLOR_WHITE, COLOR_CYAN);
init_pair(3, COLOR_RED, COLOR_WHITE);

// Make windows
top_win = newwin(halfy, maxx, 0, 0);
wbkgd(top_win, COLOR_PAIR(1));
wrefresh(top_win);

bottom_win = newwin(halfy, maxx, halfy, 0);
wbkgd(bottom_win, COLOR_PAIR(2));
wrefresh(bottom_win);

// Allow functions keys
keypad(top_win, TRUE);
keypad(bottom_win, TRUE);

// while loop to get input
while((ch = getch()) != '`')
    {
        if(ch == '@')
            {
                if(flag == 1)
                    {
                        flag = 0;
                    }
                else
                    {
                        flag = 1;
                    }
            }
        else if(ch == '#')
            {
                //waddstr(bottom_win, "testing");
                copywin(top_win, bottom_win, 0, 0, halfy, 0, halfy, maxx, TRUE);
                //overwrite(top_win, bottom_win);
                //werase(top_win);
            }
        else if(flag != 1)
            {
                waddch(top_win, ch | COLOR_PAIR(1));
            }
        else if(flag == 1)
            {
                waddch(top_win, ch | COLOR_PAIR(3));
            }
        wrefresh(top_win);
        wrefresh(bottom_win);
    }

// end curses
delwin(top_win);
delwin(bottom_win);
endwin();
return 0;
}

I know I can print to the window using the '#' character because of my commented out, testing statement. I've also just tried using overwrite(), but that didn't work either. Am I simply getting the arguments mixed up, or is it something else? Any Ideas? Thank you in advance!

Upvotes: 2

Views: 444

Answers (2)

Thomas Dickey
Thomas Dickey

Reputation: 54515

copywin checks the given rows/columns, and decides that your destination rectangle doesn't lie completely within the destination window. Here's a quick fix for your program:

--- foo.c.orig  2017-02-13 16:13:12.000000000 -0500
+++ foo.c       2017-02-13 16:30:18.037987489 -0500
@@ -51,7 +51,7 @@
         else if(ch == '#')
             {
                 //waddstr(bottom_win, "testing");
-                copywin(top_win, bottom_win, 0, 0, halfy, 0, halfy, maxx, TRUE);
+                copywin(top_win, bottom_win, 0, 0, 0, 0, halfy - 1, maxx - 1, TRUE);
                 //overwrite(top_win, bottom_win);
                 //werase(top_win);
             }
@@ -73,4 +73,3 @@
 endwin();
 return 0;
 }

Rows and columns are numbered from zero through the last row/column (which is one less than the window size), so I subtracted one from the dmaxrow and dmaxcol parameters. The fifth parameter dminrow was past the bottom of the window.

ncurses checks the parameters. Regarding compatibility and portability, running the same program with Solaris curses (changing "ncurses.h" to "curses.h") dumps core.

The manual page could be improved, but it's clear enough regarding colors:

only text where the two windows overlap is copied

Upvotes: 3

Jonathan Leffler
Jonathan Leffler

Reputation: 753785

I don't have a good explanation for why it works, but as long as xoff and yoff are at least 1 in the code below, the data from the upper window is copied to the lower window OK (and cleared from the upper window). The colour isn't copied. If either offset is 0, the data is not copied. The string testing is added at the top-left of the lower window — it can be omitted and the copied material is still OK.

#include <ncurses.h>

int main(void)
{
    // Declare variables for windows and sizes
    WINDOW *top_win, *bottom_win;
    int maxx, maxy, halfy, flag = 0, ch;

    // Start curses
    initscr();
    noecho();
    refresh();

    // get the max x's and y's
    getmaxyx(stdscr, maxy, maxx);
    halfy = maxy >> 1;

    // Start color
    start_color();
    init_pair(1, COLOR_BLACK, COLOR_WHITE);
    init_pair(2, COLOR_WHITE, COLOR_CYAN);
    init_pair(3, COLOR_RED, COLOR_WHITE);

    // Make windows
    top_win = newwin(halfy, maxx, 0, 0);
    wbkgd(top_win, COLOR_PAIR(1));
    wrefresh(top_win);

    bottom_win = newwin(halfy, maxx, halfy, 0);
    wbkgd(bottom_win, COLOR_PAIR(2));
    wrefresh(bottom_win);

    // Allow functions keys
    // keypad(top_win, TRUE);
    // keypad(bottom_win, TRUE);

    // while loop to get input
    int xoff = 1;
    int yoff = 1;
    while ((ch = getch()) != '`')
    {
        if (ch == '@')
        {
            if (flag == 1)
            {
                flag = 0;
            }
            else
            {
                flag = 1;
            }
        }
        else if (ch == '#')
        {
            waddstr(bottom_win, "testing");
            // copywin(top_win, bottom_win, 0, 0, halfy, 0, halfy, maxx, TRUE);
            copywin(top_win, bottom_win, 0, 0, yoff, xoff, halfy-yoff, maxx-xoff, TRUE);
            // overwrite(top_win, bottom_win);
            werase(top_win);
        }
        else if (flag != 1)
        {
            waddch(top_win, ch | COLOR_PAIR(1));
        }
        else if (flag == 1)
        {
            waddch(top_win, ch | COLOR_PAIR(3));
        }
        wrefresh(top_win);
        wrefresh(bottom_win);
    }

    // end curses
    delwin(top_win);
    delwin(bottom_win);
    endwin();
    return 0;
}

Testing on Mac running macOS Sierra 10.12.3 with GCC 6.3.0, using the local -lncurses library.

Upvotes: 1

Related Questions