[comp.sources.atari.st] v02i090: curses -- Screen updating package part01/02

koreth@panarthea.ebay.sun.com (Steven Grimm) (10/13/89)

Submitted-by: gray@hplb.hpl.hp.com (Graham Higgins)
Posting-number: Volume 2, Issue 90
Archive-name: curses/part01

Following a request on comp.sys.atari.st, here's the source to
curses.  Apologies to the original author, TWINKLE.TOS didn't
appear in the posting where I obtained this, the poster wanted to
post plain text - understandable.  [Since that's the way I want
sources submitted, VERY understandable. :) -sg]

Cheers,

Graham
======

------------------------------------------------------------------
Graham Higgins             	|  Phone: (0272) 799910 x 24060
Hewlett-Packard Labs    	|  gray@hpl.hp.co.uk
Bristol                       	|  gray%hplb.uucp@ukc.ac.uk
U.K.                          	|  gray@hplb.hpl.hp.com
------------------------------------------------------------------
Disclaimer: My opinions above are exactly that, mine and opinions.
------------------------------------------------------------------

#!/bin/sh
# shar:	Shell Archiver  (v1.22)
#
# This is part 1 of a multipart archive                                    
# do not concatenate these parts, unpack them in order with /bin/sh        
#
#	Run the following text with /bin/sh to create:
#	  curses.c
#	  curses.doc
#	  curses.h
#	  curses.man
#	  portab.h
#	  readme.too
#	  readme.txt
#	  twinkle.c
#
if test -r s2_seq_.tmp
then echo "Must unpack archives in sequence!"
     next=`cat s2_seq_.tmp`; echo "Please unpack part $next next"
     exit 1; fi
