[alt.sources] STDWIN 0.9.5, Part 12/19

guido@cwi.nl (Guido van Rossum) (03/04/91)

Archive-name: stdwin/part12

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 12 (of 19)."
# Contents:  Appls/bed/opmenu.c Appls/miniedit/miniedit.c
#   Appls/repeat/repeat.c Appls/test/faced.c Doc/man/textedit.man
#   Doc/man/vt.man Ports/alfa/bind.c
# Wrapped by guido@voorn.cwi.nl on Mon Mar  4 12:37:30 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'Appls/bed/opmenu.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Appls/bed/opmenu.c'\"
else
echo shar: Extracting \"'Appls/bed/opmenu.c'\" \(7521 characters\)
sed "s/^X//" >'Appls/bed/opmenu.c' <<'END_OF_FILE'
X#include "bed.h"
X#include "menu.h"
X
Xextern int	sqrsize ;
X
Xextern int	map_width ;
Xextern int	map_height ;
X
Xextern char	*raster ;
Xextern int	raster_lenght ;
Xextern int	stride ;
X
Xstatic int	bits[] = { 0xFF, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F } ;
Xextern int	lastbyte ;
X
Xextern WINDOW	*win ;
X
Xextern bool	changed ;
X
Xextern bool	selrect ;
Xextern int	sr_left ;
Xextern int	sr_top ;
Xextern int	sr_right ;
Xextern int	sr_bottom ;
X
X/* Data manipulation routines */
X
Xvoid
Xclear_bits()
X{
X	register int	row ;
X
X	if (!selrect) {
X		sr_left = sr_top = 0 ;
X		sr_right = map_width ;
X		sr_bottom = map_height ;
X	}
X
X	for (row = sr_top ; row < sr_bottom ; ++row) {
X		register int	col = sr_left ;
X		register char	*byte = raster + (row * stride) + (col / 8) ;
X		register int	pbit = col % 8 ;
X
X		while (col++ < sr_right) {
X			*byte &= ~(1 << pbit) ;
X
X			if (++pbit >= 8) {
X				pbit = 0 ;
X				++byte ;
X			}
X		}
X	}
X
X	wchange (win, sr_left * sqrsize, sr_top * sqrsize,
X		sr_right * sqrsize, sr_bottom * sqrsize) ;
X
X	changed = TRUE ;
X}
X
Xvoid
Xset_bits()
X{
X	register int	row ;
X
X	if (!selrect) {
X		sr_left = sr_top = 0 ;
X		sr_right = map_width ;
X		sr_bottom = map_height ;
X	}
X
X	for (row = sr_top ; row < sr_bottom ; ++row) {
X		register int	col = sr_left ;
X		register char	*byte = raster + (row * stride) + (col / 8) ;
X		register int	pbit = col % 8 ;
X
X		while (col++ < sr_right) {
X			*byte |= (1 << pbit) ;
X
X			if (++pbit >= 8) {
X				pbit = 0 ;
X				++byte ;
X			}
X		}
X	}
X
X	wchange (win, sr_left * sqrsize, sr_top * sqrsize,
X		sr_right * sqrsize, sr_bottom * sqrsize) ;
X
X	changed = TRUE ;
X}
X
Xvoid
Xinvert_bits()
X{
X	register int	row ;
X
X	if (!selrect) {
X		sr_left = sr_top = 0 ;
X		sr_right = map_width ;
X		sr_bottom = map_height ;
X	}
X
X	for (row = sr_top ; row < sr_bottom ; ++row) {
X		register int	col = sr_left ;
X		register char	*byte = raster + (row * stride) + (col / 8) ;
X		register int	pbit = col % 8 ;
X
X		while (col++ < sr_right) {
X			*byte ^= (1 << pbit) ;
X
X			if (++pbit >= 8) {
X				pbit = 0 ;
X				++byte ;
X			}
X		}
X	}
X
X	wchange (win, sr_left * sqrsize, sr_top * sqrsize,
X		sr_right * sqrsize, sr_bottom * sqrsize) ;
X
X	changed = TRUE ;
X}
X
Xint
Xtranspose_major()
X{
X	int	i ;
X	int	j ;
X	int	tmp ;
X
X	if (selrect) {
X		if (sr_right - sr_left != sr_bottom - sr_top) {
X			wfleep () ;
X			wmessage ("You can only transpose a square") ;
X			return ;
X		}
X
X		for (i = 0 ; i < sr_bottom - sr_top ; ++i) {
X			for (j = 0 ; j < i ; ++j) {
X				int	row = i + sr_top ;
X				int	col = j + sr_left ;
X	
X				tmp = getbit (col, row) ;
X				setbit (col, row, getbit (i + sr_left,
X								j + sr_top)) ;
X				setbit (i + sr_left, j + sr_top, tmp) ;
X			}
X		}
X
X		wchange (win, sr_left * sqrsize, sr_top * sqrsize,
X			sr_right * sqrsize, sr_bottom * sqrsize) ;
X
X		changed = TRUE ;
X	}
X	else
X		wfleep () ;
X}
X
Xvoid
Xtranspose_minor ()
X{
X	int	size ;
X	int	i ;
X	int	j ;
X	int	tmp ;
X
X	if (selrect) {
X		if (sr_bottom - sr_top != sr_right - sr_left) {
X			wfleep () ;
X			wmessage ("You can only transpose a square") ;
X			return ;
X		}
X
X		size = sr_bottom - sr_top ;
X
X		for (i = 0 ; i < size ; ++i) {
X			for (j = 0 ; j < size - 1 - i ; ++j) {
X				tmp = getbit (j + sr_left, i + sr_top) ;
X				setbit (j + sr_left, i + sr_top,
X					getbit (size - 1 - i + sr_left,
X						size - 1 - j + sr_top)) ;
X				setbit (size - 1 - i + sr_left,
X					size - 1 - j + sr_top, tmp) ;
X			}
X		}
X
X		wchange (win, sr_left * sqrsize, sr_top * sqrsize,
X			sr_right * sqrsize, sr_bottom * sqrsize) ;
X
X		changed = TRUE ;
X	}
X	else
X		wfleep () ;
X
X}
X
Xint
Xrotate_left()
X{
X	int	i ;
X	int	j ;
X	int	size ;
X	int	tmp ;
X
X	if (selrect) {
X		if (sr_bottom - sr_top != sr_right - sr_left) {
X			wfleep () ;
X			wmessage ("You can only rotate a square") ;
X			return ;	
X		}
X
X		size = sr_bottom - sr_top ;
X
X		for (i = 0 ; i < size / 2 ; ++i) {
X			for (j = 0 ; j < (size + 1) / 2 ; ++j) {
X				tmp = getbit (j + sr_left, i + sr_top) ;
X				setbit (j + sr_left, i + sr_top,
X					getbit (size - 1 - i + sr_left,
X						j + sr_top)) ;
X				setbit (size - 1 - i + sr_left, j + sr_top,
X					getbit (size - 1 - j + sr_left,
X						size - 1 - i + sr_top)) ;
X				setbit (size - 1 - j + sr_left,
X					size - 1 - i + sr_top,
X					getbit (i + sr_left,
X						size - 1 - j + sr_top)) ;
X				setbit (i + sr_left, size - 1 - j + sr_top,
X					tmp) ;
X			}
X		}
X
X		wchange (win, sr_left * sqrsize, sr_top * sqrsize,
X			sr_right * sqrsize, sr_bottom * sqrsize) ;
X
X		changed = TRUE ;
X	}
X	else
X		wfleep () ;
X}
X
Xvoid
Xrotate_right()
X{
X	int	i ;
X	int	j ;
X	int	size ;
X	int	tmp ;
X
X	if (selrect) {
X		if (sr_bottom - sr_top != sr_right - sr_left) {
X			wfleep () ;
X			wmessage ("You can only rotate a square") ;
X			return ;
X		}
X
X		size = sr_bottom - sr_top ;
X
X		for (i = 0 ; i < size / 2 ; ++i) {
X			for (j = 0 ; j < (size + 1) / 2 ; ++j) {
X				tmp = getbit (j + sr_left, i + sr_top) ; 
X				setbit (j + sr_left, i + sr_top,
X					getbit (i + sr_left,
X						size - 1 - j + sr_top)) ;
X				setbit (i + sr_left, size - 1 - j + sr_top,
X					getbit (size - 1 - j + sr_left,
X						size - 1 - i + sr_top)) ;
X				setbit (size - 1 - j + sr_left,
X					size - 1 - i + sr_top,
X					getbit (size - 1 - i + sr_left,
X						j + sr_top)) ;
X				setbit (size - 1 - i + sr_left, j + sr_top,
X					tmp) ;
X			}
X		}
X
X		wchange (win, sr_left * sqrsize, sr_top * sqrsize,
X			sr_right * sqrsize, sr_bottom * sqrsize) ;
X
X		changed = TRUE ;
X	}
X}
X
Xvoid
Xflip_horizontal()
X{
X	int	i ;
X	int	j ;
X	int	sr_width ;
X	int	sr_height ;
X	int	tmp ;
X
X	if (selrect) {
X		sr_width = sr_right - sr_left ;
X		sr_height = sr_bottom - sr_top ;
X
X		for (i = 0 ; i < sr_height ; ++ i) {
X			for (j = 0 ; j < sr_width / 2 ; ++j) {
X				tmp = getbit (j + sr_left, i + sr_top) ;
X				setbit (j + sr_left, i + sr_top,
X					getbit (sr_width - 1 - j + sr_left,
X						i + sr_top)) ;
X				setbit (sr_width - 1 - j + sr_left, i + sr_top,
X					tmp) ;
X			}
X		}
X
X		wchange (win, sr_left * sqrsize, sr_top * sqrsize,
X			sr_right * sqrsize, sr_bottom * sqrsize) ;
X
X		changed = TRUE ;
X	}
X	else
X		wfleep () ;
X}
X
Xvoid
Xflip_vertical()
X{
X	int	i ;
X	int	j ;
X	int	sr_width ;
X	int	sr_height ;
X	int	tmp ;
X
X	if (selrect) {
X		sr_width = sr_right - sr_left ;
X		sr_height = sr_bottom - sr_top ;
X
X		for (i = 0 ; i < sr_height / 2 ; ++i) {
X			for (j = 0 ; j < sr_width ; ++j) {
X				tmp = getbit (j + sr_left, i + sr_top) ;
X				setbit (j + sr_left, i + sr_top,
X					getbit (j + sr_left,
X						sr_height - 1 - i + sr_top)) ;
X				setbit (j + sr_left, sr_height - 1 - i + sr_top,
X					tmp) ;
X			}
X		}
X
X		wchange (win, sr_left * sqrsize, sr_top * sqrsize,
X			sr_right * sqrsize, sr_bottom * sqrsize) ;
X
X		changed = TRUE ;
X	}
X	else
X		wfleep () ;
X}
X
Xvoid
Xzoom_in ()
X{
X	sqrsize *= 2 ;
X	wsetdocsize (win, map_width * sqrsize, map_height * sqrsize) ;
X	wchange (win, 0, 0, map_width * sqrsize, map_height * sqrsize) ;
X}
X
Xvoid
Xzoom_out ()
X{
X	int oss = sqrsize ;
X	if (sqrsize == 1) wfleep () ;
X	else {
X		if ((sqrsize /= 2) < 1) sqrsize = 1 ;
X		wsetdocsize (win, map_width * sqrsize, map_height * sqrsize) ;
X		wchange (win, 0, 0, map_width * oss, map_height * oss) ;
X	}
X}
X
X
Xvoid
Xdo_op_menu (ep)
X	EVENT	*ep ;
X{
X	switch (ep->u.m.item) {
X	case CLEAR_ITEM :
X		clear_bits () ;
X		break ;
X	case SET_ITEM :
X		set_bits () ;
X		break ;
X	case INVERT_ITEM :
X		invert_bits () ;
X		break ;
X	case TRANS_MAJ_ITEM :
X		transpose_major () ;
X		break ;
X	case TRANS_MIN_ITEM :
X		transpose_minor () ;
X		break ;
X	case ROT_LEFT_ITEM :
X		rotate_left () ;
X		break ;
X	case ROT_RIGHT_ITEM :
X		rotate_right () ;
X		break ;
X	case FLIP_HOR_ITEM :
X		flip_horizontal () ;
X		break ;
X	case FLIP_VERT_ITEM :
X		flip_vertical () ;
X		break ;
X	case ZOOM_IN :
X		zoom_in () ;
X		break ;
X	case ZOOM_OUT :
X		zoom_out () ;
X		break ;
X	}
X}
END_OF_FILE
if test 7521 -ne `wc -c <'Appls/bed/opmenu.c'`; then
    echo shar: \"'Appls/bed/opmenu.c'\" unpacked with wrong size!
