[comp.unix.questions] Question for curses experts

dean@violet.berkeley.edu (Dean Pentcheff) (11/17/88)

I'm trying to write a program that does rudimentary windowing using
curses.  What I need is a way to restore parts of a screen when a small
window is deleted.  I'd really like to do this without reconstructing
the entire chain of overlaid windows on the screen each time I, for
example, clear a pull-down menu.

The first idea I had was to copy out the segment of the screen that a
new small window was about to blow away, then restore it once the new
window was gone.  I figured I could do this by creating a shadow window
the size of the new window as the "backup" window, then creating a
subwindow of "curscr" (the alleged virtual screen) of the same size and
location, then copying the curscr-subwindow into the backup window with
overwrite.  Next, create the new window, diddle inside it, delete it,
then wrefresh the backup window.  That should restore the original
screen image, as it was before I made the new window.

Wrong.  It turns out that curscr is somehow inaccessible to overwrite
(on both a BSD and SYSV system), though it does exist and has
reasonable WINDOW structure parameters.

Suggestions on how I might accomplish the job?  Either through more
cleverly accessing curscr, or with an entirely different approach?

-Dean

Dean Pentcheff        dean@violet.berkeley.edu
----------------------------------------------
As an adolescent I aspired to lasting fame, I craved factual certainty, and I
thirsted for a meaningful vision of human life - so I became a scientist.  This
is like becoming an archbishop so you can meet girls.               M. Cartmill
Dean Pentcheff        dean@violet.berkeley.edu
----------------------------------------------
As an adolescent I aspired to lasting fame, I craved factual certainty, and I
thirsted for a meaningful vision of human life - so I became a scientist.  This
is like becoming an archbishop so you can meet girls.               M. Cartmill

dean@violet.berkeley.edu (Dean Pentcheff) (11/26/88)

Thanks to those of you who responded to my request for help on a curses
problem involving overwrite().  

