[comp.sources.misc] v07i045: CRISP release 1.9 part 24/32

allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc) (06/22/89)

Posting-number: Volume 7, Issue 45
Submitted-by: fox@marlow.UUCP (Paul Fox)
Archive-name: crisp1.9/part25



#!/bin/sh
# this is part 4 of a multipart archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file ./cm.c continued
#
CurArch=4
if test ! -r s2_seq_.tmp
then echo "Please unpack part 1 first!"
     exit 1; fi
( read Scheck
  if test "$Scheck" != $CurArch
  then echo "Please unpack part $Scheck next!"
       exit 1;
  else exit 0; fi
) < s2_seq_.tmp || exit 1
echo "x - Continuing file ./cm.c"
sed 's/^X//' << 'SHAR_EOF' >> ./cm.c
X	if (l_flag) {
X		printf("Entering macro '%s'\n", name);
X		list_macro(0, lp);
X		}
X	macro_tbl[macro_cnt].m_list = lp;
X	macro_cnt++;
X}
Xvoid
Xpatom(first_atom, mptr, str)
XLIST	*first_atom;
XLIST	*mptr;
Xchar	*str;
X{
X	char	buf[10];
X	int	atom_no = mptr - first_atom;
X
X	switch (*mptr) {
X	  case	F_HALT:		nhalt++;	break;
X	  case	F_INT:		nint++;		break;
X	  case F_LIT: 
X	  case	F_STR:		nstr++;		break;
X	  case	F_ID:		nid++;		break;
X	  case	F_LIST:		nlist++;	break;
X	  case	F_NULL:		nnull++;	break;
X	  default:		ndontknow++; 	break;
X	  }
X
X	if (l_flag == 0 || mptr == NULL)
X		return;
X	if (*mptr == F_STR && strcmp(str, "macro") == 0)
X		printf("\n");
X	sprintf(buf, "0x%02x", *mptr);
X	printf("Atom %02x: ", atom_no);
X	if (L_flag) {
X		if (*mptr == F_HALT || *mptr == F_END)
X			printf("[%02x/........] ", *mptr);
X		else if (*mptr == F_LIST || *mptr == F_ID)
X			printf("[%02x/....%04x] ", *mptr, LGET16(mptr));
X		else
X			printf("[%02x/%08lx] ", *mptr, LGET32(mptr));
X		}
X	printf("%s	",
X		*mptr == F_HALT	? "HALT" :
X		*mptr == F_INT ? "int" :
X		*mptr == F_STR ? "str" :
X		*mptr == F_LIT ? "lit" :
X		*mptr == F_LIST ? "list" :
X		*mptr == F_END ? "***END***" :
X		*mptr == F_ID ? "ID" : buf);
X	if (*mptr == F_STR)
X		printf("%s\n", str);
X	else if (*mptr == F_LIT)
X		printf("\"%s\"\n", str);
X	else if (*mptr == F_HALT || *mptr == F_END)
X		printf("\n");
X	else if (*mptr == F_ID)
X		printf("%s\n", builtin[LGET16(mptr)].name);
X	else if (*mptr == F_LIST) {
X		int i = LGET16(mptr);
X		if (i == 0)
X			printf("======\n");
X		else
X			printf("--> %x\n", atom_no + i);
X		}
X	else
X		printf("%08lx\n", LGET32(mptr));
X
X}
Xvoid
Xewprintf(s, a, b, c, d, e, f, g, h, i, j, k)
Xchar	*s;
X{
X	fprintf(stderr, s, a, b, c, d, e, f, g, h, i, j, k);
X	fprintf(stderr, "\n");
X}
Xvoid
Xerrorf(s, a, b, c, d, e, f, g, h, i, j, k)
Xchar	*s;
X{
X	fprintf(stderr, s, a, b, c, d, e, f, g, h, i, j, k);
X	fprintf(stderr, "\n");
X}
SHAR_EOF
echo "File ./cm.c is complete"
chmod 0444 ./cm.c || echo "restore of ./cm.c fails"
mkdir . >/dev/null 2>&1
echo "x - extracting ./config.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > ./config.c &&
X/**************************************************************
X *
X *	CRISP - Custom Reduced Instruction Set Programmers Editor
X *
X *	(C) Paul Fox, 1989
X *	43, Jerome Close	      Tel: +44 6284 4222
X *	    Marlow
X *	     Bucks.
X *		England SL7 1TX
X *
X *
X *    Please See COPYRIGHT notice.
X *
X *   This file contains machine independent configuration variables.
X *
X *    Machine dependent ones appear in unix.c or vms.c
X *
X **************************************************************/
X# include	"list.h"
X# include	"alt.h"
X
XSCCSID("@(#) config.c 1.7, (C) 1989, P. Fox");
X
Xchar	*bfile = "BFILE=newfile";
Xchar	*bflags = "BFLAGS=-i60";
Xchar	*bterm = "vt100\0      Spare string space";
Xchar	*bpackages = "BPACKAGES=c,h:t";
X
Xint	strip_cr_flag = TRUE;	/* Set to FALSE if dont want <CR> stripped */
X				/* by default.				   */
XCOLOR	col_table = {
X		0,		/* Background.		*/
X		2,		/* Normal text.		*/
X		11,		/* Selected window title*/
X		14,		/* Normal messages.	*/
X		12,		/* Error messages.	*/
X		4,		/* Hi-lite background.  */
X		10,		/* Hi-lite foreground.  */
X		};
X
Xstruct k_tbl k_tbl[] = {
X		ALT_A,		"mark 4",
X		ALT_B,		"_case",
X		ALT_C,		"mark 2",
X		ALT_D,		"delete_line",
X		ALT_E,		"edit_file",
X		ALT_G,		"goto_line",
X		ALT_I,		"insert_mode",
X		ALT_J,		"goto_bookmark",
X		ALT_K,		"delete_to_eol",
X		ALT_L,		"mark 3",
X		ALT_M,		"mark",
X		ALT_O,		"output_file",
X		ALT_P,		"_print",
X		ALT_R,		"read_file",
X		ALT_S,		"search_fwd",
X		ALT_T,		"translate",
X		ALT_U,		"undo",
X		ALT_W,		"write_buffer",
X		ALT_V,		"version",
X		ALT_X,		"exit",
X		CTRL_X,		"exit",
X		ALT_Z,		"dos",
X		F1,		"change_window",
X		F2,		"move_edge",
X		F3,		"create_edge",
X		F4,		"delete_edge",
X		F5,		"search_fwd",
X		F6,		"translate",
X		F7,		"remember",
X		F8,		"playback",
X		F9,		"load_macro",
X		F10,		"execute_macro",
X		SHIFT_F1+6,	"pause",
X		KEY_0,		"paste",
X		KEY_0+1,	"end_of_line",
X		KEY_0+2,	"down",
X		KEY_0+3,	"page_down",
X		KEY_0+4,	"left",
X		KEY_0+6,	"right",
X		KEY_0+7,	"beginning_of_line",
X		KEY_0+8,	"up",
X		KEY_0+9,	"page_up",
X		KEY_0+13,	"undo",
X		213,		"copy",
X		214,		"cut",
X		212,		"delete_block",
X		223,		"top_of_window",
X		CTRL_0+1,	"end_of_window",
X		225,		"top_of_buffer",
X		219,		"end_of_buffer",
X		0,		NULL
X		};
SHAR_EOF
chmod 0444 ./config.c || echo "restore of ./config.c fails"
mkdir . >/dev/null 2>&1
echo "x - extracting ./debug.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > ./debug.c &&
X/**************************************************************
X *
X *	CRISP - Custom Reduced Instruction Set Programmers Editor
X *
X *	(C) Paul Fox, 1989
X *	43, Jerome Close	      Tel: +44 6284 4222
X *	    Marlow
X *	     Bucks.
X *		England SL7 1TX
X *
X *
X *    Please See COPYRIGHT notice.
X *
X **************************************************************/
X# include	"list.h" 
X
XSCCSID("@(#) debug.c 1.7, (C) 1989, P. Fox");
Xchar	*crisp_log = "crisp.log";
Xint	dflag = 0;
Xextern	int	pflag;
Xstatic FILE	*debug_fp = NULL;
Xextern	BUILTIN builtin[];
Xvoid	list_macro();
X
X# ifdef	PROTO
X	void	trace_log(char *, DOT);
X	void	trace_ilog(char *, DOT);
X# else
X	void	trace_log();
X	void	trace_ilog();
X# endif
X
Xdo_debug()
X{	
X
X	if (argv[1].l_flags != F_NULL)
X		dflag = argv[1].l_int & 0xffff;
X	else
X		dflag = !dflag;
X	ewprintf("[Debug %s (0x%04x)%s%s]", dflag ? "ON" : "OFF", dflag,
X		dflag & DB_REGEXP ? " REGEXP" : "",
X		dflag & DB_UNDO ? " UNDO" : "",
X		dflag & DB_PROMPT ? " PROMPT" : ""
X		);
X	if (!dflag) {
X		fclose(debug_fp);
X		debug_fp = NULL;
X		}
X	return 0;
X}
Xdo_profile()
X{	
X
X	if (argv[1].l_flags != F_NULL)
X		pflag = argv[1].l_int & 0xffff;
X	else
X		pflag = !pflag;
X	ewprintf("[Profiling %s]", pflag ? "ON" : "OFF");
X	return 0;
X}
Xtrace_bit(lp, level)
XLIST	*lp;
X{	LIST *lp1 = lp + level;
X	trace_log("First bit of list:\n");
X	if (lp == NULL) {
X		trace_log("  nil\n");
X		return;
X		}
X	while (lp < lp1) {
X		if (*lp == F_HALT) trace_log("F_HALT\n");
X		else if (*lp == F_INT) trace_log("  F_INT:  %ld\n", LGET32(lp));
X		else if (*lp == F_STR) trace_log("  F_STR:  '%s'\n", LGET32(lp));
X		else if (*lp == F_ID)  trace_log("  F_ID:   %s\n",
X			builtin[LGET16(lp)].name);
X		else if (*lp == F_LIST) trace_log("F_LIST: %d\n", LGET16(lp));
X		else {
X			trace_log("<Dont know>\n");
X			break;
X			}
X		lp += sizeof_atoms[*lp];
X		}
X}
Xvoid
Xtrace_list(lp)
XLIST	*lp;
X{	extern int dflag;
X	if (dflag == 0)
X		return;
X	if (lp == NULL) {
X		trace_ilog("nil\n");
X		return;
X		}
X	trace_ilog("(", (char *) NULL);
X	while (*lp != F_HALT) {
X		r_str	*rp;
X		if (*lp == F_INT)
X			trace_log("%ld ", LGET32(lp));
X		else if (*lp == F_STR) {
X			trace_log("%s ", (char *) LGET32(lp));
X			}
X		else if (*lp == F_RSTR) {
X			rp = (r_str *) LGET32(lp);
X			trace_log("%s ", rp->r_str);
X			}
X		else if (*lp == F_LIT) {
X			trace_log("\"%s\" ", (char *) LGET32(lp));
X			}
X		else if (*lp == F_ID)
X			trace_log("%s ", builtin[LGET16(lp)].name);
X		else if (*lp == F_LIST) {
X			u_int16 i = LGET16(lp);
X			trace_log("(..) ", (char *) NULL);
X			if (i == 0)
X				break;
X			lp += i;
X			continue;
X			}
X		lp += sizeof_atoms[*lp];
X		}
X
X	trace_log(")\n", (char *) NULL);
X}
X/* VARARGS1 */
Xvoid
Xtrace_ilog(str, ptr)
Xchar	*str;
Xchar	*ptr;
X{	int	i = nest_level;
X	char	buf[1024];
X	static	int	old_level = -1;
X
X	if (dflag == 0)
X		return;
X	if (old_level == nest_level)
X		strcpy(buf, "\t");
X	else
X		sprintf(buf, "%02d:.....", nest_level);
X
X	while (i-- > 0)
X		strcat(buf, old_level == nest_level ? " " : ".");
X	trace_log(buf);
X	trace_log(str, ptr);
X	old_level = nest_level;
X}
X/* VARARGS1 */
Xvoid
Xtrace_log(str, ptr)
Xchar	*str;
Xchar	*ptr;
X
X{
X	extern	int	dflag;
X	extern int flush_flag;
X
X	if (dflag == 0)
X		return;
X
X	if (debug_fp == NULL)
X		debug_fp = fopen(crisp_log, "w"); 
X
X	if (debug_fp) {
X		(void) fprintf(debug_fp, str, ptr);
X		if (flush_flag)
X			fflush(debug_fp);
X		}
X}
Xvoid
Xlist_macro(level, lp)
XLIST	*lp;
X{	int	tokcnt = 0;
X
X	for (; *lp != F_END; lp += sizeof_atoms[*lp]) {
X		if (tokcnt++)
X			trace_log(" ");
X		if (*lp == F_INT)
X			trace_log("%ld", LGET32(lp));
X		else if (*lp == F_ID)
X			trace_log("%s", builtin[LGET32(lp)].name);
X		else if (*lp == F_STR) {
X			char	*cp;
X			char	*str = (char *) LGET32(lp);
X			for (cp = str; *cp; cp++)
X				if (*cp == '"' && cp != str)
X					trace_log("\\\"");
X				else if (*cp == '\r')
X					trace_log("\\r");
X				else if (*cp == '\n')
X					trace_log("\\n");
X				else if (*cp == '\t')
X					trace_log("\\t");
X				else
X					trace_log("%c", *cp);
X			if (str[0] == '"')
X				trace_log("\"");
X			}
X		else if (*lp == F_LIST) {
X			int	i;
X			trace_log("\n    ");
X			for (i = level; i-- > 0; )
X				trace_log("    ");
X			trace_log("(");
X			list_macro(level+1, lp + sizeof_atoms[F_LIST]);
X			trace_log(")");
X			}
X		}
X	if (level == 0)
X		trace_log("\n");
X}
Xvoid
Xdump_all_lines()
X{
X# if 0
X	BUFFER	*bp;
X	LINE	*lp;
X	int	line_no;
X	char	buf[132];
X
X	trace_log("Dump all Lines\n");
X	for (bp = bheadp; bp; bp = bp->b_bufp) {
X		trace_log("Buffer %s:\n", bp->b_fname);
X		line_no = 0;
X		for (lp = lforw(bp->b_linep); lp != bp->b_linep; 
X		     lp = lforw(lp)) {
X			(void) sprintf(buf, "\tLine %3d: used=%2d size=%2d fl=%d\n",
X				++line_no, lp->l_used, lp->l_size,
X				lp->l_flags);
X			trace_log(buf);
X			}
X		trace_log("\n");
X		}
X# endif
X}
Xvoid
Xdmp_lines(bp)
XBUFFER	*bp;
X{	LINE	*lp;
X# if 0
X	int	i = 0;
X	
X	trace_log("DMP_LINES\n");
X	trace_log("WP=%08lx  ", curwp);
X	trace_log("WP->w_bufp=%08lx ", curwp->w_bufp);
X	trace_log("hooked=%s ", hooked ? "TRUE" : "FALSE");
X	trace_log("*cur_line=%d \n", *cur_line);
X	trace_log("BP=%08lx  ", bp);
X	trace_log("b_line=%d  ", bp->b_line);
X	trace_log("b_linep=%08lx\n\t", bp->b_linep);
X	lp = lforw(bp->b_linep);
X	while (1) {
X		if (++i > 6) {
X			i = 0;
X			trace_log("\n\t");
X			}
X		trace_log("%08lx ", lp);
X		lp = lforw(lp);
X		if (lp == lforw(bp->b_linep))
X			break;
X		}
X	trace_log("\n");
X# endif
X}
Xvoid
Xphex(str, n)
Xchar	*str;
X{
X	char	buf[256];
X	int	i = 0;
X	if (dflag == 0)
X		return;
X
X	buf[0] = NULL;
X	while (n-- > 0) {
X		(void) sprintf(buf+strlen(buf), "%02x ", *str++);
X		if (++i >= 16 || n <= 0) {
X			strcat(buf, "\n");
X			trace_log("%s", buf);
X			i = 0;
X			buf[0] = NULL;
X			}
X		}
X}
Xvoid
Xdmp_win(winp, lp)
XWINDOW	*winp;
XLINE	*lp;
X{
X	WINDOW	*wp = wheadp;
X
X	trace_log("DMP_WIN\n");
X	trace_log("wp=%08lx  ", winp);
X	trace_log("lp=%08lx  ", lp);
X	trace_log("curwp=%08lx ", curwp);
X	trace_log("curbp=%08lx\n", curbp);
X	trace_log("wheadp=");
X	for (; wp; wp = wp->w_wndp)
X		trace_log("%08lx ", wp);
X	trace_log("\n");
X	dmp_lines(curbp);
X}
Xvoid
Xdmp_coord()
X{
X	WINDOW	*wp;
X	trace_log("dmp_coord:\n");
X	for (wp = wheadp; wp; wp = wp->w_wndp) {
X		trace_log("%08lx: ", wp);
X		trace_log("(%d, ", wp->w_x);
X		trace_log("%d) ", wp->w_y);
X		trace_log("w=%d ", wp->w_w);
X		trace_log("h=%d ", wp->w_h);
X		trace_log("%s", wp->w_tiled ? 
X			"tiled" : "not tiled");
X		}
X	trace_log("curwp=%08lx\n", curwp);
X}
Xvoid
Xprint_line(lp)
XLINE	*lp;
X{	char	buf[128];
X	sprintf(buf, "%08lx:	used=%d size=%d tell=%ld fl=%d ", 
X		lp, lp->l_used, lp->l_size, lp->l_tell, lp->l_flags);
X	if (lp->l_flags & L_INCORE)
X		strcat(buf, "INCORE ");
X	if (lp->l_flags & L_LOCKED)
X		strcat(buf, "LOCKED");
X	strcat(buf, "\n");
X	trace_log(buf);
X}
Xvoid
Xtrace_sym(sp)
XSYMBOL	*sp;
X{
X	if (dflag == 0)
X		return;
X
X	trace_ilog("  %s := ", sp->s_name);
X	if (sp->s_type == F_INT)
X		trace_log("%ld\n", sp->s_int);
X	else if (sp->s_type == F_STR || sp->s_type == F_RSTR)
X		trace_log("'%s'\n", c_string(sp->s_str->r_str));
X	else {
X		if (sp->s_list == NULL)
X			trace_log("NIL\n");
X		else
X			trace_list(sp->s_list);
X		}
X}
Xvoid
Xkey_list(k)
Xchar	*k[];
X{	int	i;
X	char	buf[128];
X	u_char	*cp;
X
X	for (i = 0; i < NFKEYS; i++) {
X		sprintf(buf, "K[%d] := '", i);
X		cp = (u_char*) k[i];
X		if (cp == NULL)
X			strcat(buf, "<null>");
X		else
X			while (*cp) {
X				unsigned char ch = *cp++;
X				if (ch & 0x80) {
X					sprintf(buf+strlen(buf), "[0x%02x]", ch);
X					continue;
X					}
X				if (ch < ' ') {
X					strcat(buf, "^");
X					ch += '@';
X					}
X				sprintf(buf + strlen(buf), "%c", ch);
X				}
X		trace_log("%s'\n", buf);
X		}
X}
Xtrace_trigger(type)
X{
X	static	char	*triggers[] = {
X		"REG_TYPED",
X		"REG_EDIT",
X		"REG_ALT_H",
X		"REG_UNASSIGNED",
X		"REG_IDLE",
X		"REG_EXIT",
X		"REG_NEW",
X		"REG_CTRLC",
X		"REG_INVALID"
X		};
X	trace_log("*** TRIGGER=%s ***\n", triggers[type]);
X}
Xtrace_refs()
X{
X	BUILTIN	*bp;
X	char	buf[128];
X
X	if (dflag == 0)
X		return;
X	for (bp = builtin; bp < &builtin[sizeof_builtin]; bp++) {
X		sprintf(buf, "%5ld	%s\n", bp->reference, bp->name);
X		trace_log(buf);
X		}
X}
Xchar *
Xc_string(str)
Xregister char	*str;
X{
X	static char buf[256];
X	register char *bp = buf;
X	if (dflag == 0)
X		return str;
X	while (*str) {
X		if (*str == '\n')	*bp++ = '\\', *bp++ = 'n';
X		else if (*str == '\r')	*bp++ = '\\', *bp++ = 'r';
X		else if (*str == '\t')	*bp++ = '\\', *bp++ = 't';
X		else if (*str == '\\')	*bp++ = '\\', *bp++ = '\\';
X		else
X			*bp++ = *str;
X		str++;
X		if (bp > &buf[sizeof buf - 10]) {
X			*bp++ = '.';
X			*bp++ = '.';
X			*bp++ = '.';
X			break;
X			}
X		}
X	*bp = NULL;
X	return buf;
X}
Xtrace_acc()
X{	static	long	old_acc = -1234567;
X	if (dflag == 0)
X		return;
X	if (acc_type == F_INT) {
X		if (old_acc != accumulator)
X			trace_ilog("  ACC = %ld\n", accumulator);
X		old_acc = accumulator;
X		}
X	else if (acc_type == F_STR) {
X		old_acc = -1234567;
X		trace_ilog("  SACC = '%s'\n", c_string(saccumulator));
X		}
X	else {
X		if (saccumulator == NULL)
X			trace_ilog ("  LACC = NIL\n");
X		else {
X			trace_ilog ("  LACC = ");
X			trace_list((LIST *) saccumulator);
X			}
X		}
X}
SHAR_EOF
chmod 0444 ./debug.c || echo "restore of ./debug.c fails"
mkdir . >/dev/null 2>&1
echo "x - extracting ./display.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > ./display.c &&
X/**************************************************************
X *
X *	CRISP - Custom Reduced Instruction Set Programmers Editor
X *
X *	(C) Paul Fox, 1989
X *	43, Jerome Close	      Tel: +44 6284 4222
X *	    Marlow
X *	     Bucks.
X *		England SL7 1TX
X *
X *
X *    Please See COPYRIGHT notice.
X *
X *	24 Jan 1989 [PDF]	Improved performance when updating
X *				screen.
X *
X **************************************************************/
X
X#include	"list.h"
X
X# define	trace_log(a,b)	/* Turn off debugging here. */
XSCCSID("@(#) display.c 1.16, (C) P. Fox");
X# define	V_CHANGE	0x01
X
X/*----------------------------------------
X/*   Following #define's are expressions
X/*   which return 1 or 0 depending on
X/*   whether certain of the 4 window
X/*   borders are on or not.
X/*----------------------------------------*/
X# define	LBORDERS(wp)	(wp->w_tiled == W_POPUP || \
X				 border_flag || \
X				 wp->w_x > 1)
X# define	RBORDERS(wp)	(wp->w_tiled == W_POPUP || \
X				 border_flag || \
X				 wp->w_x + wp->w_w < ncol-3)
X# define	TBORDERS(wp)	(1)
X# define	BBORDERS(wp)	(wp->w_tiled == W_POPUP || \
X				 (wp->w_y + wp->w_h != nrow -1) || \
X				 border_flag)
X
Xint	updating = 0;
Xextern	int	border_flag;
Xextern	int	imode;
Xextern	int	start_line, start_col;
Xextern	int	end_line, end_col;
Xextern	int	mark_type;
Xstatic	int	tl;
Xstatic	int	mark_areas;	/* TRUE if should mark current window.	*/
Xint	pchar_buf[10];		/* Printable character buffer. */
Xextern unsigned char _chars_[256];
Xstatic char hex_digits[] = "0123456789ABCDEF";
Xextern int base_flag;
XWINDOW *wp;
Xstatic WINDOW	*current_window;
X
Xstatic	BYTE	vt_color;
X
Xextern	char	*echo_line;
Xint     sgarbf  = TRUE;                 /* TRUE if screen is garbage.   */
Xu_int16	vtrow   = 0;                    /* Virtual cursor row.          */
Xu_int16	vtcol   = 0;                    /* Virtual cursor column.       */
Xu_int16	ttrow   = HUGE;                 /* Physical cursor row.         */
Xu_int16	ttcol   = HUGE;                 /* Physical cursor column.      */
Xu_int16	tttop   = HUGE;                 /* Top of scroll region.        */
Xu_int16	ttbot   = HUGE;                 /* Bottom of scroll region.     */
X
XBYTE   **vscreen;
XBYTE   **pscreen;
XBYTE   *video;				/* Actual screen data.          */
XBYTE   *blanks;                         /* Blank line image.            */
Xint	*vflags;			/* Array of flags.		*/
XBYTE	*vp;
X
Xvoid	vtputs();
Xvoid	vtupdate();
Xvoid	vtputl();
Xvoid	ucopy();
Xvoid	draw_title();
Xvoid	uline();
Xstatic	int	window_indent;	/* Indent from start of line for sideways scrolling. */
Xstatic	int	indent;		/* Indent from start of line for sideways scrolling. */
X/*
X * Initialize the data structures used
X * by the display code. The edge vectors used
X * to access the screens are set up. The operating
X * system's terminal I/O channel is set up. Fill the
X * "blanks" array with ASCII blanks. The rest is done
X * at compile time. The original window is marked
X * as needing full update, and the physical screen
X * is marked as garbage, so all the right stuff happens
X * on the first call to redisplay.
X */
Xvoid
Xvtinit() 
X{
X
X	vt_color = FG(col_table.c_normal);
X	char_width_init();
X
X	ttinit();
X	ttopen();
X	vtinit1();
X}
Xvtinit1()
X{
X	register int    i;
X	
X	if (video) {
X		chk_free(video);
X		chk_free(vscreen);
X		chk_free(pscreen);
X		chk_free(vflags);
X		chk_free(blanks);
X		chk_free(echo_line);
X		}
X	video = (BYTE *) chk_alloc(sizeof (BYTE) * 2 * nrow * ncol);
X	vscreen = (BYTE **) chk_alloc(sizeof (BYTE *) * nrow);
X	pscreen = (BYTE **) chk_alloc(sizeof (BYTE *) * nrow);
X	vflags = (int *) chk_alloc(sizeof (int) * nrow);
X	blanks = (BYTE *) chk_alloc(sizeof (BYTE) * ncol);
X	echo_line = chk_alloc(ncol + 1);
X
X	if (video == NULL || vscreen == NULL || pscreen == NULL || 
X		echo_line == NULL || blanks == NULL || vflags == NULL)
X		panic("Cannot allocate screen buffer.");
X
X	vtblanks();
X	for (i = 0; i < nrow; ++i) {
X		vflags[i] = 0;
X		vscreen[i] = video + (2 * i * ncol);
X		pscreen[i] = vscreen[i] + ncol;
X		}
X	vp = vscreen[0];
X}
Xvtblanks()
X{	register int i;
X	BYTE normal_space = (BYTE) (FG(col_table.c_normal) | ' ');
X	for (i = 0; i < ncol; )
X		blanks[i++] = normal_space;
X
X}
X
X/*
X * Tidy up the virtual display system
X * in anticipation of a return back to the host
X * operating system. Right now all we do is position
X * the cursor to the last line, erase the line, and
X * close the terminal channel.
X */
Xvoid
Xvttidy() 
X{
X	ttmove(nrow-1, (u_int16) 0);
X	ttputc(FG(col_table.c_normal));
X	tteeol();
X	tttidy();
X	ttflush();
X	ttclose();
X}
X
X/*
X * Move the virtual cursor to an origin
X * 0 spot on the virtual display screen. 
X */
Xvoid
Xvtmove(row, col) 
X{
X	if (row > nrow)
X		row = nrow;
X	if (col >= ncol - 1)
X		col = ncol - 1;
X	vtrow = (u_int16) row;
X	vtcol = (u_int16) col;
X	vp = vscreen[vtrow];
X}
X
X/*
X * Write a character to the virtual display.
X */
X# define	vtputc(c) 	{ if (vtcol < ncol) VTPUTC(c); }
Xvoid
XVTPUTC(c) 
Xregister int c; 
X{	int	attr;
X
X# define	ADDC(ch)	indent ? indent-- : (vp[vtcol++] = ch)
X
X	if (_chars_[c & 0xff] & 0x08) {
X		ADDC(c);
X		return;
X		}
X		
X	attr = c & COLOR_MASK;
X	c &= 0xff;
X	if (c != '\t') {
X		int	right_edge;
X		int	*cp;
X		int	i;
X		if ((i = printable_char(c | attr)) == 1) {
X			ADDC(pchar_buf[0]);
X			return;
X			}
X		right_edge = wp->w_x + wp->w_w;
X		for (cp = pchar_buf; i-- > 0 && vtcol < right_edge; )
X			ADDC(*cp++ | attr);
X		return;
X		}
X	{int	i = vtcol + window_indent - indent;
X	int	w_x = wp->w_x - !LBORDERS(wp);
X	int	ch_width;
X	int	ch;
X	int	right;
X	
X	ch_width = next_tab_stop(i - w_x + 1) + w_x - i;
X	ch = (BYTE) (' ' | attr);
X	right = w_x + wp->w_w;
X
X	if (ch_width + vtcol >= right)
X		ch_width = right - vtcol;
X	while (ch_width-- > 0)
X		ADDC(ch);
X	return;
X	}
X
X}
Xprintable_char(c1)
X{	register int c = c1 & 0xff;
X
X	pchar_buf[0] = c1;
X	if (_chars_[c] & 0x08)
X		return 1;
X
X	if (base_flag == 0 && pt.pt_character[0]) {
X		if (c < ' ')
X			pchar_buf[0] = (BYTE) (c1 | 0x80);
X		return 1;
X		}
X	if (base_flag == 0 && c < ' ') {
X		BYTE attr = c1 & 0xff00;
X		extern char *ctrl_chars[];
X		extern char char_width_tbl[];
X		char *cp = ctrl_chars[c];
X		int	i;
X		int w = char_width_tbl[c];
X		for (i = 0; i < w; )
X			pchar_buf[i++] = attr | *cp++;
X		return w;
X		}
X	pchar_buf[0] = '\\';
X	if (base_flag < 2) {
X		pchar_buf[1] = 'x';
X		pchar_buf[2] = hex_digits[(c >> 4) & 0x0f];
X		pchar_buf[3] = hex_digits[c & 0x0f];
X		}
X	else {
X		pchar_buf[1] = hex_digits[(c >> 6) & 3];
X		pchar_buf[2] = hex_digits[(c >> 3) & 7];
X		pchar_buf[3] = hex_digits[c & 7];
X		}
X	return 4;
X}
X
X/*
X * Erase from the end of the
X * software cursor to the end of the
X * line on which the software cursor is
X * located. The display routines will decide
X * if a hardware erase to end of line command
X * should be used to display this.
X */
Xvoid
Xvteeol()
X{
X	register BYTE	*bp;
X	register u_int16 col = ncol;
X	int	color = FG(col_table.c_normal);
X	BYTE normal_space = color | ' ';
X
X	col = wp->w_x + wp->w_w;
X	bp = &vp[vtcol];
X	while (vtcol < col)
X		vtcol++, *bp++ = normal_space;
X	if (RBORDERS(wp)) {
X		vtputc(CH_VERTICAL | color);
X		}
X
X}
X
X/*
X * Make sure that the display is
X * right. This is a three part process. First,
X * scan through all of the windows looking for dirty
X * ones. Check the framing, and refresh the screen.
X * Second, make sure that "currow" and "curcol" are
X * correct for the current window. Third, make the
X * virtual and physical screens the same.
X */
Xupdate() 
X{
X	register BYTE  *vp1;
X	register BYTE  *vp2;
X	register int    i;
X	extern int display_enabled;
X
X	if (updating || !display_enabled)
X		return;
X	updating++;
X	if (typeahead()) {
X		updating--;
X		return;
X		}
X		
X	current_window = curwp;
X	
X	if (sgarbf)			/* must update everything */
X		for (wp = wheadp; wp; wp = wp->w_wndp) 
X			wp->w_flag |= WFHARD;
X	else if (curbp->b_anchor && curbp->b_anchor->a_type == MK_COLUMN)
X		curwp->w_flag |= WFHARD;
X	for (wp = wheadp; wp; wp = wp->w_wndp) {
X		WINDOW *wp1;
X		if (wp->w_flag) {
X			upd_update(wp);
X			/*----------------------------------------
X			/*   Dirty all windows after this, cos this
X			/*   could be a process window and we may 
X			/*   obscure the current window.
X			/*----------------------------------------*/
X			for (wp1 = wp->w_wndp; wp1; wp1 = wp1->w_wndp)
X				wp1->w_flag |= WFHARD;
X			}
X		wp->w_old_line = wp->w_line;
X		wp->w_mined = wp->w_maxed = 0;
X		wp->w_flag = 0;
X		}
X
X	if (sgarbf) {		                  /* Screen is garbage.   */
X		epresf = FALSE;                 /* the message area.    */
X		tttop  = HUGE;                  /* Forget where you set */
X		ttbot  = HUGE;                  /* scroll region.       */
X		ttclear();
X		echo_line[0] = NULL;
X		for (i=0; i<nrow-1; ++i) {
X			vflags[i] = 0;
X			uline(i, vscreen[i], &blanks);
X			ucopy(vscreen[i], pscreen[i]);
X			}
X		}
X	else {
X		for (i=0; i<nrow-1; ++i) {
X			if (vflags[i] & V_CHANGE) {
X				vp1 = vscreen[i];
X				vp2 = pscreen[i];
X				uline(i, vp1, vp2);
X				ucopy(vp1, vp2);
X				}
X			vflags[i] = 0;
X			}
X		}
X	line_col(sgarbf);
X	set_cursor();
X	sgarbf = FALSE;                 /* Erase-page clears    */
X	updating--;
X}
Xupd_update(wp)
Xregister WINDOW *wp;
X{	int	old_line = wp->w_old_line;
X	register int	line     = wp->w_line;
X	register int	top	 = wp->w_top_line;
X	int	height   = wp->w_h;
X	int	half_height;
X	int	bborder = BBORDERS(wp);
X	int	bottom   = wp->w_y + wp->w_h + !bborder;
X	int	flag;
X	int	scrolled = FALSE;
X
X	trace_log("nrow=%d ", nrow);
X	trace_log("w_flag=0x%02x ", wp->w_flag);
X	trace_log("w_y=%d ", wp->w_y);
X	trace_log("w_h=%d ", wp->w_h);
X	trace_log("w_top_line=%d ", top);
X	trace_log("w_line=%d ", line);
X	trace_log("bottom=%d\n", bottom);
X	if (!bborder)
X		height--;
X	half_height = height / 2;
X	/*---------------------------------------
X	 *   Sideways scrolling check.
X	 *---------------------------------------*/
X	window_indent = wp->w_indent;
X	if (wp->w_col - wp->w_indent > wp->w_w) {
X		if ((wp->w_indent = wp->w_col - wp->w_w) < 0)
X			wp->w_indent = 0;
X		}
X	else if (wp->w_col <= wp->w_indent) {
X		if ((wp->w_indent = wp->w_col - 1) < 0)
X			wp->w_indent = 0;
X		}
X	if (window_indent != wp->w_indent) {
X		wp->w_flag |= WFHARD;
X		window_indent = wp->w_indent;
X		}
X	indent = window_indent;
X
X	if (top < 1)
X		top = wp->w_top_line = 1;
X
X	flag     = wp->w_flag;
X# if 1
X# define WORTHIT	(wp->w_w == ncol - 2)
X# else
X	/************************************************************************
X	 *    This  definition  means  that  window  must  be  at  least half	*
X	 *    screen  wide  in  order  to do scrolling. However, it can cause	*
X	 *    display  bugs  in  that another window maybe destroyed in doing	*
X	 *    that.  I  cant  work  out  an  easy fix, so we'll use the above	*
X	 *    definition  that  only  allows  us to do scrolling if window is	*
X	 *    full width.							*
X	 ************************************************************************/
X# define WORTHIT	(wp->w_w > ncol / 2 + 1)
X# endif
X	if (line < top && line > top - half_height &&
X		old_line == top && WORTHIT && 
X		ttinsl(wp->w_y+1, bottom - !bborder, top - line)) {
X		int diff = top - line;
X		int j;
X		scrolled = TRUE;
X		wp->w_top_line = line;
X		for (j = 0; j++ < diff; ) {
X			upd_scroll_down(wp->w_y+2, pscreen, bottom);
X			upd_scroll_down(wp->w_y+2, vscreen, bottom);
X			}
X		if ((flag & (WFHARD|WFEDIT)) == 0) {
X			int i = wp->w_y + TBORDERS(wp);
X			vtupdate(i, wp->w_line, i + diff, FALSE);
X			return TRUE;
X			}
X		}
X	else if (line >= top + height &&
X	    line - old_line < half_height &&
X	    line < top + height + half_height && WORTHIT &&
X	    ttdell(wp->w_y+1, bottom - !bborder, line - top - height + 1)) {
X		int diff = line - top - height;
X		int j;
X		wp->w_top_line += diff + 1;
X		scrolled = TRUE;
X		for (j = 0; j++ <= diff; ) {
X			upd_scroll_up(wp->w_y+1, pscreen, bottom);
X			upd_scroll_up(wp->w_y+1, vscreen, bottom);
X			}
X		if ((flag & (WFHARD|WFEDIT)) == 0) {
X			int i = wp->w_y + TBORDERS(wp) +
X				wp->w_line - wp->w_top_line;
X			vtupdate(i - diff,  wp->w_line - diff, i, FALSE);
X			return TRUE;
X			}
X		}
X	else if (!(line >= top && line < top + height)) {
X		int	rel_line = old_line - top;
X		if (rel_line < 0)
X			wp->w_top_line = wp->w_line;
X		else if ((wp->w_top_line = line - rel_line) < 1)
X			wp->w_top_line = 1;
X		if (line >= wp->w_top_line + height)
X			wp->w_top_line = line - height + bborder;
X		flag |= WFHARD;
X		}
X	else if (flag & WFDELL) {
X		if (flag == WFDELL && WORTHIT) {
X			int rel_line = line - top + 1;
X			int	diff, j, i;
X			ttdell(wp->w_y + rel_line, bottom, 1);
X			diff = bottom - rel_line;
X			scrolled = TRUE;
X			upd_scroll_up(wp->w_y+rel_line, pscreen, bottom);
X			upd_scroll_up(wp->w_y+rel_line, vscreen, bottom);
X			i = bottom + TBORDERS(wp) - 1 - !bborder;
X# define	XX top + bottom - wp->w_y - 1 - !bborder
X			for (j = 0; j < nrow; j++) 
X				vflags[j] = TRUE;
X			vtupdate(i, XX, i, FALSE);
X			return TRUE;
X			}
X		flag |= WFHARD;
X		}
X
X	if (flag & WFHARD) {
X		trace_log("upd_update: WFHARD\n", (char *) NULL);
X		vtupdate(wp->w_y + 1, wp->w_top_line, 
X			 wp->w_y+height, TRUE);
X		}
X	else if (flag & WFEDIT) {
X		int i = wp->w_y + 1 - wp->w_top_line;
X		int mined = wp->w_mined;
X		int maxed = wp->w_maxed;
X		
X		trace_log("upd_update: WFEDIT\n", (char *) NULL);
X		if (mined < wp->w_top_line)
X			mined = wp->w_top_line;
X		if (maxed >= wp->w_top_line + wp->w_h)
X			maxed = wp->w_top_line + wp->w_h - 1;
X		vtupdate(i + mined,  mined, i + maxed, FALSE);
X		}
X	return scrolled;
X}
Xupd_scroll_down(end, screen, bottom)
XBYTE **screen;
X{	register BYTE **bp = &screen[bottom];
X	register BYTE *bp1 = *bp;
X	register int i;
X	for (i = bottom; i >= end; i--) {
X		bp[0] = bp[-1];
X		bp--;
X		}
X	*bp = bp1;
X	ucopy(blanks, bp1);
X}
Xupd_scroll_up(end, screen, bottom)
XBYTE **screen;
X{	register BYTE **bp = &screen[end];
X	register BYTE *bp1 = *bp;
X	register int i;
X
X	for (i = end; i < bottom; i++) {
X		bp[0] = bp[1];
X		bp++;
X		}
X	if (screen == vscreen) {
X		int *ip = &vflags[end];
X		for (i = end+1; i < bottom; i++) {
X			ip[0] = ip[1];
X			ip++;
X			}
X		*ip = 0;
X		}
X	*bp = bp1;
X	ucopy(blanks, bp1);
X}
Xset_cursor()
X{
X	register u_int16    currow;
X	register u_int16    curcol;
X	u_int16	c;
X	print_cursor(imode);
X	currow = curwp->w_y + (curwp->w_line - curwp->w_top_line) + 1;
X	curcol = curwp->w_col - 1 - curwp->w_indent;
X
X	if (curcol >= ncol)
X		curcol = ncol-1;
X
X	c = curcol + curwp->w_x;
X	if (curwp->w_indent == 0)
X		c -= !LBORDERS(curwp);
X	ttmove(currow, c > curwp->w_x + curwp->w_w ? 
X			(u_int16) curwp->w_x + curwp->w_w : c);
X	ttflush();
X}
Xvoid
Xucopy(vvp, pvp) 
Xregister BYTE *vvp; 
Xregister BYTE *pvp; 
X{
X	register struct s80 {BYTE	b[80];} *sp1, *sp2;
X	int	n = ncol;
X
X	sp1 = (struct s80 *) vvp;
X	sp2 = (struct s80 *) pvp;
X
X	while (n >= 80) {
X		*sp2++ = *sp1++;
X		n -= 80;
X		}
X	if (n)
X		memcpy((char *) sp2, (char *) sp1, sizeof (BYTE) * n);
X}
X/*----------------------------------------
X/*   Following two routines try to avoid
X/*   moving cursor until absolutely necessary.
X/*----------------------------------------*/
Xstatic int ucol = -1;
Xstatic int urow = -1;
X
Xvoid
Xuputc(x)
XBYTE x;
X{
X	if (ucol >= 0) {
X		ttmove((u_int16) urow, (u_int16) ucol);
X		ucol = -1;
X		}
X	if (x)
X		ttputc(x);
X}
Xvoid
Xumove(row, col)
Xu_int16 row, col;
X{
X	ucol = col;
X	urow = row;
X}	
X
Xvoid
Xuline(row, vvp, pvp) 
XBYTE *vvp; 
XBYTE *pvp; 
X{
X	register int	i;
X	register int	right, left;
X	register BYTE   *leftv = vvp;
X	register BYTE   *bp = pvp;
X	register BYTE   *rightv;
X	register BYTE   *cp5;
X	BYTE normal_space;
X	register int    nbflag;
X	BYTE	space;
X	int	cleared_line = FALSE;
X
X	for (i = ncol; --i > 0 && *leftv == *bp; )
X		leftv++, bp++;
X	if (i == 0)			        /* All equal.           */
X		return;
X	rightv = &vvp[ncol];
X	
X	bp = &pvp[ncol];		/* Compute right match. */
X	nbflag = FALSE;
X	while (rightv[-1] == bp[-1]) {
X		--bp;
X		if (*--rightv != ' ')              /* Note non-blanks in   */
X			nbflag = TRUE;          /* the right match.     */
X		}
X
X	cp5 = rightv;                              /* Is erase good?       */
X	if (nbflag == FALSE) {
X		while (cp5 != leftv && cp5[-1] == ' ')
X			--cp5;
X		if ((int)(rightv-cp5) <= tceeol)
X			cp5 = rightv;
X		}
X
X	umove((u_int16) row, (u_int16)(leftv - vvp));
X	normal_space = (BYTE) ((col_table.c_normal << FG_SHIFT) | ' ');
X	
X	left = leftv - vvp;
X	right =  cp5 - vvp;
X	while (left < right) {
X		register BYTE *vp = &vvp[left];
X		register BYTE *pp = &pvp[left];
X		register int	n = 0;
X		register int	bytes = right - left;
X		while (bytes-- > 0) {
X			if (*vp++ != *pp++)
X				break;
X			n++;
X			}
X		if (n > 8) {
X			left += n;
X			umove((u_int16) row, left);
X			continue;
X			}
X		if ((vvp[left] & 0xff) != ' ') {
X			uputc(vvp[left++]);
X			continue;
X			}
X		space = vvp[left];
X		for (i = 0; vvp[left] == space && left != right; )
X			left++, i++;
X		if (i > 2 && (cleared_line || (sgarbf && space == normal_space))) {
X			umove((u_int16) row, (u_int16)left);
X			}
X		else if (!pt.pt_color && space == normal_space && i > 10 && i > ncol - right) {
X			/*----------------------------------------
X			/*   Can only delete to end of line if
X			/*   we aren't a color screen cos otherwise
X			/*   we may clear to end of line with the
X			/*   background color set.
X			/*----------------------------------------*/
X			register BYTE *pp1, *ppend;
X			right = ncol;
X			uputc((BYTE) 0);
X			tteeol();
X			for (pp1 = &pvp[left], ppend = &pvp[right]; pp1 < ppend; )
X				*pp1++ = space;
X			umove((u_int16) row, (u_int16)left);
X			cleared_line = TRUE;
X			}
X		else {
X			uputc((BYTE) 0);
X			ttspace(i, space, FALSE);
X			}
X		}
X	uputc((BYTE) 0);
X	ucol = -1;
X}
X
X
Xvoid
Xvtputs(s, col) 
Xregister unsigned char *s; 
X{
X
X	for (; *s != NULL; s++)
X		vtputc(*s | col);
X}
Xvoid
Xvtleft(i, x)
X{
X	vtmove(i, x);
X	if (x != 0 || LBORDERS(wp)) {
X		vtputc(CH_VERTICAL | FG(col_table.c_normal));
X		}
X}
Xvoid
Xvtupdate(i, line, n, redraw)
X{	register int	x = wp->w_x - 1;
X	WINDOW	*saved_wp = curwp;
X	BUFFER	*saved_bp = curbp;
X
X	mark_areas = curwp == wp;
X	curwp = wp;
X	curbp = wp->w_bufp;
X	if (curbp && mark_areas && (mark_areas = get_marked_areas(wp)))
X		start_col--, end_col--;
X	tl = line;
X
X
X	if (redraw && wp->w_ttitle) 
X		draw_title(TRUE, wp->w_y, wp);
X	for (; i <= n; i++) {
X		vflags[i] = V_CHANGE;
X		indent = 0;
X		vtleft(i, x);
X		indent = window_indent;
X		if (curbp && line <= wp->w_bufp->b_numlines) {
X			LINE *lp = vm_lock_line(line);
X			vtputl(lp);
X			tl++;
X			vm_unlock(line);
X			line++;
X			}
X		vteeol();
X		}
X	curwp = saved_wp;
X	curbp = saved_bp;
X	if (redraw && wp->w_btitle && BBORDERS(wp)) {
X		line = wp->w_y + wp->w_h + BBORDERS(wp);
X		if (line == nrow-2 || wp->w_popup)
X			draw_title(FALSE, line, wp);
X		}
X}
Xvoid
Xdraw_title(top, line, wp)
XWINDOW	*wp;
X{	register unsigned char *cp = (unsigned char *) 
X		(top ? wp->w_ttitle : wp->w_btitle);
X	int	denom = 0, i, j;
X	int	l = cp ? strlen(cp) : 0;
X	unsigned char	buf[128];
X	extern int b_level;
X	int	digits;
X	int	ch;
X	int	col = FG(col_table.c_normal);
X
X	indent = 0;
X	if (l == 0) 
X		i = wp->w_w;
X	else {
X		if ((denom = wp->w_w - l - 2) < 0) {
X			strcpy(buf, cp);
X			cp = buf;
X			buf[wp->w_w-2] = NULL;
X			i = 0;
X			}
X		else
X			i = denom / 2;
X		}
X
X	vtmove(line, wp->w_x-1);
X	digits = (b_level > 1 && vtrow == nrow - 2)
X			? (b_level > 9 ? 2 : 1) : 0;
X	vflags[line] = V_CHANGE;
X
X	ch = col | (top ? CH_TOP_LEFT : CH_BOT_LEFT);
X	vtputc(ch);
X	if (digits)
X		j = i - digits + 1;
X	else
X		j = i;
X
X	ch = CH_HORIZONTAL | col;
X	while (j-- > 0)
X		vtputc(ch);
X
X	if (l) {
X		ch = col | ' ';
X		vtputc(ch);
X		vtputs(cp, wp == current_window ? FG(col_table.c_select) : col);
X		vtputc(ch);
X		}
X	else
X		i = 0;
X
X	ch = CH_HORIZONTAL | col;
X	for (j = i + (denom & 1); j-- > 0; )
X		vtputc(ch);
X	if (digits) {
X		char buf[4];
X		sprintf(buf, "%d", b_level);
X		vtputs(buf, col);
X		}
X	else {
X		ch = col | (top ? CH_TOP_RIGHT : CH_BOT_RIGHT);
X		vtputc(ch);
X		}
X}
Xvoid
Xvtputl(lp)
Xregister LINE	*lp;
X{	int	attr = FG(col_table.c_normal);
X	u_int16	ch;
X	register u_int16	col = ncol;
X	register u_char *cp = lp->l_text;
X	register u_char *cpend = cp + llength(lp);
X	int	mc;
X	int	dc;
X	int	column;
X	int	fg = col_table.c_fg << FG_SHIFT;
X	int	bg = col_table.c_bg << BG_SHIFT;
X
X	fg |= bg;	
X
X	indent = window_indent;
X	col = wp->w_x + wp->w_w;
X	if (!RBORDERS(wp))
X		col += 1;
X
X	if (!mark_areas || tl < start_line || tl > end_line) {
Xno_change:
X		column = ncol < col ? ncol : col;
X		for (; vtcol < column; cp++) {
X			if (cp >= cpend) {
X				vtputc(' ' | attr);
X				continue;
X				}
X			ch = *cp;
X# if 1
X			if (ch == 0x1b && curbp->b_flag & BFANSI) {
X				int inc = vtgetcolor(cp+1, cpend, attr);
X				if (inc) {
X					cp += inc;
X					if (mark_areas && !(tl < start_line || tl > end_line)) {
X						bg = (vt_color & BG_COLOR) >> BG_SHIFT;
X						fg = (vt_color & FG_COLOR) >> FG_SHIFT;
X						attr = (bg << FG_SHIFT) | (fg << BG_SHIFT);
X						}
X					else
X						attr = vt_color;
X					continue;
X					}
X				}
X# endif
X			vtputc(ch | attr);
X			}
X		return;
X		}
X
X
X	if (mark_type == MK_LINE ||
X	    (tl > start_line && tl < end_line && mark_type != MK_COLUMN)) {
X	    	attr = fg;
X		goto no_change;
X		}
X
X	mc = start_col + wp->w_x - window_indent;
X	dc = end_col + wp->w_x - window_indent;
X	column = ncol < col ? ncol : col;
X	cp = lp->l_text;
X	
X	for (; vtcol < column; cp++) {
X		int	ch_width = 1;
X		int	mask;
X
X		ch = cp < cpend ? *cp : ' ';
X		if (ch == 0x1b) {
X			int inc = vtgetcolor(cp+1, cpend, attr);
X			if (inc) {
X				cp += inc;
X				attr = vt_color;
X				continue;
X				}
X			}
X		if (ch == '\t') {
X			int i = vtcol + window_indent - indent;
X			ch_width = next_tab_stop(i - wp->w_x + 1) + wp->w_x - i;
X			if (ch_width + vtcol >= col)
X				ch_width = col - vtcol;
X			ch = ' ';
X			}
X		while (ch_width-- > 0) {
X			if ((tl == start_line && tl == end_line) || mark_type == MK_COLUMN)
X				mask =  (vtcol < mc) ? attr : 
X					(vtcol <= dc) ? fg : attr;
X			else if (tl == start_line)    /* This line is start of mark. */
X				mask = (vtcol < mc) ? attr : fg;
X			else		      /* This line is end of mark. */
X				mask = (vtcol <= dc) ? fg : attr;
X			vtputc(ch | mask);
X			}
X		}
X}
X/*----------------------------------------
X/*   Following array maps ANSI colors to BRIEFs.
X/*----------------------------------------*/
Xint ab_color_map[8] = {0, 4, 2, 6, 1, 5, 3, 7};
Xint ba_color_map[8] = {0, 4, 2, 6, 1, 5, 3, 7};
X
Xvtgetcolor(cp, cpend, attr)
Xregister u_char *cp, *cpend;
X{	u_char 	*start = cp;
X	DISPLAY dp;
X	int	ch;
X	int	bold = vt_color & FG(8);
X	int	fg = (vt_color & FG_COLOR) >> FG_SHIFT;
X	int	bg = (vt_color & BG_COLOR) >> BG_SHIFT;
X	
X	dp.d_escptr = dp.d_escape;
X	dp.d_attr = bold ? 1 : 0;
X	fg = ba_color_map[fg];
X	bg = ba_color_map[bg];
X	dp.d_color = attr;
X	for ( ; cp < cpend; cp++) {
X		ch = *cp;
X		*dp.d_escptr++ = ch;
X		if (isalpha(ch)) {
X			if (ch != 'm')
X				return 0;
X			*dp.d_escptr = NULL;
X			p_escape(&dp, FALSE);
X			vt_color = dp.d_color;
X			if (dp.d_attr & 1)
X				bold = FG(8);
X			else
X				bold = 0;
X			vt_color |= bold;
X			return cp - start + 1;
X			}
X		}
X	return 0;
X		
X}
Xscreen_dump()
X{	char *filename = get_str(1);
X	FILE *fp;
X	register int line, col;
X	BYTE	*lineptr;
X
X	if (filename == NULL || *filename == NULL)
X		filename = "/tmp/crisp.screen";
X		
X	if ((fp = fopen(filename, "w")) == NULL) {
X		accumulator = -1;
X		return;
X		}
X	for (line = 0; line < nrow-1; line++) {
X		lineptr = vscreen[line];
X		for (col = 0; col < ncol; col++) {
X			int c = lineptr[col] & 0xff;
X			switch (c) {
X			  case CH_HORIZONTAL:	c = '-'; break;
X			  case CH_VERTICAL:	c = '|'; break;
X			  case CH_TOP_LEFT:
X			  case CH_TOP_RIGHT:
X			  case CH_BOT_LEFT:
X			  case CH_BOT_RIGHT:
X			  case CH_TOP_JOIN:
X			  case CH_BOT_JOIN:
X			  case CH_LEFT_JOIN:
X			  case CH_RIGHT_JOIN:
X			  case CH_CROSS:
X			  		c = '+';
X					break;
X			  }
X			fputc(c, fp);
X			}
X		fputc('\n', fp);
X		}
X		
X	accumulator = 0;
X	fclose(fp);
X}
SHAR_EOF
chmod 0444 ./display.c || echo "restore of ./display.c fails"
mkdir . >/dev/null 2>&1
echo "x - extracting ./echo.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > ./echo.c &&
X/**************************************************************
X *
X *	CRISP - Custom Reduced Instruction Set Programmers Editor
X *
X *	(C) Paul Fox, 1989
X *	43, Jerome Close	      Tel: +44 6284 4222
X *	    Marlow
X *	     Bucks.
X *		England SL7 1TX
X *
X *
X *    Please See COPYRIGHT notice.
X *
X **************************************************************/
X
X#include        "list.h"
X# include	"alt.h"
X# include	<time.h>
X
X
XSCCSID("@(#) echo.c 1.13, (C) P. Fox");
X# define	EBUFSIZ	512
X
X# define	E_LINE		0x01	/* Line: ..			*/
X# define	E_COL		0x02	/* Col: ..			*/
X# define	E_PERCENT	0x04	/* nn%				*/
X# define	E_TIME		0x08	/* hh:mm a/pm			*/
X# define	E_REMEMBER	0x10	/* RE / PA String.		*/
X# define	E_CURSOR	0x20	/* IN / OV cursor type. 	*/
Xint	echo_flags = E_CURSOR | E_LINE | E_COL | E_REMEMBER | E_TIME;
X
X# define	ARG_LIST	x1, x2, x3, x4, x5, x6, x7, x8, x9, x10
X# define	LSIZE		ncol	/* Echo line size.		*/
X# define	LCOL		(LSIZE - 31)
X					/* Position of 'Line: ..'	*/
Xint     epresf  = FALSE;                /* Stuff in echo line flag.     */
Xstatic	u_int16	ecol = 0;		/* Current echo line column.	*/
Xchar	*echo_line;
Xint	prompting = FALSE;
Xint	prompt_len = 0;			/* Length of prompt - so we can skip */
X					/* prompt in (inq_cmd_line).	*/
Xint	pcolor = CMESSAGE;	/* Used by (error) */
X
Xextern	int	imode;
X
Xvoid	ewputs();
Xvoid	eputc();
Xvoid	eerase();
Xvoid	ewprintf();
Xvoid	eclear();
X/*
X * Ask "yes" or "no" question.
X * Return ABORT if the user answers the question
X * with the abort ("^G") character. Return FALSE
X * for "no" and TRUE for "yes". No formatting
X * services are available. No newline required.
X */
Xeyorn(sp)
Xchar *sp;
X{
X	register KEY    s;
X
X	ewprintf("%s? (y or n) ", sp);
X	for (;;) {
X		s = getkey();
X		if (s == 'y' || s == 'Y') return (TRUE);
X		if (s == 'n' || s == 'N') return (FALSE);
X		if (s == '\033')
X			return ABORT;
X		ewprintf("Please answer y or n.  %s? (y or n) ", sp);
X		}
X}
X
X/*
X * Like eyorn, but for more important question. User must type either all of
X * "yes" or "no", and the trainling newline.
X */
Xeyesno(sp) 
Xchar *sp; 
X{
X	register int    s;
X	char            buf[64];
X
X	s = ereply("%s? (yes or no) ", buf, sizeof(buf), sp);
X	for (;;) {
X		if (s == ABORT) return ABORT;
X		if (s != FALSE) {
X			if ((buf[0] == 'y' || buf[0] == 'Y')
X			&&  (buf[1] == 'e' || buf[1] == 'E')
X			&&  (buf[2] == 's' || buf[2] == 'S')) return TRUE;
X			if ((buf[0] == 'n' || buf[0] == 'N')
X			&&  (buf[1] == 'o' || buf[0] == 'O')) return FALSE;
X		}
X		s = ereply("Please answer yes or no.  %s? (yes or no) ",
X			   buf, sizeof(buf), sp);
X	}
X}
Xvoid
Xprint_cursor(insert_mode)
X{	extern int virtual_space;
X	static int old_mode = -2;
X	static int old_space = -2;
X
X	if (pt.pt_icursor[0] == NULL)
X		return;
X	set_hooked();
X	current_offset(curwp->w_col, FALSE);
X	if (old_space == virtual_space && insert_mode == old_mode)
X		return;
X
X	if (insert_mode)
X		putpad(virtual_space ? pt.pt_vicursor : pt.pt_icursor);
X	else
X		putpad(virtual_space ? pt.pt_vocursor : pt.pt_ocursor);
X	old_mode = insert_mode;
X	old_space = virtual_space;
X}
X/*
X * Write out a prompt, and read back a
X * reply. The prompt is now written out with full "ewprintf"
X * formatting, although the arguments are in a rather strange
X * place. This is always a new message, there is no auto
X * completion, and the return is echoed as such.
X */
Xereply(fp, buf, nbuf, ARG_LIST) 
Xchar	*fp;
Xchar	*buf;
X{	char	prompt[EBUFSIZ];
X
X	sprintf(prompt, fp, ARG_LIST);
X	return ereply1(prompt, (char *) NULL, buf, nbuf);
X}
Xedefreply(fp, defstr, buf, nbuf, ARG_LIST) 
Xchar	*fp;
Xchar	*defstr;
Xchar	*buf;
X{	char	prompt[EBUFSIZ];
X
X	sprintf(prompt, fp, ARG_LIST);
X	return ereply1(prompt, defstr, buf, nbuf);
X}
Xereply1(fp, defstr, buf, nbuf) 
Xchar	*fp;
Xchar	*defstr;
Xchar	*buf;
X{	int	ret;
X	char	pbuf[EBUFSIZ + 20];
X	extern int dflag;
X	int	saved_dflag = dflag;
X	int	dflag1 = dflag;
X
X
X	if (dflag && (dflag & DB_PROMPT) == 0)
X		dflag1 = 0;
X
X	prompt_len = estrlen(fp);
X	ewputs(fp, defstr);
X	sprintf(pbuf, "_prompt_begin \"%s\"", fp);
X
X	dflag = dflag1;
X	str_exec(pbuf);
X	dflag = saved_dflag;
X
X	ret = ereply2(fp, defstr, buf, nbuf);
X	dflag = dflag1;
X	str_exec("_prompt_end");
X
X	set_hooked();
X
X	dflag = saved_dflag;
X	return ret;
X
X}
Xereply2(prompt, defstr, buf, nbuf) 
Xchar  *prompt;
Xchar  *defstr;
Xchar  *buf; 
X{  register int cpos, bpos;
X   register KEY c;
X   char         *def = NULL;
X   u_int16      startcol = estrlen(prompt);
X   int          insert_mode = TRUE;
X   u_int16      n;
X   char         *cp;
X   int          first_key = TRUE;
X   int          left = 0;
X
X   prompting = TRUE;
X   print_cursor(insert_mode);
X   bpos = 0;
X   buf[0] = NULL;
X   if (defstr == NULL)
X       defstr = "";
X   strcpy(buf, defstr);
X   for (;;) {
X       c = getkey();
X       if (first_key && 
X           (c == 0x7f || c == CTRL_H || 
X            c == KEY_WLEFT || c == KEY_WRIGHT || 
X            c == KEY_HOME || c == KEY_END ||
X            c == KEY_LEFT || c == KEY_RIGHT)) {
X           if (nbuf == 1) {
X               buf[0] = (char) c;
X               buf[1] = NULL;
X               prompting = FALSE;
X               return TRUE;
X               }
X           strcpy(buf, defstr);
X           bpos = strlen(buf);
X           cpos = estrlen(defstr);
X           ewputs(prompt, (char *) NULL);
X           for (cp = buf; *cp; cp++)
X               eputc1(*cp);
X           ttflush();
X           }
X       else
X           if (first_key && c != 0x0D) {
X               ttmove(nrow-1, ecol = startcol);
X               while (ecol < LCOL - 1)
X                   eputc1(' ');
X               buf[bpos = 0] = NULL;
X               cpos = position_prompt(buf, startcol, bpos, &left);
X               }
X       defstr = "";
X       first_key = FALSE;
X       if (nbuf == 1 && c != 0x1b) {
X           buf[0] = (char) c;
X           buf[1] = NULL;
X           goto done;
X           }
X       switch (c) {
X       case 0x0D:                      /* Return, done.    */
X           goto done;
X
X       case ALT_H:
X           trigger(REG_ALT_H);         /* Fall into....    */
X       case '\033':
Xcancel:
X           print_cursor(imode);
X           ewprintf("Command cancelled.");
X           prompting = FALSE;
X           return (ABORT);
X
X       case '\t':
X       case ALT_L:
X       case KEY_DOWN:
X       case KEY_UP:
X           push_back1(c);
X           trigger(REG_INVALID);
X           str_exec("_bad_key");
X           if (acc_type != F_STR)
X               goto cancel;
X           defstr = saccumulator;
X           ewputs(prompt, saccumulator);
X           strncpy(buf, saccumulator, nbuf);
X           first_key = TRUE;
X           continue;
X
X       case KEY_WLEFT:
X           while (isspace(buf[bpos]) && bpos > 0)
X               bpos--;
X           while (!isspace(buf[bpos]) && bpos > 0)
X               bpos--;
X           cpos = position_prompt(buf, startcol, bpos, &left);
X           break;
X       case KEY_WRIGHT:
X           while (isspace(buf[bpos]) && buf[bpos])
X               bpos++;
X           while (!isspace(buf[bpos]) && buf[bpos])
X               bpos++;
X           cpos = position_prompt(buf, startcol, bpos, &left);
X           break;
X       case KEY_RIGHT:
X           if (buf[bpos]) {
X               ++bpos;
X               cpos = position_prompt(buf, startcol, bpos, &left);
X               }
X           break;
X       case KEY_LEFT:
X           if (bpos > 0) {
X               --bpos;
X               cpos = position_prompt(buf, startcol, bpos, &left);
X               }
X           break;
X       case KEY_HOME:
X           cpos = position_prompt(buf, startcol, bpos = 0, &left);
X           break;
X       case KEY_END:
X           cpos = position_prompt(buf, startcol, bpos = strlen(buf), &left);
X           break;
X       case ALT_I:
X           insert_mode = !insert_mode;
X           print_cursor(insert_mode);
X           ttflush();
X           break;
X           
X       case CCHR('H'):
X       case 0x7F:                      /* Rubout, erase.       */
X#ifdef APW
X           if (bpos == 0)
X#else
X           if ((c == CCHR('H') && bpos == 0) ||
X               (c == 0x7f && buf[bpos] == NULL))
X#endif
X               break;
X           if (insert_mode) {
X#ifndef APW
X               if (c == CCHR('H'))
X#endif
X               ecol -= printable_char(buf[--bpos]);
X               if (ecol < startcol)
X                   ecol = startcol;
X               cp = buf + bpos;
X               strcpy(cp, cp + 1);
X               ttmove(nrow-1, ecol);
X               while (*cp && ecol < LCOL - 1)
X                   eputc1(*cp++);
X               eclear();
X               cpos = position_prompt(buf, startcol, bpos, &left);
X               ttflush();
X               }
X           else
X               cpos = position_prompt(buf, startcol, --bpos, &left);
X           break;
X
X       case ALT_D:
X       case CCHR('X'):                 /* C-X                  */
X       case CCHR('U'):                 /* C-U, kill line.      */
X           {
X               ttmove(nrow-1, ecol = startcol);
X               while (ecol < LCOL - 1)
X                   eputc1(' ');
X               buf[bpos = 0] = NULL;
X               cpos = position_prompt(buf, startcol, bpos, &left);
X           }
X           break;
X
X#ifdef APW
X       case CCHR('Q'):                 /* C-Q                  */
X#endif
X       case ALT_Q:
X           c = getkey();
X#ifdef APW                             /* translate c/r to newline     */
X           if (c == '\r')
X               c = '\n';
X#endif
X       default:                        /* All the rest.        */
X           if (estrlen(buf) >= nbuf-1) {
X               ttbeep();
X               continue;
X               }
X           if (insert_mode) {
X               char    buf1[EBUFSIZ];
X               strcpy(buf1, buf+bpos);
X               strcpy(buf+bpos+1, buf1);
X               }
X           else if (buf[bpos] == NULL)
X               buf[bpos+1] = NULL;
X           cp = buf + bpos++;
X           *cp = (char) c;
X           /*--------------------------------
X            *   Echo shifted characters.
X            *--------------------------------*/
X           for (; *cp && ecol < LCOL-1; eputc1(*cp++))
X               ;
X           if (!insert_mode)
X               eclear();
X           echo_line[ecol] = NULL;
X           /*--------------------------------
X            *   Put cursor back where it was.
X            *--------------------------------*/
X           cpos = position_prompt(buf, startcol, bpos, &left);
X       }
X   }
Xdone:
X   prompting = FALSE;
X   print_cursor(imode);
X   return TRUE;
X}
X
X
Xposition_prompt(buf, startcol, bpos, left)
Xchar  *buf;
Xint   *left;
X{
X   int n, i;
X   int pos = 0;
X
X   for (i = 0; i < bpos; i++)
SHAR_EOF
echo "End of part 4"
echo "File ./echo.c is continued in part 5"
echo "5" > s2_seq_.tmp
exit 0
-- 
=====================			Reuters Ltd PLC, 
Tel: +44 628 891313 x. 212		 Westthorpe House,
UUCP:     fox%marlow.uucp@idec.stc.co.uk  Little Marlow,
					   Bucks, England SL7 3RQ