fi
# end of 'Appls/bed/opmenu.c'
fi
if test -f 'Appls/miniedit/miniedit.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Appls/miniedit/miniedit.c'\"
else
echo shar: Extracting \"'Appls/miniedit/miniedit.c'\" \(6739 characters\)
sed "s/^X//" >'Appls/miniedit/miniedit.c' <<'END_OF_FILE'
X/* Mini-editor using editwin module */
X
X#include "stdwin.h"
X#include "tools.h"
X#include "editwin.h"
X
Xmain(argc, argv)
X	int argc;
X	char **argv;
X{
X	winitargs(&argc, &argv);
X	menusetup();
X	openfiles(argc, argv);
X	mainloop();
X	wdone();
X	exit(0);
X}
X
XMENU *filemenu, *editmenu, *findmenu;
X
X#define FILE_MENU	1
X#define EDIT_MENU	2
X#define FIND_MENU	3
X
X/* File items */
X#define NEW_ITEM	0
X#define OPEN_ITEM	1
X#define CLOSE_ITEM	3
X#define SAVE_ITEM	4
X#define SAVE_AS_ITEM	5
X#define SAVE_COPY_ITEM	6
X#define REVERT_ITEM	7
X#define QUIT_ITEM	9
X
X/* Edit items */
X#define UNDO_ITEM	0
X#define CUT_ITEM	2
X#define COPY_ITEM	3
X#define PASTE_ITEM	4
X#define CLEAR_ITEM	5
X#define SEL_ALL_ITEM	6
X#define EXEC_ITEM	8
X
X/* Find items */
X#define FIND_ITEM	0
X#define FIND_SAME_ITEM	1
X#define REPL_ITEM	3
X#define REPL_SAME_ITEM	4
X#define REPL_ALL_ITEM	5
X
Xmenusetup()
X{
X	MENU *mp;
X	
X	filemenu= mp= wmenucreate(FILE_MENU, "File");
X	
X	wmenuadditem(mp, "New", 'N');
X	wmenuadditem(mp, "Open...", 'o');
X	wmenuadditem(mp, "", -1);
X	wmenuadditem(mp, "Close", 'K');
X	wmenuadditem(mp, "Save", 'S');
X	wmenuadditem(mp, "Save as...", -1);
X	wmenuadditem(mp, "Save a Copy...", -1);
X	wmenuadditem(mp, "Revert to Saved", -1);
X	wmenuadditem(mp, "", -1);
X	wmenuadditem(mp, "Quit", 'Q');
X	
X	editmenu= mp= wmenucreate(EDIT_MENU, "Edit");
X	
X	wmenuadditem(mp, "Undo", 'Z');
X	wmenuadditem(mp, "", -1);
X	wmenuadditem(mp, "Cut", 'X');
X	wmenuadditem(mp, "Copy", 'C');
X	wmenuadditem(mp, "Paste", 'V');
X	wmenuadditem(mp, "Clear", 'B');
X	wmenuadditem(mp, "Select All", 'A');
X	wmenuadditem(mp, "", -1);
X	wmenuadditem(mp, "Execute", '\r');
X	
X	findmenu= mp= wmenucreate(FIND_MENU, "Find");
X	
X	wmenuadditem(mp, "Find...", 'F');
X	wmenuadditem(mp, "Find Same", 'G');
X	wmenuadditem(mp, "", -1);
X	wmenuadditem(mp, "Replace...", 'R');
X	wmenuadditem(mp, "Replace Same", 'T');
X	wmenuadditem(mp, "Replace All", -1);
X}
X
Xfixmenus(ew)
X	EDITWIN *ew;
X{
X	bool focus;
X	
X	if (ew == NULL)
X		return;
X	
X	wmenuenable(filemenu, SAVE_ITEM, !ew->saved);
X	wmenuenable(filemenu, REVERT_ITEM, !ew->saved);
X	
X	wmenuenable(editmenu, UNDO_ITEM, FALSE);
X	wmenuenable(editmenu, EXEC_ITEM, FALSE);
X	
X	focus= tegetfoc1(ew->tp) < tegetfoc2(ew->tp);
X	wmenuenable(editmenu, CUT_ITEM, focus);
X	wmenuenable(editmenu, COPY_ITEM, focus);
X	wmenuenable(editmenu, CLEAR_ITEM, focus);
X}
X
Xopenfiles(argc, argv)
X	int argc;
X	char **argv;
X{
X	int i;
X	
X	for (i= 1; i < argc; ++i) {
X		(void) ewcreate(argv[i]);
X	}
X	if (ewcount() == 0) {
X		if (ewopen() == NULL && ewnew() == NULL) {
X			wdone();
X			fprintf(stderr, "Can't open any windows\n");
X			exit(1);
X		}
X	}
X}
X
Xmainloop()
X{
X	for (;;) {
X		EVENT e;
X		EDITWIN *ew;
X		
X		wgetevent(&e);
X		ew= ewfind(e.window);
X		switch (e.type) {
X		case WE_MENU:
X			switch (e.u.m.id) {
X			
X			case FILE_MENU:
X				switch (e.u.m.item) {
X				case NEW_ITEM:
X					(void) ewnew();
X					break;
X				case OPEN_ITEM:
X					(void) ewopen();
X					break;
X				case CLOSE_ITEM:
X					if (ew != NULL) {
X						ewclose(ew);
X						if (ewcount() == 0)
X							return;
X					}
X					break;
X				case SAVE_ITEM:
X					if (ew != NULL)
X						ewsave(ew);
X					break;
X				case SAVE_AS_ITEM:
X					if (ew != NULL)
X						ewsaveas(ew);
X					break;
X				case SAVE_COPY_ITEM:
X					if (ew != NULL)
X						ewsavecopy(ew);
X					break;
X				case REVERT_ITEM:
X					if (ew != NULL)
X						ewrevert(ew);
X					break;
X				case QUIT_ITEM:
X					if (ewcloseall())
X						return;
X					break;
X				}
X				break;
X			
X			case EDIT_MENU:
X				if (ew == NULL) {
X					wfleep();
X					break;
X				}
X				switch (e.u.m.item) {
X				case UNDO_ITEM:
X					ewundo(ew);
X					break;
X				case CUT_ITEM:
X					ewcopy(ew);
X					ewreplace(ew, "");
X					break;
X				case COPY_ITEM:
X					ewcopy(ew);
X					break;
X				case PASTE_ITEM:
X					ewpaste(ew);
X					break;
X				case CLEAR_ITEM:
X					ewreplace(ew, "");
X					break;
X				case SEL_ALL_ITEM:
X					tesetfocus(ew->tp, 0,
X						tegetlen(ew->tp));
X					break;
X				case EXEC_ITEM:
X					wfleep();
X					break;
X				}
X				break;
X			
X			case FIND_MENU:
X				switch (e.u.m.item) {
X				case FIND_ITEM:
X					find(ew, TRUE);
X					break;
X				case FIND_SAME_ITEM:
X					find(ew, FALSE);
X					break;
X				case REPL_ITEM:
X					replace(ew, TRUE);
X					break;
X				case REPL_SAME_ITEM:
X					replace(ew, FALSE);
X					break;
X				case REPL_ALL_ITEM:
X					replall(ew);
X					break;
X				}
X				break;
X			
X			}
X			break;
X		
X		default:
X			if (ew != NULL) {
X				bool closed;
X				ewevent(ew, &e, &closed);
X				if (closed && ewcount() == 0)
X					return;
X			}
X			break;
X		
X		}
X		
X		fixmenus(ew);
X	}
X}
X
X#include "regexp.h"
X
Xchar whatbuf[256];	/* Last regular expression typed */
Xregexp *prog;		/* Compiled regular expression */
Xchar replbuf[256];	/* Last replacement string */
X
Xbool
Xfind(ew, dodialog)
X	EDITWIN *ew;
X	bool dodialog;
X{
X	return finddialog(ew, dodialog, "Find regular expression:") &&
X		findit(ew, FALSE);
X}
X
Xbool
Xreplace(ew, dodialog)
X	EDITWIN *ew;
X	bool dodialog;
X{
X	if (!finddialog(ew, dodialog, "Replace regular expression:")
X		|| !findit(ew, TRUE))
X		return FALSE;
X	wupdate(ew->win); /* Show what we've found */
X	return repldialog(ew, dodialog) && replit(ew);
X}
X
Xreplall(ew)
X	EDITWIN *ew;
X{
X	if (!replace(ew, TRUE))
X		return FALSE;
X	while (findit(ew, TRUE)) {
X		wupdate(ew->win);
X		replit(ew);
X		wupdate(ew->win);
X		/* What if it takes forever? */
X	}
X	return TRUE;
X}
X
Xbool
Xfinddialog(ew, dodialog, prompt)
X	EDITWIN *ew;
X	bool dodialog;
X	char *prompt;
X{
X	if (ew == NULL)
X		return FALSE;
X	if (dodialog || prog == NULL) {
X		if (!waskstr(prompt, whatbuf, sizeof whatbuf))
X			return FALSE;
X		if (prog != NULL)
X			free((char*)prog);
X		prog= regcomp(whatbuf);
X		if (prog == NULL)
X			return FALSE;
X	}
X	return TRUE;
X}
X
Xbool
Xrepldialog(ew, dodialog)
X	EDITWIN *ew;
X	bool dodialog;
X{
X	if (!dodialog)
X		return TRUE;
X	return waskstr("Replacement string:", replbuf, sizeof replbuf);
X}
X
Xbool
Xfindit(ew, begin)
X	EDITWIN *ew;
X	bool begin; /* TRUE if must start at foc1 */
X{
X	int foc1= tegetfoc1(ew->tp);
X	int foc2= tegetfoc2(ew->tp);
X	int len= tegetlen(ew->tp);
X	char *text= tegettext(ew->tp);
X	
X	if (!reglexec(prog, text, begin ? foc1 : foc2)) {
X		wfleep();
X		return FALSE;
X	}
X	if (!begin && prog->startp[0] == text+foc2 && foc1 == foc2 &&
X		prog->startp[0] == prog->endp[0]) {
X		/* Found empty string at empty focus;
X		   try again at next position (if in range) */
X		if (++foc2 > len)
X			return FALSE;
X		if (!reglexec(prog, text, foc2)) {
X			wfleep();
X			return FALSE;
X		}
X	}
X	tesetfocus(ew->tp, (int)(prog->startp[0] - text),
X		(int)(prog->endp[0] - text));
X	return TRUE;
X}
X
Xbool
Xreplit(ew)
X	EDITWIN *ew;
X{
X	char substbuf[1024];
X	/* Should be bigger -- what if the entire file matches? */
X	
X	regsub(prog, replbuf, substbuf);
X	ewreplace(ew, substbuf);
X	return TRUE;
X}
X
Xvoid
Xregerror(str)
X	char *str;
X{
X	char buf[256];
X	
X	sprintf(buf, "Regular expression error: %s", str);
X	wmessage(buf);
X}
END_OF_FILE
if test 6739 -ne `wc -c <'Appls/miniedit/miniedit.c'`; then
    echo shar: \"'Appls/miniedit/miniedit.c'\" unpacked with wrong size!
