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.