After further experimentation, I wrote a program to test the curses function
overwrite().  It tests overwrite()ing to and from windows and subwindows.  The
depressing upshot of trying it on a Vax running BSD4.3 and a 286 box running
SVR2 (AT clone running Microport 2.2.1-L) is that there are bugs (but not the
same ones) in overwrite() on both those systems.  The one version of curses
that seems to get it right is the public domain PCurses by Bjorn Larssen 
running under MS-DOS (based on Pavel Curtis's ncurses).

*********************
My conclusion has been to avoid the use of overwrite() altogether, since it's
operation is dubious under some curses versions.
*********************

Appended below is the program, for your amusement and edification.

-Dean

Dean Pentcheff        dean@violet.berkeley.edu
----------------------------------------------
As an adolescent I aspired to lasting fame, I craved factual certainty, and I
thirsted for a meaningful vision of human life - so I became a scientist.  This
is like becoming an archbishop so you can meet girls.               M. Cartmill

------- cut here --------
/* owt.c
 * Overwrite test for curses.
 * An program which demonstrates bugs (though subtly different ones!) in
 *   both BSD and SYSV curses.  Tested on BSD4.3 (Vax), SVR2 (Microport 2.2.1-L
 *   2.2.1-L running on an AT clone) and DOS (using PCurses by Bjorn Larsson
 *   Turbo C 1.5).  The only version which works is the public domain PCurses
 *   version.  Sigh.
 * Compile with one of -DBSD, -DSYSV, or -DTURBOC as appropriate.
 *
 * Moral of the story: Avoid overwrite() (and probably overlay()) like the 
 *   plague.
 *
 * Dean Pentcheff
 * dean@violet.berkeley.edu
 */

#include	<stdio.h>
#include	<curses.h>

#ifdef	BSD
/* no special defines, etc. */
#endif	BSD

#ifdef	TURBOC
#include	<process.h>
typedef	int chtype;
#define	_y	_line
#endif	TURBOC

#ifdef	SYSV
typedef	char chtype;
#endif	SYSV

void prwin();
void dumpwin();
void status();
void prcurscr();

WINDOW	*statwin = (WINDOW *)NULL;

void
main()
{
	WINDOW	*win1;
	WINDOW	*win2;
	WINDOW	*win3;
	WINDOW	*win4;
	WINDOW	*bkup;
	WINDOW	*substd;
	WINDOW	*subcur;

	/* Curses initialization */
	initscr();
	noecho();
	cbreak();

	/* Create all the windows and subwindows we'll use */
	win1 = newwin(10, 10, 10, 10);
	win2 = subwin(stdscr, 10, 10, 10, 15);
	win3 = newwin(10, 10, 10, 65);
	win4 = newwin(10, 10, 10, 50);
	subcur = subwin(curscr, 10, 15, 10, 10);
	substd = subwin(stdscr, 10, 15, 10, 10);
	bkup   = newwin(10, 15, 0, 0);

	/* Write into a window and refresh it */
	box(win1, '1', '1');
	mvwprintw(win1, 2, 1, "hello in");
	mvwprintw(win1, 3, 1, "side of");
	mvwprintw(win1, 4, 1, "window 1");
	mvwprintw(win1, 5, 1, "4th line");
	wrefresh(win1);
	status("-> window  (win 1 written into)");
	getch();

	/* Overwrite a subwindow of stdscr from a window */
	overwrite(win1, win2);
	wrefresh(win2);
	status("window -> subwin  (win1->win2)");
	getch();

	/* Write into a subwindow */
	mvwprintw(win2, 4, 1, "window 2");
	box(win2, '2', '2');
	wrefresh(win2);
	status("-> subwin  (win2 written into)");
	getch();

	/* Write into a window, again */
	box(win3, '3', '3');
	mvwprintw(win3, 4, 1, "window 3");
	wrefresh(win3);
	status("-> window  (win 3 written into)");
	getch();

	/* Overwrite a window from a subwindow of stdscr */
	overwrite(win2, win3);
	wrefresh(win3);
	status("subwin -> window  (win2->win3)");
	getch();

	/* Write in a window, again */
	box(win4, '4', '4');
	mvwprintw(win4, 4, 1, "window 4");
	wrefresh(win4);
	status("-> window  (win 4 written into)");
	getch();

	/* Overwrite a window from a window */
	overwrite(win1, win4);
	wrefresh(win4);
	status("window -> window  (win1->win4)");
	getch();

	/* Write into a window, again */
	box(bkup, 'B', 'B');
	mvwprintw(bkup, 4, 1, "bkup window");
	wrefresh(bkup);
	status("-> window  (bkup written into)");
	getch();

	/* Overwrite a window from a subwindow of stdscr */
	overwrite(substd, bkup);
	wrefresh(bkup);
	status("subwin -> window  (substd->bkup)");
	getch();

	/* Overwrite a window from a subwindow of curscr */
	overwrite(subcur, bkup);
	wrefresh(bkup);
	status("subwin -> window  (subcur->bkup)");
	getch();

	/* Crawl into a subwindow of stdscr and show it to me */
	prwin(substd, "substd");

	/* Crawl into a subwindow of curscr and show it to me */
	prwin(subcur, "subcur");

	/* Crawl into curscr and show all of it to me.  This takes a special
	 * routine, since in BSD, at least, the _maxx and _maxy of curscr are
	 * both set to 0 (cute, eh?). */
	prcurscr();

	/* Show us the WINDOW structure elements of our windows and subwins */
	/*
	dumpwin(win1, "win1");
	dumpwin(win2, "win2");
	dumpwin(win3, "win3");
	dumpwin(win4, "win4");
	dumpwin(stdscr, "stdscr");
	dumpwin(curscr, "curscr");
	dumpwin(subcur, "subcur");
	dumpwin(bkup, "bkup");
	*/

	endwin();
}

void
prwin(win, name)
	WINDOW	*win;
	char	*name;
{
	chtype **cpp;
	chtype *cp;

	fprintf(stderr, "\n");
	fprintf(stderr, "== %s  flags: 0%o ================\n", name, win->_flags);
	for (cpp = win->_y;  cpp - win->_y  <  win->_maxy;  ++cpp) {
		fprintf(stderr, "|");
		for (cp = *cpp; cp - *cpp < win->_maxx; ++cp)
			fprintf(stderr, "%c", (char)*cp);
		fprintf(stderr, "|\n");
	}
	fprintf(stderr, "== %s end =======================\n", name);
}

void
prcurscr()
{
	chtype **cpp;
	chtype *cp;

	fprintf(stderr, "\n");
	fprintf(stderr, "== curscr  flags: 0%o ================\n", curscr->_flags);
	for (cpp = curscr->_y ;  cpp - curscr->_y  <  LINES-1;  ++cpp) {
		for (cp = *cpp; cp - *cpp < COLS-1; ++cp)
			fprintf(stderr, "%c", (char)*cp);
		fprintf(stderr, "\n");
	}
	fprintf(stderr, "== curscr end========================\n");
}

void
dumpwin(w, name)
	WINDOW	*w;
	char	*name;
{
	fprintf(stderr, "\n");
	fprintf(stderr, "== %s DUMP ================\n", name);
	fprintf(stderr, "cury: %02d curx: %02d  flags: 0%02o\n",
					w->_cury, w->_curx, w->_flags);
	fprintf(stderr, "maxy: %02d maxx: %02d  begy: %02d begx: %02d\n",
					w->_maxy, w->_maxx, w->_begy, w->_begx);
#ifdef	BSD
	fprintf(stderr, "firstch: %02d lastch: %02d  tmarg: %02d bmarg: %02d\n",
					*(w->_firstch), *(w->_lastch), w->_tmarg, w->_bmarg);
	fprintf(stderr, "clear: %d leave: %d scroll: %d use_idl: %d\n",
					w->_clear, w->_leave, w->_scroll, w->_use_idl);
	fprintf(stderr, "use_keypad: %d use_meta: %d nodelay: %d\n",
					w->_use_keypad, w->_use_meta, w->_nodelay);
#endif	BSD
}

void
status(string)
	char	*string;
{
	if (statwin == (WINDOW *)NULL)
		statwin = newwin(1, COLS, LINES-1, 0);
	werase(statwin);
	mvwaddstr(statwin, 0, 0, string);
	wrefresh(statwin);
}

#ifdef BULLSHIT
WINDOW Structure for BSD:
struct _win_st {
	short		_cury, _curx, _maxy, _maxx, _begy, _begx, _flags, _ch_off;
	bool		_clear, _leave, _scroll,
	char		**_y;
	short		*_firstch, *_lastch;
	struct		_win_st *_nextp, *_orig;
}

WINDOW Structure and flags for SYSV:
# define	_SUBWIN		01
# define	_ENDLINE	02
# define	_FULLWIN	04
# define	_SCROLLWIN	010
# define	_FLUSH		020
# define	_ISPAD		040
# define	_STANDOUT	0200
# define	_NOCHANGE	-1
struct _win_st {
	short	_cury, _curx, _maxy, _maxx, _begy, _begx, _flags;
	chtype	_attrs;
	bool	_clear, _leave, _scroll, _use_idl, _use_keypad, use_meta, _nodelay;
	chtype	**_y;
	short	*_firstch, *_lastch;
	short	_tmarg, _bmarg;
};

WINDOW structure for PCurses:
typedef struct
  {
  int	   _cury, _curx, _maxy, _maxx, _begy, _begx, _flags, _attrs, _tabsize;
  bool	   _clear, _leave, _scroll, _nodelay, _keypad;
  int    **_line;
  int	  *_minchng, *_maxchng;
  int	   _regtop, _regbottom;
  char	   _borderchars[8];
  }	WINDOW;
#endif BULLSHIT
Dean Pentcheff        dean@violet.berkeley.edu
----------------------------------------------
As an adolescent I aspired to lasting fame, I craved factual certainty, and I
thirsted for a meaningful vision of human life - so I became a scientist.  This
is like becoming an archbishop so you can meet girls.               M. Cartmill