fi
# end of 'Appls/miniedit/miniedit.c'
fi
if test -f 'Appls/repeat/repeat.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Appls/repeat/repeat.c'\"
else
echo shar: Extracting \"'Appls/repeat/repeat.c'\" \(6739 characters\)
sed "s/^X//" >'Appls/repeat/repeat.c' <<'END_OF_FILE'
X/* Repeat a command forever, displaying the output in a window.
X   This is useful to have a continuously update from status programs
X   like 'ps' or 'lpq'.
X   
X   Usage: repeat [-d delay] command [arg] ...
X   
X   To do:
X	- adapt textedit width to window width?
X	- allocate image buffer dynamically
X	- more sensible error handling (allow to cancel)
X	- add a menu option to change the delay
X	- display the delay somehow
X	- use d.ddd seconds notation instead of deciseconds
X	- avoid flickering screen in X11 version
X	  (possibly by using tereplace on the smallest changed section,
X	  except need a way to turn the caret off???)
X*/
X
X#include <stdio.h>
X#include <string.h>
X#include <stdwin.h>
X
Xextern char *malloc();
X
XWINDOW *win;
XTEXTEDIT *tp;
X
X#define MAXSIZE 10000
X
X#define DELAY 5 /* retry after success in 0.5 seconds */
X#define ERRDELAY 50 /* retry after popen error in 5 seconds */
X
Xint delay = DELAY; /* normal delay */
Xint errdelay = ERRDELAY; /* delay after popen error */
Xint tflag = 0; /* Display time above output when set */
X
Xchar *progname = "REPEAT";
X
Xvoid usage() {
X	wdone();
X	fprintf(stderr,
X		"usage: %s [-d ddd.d] [-e ddd.d] [-t] cmd [arg] ...\n",
X		progname);
X	fprintf(stderr, "-d ddd.d: delay N seconds after command\n");
X	fprintf(stderr, "-e ddd.d: delay N seconds after error\n");
X	fprintf(stderr, "-t      : display current time above output\n");
X	exit(2);
X}
X
Xextern int optind;
Xextern char *optarg;
X
Xvoid mainloop();
Xvoid rerun();
Xvoid drawproc();
Xchar *mktitle();
Xlong getfract();
X
Xint main(argc, argv)
X	int argc;
X	char **argv;
X{
X	int c;
X	winitargs(&argc, &argv); /* Must be first for X11 */
X	if (argc > 0 && argv[0] != NULL && argv[0][0] != '\0')
X		progname = argv[0];
X	while ((c = getopt(argc, argv, "d:e:t")) != EOF) {
X		switch (c) {
X		case 'd':
X			delay = getfract(&optarg, 10);
X			if (*optarg != '\0') {
X				fprintf(stderr, "-d argument format error\n");
X				usage();
X			}
X			if (delay <= 0)
X				delay = DELAY;
X			break;
X		case 'e':
X			errdelay = getfract(&optarg, 10);
X			if (*optarg != '\0') {
X				fprintf(stderr, "-e argument format error\n");
X				usage();
X			}
X			if (errdelay <= 0)
X				errdelay = ERRDELAY;
X			break;
X		case 't':
X			tflag = 1;
X			break;
X		default:
X			usage();
X			/*NOTREACHED*/
X		}
X	}
X	if (optind >= argc) {
X		usage();
X		/* NOTREACHED*/
X	}
X	win = wopen(mktitle(argc-optind, argv+optind), drawproc);
X	if (win == NULL) {
X		wdone();
X		fprintf(stderr, "can't open window\n");
X		return 1;
X	}
X	tp = tecreate(win, 0, 0, 10000, 10000);
X	if (tp == NULL) {
X		wclose(win);
X		wdone();
X		fprintf(stderr, "can't create textedit block\n");
X		return 1;
X	}
X	mainloop(argc-optind, argv+optind);
X	wdone();
X	return 0;
X}
X
Xvoid mainloop(argc, argv)
X	int argc;
X	char **argv;
X{
X	rerun(argc, argv);
X	
X	for (;;) {
X		EVENT e;
X		wgetevent(&e);
X		switch (e.type) {
X		case WE_TIMER:
X			rerun(argc, argv);
X			break;
X		case WE_COMMAND:
X			switch (e.u.command) {
X			case WC_CLOSE:
X			case WC_CANCEL:
X				return;
X			case WC_RETURN:
X				rerun(argc, argv);
X				break;
X			}
X			break;
X		case WE_CLOSE:
X			return;
X		}
X	}
X}
X
Xvoid rerun(argc, argv)
X	int argc;
X	char **argv;
X{
X	int fd;
X	char *image, *p;
X	int left, n;
X	
X	if ((image = malloc(MAXSIZE)) == NULL) {
X		wmessage("can't malloc output buffer");
X		wsettimer(win, errdelay);
X		return;
X	}
X	if ((fd = readfrom(argc, argv)) < 0) {
X		wmessage("can't start command");
X		wsettimer(win, errdelay);
X		return;
X	}
X	left = MAXSIZE;
X	p = image;
X	if (tflag) {
X		extern char *ctime();
X		extern long time();
X		long t;
X		time(&t);
X		strcpy(p, ctime(&t));
X		p = strchr(p, '\0');
X	}
X	while (left > 0 && (n = read(fd, p, left)) > 0) {
X		p += n;
X		left -= n;
X	}
X	close(fd);
X	(void) wait((int *)0); /* Get rid of child -- naively */
X	tesetbuf(tp, image, (int)(p - image));
X	wsetdocsize(win, 0, tegetbottom(tp));
X	wnocaret(win); /* Hack */
X	wsettimer(win, delay);
X}
X
Xvoid drawproc(win, left, top, right, bottom)
X	WINDOW *win;
X{
X	tedrawnew(tp, left, top, right, bottom);
X}
X
Xchar *mktitle(argc, argv)
X	int argc;
X	char **argv;
X{
X	static char buf[1000];
X	int i;
X	char *p;
X	
X	p = buf;
X	for (i = 0; i < argc; ++i) {
X		if (i > 0) *p++ = ' ';
X		strcpy(p, argv[i]);
X		p = strchr(p, '\0');
X	}
X	return buf;
X}
X
X/* Function to get a number of the form ddd.ddd from a string, without
X   using floating point variables.  Input is the address of a string
X   pointer, which is incremented by the function to point after the
X   last character that was part of the number.
X   The function return value is X * scale, where X is the exact value
X   read from the string, e.g., for input "3.14" and scale 1000, 3140 is
X   returned.
X   There is no provision for a leading sign or to leading spaces.
X   Overflow goes undetected.
X*/
X
Xlong getfract(pstr, scale)
X	char **pstr;
X	long scale;
X{
X	char *str = *pstr;
X	long x = 0;
X	int in_fraction = 0;
X	char c;
X	
X	for (; (c = *str) != '\0'; str++) {
X		if (c >= '0' && c <= '9') {
X			if (in_fraction) {
X				if (scale < 10)
X					break;
X				scale /= 10;
X			}
X			x = x*10 + (c - '0');
X		}
X		else if (c == '.' && !in_fraction)
X			in_fraction = 1;
X		else
X			break;
X	}
X	*pstr = str;
X	return x*scale;
X}
X
X/*
X                  Copyright 1989 by Douglas A. Young
X
X                           All Rights Reserved
X
X   Permission to use, copy, modify, and distribute this software 
X   for any purpose and without fee is hereby granted,
X   provided that the above copyright notice appear in all copies and that
X   both that copyright notice and this permission notice appear in
X   supporting documentation. The author disclaims all warranties with 
X   regard to this software, including all implied warranties of 
X   merchantability and fitness.
X
X   Comments and additions may be sent the author at:
X
X    dayoung@hplabs.hp.com
X
X   Modified to resemble popen(..., "r").  Returns the file descriptor
X   from which to read, or negative if an error occurred.  (The pid is lost.)
X   Name changed from talkto() to readfrom(). --Guido van Rossum, CWI
X*/
X
Xint
Xreadfrom(argc, argv)
X	int argc;
X	char **argv;
X{
X	int to_parent[2]; /* pipe descriptors from child->parent */
X	int pid;
X
X	if (pipe(to_parent) < 0) {
X		perror("pipe");
X		return -1;
X	}
X	pid = fork();
X	if (pid == 0) {                      /* in the child */
X		close(0);                    /* redirect stdin */
X		open("/dev/null", 0);
X		close(1);                    /* redirect stdout */
X		dup(to_parent[1]);
X		close(2);                    /* redirect stderr */
X		dup(to_parent[1]);
X
X		close(to_parent[0]);
X		close(to_parent[1]);
X
X		execvp(argv[0], argv);       /* exec the new cmd */
X		perror(argv[0]);             /* error in child! */
X		_exit(127);
X	}
X	else if (pid > 0) {                  /* in the parent */
X		close(to_parent[1]);
X		return to_parent[0];
X	}
X	else {                               /* error! */
X		perror("vfork");
X		return -1;
X	}
X}
END_OF_FILE
if test 6739 -ne `wc -c <'Appls/repeat/repeat.c'`; then
    echo shar: \"'Appls/repeat/repeat.c'\" unpacked with wrong size!
