Subwindows with Ncurses

Subwindows with ncurses

Here is an example showing the main window with a subwindow:

#include <curses.h>

int main(int argc, char** argv)
{
initscr();

printw("Main window");

WINDOW* subwindow = newwin(10,20,5,15);

refresh();

box(subwindow,0,0);
mvwprintw(subwindow, 1, 1, "subwindow");

refresh();
wrefresh(subwindow);

getch();
delwin(subwindow);

endwin();
return 0;
}

Moving windows in ncurses

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.

ncurses: Subwin or subpad of a pad

Pads are not regular windows; you cannot make a window inside a pad.

The ncurses library makes these checks, which relate to the question:

  • in subpad, it checks to ensure that the parent is a pad, and then calls derwin to do the rest of the work. If the parent is not a pad, subpad returns an error.
  • subwin uses derwin, which ensures that if the parent is a pad, then the result is a pad. Either way, the result is the same type as the parent.

A pad does not exactly "share" memory with a window; it is just a convenient way to translate coordinates to a window.

Python Curses Backspace detection works in main window but not in subwindows

Subwindows don't inherit the keypad setting. When you create a window, you'll have to set that, if you want to read keys that send "any" of the named KEY_ symbols.

Unable to associate an ncurses form with a window

Windows and pads are similar, but they are not the same. The set_form_win function expects a window.

The newpad manual page notes:

It is not legal to call wrefresh
with a pad as an argument; the routines prefresh or
pnoutrefresh should be called instead.

The form library does use pads — internally, for fields — but the windows are just that (no pads). The relevant functions are wcursyncup and wsyncup (it relies on wgetch for the application for the actual wrefresh calls).

How to delete a subwindow in the python curses module

Is there a good reason why you're using a subwindow? If you create a new top-level window then the code works correctly - simply change stdscr.subwin to curses.newwin and it works as you'd expect.

I'm not a curses expert, but I believe a subwindow shares the character buffer with its parent such that changes to either one will also affect the other. So, if you're looking to sub-divide a window into logical areas (perhaps a menu bar, main area and status bar) then subwindows are useful. If, however, you're looking for something more like a dialog box or pop-up menu then a whole new window (with its own separate buffer) is what you're after.

I can't find any definitive reference for ncurses which agrees or disagrees with me, but man page for AIX seems to corroborate it:

Recall that the subwindow shares its parent's window buffer. Changes made to the shared window buffer in the area covered by a subwindow, through either the parent window or any of its subwindows, affects all windows sharing the window buffer.

Of course, this isn't definitive for ncurses, but I can't find anything to the contrary and it certainly seems to explain the behaviour observed. I also did a crude experiment where, immediately after the subwin.getch() line in your example, I added this line:

raise Exception(stdscr.instr(20, 15, 3))

In your example, I get JJJ as the content of the actual main window. If I change to use curses.newwin() to create the window instead of stdscr.subwin() I get the expected MMM.

I don't know how many specific Python curses resources there are, but most of the standard tutorials and documents about ncurses are quite useful for this sort of level. Back when I had to do some work in it, this document was quite useful. If you scroll down to the "An Example" section, you'll see that the menu pop-ups are not subwindows - he alludes to this with the following slightly vague explanation:

We don't want this new window to overwrite previously written characters on the background. They should stay there after the menu closes. This is why the menu window can't be created as a subwindow of stdscr.

Also, I remember that using both stdscr and your own windows can cause issues - the "official" ncurses introduction has some warnings about this sort of thing. It also suggests avoiding overlapping windows entirely, as they're apparently error-prone, but I don't recall having any issues with them for short-term transient modal dialogs (which is the only use to which I put them). Of course, just because my simple use-case didn't expose any issues doesn't mean there aren't any. In something as complicated as ncurses, however, I can see the wisdom in keeping things as simple as you can.

I hope that's some help. As I said, I'm by no means a curses expert, but hopefully this gets you a few steps further along.

find out if cursor had been set in ncurses.h

It's in the manual page:

The curs_set routine sets the cursor state to invisible, normal, or
very visible for visibility equal to 0, 1, or 2 respectively. If the
terminal supports the visibility requested, the previous cursor state
is returned
; otherwise, ERR is returned.



Related Topics



Leave a reply



Submit