v14i070: Jove, an emacs variant, version 4.9, Part14/21
Rich Salz
rsalz at bbn.com
Thu Apr 28 10:55:42 AEST 1988
Submitted-by: Jonathan Payne <jpayne at 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 at uunet.uu.net.
More information about the Comp.sources.unix
mailing list