fi
# end of 'Appls/repeat/repeat.c'
fi
if test -f 'Appls/test/faced.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Appls/test/faced.c'\"
else
echo shar: Extracting \"'Appls/test/faced.c'\" \(7101 characters\)
sed "s/^X//" >'Appls/test/faced.c' <<'END_OF_FILE'
X/* Simple bitmap editor.
X   Uses ".face" file format (48x48).
X   
X   TO DO:
X   	- fix row/col confusion
X	- connect dots given by mouse move?
X	- optimize drawing of consequtive black squares
X	- add open... command
X	- add flexible input format
X	- support X bitmap format
X	*/
X
X#include <stdio.h>
X#include "stdwin.h"
X
X#define ROWS 48
X#define COLS 48
X#define SIZE (ROWS < COLS ? ROWS : COLS)
X
X#define BITS 16 /* Bits per word */
X
Xchar bit[ROWS][COLS];
X
Xint xscale= 5;
Xint yscale= 5;
X
XWINDOW *win;
X
Xint changed= 0;
X
X
Xmain(argc, argv)
X	int argc;
X	char **argv;
X{
X	FILE *fp;
X	
X	winitargs(&argc, &argv);
X	
X	if (argc > 1) {
X		fp= fopen(argv[1], "r");
X		if (fp == NULL) {
X			wdone();
X			perror(argv[1]);
X			exit(1);
X		}
X		input(fp);
X		fclose(fp);
X	}
X	
X	setup();
X	
X
X	for (;;) {
X		editing();
X		
X		if (changed) {
X			switch (waskync("Save changes?", 1)) {
X			case 1:
X				if (!save(argc > 1 ? argv[1] : NULL))
X					continue;
X				break;
X			case -1:
X				continue;
X			}
X		}
X		break; /* Out of loop */
X	}
X	
X	wdone();
X	exit(0);
X}
X
Xsave(name)
X	char *name;
X{
X	FILE *fp;
X	char namebuf[256];
X	
X	namebuf[0]= '\0';
X	if (name == NULL) {
X		if (!waskfile("Save as", namebuf, sizeof namebuf, 1))
X			return 0;
X		name= namebuf;
X	}
X	fp= fopen(name, "w");
X	if (fp == NULL) {
X		wperror(name);
X		return 0;
X	}
X	output(fp);
X	fclose(fp);
X	return 1;
X}
X
X#define MAIN_MENU	1
X
X#define QUIT_ITEM	0
X
X#define OP_MENU		2
X
X#define CLEAR_ITEM	0
X#define SET_ITEM	1
X#define INVERT_ITEM	2
X#define TRANS_MAJ_ITEM	3
X#define TRANS_MIN_ITEM	4
X#define ROT_LEFT_ITEM	5
X#define ROT_RIGHT_ITEM	6
X#define FLIP_HOR_ITEM	7
X#define FLIP_VERT_ITEM	8
X
X#define NOPS		9
X
Xextern int (*oplist[])(); /* Forward */
Xdrawproc(); /* Forward */
X
Xint text_only;
X
Xsetup()
X{
X	MENU *mp;
X	int width, height;
X	
X	if (wlineheight() == 1)
X		text_only= xscale= yscale= 1;
X	
X	wsetdefwinsize(COLS*xscale, ROWS*yscale);
X	
X	mp= wmenucreate(MAIN_MENU, "Faced");
X	wmenuadditem(mp, "Quit", 'Q');
X	mp= wmenucreate(OP_MENU, "Operations");
X	wmenuadditem(mp, "Clear all", -1);
X	wmenuadditem(mp, "Set all", -1);
X	wmenuadditem(mp, "Invert", -1);
X	wmenuadditem(mp, "Transpose major", -1);
X	wmenuadditem(mp, "Transpose minor", -1);
X	wmenuadditem(mp, "Rotate left", -1);
X	wmenuadditem(mp, "Rotate right", -1);
X	wmenuadditem(mp, "Flip horizontal", -1);
X	wmenuadditem(mp, "Flip vertical", -1);
X	
X	win= wopen("faced", drawproc);
X	if (win == NULL) {
X		wmessage("Can't open window");
X		return;
X	}
X	wsetdocsize(win, COLS*xscale, ROWS*yscale);
X}
X
Xediting()
X{
X	int value= 0;
X	
X	for (;;) {
X		EVENT e;
X		
X		wgetevent(&e);
X		switch (e.type) {
X		case WE_MOUSE_DOWN:
X			value= !getbit(e.u.where.h/xscale, e.u.where.v/yscale);
X		case WE_MOUSE_MOVE:
X		case WE_MOUSE_UP:
X			setbit(e.u.where.h/xscale, e.u.where.v/yscale, value);
X			break;
X		case WE_COMMAND:
X			switch (e.u.command) {
X			case WC_CLOSE:
X				return;
X			case WC_CANCEL:
X				changed= 0;
X				return;
X			}
X		case WE_CLOSE:
X			return;
X		case WE_MENU:
X			switch (e.u.m.id) {
X			case MAIN_MENU:
X				switch (e.u.m.item) {
X				case QUIT_ITEM:
X					return;
X				}
X				break;
X			case OP_MENU:
X				if (e.u.m.item >= 0 && e.u.m.item < NOPS) {
X					(*oplist[e.u.m.item])();
X					wchange(win, 0, 0,
X						COLS*xscale, ROWS*yscale);
X					changed= 1;
X				}
X				break;
X			}
X		}
X	}
X}
X
Xint
Xgetbit(col, row)
X{
X	if (row >= 0 && row < ROWS && col >= 0 && col < COLS)
X		return bit[row][col];
X	else
X		return 0;
X}
X
Xsetbit(col, row, value)
X{
X	if (row >= 0 && row < ROWS && col >= 0 && col < COLS &&
X			bit[row][col] != value) {
X		changed= 1;
X		bit[row][col]= value;
X		wchange(win, col*xscale, row*yscale,
X			(col+1)*xscale, (row+1)*yscale);
X	}
X}
X
Xdrawproc(win, left, top, right, bottom)
X	WINDOW *win;
X{
X	int row, col;
X	
X	if (left < 0)
X		left= 0;
X	if (right > COLS*xscale)
X		right= COLS*xscale;
X	if (top < 0)
X		top= 0;
X	if (bottom > ROWS*yscale)
X		bottom= ROWS*yscale;
X	
X	for (row= top/yscale; row*yscale < bottom; ++row) {
X		for (col= left/xscale; col*xscale < right; ++col) {
X			if (bit[row][col]) {
X				if (text_only)
X					wdrawchar(col, row, 'x');
X				else
X					wpaint(col*xscale, row*yscale,
X					    (col+1)*xscale, (row+1)*yscale);
X			}
X		}
X	}
X}
X
X
X/* File I/O routines */
X
Xinput(fp)
X	FILE *fp;
X{
X	int row;
X	
X	for (row= 0; row < ROWS; ++row) {
X		read_row(fp, row);
X	}
X}
X
Xread_row(fp, row)
X	FILE *fp;
X	int row;
X{
X	int left= 0;
X	long ibuf;
X	int col;
X	
X	for (col= 0; col < COLS; ++col) {
X		if (left <= 0) {
X			if (fscanf(fp, " 0x%4lx,", &ibuf) != 1) {
X				wdone();
X				fprintf(stderr,
X					"Bad input format, row %d\n", row);
X				exit(1);
X			}
X			left= BITS;
X		}
X		--left;
X		bit[row][col]= (ibuf >> left) & 1;
X	}
X}
X
Xoutput(fp)
X	FILE *fp;
X{
X	int row;
X	
X	for (row= 0; row < ROWS; ++row)
X		write_row(fp, row);
X}
X
Xwrite_row(fp, row)
X	FILE *fp;
X	int row;
X{
X	int col;
X	int left= BITS;
X	long ibuf= 0;
X	
X	for (col= 0; col < COLS; ++col) {
X		if (left <= 0) {
X			fprintf(fp, "0x%04lX,", ibuf);
X			ibuf= 0;
X			left= BITS;
X		}
X		--left;
X		if (bit[row][col]) {
X			ibuf |= 1<<left;
X		}
X	}
X	if (left < BITS)
X		fprintf(fp, "0x%04lX,", ibuf);
X	fprintf(fp, "\n");
X}
X
X
X/* Data manipulation routines */
X
Xclear_bits()
X{
X	int row, col;
X	
X	for (row= 0; row < ROWS; ++row)
X		for (col= 0; col < COLS; ++col)
X			bit[row][col]= 0;
X}
X
Xset_bits()
X{
X	int row, col;
X	
X	for (row= 0; row < ROWS; ++row)
X		for (col= 0; col < COLS; ++col)
X			bit[row][col]= 1;
X}
X
Xinvert_bits()
X{
X	int row, col;
X	
X	for (row= 0; row < ROWS; ++row)
X		for (col= 0; col < COLS; ++col)
X			bit[row][col]= !bit[row][col];
X}
X
Xtranspose_major()
X{
X	int row, col;
X	char tmp;
X	
X	for (row= 0; row < SIZE; ++row) {
X		for (col= 0; col < row; ++col) {
X			tmp= bit[row][col];
X			bit[row][col]= bit[col][row];
X			bit[col][row]= tmp;
X		}
X	}
X}
X
Xtranspose_minor()
X{
X	int row, col;
X	char tmp;
X	
X	for (row= 0; row < SIZE; ++row) {
X		for (col= 0; col < SIZE-1-row; ++col) {
X			tmp= bit[row][col];
X			bit[row][col]= bit[SIZE-1-col][SIZE-1-row];
X			bit[SIZE-1-col][SIZE-1-row]= tmp;
X		}
X	}
X}
X
Xrotate_left()
X{
X	int row, col;
X	char tmp;
X	
X	for (row= 0; row < SIZE/2; ++row) {
X		for (col= 0; col < SIZE/2; ++col) {
X			tmp= bit[row][col];
X			bit[row][col]= bit[col][SIZE-1-row];
X			bit[col][SIZE-1-row]= bit[SIZE-1-row][SIZE-1-col];
X			bit[SIZE-1-row][SIZE-1-col]= bit[SIZE-1-col][row];
X			bit[SIZE-1-col][row]= tmp;
X		}
X	}
X}
X
Xrotate_right()
X{
X	int row, col;
X	char tmp;
X	
X	for (row= 0; row < SIZE/2; ++row) {
X		for (col= 0; col < SIZE/2; ++col) {
X			tmp= bit[row][col];
X			bit[row][col]= bit[SIZE-1-col][row];
X			bit[SIZE-1-col][row]= bit[SIZE-1-row][SIZE-1-col];
X			bit[SIZE-1-row][SIZE-1-col]= bit[col][SIZE-1-row];
X			bit[col][SIZE-1-row]= tmp;
X		}
X	}
X}
X
Xflip_horizontal()
X{
X	int row, col;
X	char tmp;
X	
X	for (row= 0; row < ROWS; ++row) {
X		for (col= 0; col < COLS/2; ++col) {
X			tmp= bit[row][col];
X			bit[row][col]= bit[row][COLS-1-col];
X			bit[row][COLS-1-col]= tmp;
X		}
X	}
X}
X
Xflip_vertical()
X{
X	int row, col;
X	char tmp;
X	
X	for (row= 0; row < ROWS/2; ++row) {
X		for (col= 0; col < COLS; ++col) {
X			tmp= bit[row][col];
X			bit[row][col]= bit[ROWS-1-row][col];
X			bit[ROWS-1-row][col]= tmp;
X		}
X	}
X}
X
Xint (*oplist[])() = {
X	clear_bits,
X	set_bits,
X	invert_bits,
X	transpose_major,
X	transpose_minor,
X	rotate_left,
X	rotate_right,
X	flip_horizontal,
X	flip_vertical,
X};
END_OF_FILE
if test 7101 -ne `wc -c <'Appls/test/faced.c'`; then
    echo shar: \"'Appls/test/faced.c'\" unpacked with wrong size!
