user8996961
user8996961

Reputation:

Moving windows in ncurses

I've read window(3NCURSES) man page, but I can't fully understand what mvwin() function actually does and what happens to its subwindows.

The code below creates a window with a title "Window" and a border, it also creates a subwindow that is used for printing y,x position without corrupting parent window border. It then moves the parent window to a new location, but the result is not what I expected:

  1. After the window is moved, the outline of the windows border + text is not automatically erased at the old location.

  2. After the move, writing text to a subwindow, outputs it at the old and new location.

  3. After the move, parent window has new y,x coordinates, but subwindow still shows old coordinates.

I don't have a lot of experience with ncurses, and maybe I'm missing something, but this behaviour is completely illogical. If I have to manually erase windows at old location and manually move all subwindows, then this negates the benefit of using ncurses in the first place. I was expecting ncurses to automatically handle these low-level details.

My understanding of subwindows was that they are used to partition one large window into smaller non-overlapping areas. So when the parent window is moved or refreshed, all its subwindows should be moved or refreshed automatically. Is this correct?

#include <assert.h>
#include <ncurses.h>
#include <unistd.h>

int main()
{
    WINDOW *win, *swin;
    int lines, cols, y, x;

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

    // Create window
    lines = 10; cols  = 40;
    y = 5; x = 5;
    win = newwin(lines, cols, y, x);
    assert(win != NULL);

    // Create window border
    box(win, 0, 0);
    mvwprintw(win, 0, 2, " Window ");

    // Create subwindow
    swin = subwin(win, lines-2, cols-2, y+1, x+1);
    assert(swin != NULL);
    // Print window and subwindow y,x
    mvwprintw(swin, 0, 0, "win y,x=%d,%d  swin y,x=%d,%d\n",
        getbegy(win), getbegx(win), getbegy(swin), getbegx(swin));

    // Refresh
    wnoutrefresh(stdscr);
    wnoutrefresh(win);
    wnoutrefresh(swin);
    doupdate();

    sleep(2);

    // Move window
    y = 20; x = 40;
    mvwin(win, y, x);
    mvwprintw(swin, 0, 0, "win y,x=%d,%d  swin y,x=%d,%d\n",
        getbegy(win), getbegx(win), getbegy(swin), getbegx(swin));

    // Refresh
    wnoutrefresh(stdscr);
    wnoutrefresh(win);
    wnoutrefresh(swin);
    doupdate();

    wgetch(swin);

    endwin();
    return 0;
}

Upvotes: 2

Views: 3588

Answers (1)

Thomas Dickey
Thomas Dickey

Reputation: 54583

Apparently not: a quick check with Solaris 10 gives the same behavior. You might find some scenario where ncurses differs unintentionally, but this is not one of those. The FAQ makes this point about compatibility:

extensions (deviations from SVr4 curses) are allowed only if they do not modify the documented/observed behavior of the API.

The Solaris manual page does not make this clear, since the only mention of subwindows is in regard to moving them:

The mvwin() routine moves the window so that the upper left-hand corner is at position (x, y). If the move would cause the window to be off the screen, it is an error and the window is not moved. Moving subwindows is allowed, but should be avoided.

The Solaris source code tells the story for that: it does nothing with subwindows. Some retesting a while back (early 2006) in response to a user's comment about differences pointed out that ncurses was incorrectly attempting to copy subwindows. That part is ifdef'd out (since it's too interesting to just delete). Since there's not much left for mvwin to do, the actual code is fairly similar.

X/Open's description of mvwin is too brief and vague to be of any use.

Upvotes: 2

Related Questions