sed 's/^X//' << 'SHAR_EOF' > curses.c &&
X/* #[curses: simple-minded implementation of the curses package				*/
X/* #[intro: introduction													*/
X/* 																			*/
X/* This source and resulting object may be modified, used or distributed by */
X/* anyone who so desires under the following conditions :                   */
X/*																			*/
X/*		1) This notice and the copyright notice shall not be removed or     */
X/*		   changed.															*/
X/*		2) No credit shall be taken for this source and resulting objects   */
X/*		3) This source or resulting objects is not to be traded, sold or    */
X/*		   used for personal gain or profit.								*/
X/*		4) Inclusion of this source or resulting objects in commercially    */
X/*		   available packages is forbidden without written consent of the   */
X/*		   author of this source.											*/
X/*                                                                          */
X/* #]intro:																	*/
X/* #[include: include files													*/
X#include "portab.h"
X#include "osbind.h"
X#include "curses.h"
X/* #]include:																*/
X/* define supervisor mode entry forgotten in osbind.h						*/
X#define Supexec(a)	xbios(38,a)
X/* terminal states : cooked, cbreak and raw									*/
X#define COOKED 0
X#define CBREAK 1
X#define RAW    2
X/* define address of system-variable _conterm for kbshift return value		*/
X#define CONTERM		(*((char *)0x484))
X/* #[globals: definition of global variables								*/
X/* #[curglob: define the following variables as external in curses.h		*/
XWINDOW *curscr ;
XWINDOW *stdscr ;
Xchar	*Def_term = "AtariST" ;
Xbool	My_term = FALSE ;
Xchar	*ttytype = "Atari ST-series computer, VT52/CURSES mode" ;
Xint		LINES = 25 ;
Xint		COLS = 80 ;
Xint		ERR = 0 ;
Xint		OK = 1 ;
X/* #]curglob:																*/
Xbool   _doecho = FALSE ;
Xbool   _nlmap = FALSE ;
Xbool   _curini = FALSE ;
XBYTE	_modinp = 0 ; /* set input to Un*x compatability, i.e only char's	*/
XBYTE	_csry = 0 ;
XBYTE	_csrx = 0 ;
Xchar *cpyrid = "Copyright, R. van't Veen. All rights reserved. 1987" ;
X
Xoverlay "curses"	/* put in separate segment */
X
X/* #]globals:																*/
X/* #[miscel: miscellaneous curses functions									*/
X/* #[initscr: initialize the curses package									*/
Xinitscr()
X{
X	WORD i,j ;
X	WINDOW *newwin() ;
X
X	if ( _curini )
X		{
X		wrefresh(curscr) ;
X		if ( cpyrid == NULL )
X			Pterm(-12L) ;
X		ERR = 1 ;
X		OK = 0 ;
X		return ;
X		} ;
X	_curini = 1 ;
X	curscr = newwin(0,0,0,0) ;
X	if ( curscr == NULL )
X		{
X		ERR = 1 ;
X		OK = 0 ;
X		return ;
X		} ;
X	stdscr = newwin(0,0,0,0) ;
X	if ( stdscr == NULL )
X		{
X		ERR = 1 ;
X		OK = 0 ;
X		return ;
X		} ;
X	Bconout(2,'\033') ;
X	Bconout(2,'E') ;
X	Bconout(2,'\033') ;
X	Bconout(2,'w') ;
X	Bconout(2,'\033') ;
X	Bconout(2,'f') ;
X	_csry = 0 ;
X	_csrx = 0 ;
X	ERR = 0 ;
X	OK = 1 ;
X}
X/* #]initscr:																*/
X/* #[endwin: end of curses package											*/
Xendwin()
X{
X	if ( !_curini )
X		{
X		ERR = 1 ;
X		OK = 0 ;
X		return ;
X		} ;
X	_curini = 0 ;
X	delwin(stdscr) ;
X	delwin(curscr) ;
X	_movcur(LINES,0) ;
X	Bconout(2,'\033') ;
X	Bconout(2,'e') ;
X	ERR = 1 ;
X	OK = 0 ;
X}
X/* #]endwin:																*/
X/* #[newwin: create a new window for the user								*/
XWINDOW *newwin(l,c,by,bx)
Xint l,c,bx,by ;
X{
X	WINDOW *tmp ;
X	WORD   i, j, nl, nc ;
X	char	*malloc() ;
X	
X	tmp = ( WINDOW * ) malloc(sizeof(WINDOW)) ;
X	if ( tmp == NULL )
X		{
X		ERR = 1 ;
X		OK = 0 ;
X		return(NULL) ;
X		} ;
X	tmp->_curx = 0 ;
X	tmp->_cury = 0 ;
X	tmp->_clear = 0 ;
X	tmp->_leave = 0 ;
X	tmp->_scroll = 0 ;
X	if ( l == 0 )
X		nl = LINES - by ;
X	else
X		nl = l ;
X	if ( c == 0 )
X		nc = COLS - bx ;
X	else
X		nc = c ;
X	if ( nl < 1 || nl > LINES || nc < 1 || nc > COLS )
X		{
X		free(tmp) ;
X		ERR = 1 ;
X		OK = 0 ;
X		return(NULL) ;
X		} ;
X	tmp->_maxy = nl - 1 ;
X	tmp->_maxx = nc - 1 ;
X	if ( nl == LINES && nc == COLS )
X		tmp->_flags = _FULLWIN ;
X	else
X		tmp->_flags = 0 ;
X	if ( by < 0 || by >= LINES || bx < 0 || bx >= COLS )
X		{
X		free(tmp) ;
X		ERR = 1 ;
X		OK = 0 ;
X		return(NULL) ;
X		} ;
X	tmp->_begy = by ;
X	tmp->_begx = bx ;
X	tmp->_y = ( WORD ** ) malloc(sizeof(WORD *)*(tmp->_maxy+1)) ;
X	if ( tmp->_y == NULL )
X		{
X		free(tmp) ;
X		ERR = 1 ;
X		OK = 0 ;
X		return(NULL) ;
X		} ;
X	tmp->_y[0] = ( WORD * ) malloc(sizeof(WORD)*(tmp->_maxy+1)*(tmp->_maxx+1)) ;
X	if ( tmp->_y[0] == NULL )
X		{
X		free(tmp->_y) ;
X		free(tmp) ;
X		ERR = 1 ;
X		OK = 0 ;
X		return(NULL) ;
X		} ;
X	for ( i = 1 ; i <= tmp->_maxy ; i++ )
X		tmp->_y[i] = tmp->_y[0] + i * ( tmp->_maxx + 1 ) ;
X	for ( i = 0 ; i <= tmp->_maxy ; i++ )
X		{
X		for ( j = 0 ; j <= tmp->_maxx ; j++ )
X			tmp->_y[i][j] = ' ' ;
X		} ;
X/* make everything changed on first update of tmp							*/
X	touchwin(tmp) ;
X	ERR = 0 ;
X	OK = 1 ;
X	return(tmp) ;
X}
X/* #]newwin:																*/
X/* #[delwin: delete a window												*/
Xdelwin(w)
XWINDOW *w ;
X{
X	if ( w == NULL )
X		{
X		ERR = 1 ;
X		OK = 0 ;
X		return ;
X		} ;
X	if ( w->_flags & _SUBWIN )
X		free(w->_y) ;
X	else
X		{
X		free(w->_y[0]) ;
X		free(w->_y) ;
X		} ;
X	free(w) ;
X	ERR = 0 ;
X	OK = 1 ;
X}
X/* #]delwin:																*/
X/* #[mvwin: move window														*/
Xmvwin(w,y,x)
XWINDOW *w ;
Xint y,x ;
X{
X	if ( y < 0 || x < 0 || ( y + w->_maxy + 1 ) > LINES || ( x + w->_maxx + 1 ) > COLS )
X		{
X		ERR = 1 ;
X		OK = 0 ;
X		return ;
X		} ;
X	w->_begy = y ;
X	w->_begx = x ;
X	touchwin(w) ;
X	ERR = 0 ;
X	OK = 1 ;
X}
X/* #]mvwin:																	*/
X/* #[touchwin: touch a window												*/
Xtouchwin(w)
XWINDOW *w ;
X{
X	WORD i,j ;
X	w->_firstch = w->_y[0] ;
X	w->_lastch = &(w->_y[w->_maxy][w->_maxx]) ;
X	for ( i = 0 ; i <= w->_maxy ; i++ )
X		for ( j = 0 ; j <= w->_maxx ; j++ )
X			w->_y[i][j] = w->_y[i][j] | TOUCHED ;
X	ERR = 0 ;
X	OK = 1 ;
X}
X/* #]touchwin:																*/
X/* #[subwin: create a sub-window											*/
XWINDOW *subwin(w,l,c,by,bx)
XWINDOW *w ;
Xint l,c,by,bx ;
X{
X	WINDOW *tmp ;
X	WORD   i, nl, nc ;
X	char	*malloc() ;
X	
X/* cannot take subwindows of curscr											*/
X	if ( w == curscr )
X		{
X		ERR = 1 ;
X		OK = 0 ;
X		return(NULL) ;
X		} ;
X	tmp = ( WINDOW * ) malloc(sizeof(WINDOW)) ;
X	if ( tmp == NULL )
X		{
X		ERR = 1 ;
X		OK = 0 ;
X		return(NULL) ;
X		} ;
X	tmp->_curx = 0 ;
X	tmp->_cury = 0 ;
X	tmp->_clear = 0 ;
X	tmp->_leave = 0 ;
X	tmp->_scroll = 0 ;
X	if ( l == 0 )
X		nl = LINES - by ;
X	else
X		nl = l ;
X	if ( c == 0 )
X		nc = COLS - bx ;
X	else
X		nc = c ;
X	if ( l < 1 || l > (w->_maxy+1) || c < 1 || c > (w->_maxx+1) )
X		{
X		free(tmp) ;
X		ERR = 1 ;
X		OK = 0 ;
X		return(NULL) ;
X		} ;
X	tmp->_maxy = nl - 1 ;
X	tmp->_maxx = nc - 1 ;
X	if ( nl == LINES && nc == COLS )
X		tmp->_flags = _FULLWIN | _SUBWIN ;
X	else
X		tmp->_flags = _SUBWIN ;
X	if ( by < w->_begy || by >= (w->_maxy+w->_begy) ||
X		 bx < w->_begx || bx >= (w->_maxx+w->_begx) )
X		{
X		free(tmp) ;
X		ERR = 1 ;
X		OK = 0 ;
X		return(NULL) ;
X		} ;
X	tmp->_begy = by ;
X	tmp->_begx = bx ;
X	tmp->_y = ( WORD ** ) malloc(sizeof(WORD *)*(tmp->_maxy+1)) ;
X	if ( tmp->_y == NULL )
X		{
X		free(tmp) ;
X		ERR = 1 ;
X		OK = 0 ;
X		return(NULL) ;
X		} ;
X	tmp->_y[0] = w->_y[0] + ( tmp->_begy - w->_begy ) * ( w->_maxx + 2 ) + ( tmp->_maxx - w->_maxx ) ;
X	for ( i = 1 ; i <= tmp->_maxy ; i++ )
X		tmp->_y[i] = tmp->_y[0] + i * ( w->_maxx + 2 ) ;
X/* make everything changed on first update of tmp							*/
X	touchwin(tmp) ;
X	ERR = 0 ;
X	OK = 1 ;
X	return(tmp) ;
X}
X/* #]subwin:																*/
X/* #[leaveok: tell curses where to leave the cursor after updating			*/
Xleaveok(w,f)
XWINDOW *w ;
Xbool f ;
X{
X	w->_leave = f ;
X	ERR = 0 ;
X	OK = 1 ;
X}
X/* #]leaveok:																*/
X/* #[scrollok: tell curses it is ok to scroll the window					*/
Xscrollok(w,f)
XWINDOW *w ;
Xbool f ;
X{
X	w->_scroll = f ;
X	ERR = 0 ;
X	OK = 1 ;
X}
X/* #]scrollok:																*/
X/* #[nl: tell curses to map CR to CR,LF										*/
Xnl()
X{
X	_nlmap = 1 ;
X	ERR = 0 ;
X	OK = 1 ;
X}
X/* #]nl:																	*/
X/* #[nonl: tell curses not to map CR to CR,LF								*/
Xnonl()
X{
X	_nlmap = 0 ;
X	ERR = 0 ;
X	OK = 1 ;
X}
X/* #]nonl:																	*/
X/* #[longname: return the full name of the terminal                         */
X/* always returns the contents of ttytype in name							*/
Xlongname(termbuf,name)
Xchar *termbuf, *name ;
X{
X	int i ;
X	
X	for ( i = 0 ; ttytype[i] != '\0' ; i++ )
X		name[i] = ttytype[i] ;
X	name[i] = '\0' ;
X}
X/* #]longname:																*/
X/* #]miscel:																*/
X/* #[output: output functions												*/
X/* #[waddch: add a character to a window									*/
Xwaddch(w,c)
XWINDOW *w ;
Xchar   c ;
X{
X	WORD i, tpos ;
X
X	ERR = 0 ;
X	OK = 1 ;
X	if ( c >= 0x20 )
X		{
X		if ( w == curscr )
X			{
X			if ( ( w->_flags & _STANDOUT ))
X				{
X				w->_y[w->_cury][w->_curx] = c | STANDOUT | TOUCHED ;
X				Bconout(2,'\033') ;
X				Bconout(2,'p') ;
X				Bconout(5,c) ;
X				Bconout(2,'\033') ;
X				Bconout(2,'q') ;
X				}
X			else
X				{
X				w->_y[w->_cury][w->_curx] = c | TOUCHED ;
X				Bconout(5,c) ;
X				} ;
X			_csrx++ ;
X			}
X		else
X			{
X			if ( (w->_flags & _STANDOUT ))
X				w->_y[w->_cury][w->_curx] = c | STANDOUT | TOUCHED ;
X			else
X				w->_y[w->_cury][w->_curx] = c | TOUCHED ;
X			if ( w->_firstch == 0 )
X				{
X				w->_firstch = &(w->_y[w->_cury][w->_curx]) ;
X				w->_lastch = w->_firstch ;
X				}
X			else
X				{
X				if ( w->_firstch > &(w->_y[w->_cury][w->_curx]) )
X					w->_firstch = &(w->_y[w->_cury][w->_curx]) ;
X				else
X					{
X					if ( w->_lastch < &(w->_y[w->_cury][w->_curx]) )
X						w->_lastch = &(w->_y[w->_cury][w->_curx]) ;
X					} ;
X				} ;
X			} ;
X		wmove(w,w->_cury,w->_curx+1) ;
X		}
X	else if ( c == '\n' )
X		{
X		wclrtoeol(w) ;
X		if ( _nlmap )
X			wmove(w,w->_cury+1,0) ;
X		else
X			wmove(w,w->_cury+1,w->_curx) ;
X		}
X	else if ( c == '\r' )
X		{
X		wmove(w,w->_cury,0) ;
X		}
X	else if ( c == '\t' )
X		{
X		tpos = ( w->_curx + w->_begx ) % 8 ;
X		tpos = ( tpos == 0 ) ? 8 : tpos ;
X		for ( i = 0 ; i < tpos ; i++ )
X			waddch(w,' ') ;
X		}
X	else
X		{
X		if ( w == curscr )
X			{
X			if ( ( w->_flags & _STANDOUT ))
X				{
X				w->_y[w->_cury][w->_curx] = c | STANDOUT | TOUCHED ;
X				Bconout(2,'\033') ;
X				Bconout(2,'p') ;
X				Bconout(5,c) ;
X				Bconout(2,'\033') ;
X				Bconout(2,'q') ;
X				}
X			else
X				{
X				w->_y[w->_cury][w->_curx] = c | TOUCHED ;
X				Bconout(5,c) ;
X				} ;
X			_csrx++ ;
X			}
X		else
X			{
X			if ( (w->_flags & _STANDOUT ))
X				w->_y[w->_cury][w->_curx] = c | STANDOUT | TOUCHED ;
X			else
X				w->_y[w->_cury][w->_curx] = c | TOUCHED ;
X			if ( w->_firstch == 0 )
X				{
X				w->_firstch = &(w->_y[w->_cury][w->_curx]) ;
X				w->_lastch = w->_firstch ;
X				}
X			else
X				{
X				if ( w->_firstch > &(w->_y[w->_cury][w->_curx]) )
X					w->_firstch = &(w->_y[w->_cury][w->_curx]) ;
X				else
X					{
X					if ( w->_lastch < &(w->_y[w->_cury][w->_curx]) )
X						w->_lastch = &(w->_y[w->_cury][w->_curx]) ;
X					} ;
X				} ;
X			} ;
X		wmove(w,w->_cury,w->_curx+1) ;
X		} ;
X}
X/* #]waddch:																*/
X/* #[waddstr: add a string of characters to a window						*/
Xwaddstr(w,s)
XWINDOW *w ;
Xchar   *s ;
X{
X	WORD  i ;
X	
X	ERR = 0 ;
X	OK = 1 ;
X	for ( i = 0 ; s[i] != '\0' ; i++ )
X		waddch(w,s[i]) ;
X}
X/* #]waddstr:																*/
X/* #[box: draw a box around a window										*/
Xbox(w,v,h)
XWINDOW *w ;
Xchar v,h ;
X{
X	WORD i ;
X	
X	ERR = 0 ;
X	OK = 1 ;
X	for ( i = 0 ; i <= w->_maxy ; i++ )
X		{
X		mvwaddch(w,i,0,v) ;
X		mvwaddch(w,i,w->_maxx,v) ;
X		} ;
X	for ( i = 1 ; i < w->_maxx ; i++ )
X		{
X		mvwaddch(w,0,i,h) ;
X		mvwaddch(w,w->_maxy,i,h) ;
X		} ;
X}
X/* #]box:																	*/
X/* #[wclear: clear a window													*/
Xwclear(w)
XWINDOW *w ;
X{
X	ERR = 0 ;
X	OK = 1 ;
X	werase(w) ;
X	clearok(w,TRUE) ;
X	w->_curx = 0 ;
X	w->_cury = 0 ;
X}
X/* #]wclear:																*/
X/* #[wclrtobo: clear a window to the bottom									*/
Xwclrtobot(w)
XWINDOW *w ;
X{
X	WORD i,j ;
X
X	ERR = 0 ;
X	OK = 1 ;
X	for ( i = w->_curx ; i <= w->_maxx ; i++ )
X		w->_y[w->_cury][i] = ' ' | TOUCHED ;
X	for ( i = w->_cury + 1 ; i <= w->_maxy ; i++ )
X		{
X		for ( j = 0 ; j <= w->_maxx ; j++ )
X			w->_y[i][j] = ' ' | TOUCHED ;
X		} ;
X	if ( w == curscr )
X		{
X		Bconout(2,'\033') ;
X		Bconout(2,'J') ;
X		}
X	else
X		{
X		if ( w->_firstch == 0 )
X			{
X			w->_firstch = &(w->_y[w->_cury][w->_curx]) ;
X			w->_lastch = &(w->_y[w->_maxy][w->_maxx]) ;
X			}
X		else
X			{
X			if ( w->_firstch > &(w->_y[w->_cury][w->_curx]) )
X				w->_firstch = &(w->_y[w->_cury][w->_curx]) ;
X			w->_lastch = &(w->_y[w->_maxy][w->_maxx]) ;
X			} ;
X		} ;
X}
X/* #]wclrtobo:																*/
X/* #[wclrtoeo: clear a window to the end of the line						*/
Xwclrtoeol(w)
XWINDOW *w ;
X{
X	WORD i ;
X
X	ERR = 0 ;
X	OK = 1 ;
X	for ( i = w->_curx ; i <= w->_maxx ; i++ )
X		w->_y[w->_cury][i] = ' ' | TOUCHED ;
X	if ( w == curscr )
X		{
X		Bconout(2,'\033') ;
X		Bconout(2,'K') ;
X		}
X	else
X		{
X		if ( w->_firstch == 0 )
X			{
X			w->_firstch = &(w->_y[w->_cury][w->_curx]) ;
X			w->_lastch = &(w->_y[w->_cury][w->_maxx]) ;
X			}
X		else
X			{
X			if ( w->_firstch > &(w->_y[w->_cury][w->_curx]) )
X				w->_firstch = &(w->_y[w->_cury][w->_curx]) ;
X			if ( w->_lastch < &(w->_y[w->_cury][w->_maxx]) )
X				w->_lastch = &(w->_y[w->_cury][w->_maxx]) ;
X			} ;
X		} ;
X}
X/* #]wclrtoeo:																*/
X/* #[wdelch: delete a character on a window									*/
Xwdelch(w)
XWINDOW *w ;
X{
X	WORD ox, oy, i ;
X	
X	ERR = 0 ;
X	OK = 1 ;
X	ox = w->_curx ;
X	oy = w->_cury ;
X	for ( i = ox + 1 ; i <= w->_maxx ; i++ )
X		{
X		w->_y[oy][i-1] = w->_y[oy][i] | TOUCHED ;
X		} ;
X	w->_y[oy][w->_maxx] = ' ' | TOUCHED ;
X	w->_curx = ox ;
X	w->_cury = oy ;
X	if ( w == curscr )
X		{
X		Bconout(2,'\033') ;
X		Bconout(2,'K') ;
X		for ( i = w->_curx ; i <= w->_maxx ; i++ )
X			{
X			Bconout(5,(w->_y[w->_cury][i] & 0xff )) ;
X			_csrx++ ;
X			} ;
X		_movcur(w->_cury,w->_curx) ;
X		}
X	else
X		{
X		if ( w->_firstch == 0 )
X			{
X			w->_firstch = &(w->_y[w->_cury][w->_curx]) ;
X			w->_lastch = &(w->_y[w->_cury][w->_maxx]) ;
X			}
X		else
X			{
X			if ( w->_firstch > &(w->_y[w->_cury][w->_curx]) )
X				w->_firstch = w->_y[w->_cury] ;
X			if ( w->_lastch < &(w->_y[w->_cury][w->_maxx]) )
X				w->_lastch = &(w->_y[w->_cury][w->_maxx]) ;
X			} ;
X		} ;
X}
X/* #]wdelch:																*/
X/* #[wdeletel: delete a line from a window									*/
Xwdeleteln(w)
XWINDOW *w ;
X{
X	WORD i,j ;
X	
X	ERR = 0 ;
X	OK = 1 ;
X	for ( i = w->_cury + 1 ; i <= w->_maxy ; i++ )
X		{
X		for ( j = 0 ; j <= w->_maxx ; j++ )
X			w->_y[i-1][j] = w->_y[i][j] | TOUCHED ;
X		} ;
X	for ( j = 0 ; j <= w->_maxx ; j++ )
X		w->_y[w->_maxy][j] = ' ' | TOUCHED ;
X	if ( w == curscr )
X		{
X		Bconout(2,'\033') ;
X		Bconout(2,'M') ;
X		_csrx = 0 ;
X		_movcur(w->_cury,w->_curx) ;
X		}
X	else
X		{
X		if ( w->_firstch == 0 )
X			{
X			w->_firstch = w->_y[w->_cury] ;
X			w->_lastch = &(w->_y[w->_maxy][w->_maxx]) ;
X			}
X		else
X			{
X			if ( w->_firstch > w->_y[w->_cury] )
X				w->_firstch = w->_y[w->_cury] ;
X			w->_lastch = &(w->_y[w->_maxy][w->_maxx]) ;
X			} ;
X		} ;
X}
X/* #]wdeletel:	 															*/
X/* #[werase: erase a window													*/
Xwerase(w)
XWINDOW *w ;
X{
X	WORD i,j ;
X	
X	ERR = 0 ;
X	OK = 1 ;
X	for ( i = 0 ; i <= w->_maxy ; i++ )
X		{
X		for ( j = 0 ; j <= w->_maxx ; j++ )
X			w->_y[i][j] = ' ' | TOUCHED ;
X		} ;
X	if ( w == curscr )
X		{
X		Bconout(2,'\033') ;
X		Bconout(2,'E') ;
X		_csry = 0 ;
X		_csrx = 0 ;
X		_movcur(curscr->_cury,curscr->_curx) ;
X		}
X	else
X		{
X		w->_firstch = w->_y[0] ;
X		w->_lastch = &(w->_y[w->_maxy][w->_maxx]) ;
X		} ;
X}
X/* #]werase:																*/
X/* #[winsch: insert a character												*/
Xwinsch(w,c)
XWINDOW *w ;
Xchar c ;
X{
X	WORD ox,oy,i ;
X	BYTE tstr[2] ;
X	
X	ERR = 0 ;
X	OK = 1 ;
X	ox = w->_curx ;
X	oy = w->_cury ;
X	for ( i = w->_maxx - 1 ; i >= ox ; --i )
X		{
X		w->_y[oy][i+1] = w->_y[oy][i] | TOUCHED ;
X		} ;
X	if ( w == curscr )
X		{
X		Bconout(2,'\033') ;
X		Bconout(2,'K') ;
X		for ( i = w->_curx ; i <= w->_maxx ; i++ )
X			{
X			Bconout(5,(w->_y[w->_cury][i] & 0xff )) ;
X			_csrx++ ;
X			} ;
X		_movcur(w->_cury,w->_curx) ;
X		}		
X	else
X		{
X		if ( w->_firstch == 0 )
X			{
X			w->_firstch = &(w->_y[w->_cury][w->_curx]) ;
X			w->_lastch = &(w->_y[w->_cury][w->_maxx]) ;
X			}
X		else
X			{
X			if ( w->_firstch > &(w->_y[w->_cury][w->_curx]) )
X				w->_firstch = &(w->_y[w->_cury][w->_curx]) ;
X			if ( w->_lastch < &(w->_y[w->_cury][w->_maxx]) )
X				w->_lastch = &(w->_y[w->_cury][w->_maxx]) ;
X			} ;
X		} ;
X	mvwaddch(w,oy,ox,c) ;
X}
X/* #]winsch:																*/
X/* #[winsertl: insert a line in a window									*/
Xwinsertln(w)
XWINDOW *w ;
X{
X	WORD ox,oy,i,j ;
X	
X	ERR = 0 ;
X	OK = 1 ;
X	for ( i = w->_maxy - 1 ; i >= w->_cury ; --i )
X		{
X		for ( j = 0 ; j <= w->_maxx ; j++ )
X			w->_y[i+1][j] = w->_y[i][j] | TOUCHED ;
X		} ;
X	for ( j = 0 ; j <= w->_maxx ; j++ )
X		w->_y[w->_cury][j] = ' ' | TOUCHED ;
X	if ( w == curscr )
X		{
X		Bconout(2,'\033') ;
X		Bconout(2,'L') ;
X		_csrx = 0 ;
X		_movcur(w->_cury,w->_curx) ;
X		}
X	else
X		{
X		if ( w->_firstch == 0 )
X			w->_firstch = w->_y[w->_cury] ;
X		else
X			{
X			if ( w->_firstch > w->_y[w->_cury] )
X				w->_firstch = w->_y[w->_cury] ;
X			} ;
X		w->_lastch = &(w->_y[w->_maxy][w->_maxx]) ;
X		} ;
X}
X/* #]winsertl:																*/
X/* #[wmove: move the cursor of the window to a location						*/
Xwmove(w,y,x)
XWINDOW *w ;
Xint y,x ;
X{
X	WORD i ;
X
X	ERR = 0 ;
X	OK = 1 ;
X	if ( x < 0 )
X		{
X		w->_curx = 0 ;
X		ERR = 1 ;
X		OK = 0 ;
X		}
X	else
X		{
X		if ( x > w->_maxx )
X			{
X			w->_curx = w->_maxx ;
X			ERR = 1 ;
X			OK = 0 ;
X			}
X		else
X			w->_curx = x ;
X		} ;
X	if ( y < 0 )
X		{
X		w->_cury = 0 ;
X		ERR = 1 ;
X		OK = 0 ;
X		}
X	else
X		{
X		if ( y > w->_maxy )
X			{
X			if ( w->_scroll )
X				{
X				for ( i = w->_maxy ; i < y ; i++ )
X					scroll(w) ;
X				} ;
X			w->_cury = w->_maxy ;
X			ERR = 1 ;
X			OK = 0 ;
X			}
X		else
X			w->_cury = y ;
X		} ;
X	if ( w == curscr )
X		{
X		_movcur(curscr->_cury,curscr->_curx) ;
X		} ;
X}
X/* #]wmove:																	*/	
X/* #[woverlay: overlay two windows.											*/
Xwoverlay(v,w)
XWINDOW *v, *w ;
X{
X	WORD i, j ;
X	
X	for ( i = 0 ; i <= w->_maxy && i <= v->_maxy ; i++ )
X		{
X		for ( j = 0 ; j <= w->_maxx && j <= v->_maxx ; j++ )
X			{
X			if ( ( v->_y[i][j] & 0xff ) == 0x20 )
X				w->_y[i][j] = v->_y[i][j] | TOUCHED ;
X			} ;
X		} ;
X	if ( w == curscr )
X		wrefresh(curscr) ;
X	else
X		{
X		w->_firstch = w->_y[0] ;
X		w->_lastch = &(w->_y[w->_maxy][w->_maxx]) ;
X		} ;
X}
X/* #]woverlay:																*/
X/* #[overwrit: overwrite two windows.										*/
Xoverwrite(v,w)
XWINDOW *v, *w ;
X{
X	WORD i, j ;
X	
X	for ( i = 0 ; i <= w->_maxy && i <= v->_maxy ; i++ )
X		{
X		for ( j = 0 ; j <= w->_maxx && j <= v->_maxx ; j++ )
X			{
X			w->_y[i][j] = v->_y[i][j] | TOUCHED ;
X			} ;
X		} ;
X	if ( w == curscr )
X		wrefresh(curscr) ;
X	else
X		{
X		w->_firstch = w->_y[0] ;
X		w->_lastch = &(w->_y[w->_maxy][w->_maxx]) ;
X		} ;
X}
X/* #]overwrit:																*/
X/* #[wstandou: set the standout flag for a window							*/
Xwstandout(w)
XWINDOW *w ;
X{
X	w->_flags = w->_flags | _STANDOUT ;
X	ERR = 0 ;
X	OK = 1 ;
X}
X/* #]wstandou:																*/
X/* #[wstanden: end standout mode											*/
Xwstandend(w)
XWINDOW *w ;
X{
X	w->_flags = w->_flags & ( ~_STANDOUT) ;
X	ERR = 0 ;
X	OK = 1 ;
X}
X/* #]wstanden:																*/
X/* #]output:																*/
X/* #[input:	input functions													*/
X/* #[raw: set terminal in raw mode											*/
Xraw()
X{
X/*
X * raw mode means : 
X * when getting a character from the keyboard, return everything
X * including keyboard shift state.
X */
X  int	__sshft() ;
X  
X  if ( _modinp == RAW )
X  	return ;
X  Supexec(__sshft) ;
X  _modinp = RAW ;
X}
X/* #]raw:																	*/
X/* #[noraw: reset terminal from raw mode into cooked mode					*/
Xnoraw()
X{
X	int __ushft() ;
X	if ( _modinp != RAW )
X		return ;
X	Supexec(__ushft) ;
X	_modinp = COOKED ;
X}
X/* #]noraw:																	*/
X/* #[__sshft: set terminal to return keyboard shift state					*/
X/* execute in supervisor mode only											*/
X__sshft()
X{
X	int ov, nv ;
X	
X	ov = CONTERM ;
X	nv = ov | 0x08 ;
X	CONTERM = nv ;
X}
X/* #]__sshft:																*/
X/* #[__ushft: set terminal to not return keyboard shift state				*/
X/* execute in supervisor mode only											*/
X__ushft()
X{
X	int ov, nv ;
X	
X	ov = CONTERM ;
X	nv = ov & ~0x08 ;
X	CONTERM = nv ;
X}
X/* #]__ushft:																*/
X/* #[crmode: set terminal in cbreak mode									*/
X/*
X * cbreak mode means for the atari ;
X * return both keyboard scan code as well as the character value.
X * kill the process with a process terminate -1 as soons as a control C is met
X * control D is also recognized to be the EOF.
X */
Xcrmode()
X{
X	if ( _modinp == CBREAK )
X		return ;
X	if ( _modinp == RAW )
X		noraw() ;
X	_modinp = CBREAK ;
X}
X/* #]crmode:																*/
X/* #[nocrmode: reset terminal from cbreak into cooked mode					*/		
Xnocrmode()
X{
X	if ( _modinp != CBREAK )
X		return ;
X	_modinp = COOKED ;
X}
X/* #]nocrmode:																*/
X/* #[echo: set curses to echo characters on input							*/
Xecho()
X{
X	_doecho = TRUE ;
X	ERR = 0 ;
X	OK = 1 ;
X}
X/* #]echo:																	*/
X/* #[noecho: set curses not to echo characters on input						*/
Xnoecho()
X{
X	_doecho = FALSE ;
X	ERR = 0 ;
X	OK = 1 ;
X}
X/* #]noecho:																*/
X/* #[wgetch: get a character from the terminal								*/
X/* WARNING : wgetch returns a 32-bit value, not a char although only		*/
X/* the lowest 8 bits may actually be transmitted.							*/
Xwgetch(w)
XWINDOW *w ;
X{
X	bool reset ;
X	LONG	retval ;
X
X	reset = FALSE ;
X	if ( _modinp == COOKED && _doecho == TRUE )
X		{
X		reset = TRUE ;
X		crmode() ;
X		} ;
X	Bconout(2,'\033') ;
X	Bconout(2,'e') ;
X	switch ( _modinp )
X		{
X		case COOKED:
X			while ( !Cconis() ) ;
X			retval = Cnecin() ;
X			retval = retval & 0x00ff ;
X/* kill process on control C												*/
X			if ( retval == 0x03 )
X				Pterm(-1L) ;
X			break ;
X		case CBREAK:
X			while ( !Cconis() ) ;
X			retval = Cnecin() ;
X/* kill process on control C												*/
X			if ( ( retval & 0x00ff ) == 0x03 )
X				Pterm(-1L) ;
X			break ;
X		case RAW:
X			while ( !Cconis() ) ;
X			retval = Crawcin() ;
X			break ;
X		} ;
X	Bconout(2,'\033') ;
X	Bconout(2,'f') ;
X	if ( _doecho )
X		waddch(w,(char ) ( 0x00ff & retval )) ;
X	if ( reset )
X		nocrmode() ;
X	return(retval) ;
X}
X/* #]wgetch:																*/
X/* #[wgetstr: get a string from the terminal								*/
Xwgetstr(w,s)
XWINDOW *w ;
Xchar *s ;
X{
X	WORD ox, oy ;
X	bool reset, end ;
X	char c ;
X	int i ;
X	LONG wgetch() ;
X	
X	reset = FALSE ;
X	getyx(w,oy,ox) ;
X	if ( _modinp == COOKED && _doecho == TRUE )
X		{
X		reset = TRUE ;
X		_doecho = FALSE ;
X		} ;
X	i = 0 ;
X	for ( end = FALSE ; !end ; i++ )
X		{ 
X		wrefresh(w);
X		switch ( _modinp )
X			{
X			case COOKED:
X				c = ( char ) wgetch(w) ;
X				if ( c == 0x0d || c == 0x0a || c == 0x04 || c == 0 )
X					{
X					s[i] = '\0' ;
X					end = TRUE ;
X					break ;
X					} ;
X/* receive a backspace */
X				if ( c == 0x08 ) {
X					if ( i != 0 )
X						{
X						--i ;
X						s[i] = 0 ;
X						if ( reset ) {
X							int	x, y;
X							getyx(w, y, x);
X							mvwaddch(w,y,x-1,' ');
X							wmove(w, y, x-1);
X/*
X							mvwaddstr(w,oy,ox,s) ;
X*/
X						}
X					}
X					i--;
X					break;
X				}
X/* receive control U or line kill 											*/
X				if ( c == 0x13 )
X					{
X					i = 0 ;
X					if ( reset )
X						wmove(w,oy,ox) ;
X					break ;
X					} ;
X				s[i] = c ;
X				if (reset)
X					waddch(w,c) ;
X				break ;
X			case CBREAK:
X				c = ( char ) wgetch(w) ;
X				if ( c == 0x0d || c == 0x0a || c == 0x04 || c == 0 )
X					{
X					s[i] = '\0' ;
X					end = TRUE ;
X					break ;
X					} ;
X				s[i] = c ;
X				break ;
X			case RAW:
X				c = ( char ) wgetch(w) ;
X				if ( c == 0x0d || c == 0x0a || c == 0x04 || c == 0 )
X					{
X					s[i] = '\0' ;
X					end = TRUE ;
X					break ;
X					} ;
X				s[i] = c ;
X				break ;
X			} ;
X		} ;
X	if ( reset )
X		_doecho = TRUE ;
X}
X/* #]wgetstr:																*/
X/* #]input: 																*/
X/* #[wrefresh: refresh a window on the screen								*/
Xwrefresh(w)
XWINDOW *w ;
X{
X	WORD i,j,k,l ;
X	WORD c, *ptr ;
X	
X	ERR = 0 ;
X	OK = 1 ;
X	if ( w != curscr && curscr->_clear )
X		{
X		Bconout(2,'\033') ;
X		Bconout(2,'E') ;
X		_csry = 0 ;
X		_csrx = 0 ;
X		for ( i = 0 ; i < LINES ; i++ )
X			{
X			for ( j = 0 ; j < COLS ; j++ )
X				curscr->_y[i][j] = ' ' ;
X			} ;
X		curscr->_clear = 0 ;
X		} ;
X	if ( w->_clear )
X		{
X		if ( ( w->_flags & _FULLWIN ) )
X			{
X			Bconout(2,'\033') ;
X			Bconout(2,'E') ;
X			_csry = 0 ;
X			_csrx = 0 ;
X			for ( i = 0 ; i < LINES ; i++ )
X				{
X				for ( j = 0 ; j < COLS ; j++ )
X					curscr->_y[i][j] = ' ' ;
X				} ;
X			} ;
X		w->_firstch = w->_y[0] ;
X		w->_lastch = &(w->_y[w->_maxy][w->_maxx]) ;
X		w->_clear = 0 ;
X		} ;
X	if ( w != curscr )
X		{
X		if ( w->_firstch != 0 )
X			{
X			if ( w->_flags & _SUBWIN )
X				{
X				for ( i = 0 ; i <= w->_maxy ; i++ )
X					{
X					ptr = w->_y[i] ;
X					if ( ptr >= w->_firstch && ptr <= w->_lastch )
X						{
X						for ( j = 0 ; j <= w->_maxx ; j++ )
X							{
X							c = ptr[j] ;
X							k = i + w->_begy ;
X							l = j + w->_begx ;
X							if ( ( c & TOUCHED ) && ( k >= 0 && k < LINES && l >= 0 && l < COLS ) )
X								{
X								ptr[j] = c & ~TOUCHED ;
X								if ( ( curscr->_y[k][l] & 0x01ff ) != ( c & 0x01ff ) )
X									{
X									curscr->_y[k][l] = c ;
X									_movcur(k,l) ;
X									if ( ( c & STANDOUT ) )
X										{
X										Bconout(2,'\033') ;
X										Bconout(2,'p') ;
X										Bconout(5,(c & 0xff)) ;
X										Bconout(2,'\033') ;
X										Bconout(2,'q') ;
X										}
X									else
X										{
X										Bconout(5,( c & 0xff )) ;
X										} ;
X									_csry = k ;
X									_csrx = l + 1 ;
X									} ;
X								} ;
X							} ;
X						} ;
X					} ;
X				}
X			else
X				{
X				for ( ptr = w->_firstch ; ptr <= w->_lastch ; ptr++ )
X					{
X					c = *ptr ;
X					if ( c & TOUCHED )
X						{
X						k = ( WORD ) ( ptr - w->_y[0] ) ;
X						k = k / (  w->_maxx + 1 ) ;
X						l = ( WORD ) ( ptr - w->_y[k] ) + w->_begx ;
X						k = k + w->_begy ;
X						if ( k >= 0 && k < LINES && l >= 0 && l < COLS ) 
X							{
X							*ptr = c & ~TOUCHED ;
X							if ( ( curscr->_y[k][l] & 0x01ff ) != ( c & 0x01ff ) )
X								{
X								curscr->_y[k][l] = c ;
X								_movcur(k,l) ;
X								if ( ( c & STANDOUT ) )
X									{
X									Bconout(2,'\033') ;
X									Bconout(2,'p') ;
X									Bconout(5,(c & 0xff)) ;
X									Bconout(2,'\033') ;
X									Bconout(2,'q') ;
X									}
X								else
X									{
X									Bconout(5,( c & 0xff )) ;
X									} ;
X								_csry = k ;
X								_csrx = l + 1 ;
X								} ;
X							} ;
X						} ;
X					} ;
X				} ;
X			w->_firstch = 0 ;
X			w->_lastch = 0 ;
X			if ( w->_leave )
X				{
X				w->_curx = _csrx - w->_begx ;
X				w->_cury = _csry - w->_begy ;
X				curscr->_cury = _csry ;
X				curscr->_curx = _csrx ;
X				}
X			else
X				{
X				curscr->_cury = w->_cury + w->_begy ;
X				curscr->_curx = w->_curx + w->_begx ;
X				_movcur(curscr->_cury, curscr->_curx) ;
X				} ;
X			}
X		else
X			{
X			curscr->_cury = w->_cury + w->_begy ;
X			curscr->_curx = w->_curx + w->_begx ;
X			_movcur(curscr->_cury, curscr->_curx) ;
X			} ;
X		}
X	else
X		{
X		Bconout(2,'\033') ;
X		Bconout(2,'H') ;
X		_csry = 0 ;
X		_csrx = 0 ;
X		for ( i = 0 ; i < LINES ; i++ )
X			{
X			for ( j = 0 ; j < COLS ; j++ )
X				{
X				c = w->_y[i][j] ;
X				if ( ( c & STANDOUT ) )
X					{
X					Bconout(2,'\033') ;
X					Bconout(2,'p') ;
X					Bconout(5,(c & 0xff)) ;
X					Bconout(2,'\033') ;
X					Bconout(2,'q') ;
X					}
X				else
X					{
X					Bconout(5,(c & 0xff)) ;
X					} ;
X				_csrx++ ;
X				} ;
X			_movcur(i+1,0) ;
X			} ;
X		_movcur( curscr->_cury, curscr->_curx) ; 
X		} ;
X}
X/* #]wrefresh:																*/
X/* #[detail: detail functions of curses										*/
X/* #[mvcur: move cursor in standard curses manner							*/
Xmvcur(ly,lx,ny,nx)
Xint ly,lx,ny,nx ;
X{
X	_movcur((WORD) ny,( WORD) nx) ;
X}
X/* #]mvcur:																	*/
X/* #[_movcur: move cursor													*/
X_movcur(y,x)
XWORD y,x ;
X{
X	if ( _csry == y && _csrx == x )
X		return ;
X	Bconout(2,'\033') ;
X	Bconout(2,'Y') ;
X	Bconout(2,y+' ') ;
X	Bconout(2,x+' ') ;
X	_csry = y ;
X	_csrx = x ;
X}
X/* #]_movcur:																*/
X/* #[scroll: scroll a window upward one line								*/
Xscroll(w)
XWINDOW *w ;
X{
X	WORD i,j ;
X	
X	ERR = 0 ;
X	OK = 1 ;
X	for ( i = 0 ; i < w->_maxy ; i++ )
X		for ( j = 0 ; j <= w->_maxx ; j++ )
X			w->_y[i][j] = w->_y[i+1][j] ;
X	for ( i = 0 ; i <= w->_maxx ; i++ )
X		w->_y[w->_maxy][i] = ' ' ;
X	if ( w == curscr )
X		wrefresh(curscr) ;
X	else
X		{
X		w->_firstch = w->_y[0] ;
X		w->_lastch = &(w->_y[w->_maxy][w->_maxx]) ;
X		} ;
X}
X/* #]scroll:																*/
X/* #]detail:																*/
X/* #]curses:																*/
X
X/*
X * Extra stuff added - tony
X */
X
Xprintw(format, a1, a2, a3, a4, a5, a6, a7, a8, a9)
Xchar	*format;
Xint	a1, a2, a3, a4, a5, a6, a7, a8, a9;
X{
X	char	lbuf[256];
X
X	sprintf(lbuf, format, a1, a2, a3, a4, a5, a6, a7, a8, a9);
X	addstr(lbuf);
X}
X
Xscanw(format, a1, a2, a3, a4, a5, a6, a7, a8, a9)
Xchar	*format;
Xint	a1, a2, a3, a4, a5, a6, a7, a8, a9;
X{
X	char	lbuf[256];
X
X	echo();
X	getstr(lbuf);
X	sscanf(lbuf, format, a1, a2, a3, a4, a5, a6, a7, a8, a9);
X}
SHAR_EOF
chmod 0640 curses.c || echo "restore of curses.c fails"
sed 's/^X//' << 'SHAR_EOF' > curses.doc &&
X           The CURSES screen updating and cursor movement package.
X
X          A collection of C-functions for Atari ST-series computers
X
X                               Version 1.0
X
X
X                             R. van 't Veen 
X
X
X
X
X    This document describes a set of C-functions which allow the user
Xeasier design of full-screen applications. This package is intended for
Xprograms that perform graphics-like operations on terminal screens.
XIt is largely compatible with the UN*X curses(3x) package. This document
Xprovides pointers to its use, a little detail about its inner workings and it
Xstresses differences between the UN*X-implementation and the Atari-ST series
Ximplementation.
X
X
X
X
X
X
X   Introduction.
X   
X   This package was born out of my desire to make more programs available for
XUN*X also available on my Atari. A side-effect of this is that it provides
Xeasier screen updating than by means of sending escape codes. The package is
Xalso quite fast, timing of a sample application yielded a rate of about
X90 kilobaud per second.
X
X   Terminology.
X   
X   Throughout this document  the following words will be used frequently :
X
XWINDOW       An internal representation of what a section of the terminal
X       screen may eventually look like. A window is a rectangular
X             array, which may be as big as the terminal screen or even as 
X             small as a single character.
X
XTERMINAL     Or terminal screen, the packages idea of what the Atari's VT52
X     emulation looks like. If everything is allright this is what you
X             see. The terminal screen is a special screen.
X
XSCREEN       A screen is an element of the set of windows that are as large as 
X       the terminal screen. One screen, called stdscr, is already
X             provided for.
X
X   Using the package.
X   
X   To use the package, include the file "curses.h" in your source. This gives
Xyou the types and definitions necessary to be able to use it. After compilation
Xone should link with the file containing the compiled curses-source, as well as
Xwith the object-file or library giving you access to the system calls,
Xgemdos, bios and xbios. You also should link in a file giving you access
Xto the malloc() and free() calls. ( Note : this is not the GEMDOS Malloc/Mfree
Xpair, but a malloc() and free(), which should be contained in any decent
Xstandard C-function library. GEMDOS Malloc/Mfree are very buggy indeed.)
XThere is a difference with UN*X here : the UN*X-curses includes stdio.h
Xand sgtty.h, whereas Atari-curses includes portab.h and stdio.h. This should
Xgive you the definitions for BYTE, WORD and LONG. 
X Some compilers supply default startup files that don't supply enough heap space
Xto run curses in, you should adapt these startup files to your liking.
X
X   Installing the package.
X   
X   Compile the file "curses.c" with your favorite C-compiler, to create an
Xobject-file or library, whatever you prefer. Curses.c includes "portab.h"
Xfor BYTE, WORD, LONG, and NULL definitions, osbind.h for system-call macros
Xand curses.h for its own definitions. Remember curses.h also includes stdio.h.
XThe code should be portable between various brands of compilers. Forget about
Xwarnings like : warning : pointer substraction yields a long result. 
XNot all compilers adhere to Kernighan and Ritchie standards in this respect.
XThe meaning of each of the constants is given in the table below. In another
Xtable the used system call macro's are given.
X
X+---------------+----------------------------------------------------+
X| constant name | meaning                                            |
X+===============+====================================================+
X| BYTE          | a type with at least 8 bits in it, usually a char  |
X| WORD          | a type with at least 16 bits in it                 |
X| LONG          | a type with at least 32 bits, used for pointers    |
X| NULL          | a value assigned to pointers pointing nowhere      |
X+---------------+----------------------------------------------------+
X
X+---------------+-----------------------------------------------------+
X| macro name    | meaning                                             |
X+===============+=====================================================+
X| Pterm         | gemdos $4c, terminate process and return to caller  |
X| Cconis        | gemdos $0b, console character available ?           |
X| Crawcin       | gemdos $07, get a raw character from console        |
X| Cnecin        | gemdos $08, get a not-so raw character from console |
X| Bconout       | bios $03, output a character to a device            |
X| Bconstat      | bios $01, get input device status                   |
X| Bconin        | bios $02, input a character from a device           |
X| Supexec       | xbios $26, execute function in supervisor mode      |
X+---------------+-----------------------------------------------------+
X
X   Screen updating.
X   
X   The package defines a data type called WINDOW, which represents what a
Xsection of the terminal may eventually look like. It can be used as a
Xscratch-pad onto which you can make changes. Only after calling
Xthe function refresh() or wrefresh() an attempt will be made by the package
Xto make things on the screen look like the things you specified in the
Xwindow. Information contained in the window include not only its contents,
Xbut also its size, its starting point and various other information. Two
Xstandard window are defined after initialization of the package, namely
Xcurscr, which constitutes the package's idea of what the screen looks like,
Xand stdscr, which is a default window to make changes on. It is advised not
Xto address curscr directly, but first to make changes on another window and
Xthen to call refresh() or wrefresh() to make curscr look like the other
Xwindow. Making a change on curscr results in immediate execution of the
Xchange, this greatly reduces any chances of optimization and therefore results
Xin a sizeable loss of speed ( unless you know what you're doing, of course ).
X
X   Naming conventions.
X   
X   All output and input functions can be used with any window. These functions
Xhave two variants, one to act on the default screen stdscr, and another to
Xact on any window. An example is the function addch(), which adds a character
Xto stdscr. The variant, which adds a character to a window w is called
Xwaddch() and takes w as an argument. This convention is used throughout the
Xpackage. The routines which do not adhere to this convention always take a 
Xwindow as an argument.
X   Apart from the w-convention some functions also take a mv- prefix.
XOrdinarily one moves the current coordinates of a window by calling
Xthe move or wmove function. Preceding an I/O function by mv first moves
Xthe current coordinates and then performs the I/O function. In this way
Xone can write the sequence :
X
Xmove(y,x) ;
Xaddch('Q') ;
X
Xas :
X
Xmvaddch(y,x,'Q') ;
X
Xand the sequence :
X
Xwmove(win,y,x) ;
Xwaddch(win,'W') ;
X
Xmay be replaced by :
X
Xmvwaddch(win,y,x,'W') ;
X
XYou may have noticed the following other conventions :
X1. If a window must be specified as a parameter, it is always the first
X   parameter.
X2. Coordinates are specified as (y,x) pairs, where y is in the up/down
X   direction, and x in the letf/right direction, the coordinate (0,0) is
X   in the upper-left corner of the window.
X
X
X   Programming with curses.
X   
X   The following sections deal with programming with the library.
XFirst of all curses should be initialized first. This is done by a call to
Xinitscr(). On return curses will have initialized the screen to a state known
Xby curses, and have initialized curscr and stdscr, whereas prior to the
Xinitscr() call, any reference to curscr or stdscr will result in bombs.
XAfter calling initscr() you should perform any terminal status changing
Xroutines like crmode() or nonl(), although these may be performed anytime
Xwhen curses is active. After that you can set up the screen status using
Xfunctions like leaveok() and scrollok() or allocate new windows with newwin()
Xor subwin(), delete them with delwin(). 
X   Calling initscr() again will either result in a redraw of the screen or
Xanother initialization step when the variables LINES or COLS have changed.
XThis enables you to set the screen size by hand, because normally
Xthe variables LINES and COLS contain the true size of the terminal. Calling
Xinitscr ni such a way again, results in the deletion and regeneration of
Xcurscr and stdscr.
X   The basic functions that allow you to change the contents of a window
Xare addch() and move(). Addch() adds a character to a window and move() moves
Xthe current coordinates. Other output functions exist to let you do some
Xmore elaborate things, like addstr() to add an entire string, insertln() to
Xinsert a line etc.. When you have composed the contents of the window to your
Xliking you can call refresh() to make the portion of the terminal screen
Xoverlapped by the window look like the window. When updating one must keep
Xin mind that refresh assumes that parts of the window not changed since the
Xlast update of the window are also not changed on the terminal. Use the
Xtouchwin() function to let curses think the entire window has changed when
Xusing overlapping windows.
X   Calling wrefresh() with curscr as an argument results in a complete redraw
Xof the terminal screen. Because curses has to know what the contents of the
Xphysical screen is at all times, you should not do any other screen output,
Xthan by curses alone. Or if you really have to, do a redraw afterwards. If
Xyou don't, you're bound to end up with some very confused screens.
X   Input is done by the getch() function, which inputs a character from the
SHAR_EOF
echo "End of part 1, continue with part 2"
echo "2" > s2_seq_.tmp
exit 0