fi
# end of 'Appls/test/faced.c'
fi
if test -f 'Doc/man/textedit.man' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Doc/man/textedit.man'\"
else
echo shar: Extracting \"'Doc/man/textedit.man'\" \(6406 characters\)
sed "s/^X//" >'Doc/man/textedit.man' <<'END_OF_FILE'
X.TH TEXTEDIT 3
X.SH NAME
XTextedit \- text-editing package for STDWIN
X.SH SYNOPSIS
X.nf
X.ft C
X#include "stdwin.h"
X
XTEXTEDIT *tealloc(WINDOW *win, int left, int top, int width);
XTEXTEDIT *tecreate(WINDOW *win, int left, int top, int right, int bottom);
Xvoid tefree(TEXTEDIT *tp);
Xvoid tedestroy(TEXTEDIT *tp);
X
Xvoid tedraw(TEXTEDIT *tp);
Xvoid tedrawnew(TEXTEDIT *tp, int left, int top, int right, int bottom);
Xvoid temove(TEXTEDIT *tp, int left, int top, int width);
Xvoid temovenew(TEXTEDIT *tp, int left, int top, int right, int bottom);
X
Xvoid tesetfocus(TEXTEDIT *tp, int foc1, int foc2);
Xvoid tereplace(TEXTEDIT *tp, char *str);
Xvoid tesetbuf(TEXTEDIT *tp, char *buf, int buflen);
X
Xvoid tearrow(TEXTEDIT *tp, int code);
Xvoid tebackspace(TEXTEDIT *tp);
Xbool teclicknew(TEXTEDIT *tp, int h, int v, bool extend);
Xbool tedoubleclick(TEXTEDIT *tp, int h, int v);
Xbool teevent(TEXTEDIT *tp, EVENT *ep);
X
X#define teclick(tp, h, v) teclicknew(tp, h, v, FALSE)
X#define teclickextend(tp, h, v) teclicknew(tp, h, v, TRUE)
X
Xchar *tegettext(TEXTEDIT *tp);
Xint tegetlen(TEXTEDIT *tp);
Xint tegetnlines(TEXTEDIT *tp);
Xint tegetfoc1(TEXTEDIT *tp);
Xint tegetfoc2(TEXTEDIT *tp);
Xint tegetleft(TEXTEDIT *tp);
Xint tegettop(TEXTEDIT *tp);
Xint tegetright(TEXTEDIT *tp);
Xint tegetbottom(TEXTEDIT *tp);
X
Xint wdrawpar(int h, int v, char *text, int width);
Xint wparheight(char *text, int width);
X.ft 1
X.fi
X.SH DESCRIPTION
X.I Textedit
Xis the standard text-editing package for STDWIN.
XIt allows you to designate any part of a window as a ``text-editing''
Xarea, in which the user can see or edit arbitrary text.
XUntil I find the time and the mental rest to write a decent manual,
Xyou'll have to do with the example and hints on this man page.
X.PP
XA textedit area need not occupy an entire window, and there can be
Xmore than one textedit area in a given window.
XConsequently, textedit areas are not resized automatically when their
Xwindow is resized, and the document size is not set automatically when
Xthe textedit area's size changes.
XIf you want to use a single textedit area in a window, and want them to
Xbe coupled more tightly, use the
X.I editwin
Xpackage instead.
X.PP
XThe functions
X.I wdrawpar
Xand
X.I wparheight
Xdraw a paragraph of text exactly like the
X.I textedit
Xroutines would draw it, without the need to allocate a textedit data
Xstructure for it.
X.I Wdrawpar
Xreturns the ``v'' coordinate of the bottom of the paragraph drawn, and
X.I wparheight
Xreturns its height.
X.PP
XAvailable routines are:
X.IP tealloc
X.IP tecreate
X.IP tefree
X.IP tedestroy
X.IP tedraw
X.IP tedrawnew
X.IP temove
X.IP temovenew
X.IP tesetfocus
X.IP tereplace
X.IP tesetbuf
X.IP tearrow
X.IP tebackspace
X.IP teclicknew
X.IP tedoubleclick
X.IP teevent
X.IP teclick
X.IP teclickextend
X.IP tegettext
X.IP tegetlen
X.IP tegetnlines
X.IP tegetfoc1
X.IP tegetfoc2
X.IP tegetleft
X.IP tegettop
X.IP tegetright
X.IP tegetbottom
X.IP wdrawpar
X.IP wparheight
X.SH EXAMPLE
X.nf
X.ft C
X#include "stdwin.h"
X
XWINDOW *win;
XTEXTEDIT *tp;
X
Xvoid drawproc(win, left, top, right, bottom) WINDOW *win; {
X	tedrawnew(tp,left, top, right, bottom);
X}
X
Xmain() {
X	winit();
X	win= wopen("Hello world", &drawproc);
X	tp= tecreate(win, 20, 20, 200, 200);
X	tereplace(tp, "Guido is gek");
X	for (;;) {
X		EVENT e;
X		wgetevent(&e);
X		if (teevent(tp, &e)) continue; /* Event has been handled */
X		if (e.type == WE_COMMAND && e.u.command == WC_CLOSE) break;
X	}
X	wdone();
X	exit(0);
X}
X.ft 1
X.fi
X.SH HINTS
X.I Tedestroy
Xcalls
X.I wchange
Xfor the area occupied by the textedit area, and then calls
X.IR tefree ;
X.I tefree
Xgets rid of the data structures allocated for it.
X.PP
X.I Tesetbuf
X``gives the buffer away.''
XThat is, you should have allocated the buffer using
X.IR malloc (3),
Xbut you shouldn't call
X.I free
Xto get rid of it \- a pointer to the buffer is incorporated in the
Xtextedit data structures, and it will be freed later by
X.I tefree.
XDon't pass a buffer that wasn't allocated through
X.IR malloc (3)!
X.PP
X.I Tegettext
Xreturns a pointer to the internal buffer used to represent the text.
XSubsequent calls to textedit routines that modify the buffer may
Xinvalidate this pointer.
XYou shouldn't modify the text found there.
XTo get the text selected in the focus, copy the substring found between
Xpositions
X.I tegetfoc1
Xand
X.I tegetfoc2,
Xfor example:
X.nf
X.ft C
X/* Copy focus text into buffer, whose size is len */
Xgetfocus(tp, buf, len) TEXTEDIT *tp; char *buf; {
X	int f1= tegetfoc1(tp), f2= tegetfoc2(tp);
X	char *text= tegettext(tp);
X	if (f2-f1 < len) len= f2-f1+1;
X	strncpy(buf, len-1, text+f1);
X	buf[len-1]= '\0';
X}
X.ft 1
X.fi
X.SH DIAGNOSTICS
X.I Tealloc
Xand
X.I tecreate
Xreturn NULL when they could not get all the necessary memory.
XThe other routines may fail but there is no way to find out.
X.SH SEE ALSO
XSTDWIN documentation
X.br
Xeditwin(3)
X.SH AUTHOR
XGuido van Rossum
X.SH BUGS
XTextedit areas always grow and shrunk automaticatically at the bottom.
XTherefore,
X.I tecreate
Xignores the bottom coordinate.
X.br
XWhen a textedit area shrinks more than a line at a time, garbage may
Xremain on the screen between the old and the new bottom position.
X.br
XThe text attributes (font, size and style) in effect when any of the
Xtextedit routines are called must be those that were in effect when the
Xtextedit area was created.  (The routines should save and restore the
Xtext attributes, but currently they don't.)
X.br
XThe constants TRUE and FALSE used in the #include file are not defined
Xthere, even though the typedef bool is.
X.br
XBeware that the last argument to
X.I tealloc
Xand
X.I temove
Xis the width of the textedit area on the screen, not its right
Xcoordinate!
X.br
XIt is a pain that there are ``new'' and ``old'' versions of routines
Xlike tealloc, tedraw, temove and teclick.
XThe old routines should not be used any more, and the new ones should be
Xrenamed to the old names.
X.br
X.I Wdrawpar
Xand
X.I wparheight
Xare easy to use but not particularly efficient; they allocate a textedit
Xdata structure, call internal textedit routines to do the work, and then
Xdeallocate the data structure again.
X.br
XMissing functionality:
Xa way to affect the line breaking algorithm;
Xa way to display text centered or with justified margins;
Xa way to disable changes while still passing events (for selection, etc.);
Xmore keyboard editing functions (begin/end of line/file, etc.);
Xa way to suppress the automatic growing of the textedit area;
Xa way to specify a margin around the textedit area where mouse clicks
Xare still accepted by
X.I teevent.
END_OF_FILE
if test 6406 -ne `wc -c <'Doc/man/textedit.man'`; then
    echo shar: \"'Doc/man/textedit.man'\" unpacked with wrong size!
fi
# end of 'Doc/man/textedit.man'
fi
if test -f 'Doc/man/vt.man' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Doc/man/vt.man'\"
else
echo shar: Extracting \"'Doc/man/vt.man'\" \(7408 characters\)
sed "s/^X//" >'Doc/man/vt.man' <<'END_OF_FILE'
X.TH VT 3
X.SH NAME
XVT \- virtual terminal package for STDWIN
X.SH SYNOPSIS
X.nf
X.ft C
X#include "stdwin.h"
X#include "vt.h"
X
XVT *vtopen(char *title, int rows, int cols, int saverows);
Xvoid vtclose(VT *vt);
Xvoid vtansiputs(VT *vt, char *text, int len);
Xvoid vtsetcursor(VT *vt, int row, int col);
Xvoid vtreset(VT *vt);
Xbool vtresize(VT *vt, int rows, int cols, int saverows);
Xbool vtautosize(VT *vt);
XVT *vtfind(WINDOW *win);
Xvoid vtsend(VT *vt, char *text, int buf);
X.ft 1
X
X/* The following functions are actually macros */
X.ft C
XWINDOW *vtwindow(VT *vt);
Xint vtcwidth(VT *vt);
Xint vtcheight(VT *vt);
Xvoid vtsetnlcr(VT *vt, bool nlcr);
Xvoid vtsetlazy(VT *vt, bool lazy);
X.ft 1
X.fi
X.SH DESCRIPTION
X.I VT
Xis a package which emulates one or more virtual terminals in STDWIN
Xwindows.
XA VT structure contains a WINDOW pointer and data structures to save the
Xscreen contents, cursor position, etc.
XSuch a virtual terminal may be used to implement a terminal emulation
Xprogram on a micro-computer (which was the original goal of this
Xprogramming exercise), or as a tool to simplify interfacing a program
Xusing printf-style output to STDWIN.
XThe virtual terminal's cursor position is indicated by STDWIN's standard
Xtext caret, appearing to the left of the character at the cursor
Xposition.
XThis actually feels very natural in most cases.
X.PP
XThe functions you might want to know about are:
X.IP vtopen
XCreates the window and returns a pointer to a VT struct.
X.I Rows
Xand
X.I cols
Xspecify the size of the virtual terminal;
X.I saverows
Xspecifies the number of rows saved after they have scrolled off the top
Xof the terminal.
XIf something went wrong, a nil pointer is returned.
X.IP vtclose
XCloses the window and deallocates the data contained in the VT struct.
X.IP vtansiputs
XSends an output string to the virtual terminal.
X.I Len
Xspecifies the length of the string; if it is negative, the string is
Xterminated by a null character.
XControl character and escape sequence processing is done in the style of
XANSI terminals, with some limitations and extensions.
XWarning: unless
X.I "vtsetnlcr(vt, 1)"
Xhas been called, both a CR and LF character must be sent to properly
Xstart a new line.
X.IP vtsetcursor
XMoves the terminal's cursor to the indicated position.
XThe top left corner of the virtual terminal is position (0, 0).
X.IP vtreset
XCompletely resets the virtual terminal to its initial state.
XThe cursor is moved to position (0, 0).
XThe
X.I lazy
Xand
X.I nlcr
Xflags are not changed.
X.IP vtresize
XChanges the dimensions of the virtual terminal to explicitly given
Xnumbers.
XIn case of memory shortage, this function may fail irrecoverably,
Xleaving the VT struct in an unusable state (except to
X.IR vtclose ).
X.IP vtautosize
XChanges the dimensions of the virtual terminal to conform to the new
Xwindow size.
XIf possible, the sum of rows and saverows is kept constant.
XThe same limitations as for
X.I vtresize
Xapply.
X.IP vtfind
XGiven a window pointer, returns a pointer to the VT struct containing
Xthat window.
XReturns a nil pointer if no such VT struct exists.
X.IP vtsend
XThis function is defined in the library, but you might want to write
Xyour own version.
XIt is called by the library for cases where the virtual terminal must
Xsend a reply back to the computer system.
X(This happens in response to certain ANSI escape sequences, in
Xparticular ESC-[-6-n or ESC-[-c.)
XYou may want to ignore this output, or actually send it down a serial
Xline if you are implementing a terminal emulator program for a
Xmicro-computer.
XThe library's default version calls
X.I vtansiputs
Xwith the same parameters as passed to
X.I vtsend.
X.IP vtwindow
XReturns a pointer to the window contained in the VT struct.
X.IP vtcwidth
XReturns the width of characters drawn in the VT's window.
X.IP vtcheight
XReturns the height of characters drawn in the VT's window.
X.IP vtsetnlcr
XTurns the
X.I nlcr
Xoption on or off.
XWhen on, every LF character received is translated into a CR plus LF.
XThis is useful if you want to perform C style output to a VT window,
Xwhere lines are terminated by a single LF.
XInitially this option is off.
X.IP vtsetlazy
XTurns the
X.I lazy
Xoption on or off.
XWhen on, actual output to the terminal is delayed until the window's
Xdraw procedure is called; when off, all output is drawn immediately.
XInitially this option is off.
X.SH ANSI ESCAPE SEQUENCES
XThe termcap entries for xterm, vt100, vt100em and versaterm would all
Xwork with the emulated terminal (if you could somehow translate the
Xoutput intended for a Unix terminal into calls to
X.IR vtansiputs ).
XUnrecognized escape sequences and control characters are ignored.
X.PP
X*** List all implemented escape sequences here. ***
X.SH EXAMPLE
X.nf
X.ft C
X#include "stdwin.h"
X#include "vt.h"
X
Xmain() {
X	VT *vt;
X	winit();
X	wsetdefwinsize(80*wcharwidth('0'), 24*wlineheight());
X	vt= vtopen("VT", 24, 80, 100); /* Should check outcome */
X	vtautosize(vt);
X	vtsetnlcr(vt, 1); /* Map LF to CR LF */
X	vtansiputs(vt, "Hello, world\en", -1);
X	eventloop();
X	wdone();
X	exit(0);
X}
X
Xeventloop(vt) VT *vt; {
X	for (;;) {
X		EVENT e;
X		wgetevent(&e);
X		switch (e.type) {
X		case WE_SIZE:
X			vtautosize(vt); /* Should check outcome */
X			break;
X		case WE_CHAR:
X			{ char buf[2];
X			  buf[0]= e.u.character;
X			  vtansiputs(vt, buf, 1);
X			  break; }
X		case WE_MOUSE_DOWN:
X			vtsetcursor(vt,
X			            e.u.where.v / vtcheight(vt),
X			            e.u.where.h / vtcwidth(vt));
X			break;
X		case WE_COMMAND:
X			switch (e.u.command) {
X			case WC_CLOSE:                              return;
X			case WC_RETURN: vtansiputs(vt, "\en", 1);    break;
X			case WC_BACKSPACE: vtansiputs(vt, "\eb", 1); break;
X			case WC_TAB: vtansiputs(vt, "\et", 1);       break;
X			}
X			break;
X		}
X	}
X}
X.ft 1
X.fi
X.SH DIAGNOSTICS
X.I Vtopen
Xreturns a nil pointer if it can't allocate all the required memory or if
Xthe call to
X.I wopen
Xit makes fails.
X.br
X.I Vtresize
Xand
X.I vtautosize
Xreturn false (zero) if they can't allocate the extra memory required;
Xin this case the VT struct has been damaged beyond repair.
X.SH SEE ALSO
XSTDWIN documentation
X.SH AUTHOR
XGuido van Rossum
X.SH BUGS
XIn some versions of STDWIN, the scroll bars won't appear and some other
Xfunctionality won't be available unless the program calls
X.I wgetevent.
X.br
XUnless the application calls
X.I vtautosize
Xat all the right moments, it is quite possible that the window size
Xdoesn't match the size of the virtual terminal.
XWhen the window is too small, STDWIN's automatic scrolling will cause
Xthe text to jump around; when it is too large, portions of the
Xscrolled-away text will remain visible but unreachable by the cursor.
X.br
XThe ANSI terminal implementation is incomplete.
XIt certainly isn't a full-fledged VT100.
X.br
XThe behaviour of the cursor at the right margin is slightly
Xunconventional.
X.br
XBold output only works on the Macintosh, and requires that a font called
X``Bold'' (9 points) be available in the system file.  This font can be
Xfound in the resources for (some versions of) VersaTerm(TM).
X.br
XThe package makes the assumption that all characters have the same
Xwidth.
X.br
XThe order of parameters indicating rows and columns is internally
Xconsistent, but reversed with respect to order used for h and v
Xcoordinates in the rest of STDWIN.
X.br
XThe origin of cursor coordinates passed to
X.I vtsetcursor
Xis (0, 0), even though the origin used by ANSI escape sequences is
X(1, 1).
X.br
XThe header file defines functions that aren't really part of the public
Xinterface.
END_OF_FILE
if test 7408 -ne `wc -c <'Doc/man/vt.man'`; then
    echo shar: \"'Doc/man/vt.man'\" unpacked with wrong size!
fi
# end of 'Doc/man/vt.man'
fi
if test -f 'Ports/alfa/bind.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Ports/alfa/bind.c'\"
else
echo shar: Extracting \"'Ports/alfa/bind.c'\" \(7177 characters\)
sed "s/^X//" >'Ports/alfa/bind.c' <<'END_OF_FILE'
X/* TERMCAP STDWIN -- KEY BINDING. */
X
X/* Separated from the default tables; the application may override
X   the tables but not the executable code. */
X
X#ifdef SYSV
X#define TERMIO
X#endif
X
X#ifdef unix
X#ifndef TERMIO
X#define DO_SGTTY
X#endif
X#define DO_TERMCAP
X#endif
X
X#include "alfa.h"
X
X#ifdef DO_SGTTY
X#include <sgtty.h>
X#endif
X#ifdef TERMIO
X#include <termio.h>
X#endif
X
X#ifdef DO_TERMCAP
X/* Termcap functions: */
Xchar *tgetstr();
Xint tgetnum();
Xbool tgetflag();
X#endif /* DO_TERMCAP */
X
Xstatic void charbinding(), tcbinding(), setbinding();
X
X/* Get key definitions from tty settings. */
X
Xvoid
Xgetttykeydefs(fd)
X	int fd;
X{
X#ifdef unix
X#ifdef DO_SGTTY
X	struct sgttyb gttybuf;
X	struct tchars tcharbuf;
X#endif
X#ifdef TERMIO
X	struct termio tio;
X#endif
X
X	copydefaults();
X	
X#ifdef DO_SGTTY
X	gtty(fd, &gttybuf);
X	charbinding(SHORTCUT, 0, FIRST_CMD+WC_BACKSPACE,(int)gttybuf.sg_erase);
X	
X	ioctl(fd, TIOCGETC, (char *) &tcharbuf);
X	charbinding(SHORTCUT, 0, FIRST_CMD+WC_CANCEL, (int)tcharbuf.t_intrc);
X#endif
X#ifdef TERMIO
X	ioctl(fd, TCGETA, &tio);
X	charbinding(SHORTCUT, 0, FIRST_CMD+WC_BACKSPACE, (int)tio.c_cc[2]);
X	charbinding(SHORTCUT, 0, FIRST_CMD+WC_CANCEL, (int)tio.c_cc[0]);
X#endif
X
X#ifdef TIOCGLTC
X	{
X		struct ltchars ltcharbuf;
X		
X		ioctl(fd, TIOCGLTC, (char *) &ltcharbuf);
X		charbinding(SHORTCUT, 0, SUSPEND_PROC, ltcharbuf.t_suspc);
X		charbinding(SHORTCUT, 0, REDRAW_SCREEN, ltcharbuf.t_rprntc);
X		charbinding(SHORTCUT, 0, LITERAL_NEXT, ltcharbuf.t_lnextc);
X	}
X#endif /* TIOCGLTC */
X#endif /* unix */
X}
X
X#ifdef unix
Xstatic void
Xcharbinding(type, id, item, key)
X	int type;
X	int id, item;
X	int key;
X{
X	if (key != 0 && (key&0xff) != 0xff) {
X		char keys[2];
X		keys[0]= key;
X		keys[1]= EOS;
X		setbinding(&_wprimap[*keys & 0xff], type, id, item, keys);
X	}
X}
X#endif /* unix */
X
X/* Get key definitions from termcap. */
X
Xvoid
Xgettckeydefs()
X{
X#ifdef DO_TERMCAP
X	copydefaults();
X	tcbinding(SHORTCUT, 0, FIRST_CMD+WC_BACKSPACE,	"kb");
X	tcbinding(SHORTCUT, 0, FIRST_CMD+WC_LEFT,	"kl");
X	tcbinding(SHORTCUT, 0, FIRST_CMD+WC_RIGHT,	"kr");
X	tcbinding(SHORTCUT, 0, FIRST_CMD+WC_UP,		"ku");
X	tcbinding(SHORTCUT, 0, FIRST_CMD+WC_DOWN,	"kd");
X	/*
X	tcbinding(SHORTCUT, 0, FIRST_CMD+WC_CLEAR,	"kC");
X	tcbinding(SHORTCUT, 0, FIRST_CMD+WC_HOME,	"kh");
X	tcbinding(SHORTCUT, 0, FIRST_CMD+WC_HOME_DOWN,	"kH");
X	*/
X#endif /* DO_TERMCAP */
X}
X
X#ifdef DO_TERMCAP
Xstatic void
Xtcbinding(type, id, item, capname)
X	int type;
X	int id, item;
X	char capname[2];	/* Termcap capability name, e.g. "k1" */
X{
X	char buf[100];
X	char *p= buf;
X	char *keys;
X	
X	keys= tgetstr(capname, &p);
X	if (keys != NULL)
X		setbinding(&_wprimap[*keys & 0xff], type, id, item, keys);
X}
X#endif /* DO_TERMCAP */
X
X/* Bind a menu item to a meta-key.
X   As there are no meta-keys on standard Unix,
X   this is translated to ESC-key. */
X
Xvoid
Xwsetmetakey(id, item, key)
X	int id, item;
X	int key;
X{
X	char buf[3];
X	
X	buf[0]= '\033'; /* ESC */
X	buf[1]= key;
X	buf[2]= EOS;
X	wsetshortcut(id, item, buf);
X}
X
X/* Bind a menu item to a key sequence.
X   Note that this call is not part of the universal STDWIN interface,
X   only of the Unix interface for ASCII terminals. */
X
Xvoid
Xwsetshortcut(id, item, keys)
X	int id, item;
X	char *keys;
X{
X	if (keys == NULL || *keys == EOS)
X		return; /* Can't bind empty string */
X	copydefaults();
X	setbinding(&_wprimap[*keys & 0xff], SHORTCUT, id, item, keys);
X}
X
Xstatic struct keymap *extendmap();
X
Xstatic int
Xmapsize(map)
X	struct keymap *map;
X{
X	int size;
X	
X	if (map == NULL)
X		return 0;
X	for (size= 0; map[size].type != SENTINEL; ++size)
X		;
X	return size+1;
X}
X
Xstatic void
Xsetbinding(map, type, id, item, keys)
X	struct keymap *map;
X	int type;
X	int id, item;
X	char *keys;
X{
X	if (keys[1] == EOS) {
X		map->key= *keys;
X		map->type= type;
X		map->id= id;
X		map->item= item;
X	}
X	else {
X		struct keymap *nmap;
X		if (map->type != SECONDARY) {
X			map->type= SECONDARY;
X			map->id= createmap();
X		}
X		for (nmap= _wsecmap[map->id];
X			nmap->type != SENTINEL; ++nmap) {
X			if (nmap->key == keys[1])
X				break;
X		}
X		if (nmap->type == SENTINEL)
X			nmap= extendmap((int) map->id, (int) keys[1]);
X		if (nmap != NULL)
X			setbinding(nmap, type, id, item, keys+1);
X	}
X}
X
Xstatic struct keymap *
Xextendmap(imap, c)
X	int imap;
X	int c;
X{
X	L_DECLARE(size, map, struct keymap);
X	
X	if (imap == 0 || imap >= SECMAPSIZE || (map= _wsecmap[imap]) == NULL)
X		return NULL;
X	size= mapsize(map);
X	L_EXTEND(size, map, struct keymap, 1);
X	_wsecmap[imap]= map;
X	if (map == NULL)
X		return NULL;
X	map += size - 2;
X	map->type= ORDINARY;
X	map->key= c;
X	map[1].type= SENTINEL;
X	return map;
X}
X
Xstatic int
Xcreatemap()
X{
X	L_DECLARE(size, map, struct keymap);
X	int i;
X	
X	L_EXTEND(size, map, struct keymap, 1);
X	if (map == NULL)
X		return 0;
X	map->type= SENTINEL;
X	for (i= 0; i < SECMAPSIZE && _wsecmap[i] != NULL; ++i)
X		;
X	if (i >= SECMAPSIZE) { /* Overflow of _wsecmap array */
X		L_DEALLOC(size, map);
X		return 0;
X	}
X	else {
X		_wsecmap[i]= map;
X		return i;
X	}
X}
X
X/* Copy existing secondary key maps to dynamic memory.
X   Note: don't copy map 0, which is a dummy to force a dead-end street. */
X
Xstatic
Xcopydefaults()
X{
X	static bool been_here= FALSE;
X	int i;
X	struct keymap *map;
X	
X	if (been_here)
X		return;
X	been_here= TRUE;
X	
X	for (i= 1; i < SECMAPSIZE; ++i) {
X		map= _wsecmap[i];
X		if (map != NULL) {
X			int size= mapsize(map);
X			struct keymap *nmap;
X			int k;
X			nmap= (struct keymap *) malloc(
X				(unsigned) (size * sizeof(struct keymap)));
X			if (nmap != NULL) {
X				for (k= 0; k < size; ++k)
X					nmap[k]= map[k];
X			}
X			_wsecmap[i]= nmap;
X		}
X	}
X}
X
X/* Routines to get a nice description of a menu item's shortcuts.
X   TO DO: protect against buffer overflow; cache output so it
X   isn't called so often (i.e., twice for each drawitem call!). */
X
Xstatic char *
Xcharrepr(c)
X	int c;
X{
X	static char repr[10];
X
X	switch (c) {
X
X	case 033:
X		return "ESC";
X	
X	case '\r':
X		return "CR";
X	
X	case '\b':
X		return "BS";
X	
X	case '\t':
X		return "TAB";
X	
X	case 0177:
X		return "DEL";
X
X	default:
X		if (c < ' ') {
X			repr[0]= '^';
X			repr[1]= c|'@';
X			repr[2]= '\0';
X		}
X		else if (c < 0177) {
X			repr[0]= c;
X			repr[1]= '\0';
X		}
X		else {
X			repr[0]= '\\';
X			repr[1]= '0' + (c>>6);
X			repr[2]= '0' + ((c>>3) & 07);
X			repr[3]= '0' + (c & 07);
X			repr[4]= '\0';
X		}
X		return repr;
X
X	}
X}
X
Xstatic char *
Xaddrepr(cp, c)
X	char *cp;
X	int c;
X{
X	char *rp= charrepr(c);
X	
X	while (*rp != '\0')
X		*cp++ = *rp++;
X	return cp;
X}
X
Xstatic char *
Xfollowmap(cp, map, id, item, stack, level)
X	char *cp;
X	struct keymap *map;
X	int id, item;
X	unsigned char *stack;
X	int level;
X{
X	if (map->type == SHORTCUT) {
X		if (map->id == id && map->item == item) {
X			int i;
X			for (i= 0; i < level; ++i) {
X				cp= addrepr(cp, (int) stack[i]);
X				*cp++ = '-';
X			}
X			cp= addrepr(cp, (int) map->key);
X			*cp++ = ',';
X			*cp++ = ' ';
X		}
X	}
X	else if (map->type == SECONDARY) {
X		stack[level]= map->key;
X		map= _wsecmap[map->id];
X		for (; map->type != SENTINEL; ++map)
X			cp= followmap(cp, map, id, item, stack, level+1);
X	}
X	return cp;
X}
X
Xvoid
Xgetbindings(buf, id, item)
X	char *buf;
X	int id;
X	int item;
X{
X	char *cp= buf;
X	unsigned char stack[50];
X	struct keymap *map;
X	
X	for (map= _wprimap; map < &_wprimap[256]; ++map)
X		cp= followmap(cp, map, id, item, stack, 0);
X	if (cp > buf)
X		cp -= 2;
X	*cp= EOS;
X}
END_OF_FILE
if test 7177 -ne `wc -c <'Ports/alfa/bind.c'`; then
    echo shar: \"'Ports/alfa/bind.c'\" unpacked with wrong size!
fi
# end of 'Ports/alfa/bind.c'
fi
echo shar: End of archive 12 \(of 19\).
cp /dev/null ark12isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 19 archives.
    rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0