[comp.sources.unix] v14i070: Jove, an emacs variant, version 4.9, Part14/21

rsalz@bbn.com (Rich Salz) (04/28/88)

Submitted-by: Jonathan Payne <jpayne@cs.rochester.edu>
Posting-number: Volume 14, Issue 70
Archive-name: jove4.9/part14

#! /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 14 (of 21)."
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f './screen.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'./screen.c'\"
else
echo shar: Extracting \"'./screen.c'\" \(28777 characters\)
sed "s/^X//" >'./screen.c' <<'END_OF_FILE'
X/***************************************************************************
X * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne.  JOVE *
X * is provided to you without charge, and with no warranty.  You may give  *
X * away copies of JOVE, including sources, provided that this notice is    *
X * included in all the files.                                              *
X ***************************************************************************/
X
X#include "jove.h"
X#include "io.h"
X#include "ctype.h"
X#include "termcap.h"
X
X#ifdef IBMPC
X
X/* here come the actual emulation routines	*/
X
X#include <dos.h>
X#include <conio.h>
X
X#define BYTE	unsigned char
X#define WORD	unsigned int
X
X#ifdef MAC
X#	undef private
X#	define private
X#endif
X
X#ifdef	LINT_ARGS
private BYTE near get_mode(void);
X
private WORD
X	near cur_page(void),
X	near get_cur(void);
X
private void
X	near ch_out(BYTE, BYTE),
X	near clr_eop(void),
X	near cur_advance(void),
X	near cur_down(void),
X	near cur_left(void),
X	near cur_right(void),
X	near cur_up(void),
X	near line_feed(void),
X	near normfun(char),
X	near scr_win(int, BYTE, BYTE, BYTE, BYTE),
X	near set_cur(WORD),
X	near set_mode(BYTE),
X	near wherexy(BYTE *, BYTE *);
X#else
private BYTE near get_mode();
X
private WORD
X	near cur_page(),
X	near get_cur();
X
private void
X	near ch_out(),
X	near clr_eop(),
X	near cur_advance(),
X	near cur_down(),
X	near cur_left(),
X	near cur_right(),
X	near cur_up(),
X	near line_feed(),
X	near normfun(),
X	near scr_win(),
X	near set_cur(),
X	near set_mode(),
X	near wherexy();
X#endif	/* LINT_ARGS */
X
X#ifdef MAC
X#	undef private
X#	define private static
X#endif
X
X#define VIDEO   0x10
X
X#define intr(n, r)	int86(n, r, r);
X
BYTE CHPL=80, 
X     LPP=25, 
X     CUR_PAGE=0, 
X     C_ATTR = 0x07,
X     C_X=0, 
X     C_Y=0;
X
int Fgcolor = 7,
X    Bgcolor = 0,
X	Mdcolor = 0;
X    
void setcolor(fg, bg)
BYTE fg, bg;
X{
X   C_ATTR = ((bg&0xf)<<4)|(fg&0xf);
X}   
X
private
WORD near cur_page()
X{
X   union REGS vr;
X
X   vr.h.ah = 0x0f;
X   intr(VIDEO, &vr);
X   return(vr.h.bh);
X}
X   
private
void near set_cur(xy)
WORD xy;
X{
X   union REGS vr;
X   
X   vr.h.bh = CUR_PAGE;
X   vr.h.ah = 0x02;
X   vr.x.dx = xy;
X   intr(VIDEO, &vr);
X}
X
private
WORD near get_cur()
X{
X   union REGS vr;
X
X   vr.h.bh = CUR_PAGE;
X   vr.h.ah = 0x03;
X   intr(VIDEO, &vr);
X   return (vr.x.dx);
X}		    
X 
private
BYTE near get_mode()
X{
X  union REGS vr;
X
X  vr.h.ah = 0x0f;
X  intr(VIDEO, &vr);
X  return(vr.h.al);
X}
X
BYTE lpp()
X{
X   int far *regen = (int far *) 0x44C;
X   int what;
X   BYTE chpl();
X   
X   what = (*regen&0xff00)/2/chpl();
X   return (what > 43 ? 25 : what);
X}    
X	  
private
void near set_mode(n)
BYTE n;
X{
X  union REGS vr;
X
X  vr.h.ah = 0x00;
X  vr.h.al = n;
X  intr(VIDEO, &vr);
X} 
X
X#define gotoxy(x,y)	set_cur((x)<<8|((y)&0xff))
X#define cur_mov(x,y)	set_cur((C_X=x)<<8|((C_Y=y)&0xff))
X
private
void near wherexy( x, y)
BYTE *x, *y;
X{
X  register WORD xy;
X
X  xy = get_cur();
X  *x = xy>>8;
X  *y = xy&0xff;
X}
X    
X#define wherex()	C_X
X#define wherey()	C_Y
X
private
void near scr_win(no, ulr, ulc, lrr, lrc)
int no;
BYTE ulr, ulc, lrr, lrc;
X{
X  union REGS vr;
X
X  if (no >= 0)
X     vr.h.ah = 0x06;
X  else {
X     vr.h.ah = 0x07;
X     no = - no;
X  }
X  vr.h.al = no;
X  vr.x.cx = ulr<<8 | ulc;
X  vr.x.dx = lrr<<8 | lrc;
X  vr.h.bh = C_ATTR;
X  intr(VIDEO, &vr);
X}    
X
BYTE chpl()
X{
X  union REGS vr;
X
X  vr.h.ah = 0x0f;
X  intr(VIDEO, &vr);
X  return(vr.h.ah);
X}
X   
X#define clr_page()	scr_win(0, 0, 0, LPP-1, CHPL-1), \
X			gotoxy(C_X = 0, C_Y = 0)
X		
private
void near cur_right()
X{
X   if (C_Y < CHPL-1) 
X      C_Y++;
X   gotoxy(C_X, C_Y);
X}	     
X
private
void near cur_up()
X{
X   if (C_X)
X      C_X--;
X   gotoxy(C_X, C_Y);
X}
X
private
void near cur_left()
X{
X   if (C_Y)
X      C_Y--;
X   gotoxy(C_X, C_Y);
X}
X
private
void near cur_down()
X{
X   if (C_X < LPP-1)
X      C_X++;
X   gotoxy(C_X, C_Y);
X}
X 			  
private
void near ch_out(c, n)
BYTE c, n;
X{
X  union REGS vr;
X
X  vr.h.ah = 0x09;
X  vr.h.al = c;
X  vr.h.bl = C_ATTR;
X  vr.h.bh = CUR_PAGE;
X  vr.x.cx = n;
X  intr(VIDEO, &vr);
X}
X
X#define wrch(c)		ch_out((c), 1), cur_advance()
X
X#define home_cur()	gotoxy(C_X = 0, C_Y = 0)
X
X#define clr_eoln()	ch_out(' ', CHPL-wherey())
X
private
void near clr_eop()
X{
X  clr_eoln();
X  scr_win(LPP-1-wherex(), wherex()+1, 0, LPP-1, CHPL-1);
X}
X
void init_43()
X{
X   BYTE far *info = (BYTE far *) 0x487;
X   WORD far *CRTC = (WORD far *) 0x463;
X   union REGS vr;
X   WORD cur;
X         
X   CUR_PAGE = cur_page();
X   CHPL = chpl();
X   LPP = lpp();
X
X   if (get_mode()!=3)
X      set_mode(3);
X   cur = get_cur();
X   
X   vr.x.ax = 0x1112;
X   vr.h.bl = 0;
X   intr(VIDEO, &vr);
X
X   *info |= 1;
X   vr.x.ax = 0x0100;
X   vr.h.bh = 0;
X   vr.x.cx = 0x0600;
X   intr(VIDEO, &vr);
X
X   outp(*CRTC, 0x14);
X   outp(*CRTC+1, 0x07);
X
X   vr.x.ax = 0x1200;
X   vr.h.bl = 0x20;
X   intr(VIDEO, &vr);
X   
X   LPP = lpp();
X
X   set_cur(cur);
X   wherexy(&C_X, &C_Y);
X}
X
void reset_43()
X{
X   BYTE far *info = (BYTE far *) 0x487;
X   WORD far *CRTC = (WORD far *) 0x463;
X   union REGS vr;
X   
X   set_mode(3);
X
X   *info &= 128;
X   vr.x.ax = 0x0100;
X   vr.h.bh = 0x0607;
X   vr.x.cx = 0x0607;
X   intr(VIDEO, &vr);             
X
X   outp(*CRTC, 0x14);
X   outp(*CRTC+1, 13);
X
X}
X
X#define scr_up()		scr_win(1, 0, 0, LPP-1, CHPL-1)
X#define back_space()	cur_left()
X
private
void near line_feed()
X{
X   if (++C_X > LPP-1) {
X      C_X = LPP-1;
X      scr_up();
X   }   
X   gotoxy(C_X, C_Y);
X}
X
X#define BELL_P 0x61			/* speaker */
X#define BELL_D 0x2dc			/* 550 hz  */
X#define TIME_P 0x40			/* timer   */
X#define TINI   182			/* 10110110b timer initialization */
X
void dobell(x)
X{
X   unsigned int n = 0x8888;
X   int orgval;
X
X   outp(TIME_P+3, TINI);
X   outp(TIME_P+2, BELL_D&0xff);
X   outp(TIME_P+2, BELL_D>>8);
X   orgval = inp(BELL_P);
X   outp(BELL_P, orgval|3);		/* turn speaker on  */
X   while (--n > 0)
X	 ;
X   outp(BELL_P, orgval);
X}
X
X#define carriage_return()	gotoxy(wherex(), C_Y = 0)
X   
private
void near cur_advance()
X{
X   if (++C_Y > CHPL-1) {
X      C_Y = 0;
X      if (++C_X > LPP-1) {
X         scr_up();   	
X         C_X = LPP-1;
X      }   
X   }
X   gotoxy(C_X, C_Y);
X}	     
X
void init_term()
X{
X   if (lpp() == 43)
X      reset_43();   
X   CUR_PAGE = cur_page();
X   CHPL = chpl();
X   LPP = lpp();
X   wherexy(&C_X, &C_Y); 
X}
X
private
void near normfun();
X
void write_em(s)
char *s;
X{
X  while (*s)
X        normfun(*s++);
X}          
X
void write_emif(s)
char *s;
X{
X  if (s)
X	 write_em(s);
X}
X
void write_emc(s, n)
char *s;
int n;
X{
X   while (n--)
X         normfun(*s++);
X}           
X
private
void near normfun(c)
char c;
X{
X      switch (c) {
X        case 10: line_feed(); break;
X        case 13: carriage_return(); break;
X        case  8: back_space(); break;
X        case  7: dobell(0); break;
X		case  0: break;
X        default: wrch(c);
X      }  
X}
X
X#endif	/* IBMPC */
X
X
extern int	BufSize;
X
int	AbortCnt,
X	tabstop = 8;
X
X#if !(defined(IBMPC) || defined(MAC))	
int	(*TTins_line)(),
X	(*TTdel_line)();
X#endif /* (defined(IBMPC) || defined(MAC)) */
X
struct scrimage
X	*DesiredScreen = 0,
X	*PhysScreen = 0;
X
struct screenline	*Screen = 0,	/* the screen (a bunch of screenline) */
X			*Savelines = 0,	/* another bunch (LI of them) */
X			*Curline = 0;	/* current line */
char	*cursor,			/* offset into current Line */
X	*cursend;
X
int	CapCol,
X	CapLine,
X
X	i_line,
X	i_col;
X
void
make_scr()
X{
X	register int	i;
X	register struct screenline	*ns;
X	register char	*nsp;
X
X#ifdef RESHAPING
X	/* In case we are RESHAPING the window! */
X	if (DesiredScreen)
X		free((char *) DesiredScreen);
X	if (PhysScreen)
X		free((char *) PhysScreen);
X	if (Savelines)
X		free((char *) Savelines);
X	if (Screen) {
X		free(Screen->s_line);	/* free all the screen data */
X		free((char *) Screen);
X	}
X#endif /* RESHAPING */
X
X	DesiredScreen = (struct scrimage *) malloc((unsigned) LI * sizeof (struct scrimage));
X	PhysScreen = (struct scrimage *) malloc((unsigned) LI * sizeof (struct scrimage));
X
X	Savelines = (struct screenline *)
X			malloc((unsigned) LI * sizeof(struct screenline));
X	ns = Screen = (struct screenline *)
X			malloc((unsigned) LI * sizeof(struct screenline));
X
X	nsp = (char *) malloc((unsigned)CO * LI);
X	if (nsp == 0) {
X		printf("\n\rCannot malloc screen!\n");
X		finish(1);
X	}
X
X	for (i = 0; i < LI; i++) {
X		ns->s_line = nsp;
X		nsp += CO;
X		ns->s_length = nsp - 1;		/* End of Line */
X		ns += 1;
X	}
X	cl_scr(0);
X}
X
void
clrline(cp1, cp2)
register char	*cp1,
X		*cp2;
X{
X	while (cp1 <= cp2)
X		*cp1++ = ' ';
X}
X
X#if !(defined(IBMPC) || defined(MAC))
X#define sputc(c)	((*cursor != (char) (c)) ? dosputc(c) : (cursor++, i_col++))
X#endif /* (defined(IBMPC) || defined(MAC)) */
X
X#ifdef IBMPC
int force = 0;
X#define sputc(c)	dosputc(c)
X#endif /* IBMPC */
X
X#ifdef MAC
X#define sputc(c)	bufputc(c)	/* line buffered for mac display */
X#endif /* MAC */
X
X#define soutputc(c)	if (--n <= 0) break; else sputc(c)
X
void
cl_eol()
X{
X	if (cursor > cursend)
X		return;
X
X	if (cursor < Curline->s_length) {
X#if !(defined(IBMPC) || defined(MAC))
X		if (CE) {
X#endif /* (defined(IBMPC) || defined(MAC)) */
X			Placur(i_line, i_col);
X#ifdef TERMCAP
X			putpad(CE, 1);
X#else 
X		clr_eoln();
X#endif /* TERMCAP */
X			clrline(cursor, Curline->s_length);
X#if !(defined(IBMPC) || defined(MAC))
X		} else {
X		/* Ugh.  The slow way for dumb terminals. */
X			register char *savecp = cursor;
X
X			while (cursor <= Curline->s_length)
X				sputc(' ');
X			cursor = savecp;
X		}
X#endif /* (defined(IBMPC) || defined(MAC)) */
X		Curline->s_length = cursor;
X	}
X}
X
void
cl_scr(doit)
X{
X	register int	i;
X	register struct screenline	*sp = Screen;
X
X	for (i = 0; i < LI; i++, sp++) {
X		clrline(sp->s_line, sp->s_length);
X		sp->s_length = sp->s_line;
X		PhysScreen[i].s_id = 0;
X	}
X	if (doit) {
X#ifdef TERMCAP
X		putpad(CL, LI);
X#else 
X		clr_page();
X#endif /* TERMCAP */
X		CapCol = CapLine = 0;
X		UpdMesg = YES;
X	}
X}
X
X#ifdef ID_CHAR
extern int	IN_INSmode;
X#endif
X
X/* Output one character (if necessary) at the current position */
X
X#ifndef MAC
int		/* only for lints sake */
dosputc(c)
register char	c;
X{
X#ifndef IBMPC
X	if (*cursor != c) {
X#ifdef ID_CHAR
X		if (IN_INSmode)
X			INSmode(0);
X#endif
X#else /* IBMPC */
X	if ((force) || (*cursor != c)) {
X#endif /* IBMPC */
X		if (i_line != CapLine || i_col != CapCol)
X			Placur(i_line, i_col);
X#ifndef IBMPC
X		if (UL && (c & CHARMASK) == '_' && (*cursor & CHARMASK) != ' ')
X			putstr(" \b");		/* Erase so '_' looks right. */
X#endif /* IBMPC */
X		*cursor++ = c;
X#ifndef IBMPC
X		putchar(c & CHARMASK);
X#else /* IBMPC */
X		normfun(c);
X#endif /* IBMPC */
X		AbortCnt -= 1;
X		CapCol += 1;
X		i_col += 1;
X	} else {
X		cursor += 1;
X		i_col += 1;
X	}
X}
X#else /* MAC */
X
X/* Character output to bit-mapped screen is very expensive. It makes
X   much more sense to write the entire line at once. So, we print all
X   the characters, whether already there or not, once the line is
X   complete.  */
X   
X#define BUFFLUSH (char) 0
X#define BUFSTART (char) 1
X    
bufputc(c)
register char c;
X{
X	static char buf[256];
X	static int len = 0;
X	
X	if(c == BUFSTART) {
X/*		if (i_line != CapLine || i_col != CapCol)*/
X			NPlacur(i_line, i_col);
X		len = 0;
X		return;
X	}
X	if(c == BUFFLUSH) {
X		buf[0] = (unsigned char) len;
X		writechr(buf);
X		len = 0;
X	}
X	else {
X		if(len > 255) return;
X		*cursor++ = c;
X		if(c == '0') buf[++len] = 0xAF;	/* slashed zero */
X 		else buf[++len] = c;
X		CapCol++;
X		i_col++;
X	}
X	return;
X}
X#endif /* MAC */
X
X/* Write `line' at the current position of `cursor'.  Stop when we
X   reach the end of the screen.  Aborts if there is a character
X   waiting.  */
X
X#ifdef MAC		/* This was getting too complicated with ifdefs ... */
int
swrite(line, inversep, abortable)
register char	*line;
register int	abortable;
X{
X	register int	c;
X	int	col = i_col,
X		aborted = 0;
X	register int	n = cursend - cursor;
X
X	if (n <= 0)
X		return 1;
X	sputc(BUFSTART);	/* Okay, because no interruption possible */
X
X	while (c = *line++) {
X		if (c == '\t') {
X			int	nchars;
X
X			nchars = (tabstop - (col % tabstop));
X			col += nchars;
X
X			while (nchars--)
X				soutputc(' ');
X			if (n <= 0)
X				break;
X		} else if (isctrl(c)) {
X			soutputc('^');
X			c = ((c == '\177') ? '?' : c + '@');
X			soutputc(c);
X			col += 2;
X		} else {
X			soutputc(c);
X			col += 1;
X		}
X	}
X	if (n <= 0) {
X		if ((*line == '\0') && (c != '\t') && !isctrl(c))
X			sputc(c);
X			sputc('!');
X	}
X	if (cursor > Curline->s_length)
X		Curline->s_length = cursor;
X	sputc(BUFFLUSH);
X	return !aborted;
X}
X#else /* MAC */
X
int
swrite(line, inversep, abortable)
register char	*line;
register int	abortable;
X{
X	register int	c;
X	int	col = i_col,
X		aborted = 0;
X	register int	n = cursend - cursor;
X#ifndef IBMPC
X	int	or_byte = inversep ? 0200 : 0,
X		thebyte;
X#else 
X	int	thebyte;
X#endif /* IBMPC */
X
X#ifdef IBMPC
X        force = inversep? 1: 0;  /* to force a redraw of the modeline */
X#endif /* IBMPC */
X
X	if (n <= 0)
X		return 1;
X	while (c = *line++) {
X#if !(defined(IBMPC) || defined(MAC))	/* don't check after every character */
X		if (abortable && AbortCnt < 0) {
X			AbortCnt = BufSize;
X			if (InputPending = charp()) {
X				aborted = 1;
X				break;
X			}
X		}
X#endif /* (defined(IBMPC) || defined(MAC)) */
X		if (c == '\t') {
X			int	nchars;
X
X			nchars = (tabstop - (col % tabstop));
X			col += nchars;
X
X#ifndef IBMPC
X			thebyte = (' ' | or_byte);
X#endif /* IBMPC */
X			while (nchars--)
X#ifndef IBMPC
X				soutputc(thebyte);
X#else /* IBMPC */
X				soutputc(' ');
X#endif /* IBMPC */
X			if (n <= 0)
X				break;
X		} else if (isctrl(c)) {
X#ifndef IBMPC
X			thebyte = ('^' | or_byte);
X			soutputc(thebyte);
X			thebyte = (((c == '\177') ? '?' : c + '@') | or_byte);
X			soutputc(thebyte);
X#else /* IBMPC */
X			soutputc('^');
X			c = ((c == '\177') ? '?' : c + '@');
X			soutputc(c);
X#endif /* IBMPC */
X			col += 2;
X		} else {
X#ifndef IBMPC
X			thebyte = (c | or_byte);
X			soutputc(thebyte);
X#else /* IBMPC */
X 		    if (c == 255) c = 1;
X			if (c == ' ' && inversep) c = 255;
X			soutputc(c);
X#endif /* IBMPC */
X			col += 1;
X		}
X	}
X	if (n <= 0) {
X		if ((*line == '\0') && (c != '\t') && !isctrl(c))
X#ifndef IBMPC
X			sputc(c|or_byte);
X#else /* IBMPC */
X			sputc(c);
X#endif /* IBMPC */
X		else
X#ifndef IBMPC
X			sputc('!'|or_byte);
X#else /* IBMPC */
X			sputc('!');
X#endif /* IBMPC */
X	}
X	if (cursor > Curline->s_length)
X		Curline->s_length = cursor;
X#ifdef IBMPC
X	force = 0;
X#endif
X	return !aborted;
X}
X#endif /* MAC */
X/* This is for writing a buffer line to the screen.  This is to
X   minimize the amount of copying from one buffer to another buffer.
X   This gets the info directly from the disk buffers. */
X
int
BufSwrite(linenum)
X{
X	register int	n = cursend - cursor,
X			col = 0,
X			c = -1;
X	register char	*bp;
X	int	StartCol = DesiredScreen[linenum].s_offset,
X		visspace = DesiredScreen[linenum].s_window->w_flags & W_VISSPACE,
X		aborted = 0;
X
X	bp = lcontents(DesiredScreen[linenum].s_lp);
X	if (*bp) for (;;) {
X		if (col >= StartCol) {
X			DesiredScreen[linenum].s_offset = col;
X			break;
X		}
X
X		c = *bp++ & CHARMASK;
X		if (c == '\0')
X			break;
X		if (c == '\t')
X			col += (tabstop - (col % tabstop));
X		else if (isctrl(c))
X			col += 2;
X		else
X			col += 1;
X	}
X#ifdef MAC
X	sputc(BUFSTART);	/* Okay because we can't be interrupted */
X#endif
X
X	if (c != '\0') while (c = *bp++) {
X#if !(defined(IBMPC) || defined(MAC))		/* will never get true so why bother */
X		if (AbortCnt < 0) {
X			AbortCnt = BufSize;
X			if (InputPending = charp()) {
X				aborted = 1;
X				break;
X			}
X		}
X#endif /* (defined(IBMPC) || defined(MAC)) */
X		if (c == '\t') {
X			int	nchars = (tabstop - (col % tabstop));
X
X			col += nchars;
X			if (visspace) {
X				soutputc('>');
X				nchars -= 1;
X			}
X			while (--nchars >= 0)
X				soutputc(' ');
X			if (n <= 0)
X				break;
X		} else if (isctrl(c)) {
X			soutputc('^');
X			soutputc((c == '\177') ? '?' : c + '@');
X			col += 2;
X		} else {
X			if (c == ' ' && visspace)
X				c = '_';
X#ifdef IBMPC
X			if (c == 255)
X			   c = 1;
X#endif /* IBMPC */
X			soutputc(c);
X			col += 1;
X		}
X	}
X	if (n <= 0) {
X		if ((*bp == '\0') && (c != '\t') && !isctrl(c))
X			sputc(c);
X		else
X			sputc('!');
X	}
X	if (cursor > Curline->s_length)
X		Curline->s_length = cursor;
X#ifdef MAC
X	sputc(BUFFLUSH);
X#endif
X	return !aborted;		/* Didn't abort */
X}
X
void
i_set(nline, ncol)
register int	nline,
X		ncol;
X{
X	Curline = &Screen[nline];
X	cursor = Curline->s_line + ncol;
X	cursend = &Curline->s_line[CO - 1];
X	i_line = nline;
X	i_col = ncol;
X}
X
X/* Insert `num' lines a top, but leave all the lines BELOW `bottom'
X   alone (at least they won't look any different when we are done).
X   This changes the screen array AND does the physical changes. */
X
void
v_ins_line(num, top, bottom)
X{
X	register int	i;
X
X	/* Save the screen pointers. */
X
X	for(i = 0; i < num && top + i <= bottom; i++)
X		Savelines[i] = Screen[bottom - i];
X
X	/* Num number of bottom lines will be lost.
X	   Copy everything down num number of times. */
X
X	for (i = bottom; i > top && i-num >= 0; i--)
X		Screen[i] = Screen[i - num];
X
X	/* Restore the saved ones, making them blank. */
X
X	for (i = 0; i < num; i++) {
X		Screen[top + i] = Savelines[i];
X		clrline(Screen[top + i].s_line, Screen[top + i].s_length);
X		Screen[top + i].s_length = Screen[top + i].s_line;
X	}
X
X#if !(defined(IBMPC) || defined(MAC))
X	(*TTins_line)(top, bottom, num);
X#endif
X
X#ifdef MAC
X	i_lines(top, bottom, num);
X#endif 
X
X#ifdef IBMPC
X	scr_win(-num, top, 0, bottom, CHPL-1);
X#endif 
X}
X
X/* Delete `num' lines starting at `top' leaving the lines below `bottom'
X   alone.  This updates the internal image as well as the physical image.  */
X
void
v_del_line(num, top, bottom)
X{
X	register int	i,
X			bot;
X
X	bot = bottom;
X
X	/* Save the lost lines. */
X
X	for (i = 0; i < num && top + i <= bottom; i++)
X		Savelines[i] = Screen[top + i];
X
X	/* Copy everything up num number of lines. */
X
X	for (i = top; num + i <= bottom; i++)
X		Screen[i] = Screen[i + num];
X
X	/* Restore the lost ones, clearing them. */
X
X	for (i = 0; i < num; i++) {
X		Screen[bottom - i] = Savelines[i];
X		clrline(Screen[bot].s_line, Screen[bot].s_length);
X		Screen[bot].s_length = Screen[bot].s_line;
X		bot -= 1;
X	}
X
X#if !(defined(IBMPC) || defined(MAC))
X	(*TTdel_line)(top, bottom, num);
X#endif
X
X#ifdef MAC
X	d_lines(top, bottom, num);
X#endif
X
X#ifdef IBMPC
X	scr_win(num, top, 0, bottom, CHPL-1);
X#endif 
X
X}
X
X#ifndef MAC	/* remainder of this file */
X#ifdef IBMPC
X
X/* No cursor optimization on an IBMPC, this simplifies things a lot.
X   Think about it: it would be silly!
X */
X
int	phystab = 8;
X
void
Placur(line, col)
X{
X	cur_mov(line, col);
X	CapCol = col;
X	CapLine = line;
X}
X
void
SO_on()
X{
X	if (Mdcolor)
X		setcolor(Mdcolor&0xf, Mdcolor>>4);
X	else
X		setcolor(Bgcolor, Fgcolor);
X}
X
void
SO_off()
X{
X   setcolor(Fgcolor, Bgcolor);
X}
X
extern int EGA;
X
void
X
UnsetTerm(foo)
char *foo;
X{
X  Placur(ILI, 0);
X  clr_eoln();
X  if (EGA)
X	 reset_43();
X}
X
X
void
ResetTerm()
X{
X	if (EGA)
X	   init_43();
X	else
X   	   init_term();
X	   
X	do_sgtty();		/* this is so if you change baudrate or stuff
X				   like that, JOVE will notice. */
X	ttyset(ON);
X}
X
X#else /* IBMPC */ 
X
X/* The cursor optimization happens here.  You may decide that this
X   is going too far with cursor optimization, or perhaps it should
X   limit the amount of checking to when the output speed is slow.
X   What ever turns you on ...   */
X
private struct cursaddr {
X	int	cm_numchars,
X		(*cm_proc)();
X};
X
private char	*Cmstr;
private struct cursaddr	*HorMin,
X			*VertMin,
X			*DirectMin;
X
private void
X	GENi_lines(),
X	GENd_lines(),
X	ForMotion(),
X	ForTab(),
X	BackMotion(),
X	RetTab(),
X	DownMotion(),
X	UpMotion(),
X	GoDirect(),
X	HomeGo(),
X	BottomUp();
X	
X
private struct cursaddr	WarpHor[] = {
X	0,	ForMotion,
X	0,	ForTab,
X	0,	BackMotion,
X	0,	RetTab
X};
X
private struct cursaddr	WarpVert[] = {
X	0,	DownMotion,
X	0,	UpMotion
X};
X
private struct cursaddr	WarpDirect[] = {
X	0,	GoDirect,
X	0,	HomeGo,
X	0,	BottomUp
X};
X
X#undef	FORWARD
X#define	FORWARD		0	/* Move forward */
X#define FORTAB		1	/* Forward using tabs */
X#undef	BACKWARD
X#define	BACKWARD	2	/* Move backward */
X#define RETFORWARD	3	/* Beginning of line and then tabs */
X#define NUMHOR		4
X
X#define DOWN		0	/* Move down */
X#define UPMOVE		1	/* Move up */
X#define NUMVERT		2
X
X#define DIRECT		0	/* Using CM */
X#define HOME		1	/* HOME	*/
X#define LOWER		2	/* Lower Line */
X#define NUMDIRECT	3
X
X#define	home()		Placur(0, 0)
X#define LowLine()	putpad(LL, 1), CapLine = ILI, CapCol = 0
X#define PrintHo()	putpad(HO, 1), CapLine = CapCol = 0
X
int	phystab = 8;
X
private void
GoDirect(line, col)
register int	line,
X		col;
X{
X	putpad(Cmstr, 1);
X	CapLine = line;
X	CapCol = col;
X}
X
private void
RetTab(col)
register int	col;
X{
X	putchar('\r');
X	CapCol = 0;
X	ForTab(col);
X}
X
private void
HomeGo(line, col)
X{
X	PrintHo();
X	DownMotion(line);
X	ForTab(col);
X}
X
private void
BottomUp(line, col)
register int	line,
X		col;
X{
X	LowLine();
X	UpMotion(line);
X	ForTab(col);
X}
X
X/* Tries to move forward using tabs (if possible).  It tabs to the
X   closest tabstop which means it may go past 'destcol' and backspace
X   to it. */
X
private void
ForTab(destcol)
int	destcol;
X{
X	register int	tabgoal,
X			ntabs,
X			tabstp = phystab;
X
X	if (TABS && (tabstp > 0)) {
X		tabgoal = destcol + (tabstp / 2);
X		tabgoal -= (tabgoal % tabstp);
X
X		/* Don't tab to last place or else it is likely to screw up. */
X		if (tabgoal >= CO)
X			tabgoal -= tabstp;
X
X		ntabs = (tabgoal / tabstp) - (CapCol / tabstp);
X		while (--ntabs >= 0)
X			putchar('\t');
X		CapCol = tabgoal;
X	}
X	if (CapCol > destcol)
X		BackMotion(destcol);
X	else if (CapCol < destcol)
X		ForMotion(destcol);
X}
X
private void
ForMotion(destcol)
register int	destcol;
X{
X	register int	nchars = destcol - CapCol;
X	register char	*cp = &Screen[CapLine].s_line[CapCol];
X
X	while (--nchars >= 0)
X		putchar(*cp++ & CHARMASK);
X	CapCol = destcol;
X}
X
private void
BackMotion(destcol)
register int	destcol;
X{
X	register int	nchars = CapCol - destcol;
X
X	if (BC)
X		while (--nchars >= 0)
X			putpad(BC, 1);
X	else
X		while (--nchars >= 0)
X			putchar('\b');
X	CapCol = destcol;
X}
X
private void
DownMotion(destline)
register int	destline;
X{
X	register int	nlines = destline - CapLine;
X
X	while (--nlines >= 0)
X		putpad(NL, 1);
X	CapLine = destline;
X}
X
private void
UpMotion(destline)
register int	destline;
X{
X	register int	nchars = CapLine - destline;
X
X	while (--nchars >= 0)
X		putpad(UP, 1);
X	CapLine = destline;
X}
X
X#ifdef ID_CHAR
static int	EIlen;
X#endif
extern int	IMlen;
X
void
InitCM()
X{
X	HOlen = HO ? strlen(HO) : 1000;
X	LLlen = LL ? strlen(LL) : 1000;
X	UPlen = UP ? strlen(UP) : 1000;
X#ifdef ID_CHAR
X	if (EI)
X		EIlen = strlen(EI);
X#endif
X}
X
void
Placur(line, col)
X{
X	int	dline,		/* Number of lines to move */
X		dcol;		/* Number of columns to move */
X	register int	best,
X			i;
X	register struct cursaddr	*cp;
X	int	xtracost = 0;	/* Misc addition to cost. */
X
X#define CursMin(which,addrs,max) \
X	for (best = 0, cp = &addrs[1], i = 1; i < max; i++, cp++) \
X		if (cp->cm_numchars < addrs[best].cm_numchars) \
X			best = i; \
X	which = &addrs[best];
X
X	if (line == CapLine && col == CapCol)
X		return;		/* We are already there. */
X
X	dline = line - CapLine;
X	dcol = col - CapCol;
X#ifdef ID_CHAR
X	if (IN_INSmode && MI)
X		xtracost = EIlen + IMlen;
X	/* If we're already in insert mode, it is likely that we will
X	   want to be in insert mode again, after the insert. */
X#endif
X
X	/* Number of characters to move horizontally for each case.
X	   1: Just move forward by typing the right character on the screen.
X	   2: Print the correct number of back spaces.
X	   3: Try tabbing to the correct place.
X	   4: Try going to the beginning of the line, and then tab. */
X
X	if (dcol == 1 || dcol == 0) {		/* Most common case. */
X		HorMin = &WarpHor[FORWARD];
X		HorMin->cm_numchars = dcol + xtracost;
X	} else {
X		WarpHor[FORWARD].cm_numchars = dcol >= 0 ? dcol + xtracost : 1000;
X		WarpHor[BACKWARD].cm_numchars = dcol < 0 ? -(dcol + xtracost) : 1000;
X		WarpHor[FORTAB].cm_numchars = dcol >= 0 && TABS ?
X				ForNum(CapCol, col) + xtracost : 1000;
X		WarpHor[RETFORWARD].cm_numchars = (xtracost + 1 + (TABS ? ForNum(0, col) : col));
X
X		/* Which is the shortest of the bunch */
X
X		CursMin(HorMin, WarpHor, NUMHOR);
X	}
X
X	/* Moving vertically is more simple. */
X
X	WarpVert[DOWN].cm_numchars = dline >= 0 ? dline : 1000;
X	WarpVert[UPMOVE].cm_numchars = dline < 0 ? ((-dline) * UPlen) : 1000;
X
X	/* Which of these is simpler */
X	CursMin(VertMin, WarpVert, NUMVERT);
X
X	/* Homing first and lowering first are considered 
X	   direct motions.
X	   Homing first's total is the sum of the cost of homing
X	   and the sum of tabbing (if possible) to the right. */
X	
X	if (VertMin->cm_numchars + HorMin->cm_numchars <= 3) {
X		DirectMin = &WarpDirect[DIRECT];	/* A dummy ... */
X		DirectMin->cm_numchars = 100;
X	} else {
X		WarpDirect[DIRECT].cm_numchars = CM ?
X				strlen(Cmstr = tgoto(CM, col, line)) : 1000;
X		WarpDirect[HOME].cm_numchars = HOlen + line +
X				WarpHor[RETFORWARD].cm_numchars;
X		WarpDirect[LOWER].cm_numchars = LLlen + ((ILI - line) * UPlen) +
X				WarpHor[RETFORWARD].cm_numchars;
X		CursMin(DirectMin, WarpDirect, NUMDIRECT);
X	}
X
X	if (HorMin->cm_numchars + VertMin->cm_numchars < DirectMin->cm_numchars) {
X		if (line != CapLine)
X			(*VertMin->cm_proc)(line);
X		if (col != CapCol) {
X#ifdef ID_CHAR
X			if (IN_INSmode)	/* We may use real characters ... */
X				INSmode(0);
X#endif
X			(*HorMin->cm_proc)(col);
X		}
X	} else {
X#ifdef ID_CHAR
X		if (IN_INSmode && !MI)
X			INSmode(0);
X#endif
X		(*DirectMin->cm_proc)(line, col);
X	}
X}
X
X#define abs(x)	((x) >= 0 ? (x) : -(x))
X
int
ForNum(from, to)
register int	from;
X{
X	register int	tabgoal,
X			tabstp = phystab;
X	int		numchars = 0;
X
X	if (from >= to)
X		return from - to;
X	if (TABS && (tabstp > 0)) {
X		tabgoal = to + (tabstp / 2);
X		tabgoal -= (tabgoal % tabstp);
X		if (tabgoal >= CO)
X			tabgoal -= tabstp;
X		numchars = (tabgoal / tabstop) - (from / tabstp);
X		from = tabgoal;
X	}
X	return numchars + abs(from - to);
X}
X
X#ifdef WIRED_TERMS
X
void
BGi_lines(top, bottom, num)
X{
X	printf("\033[%d;%dr\033[%dL\033[r", top + 1, bottom + 1, num);
X	CapCol = CapLine = 0;
X}
X
void
SUNi_lines(top, bottom, num)
X{
X	Placur(bottom - num + 1, 0);
X	printf("\033[%dM", num);
X	Placur(top, 0);
X	printf("\033[%dL", num);
X}
X
void
C100i_lines(top, bottom, num)
X{
X	if (num <= 1) {
X		GENi_lines(top, bottom, num);
X		return;
X	}
X	printf("\033v%c%c%c%c", ' ', ' ', ' ' + bottom + 1, ' ' + CO);
X	CapLine = CapCol = 0;
X	Placur(top, 0);
X	while (num--)
X		putpad(AL, ILI - CapLine);
X	printf("\033v%c%c%c%c", ' ', ' ', ' ' + LI, ' ' + CO);
X	CapLine = CapCol = 0;
X}
X
X#endif /* WIRED_TERMS */
X
private void
GENi_lines(top, bottom, num)
X{
X	register int	i;
X
X	if (CS) {
X		putpad(tgoto(CS, bottom, top), 1);
X		CapCol = CapLine = 0;
X		Placur(top, 0);
X		for (i = 0; i < num; i++)
X			putpad(SR, bottom - top);
X		putpad(tgoto(CS, ILI, 0), 1);
X		CapCol = CapLine = 0;
X	} else {
X		Placur(bottom - num + 1, 0);
X		if (M_DL && (num > 1)) {
X			char	minibuf[16];
X
X			sprintf(minibuf, M_DL, num);
X			putpad(minibuf, ILI - CapLine);
X		} else {
X			for (i = 0; i < num; i++)
X				putpad(DL, ILI - CapLine);
X		}
X		Placur(top, 0);
X		if (M_AL && (num > 1)) {
X			char	minibuf[16];
X
X			sprintf(minibuf, M_AL, num);
X			putpad(minibuf, ILI - CapLine);
X		} else {
X			for (i = 0; i < num; i++)
X				putpad(AL, ILI - CapLine);
X		}
X	}
X}
X
X#ifdef WIRED_TERMS
X
void
BGd_lines(top, bottom, num)
X{
X	printf("\033[%d;%dr\033[%dM\033[r", top + 1, bottom + 1, num);
X	CapCol = CapLine = 0;
X}
X
void
SUNd_lines(top, bottom, num)
X{
X	Placur(top, 0);
X	printf("\033[%dM", num);
X	Placur(bottom + 1 - num, 0);
X	printf("\033[%dL", num);
X}
X
void
C100d_lines(top, bottom, num)
X{
X	if (num <= 1) {
X		GENd_lines(top, bottom, num);
X		return;
X	}
X	printf("\033v%c%c%c%c", ' ', ' ', ' ' + bottom + 1, ' ' + CO);
X	CapLine = CapCol = 0;
X	Placur(top, 0);
X	while (num--)
X		putpad(DL, ILI - CapLine);
X	printf("\033v%c%c%c%c", ' ', ' ', ' ' + LI, ' ' + CO);
X	CapLine = CapCol = 0;
X}
X
X#endif /* WIRED_TERMS */
X
private void
GENd_lines(top, bottom, num)
X{
X	register int	i;
X
X	if (CS) {
X		putpad(tgoto(CS, bottom, top), 1);
X		CapCol = CapLine = 0;
X		Placur(bottom, 0);
X		for (i = 0; i < num; i++)
X			putpad(SF, bottom - top);
X		putpad(tgoto(CS, ILI, 0), 1);
X		CapCol = CapLine = 0;
X	} else {
X		Placur(top, 0);
X		if (M_DL && (num > 1)) {
X			char	minibuf[16];
X
X			sprintf(minibuf, M_DL, num);
X			putpad(minibuf, ILI - top);
X		} else {
X			for (i = 0; i < num; i++)
X				putpad(DL, ILI - top);
X		}
X		Placur(bottom + 1 - num, 0);
X		if (M_AL && (num > 1)) {
X			char	minibuf[16];
X
X			sprintf(minibuf, M_AL, num);
X			putpad(minibuf, ILI - CapLine);
X		} else {
X			for (i = 0; i < num; i++)
X				putpad(AL, ILI - CapLine);
X		}
X	}
X}
X
struct ID_lookup {
X	char	*ID_name;
X	int	(*I_proc)();	/* proc to insert lines */
X	int	(*D_proc)();	/* proc to delete lines */
X} ID_trms[] = {
X	"generic",	GENi_lines,	GENd_lines,	/* This should stay here */
X#ifdef WIRED_TERMS
X	"sun",		SUNi_lines,	SUNd_lines,
X	"bg",		BGi_lines,	BGd_lines,
X	"c1",		C100i_lines,	C100d_lines,
X#endif /* WIRED_TERMS */
X	0,		0,		0
X};
X
void
IDline_setup(tname)
char	*tname;
X{
X	register struct ID_lookup	*idp;
X
X	for (idp = &ID_trms[1]; idp->ID_name; idp++)
X		if (strncmp(idp->ID_name, tname, strlen(idp->ID_name)) == 0)
X			break;
X	if (idp->ID_name == 0)
X		idp = &ID_trms[0];
X	TTins_line = idp->I_proc;
X	TTdel_line = idp->D_proc;
X}
X
X#endif /* IBMPC */
X#endif /* MAC */
END_OF_FILE
if test 28777 -ne `wc -c <'./screen.c'`; then
    echo shar: \"'./screen.c'\" unpacked with wrong size!
fi
# end of './screen.c'
fi
echo shar: End of archive 14 \(of 21\).
cp /dev/null ark14isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 21 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
-- 
Please send comp.sources.unix-related mail to rsalz@uunet.uu.net.