sources-request@mirror.UUCP (03/13/87)
Submitted by: genrad!mlf
Mod.sources: Volume 9, Issue 31
Archive-name: teco/Part04
#! /bin/sh
# This is a shell archive. Remove anything before this line,
# then unpack it by saving it in a file and typing "sh file".
# If this archive is complete, you will see the message:
# "End of archive 4 (of 4)."
# Contents: te_window.c
# Wrapped by rs@mirror on Thu Mar 12 19:54:35 1987
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
echo shar: Extracting \"te_window.c\" \(33018 characters\)
if test -f te_window.c ; then
echo shar: Will not over-write existing file \"te_window.c\"
else
sed "s/^X//" >te_window.c <<'END_OF_te_window.c'
X/* TECO for Ultrix Copyright 1986 Matt Fichtenbaum */
X/* This program and its components belong to GenRad Inc, Concord MA 01742 */
X/* They may be copied if this copyright notice is included */
X
X/* te_window.c window for teco 10/10/86 */
X/* This attempts to be a real window, without unecessary redraw */
X/* it is very VT-100 specific, and ought to be rewritten to be general */
X
X#include "te_defs.h"
X
X/* maximum screen height and width (horiz and vert, not height and vidth) */
X#define W_MAX_V 70
X#define W_MAX_H 150
X#define MAX 0x7fffffff /* maximum positive integer, for "last modified" location */
X#define W_MARK 0200 /* "this loc is special" in screen image */
X
X
X/* image of current window */
X
Xstruct w_line /* data associated with one screen line */
X {
X int start, end; /* dot at beginning, at end */
X short n, cflag, col; /* number of char positions used, line continuation flag, starting col */
X char ch[W_MAX_H]; /* image of line */
X }
X w_image[W_MAX_V];
X
X
X/* define "this line is continued" / "this line is a continuation" flags */
X#define WF_BEG 1
X#define WF_CONT 2
X
Xstruct w_line *wlp[W_MAX_V]; /* each word points to the corresponding line's data structure */
X
Xstruct qp w_p1; /* pointer for window access to buffer */
X
Xshort curr_x, curr_y; /* active character position */
Xshort term_x, term_y; /* current terminal cursor position */
Xshort curs_x, curs_y; /* current teco dot screen coordinates */
Xshort last_y; /* last used line in window */
Xchar curs_c; /* code for char at cursor */
Xchar *curs_p; /* pointer to cursor loc in window image */
Xshort curs_crflag; /* flag that cursor is on a CR */
Xshort redraw_sw; /* forces absolute redraw */
X
X
X/* fill characters and terminal speeds: 0th entry used when std out is not a terminal */
Xchar win_speeds[] = { 0, 0, B9600, B4800, B2400, B1800, B1200, B600, B300, B200, B150, B134, B110 };
Xchar win_dlye[] = { 0, 90, 45, 23, 11, 9, 6, 3, 1, 1, 1, 1, 1 }; /* delay for erase-screen */
Xchar win_dlys[] = { 0, 60, 30, 15, 7, 6, 4, 2, 1, 1, 0, 0, 0 }; /* delay for scroll ops */
Xchar win_dlyl[] = { 0, 4, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; /* delay for erase line */
Xchar win_dlyc[] = { 0, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; /* delay for other control functions */
Xshort win_speed;
X/* routine to perform simple scope operations */
X/* (an attempt to concentrate VT-100 specific things in one place) */
X
Xvt(func)
X int func;
X {
X short t;
X switch (func)
X {
X case VT_CLEAR: /* clear screen */
X fputs("\033[H\033[J", stdout);
X for (t = 0; t < win_dlye[win_speed]; t++) putchar('\0'); /* fill chars */
X break;
X
X case VT_EEOL: /* erase to end of line */
X fputs("\033[K", stdout);
X for (t = 0; t < win_dlyl[win_speed]; t++) putchar('\0'); /* fill chars */
X break;
X
X case VT_EBOL: /* erase from beginning of line */
X fputs("\033[1K", stdout);
X for (t = 0; t < win_dlyl[win_speed]; t++) putchar('\0'); /* fill chars */
X break;
X
X case VT_SETSPEC1: /* reverse video */
X fputs("\033[7m", stdout);
X break;
X
X case VT_SETSPEC2: /* bright reverse video */
X fputs("\033[1;7m", stdout);
X break;
X
X case VT_CLRSPEC: /* normal video */
X fputs("\033[0m", stdout);
X break;
X
X case VT_BS1: /* backspace 1 spot */
X fputs("\b \b", stdout);
X break;
X
X case VT_BS2: /* backspace 2 spots */
X fputs("\b \b\b \b", stdout);
X break;
X
X case VT_LINEUP: /* up one line */
X fputs("\033[1A", stdout);
X break;
X }
X }
X/* routine to set window parameters */
X
X/* 0: scope type, 1: width, 2: height, 3: seeall, 4: mark position, */
X/* 5: hold mode, 6: upper left corner position, 7: scroll region size */
X
X/* 0 1 2 3 4 5 6 7 */
Xint win_min[] = { 4, 20, 4, 0, 0, -1, 1, 0 } ; /* min values for window parameters */
Xint win_max[] = { 4, W_MAX_H, W_MAX_V, 1, MAX, 12, -1, 20 } ; /* max values */
Xint win_data[] = { 4, 132, 24, 0, 0, 0, 0, 0 } ; /* window parameters */
X
Xint window_size; /* # of lines in a window */
X
Xdo_window(ref_flag)
X int ref_flag; /* nonzero forces "refresh" operation */
X {
X int i;
X
X if (colonflag && !ref_flag)
X {
X i = get_value(0); /* get sub-function */
X if ((i < 0) || (i > 7)) ERROR(E_IWA);
X if (!esp->flag2) /* it's a "get" */
X {
X esp->val1 = win_data[i];
X esp->flag1 = 1;
X }
X else
X {
X if ((esp->val2 < win_min[i]) || (esp->val2 > win_max[i])) /* check range */
X ERROR(E_IWA);
X if (i == 7)
X {
X if (esp->val2)
X {
X WN_scroll = esp->val2;
X window_size = WN_height - WN_scroll; /* define size of window area */
X window(WIN_INIT); /* turn on window */
X }
X else window(WIN_OFF); /* turn off window */
X }
X win_data[i] = esp->val2; /* redundant for ~0,7:w, but no harm */
X esp->flag2 = 0;
X window(WIN_REDRAW); /* redraw window */
X }
X }
X
X else /* no colon, or ^W command */
X {
X if (esp->flag1 || ref_flag)
X {
X if (!ref_flag && (esp->val1 == -1000)) redraw_sw = 0; /* -1000W: "forget that output was done" */
X else window(WIN_DISP); /* nW or ^W refreshes window */
X }
X esp->flag2 = esp->flag1 = 0; /* no colon, consume args */
X }
X colonflag = 0;
X esp->op = OP_START;
X }
X/* routine to update screen size with numbers obtained from environment */
X/* (called by main program's initialization) */
X
Xset_term_par(lines, cols)
X int lines, cols;
X {
X if ((lines >= win_min[2]) && (lines <= win_max[2])) window_size = win_data[2] = lines;
X if ((cols >= win_min[1]) && (cols <= win_max[1])) win_data[1] = cols;
X }
X
X
X/* window routine. performs function as indicated by argument */
X/* WIN_OFF: disables split-screen scrolling */
X/* WIN_SUSP: disables split-screen scrolling temporarily */
X/* WIN_INIT: sets up display support if split-screen scrolling enabled, else nop */
X/* WIN_RESUME: re-enables display support */
X/* WIN_REDRAW: causes window to be redrawn on next refresh call */
X/* WIN_REFR: if scrolling enabled, redoes window, else if ev or es enabled, does */
X/* that, else nop */
X/* WIN_LINE: does WIN_REFR unless that wouldn't do anything, in which case */
X/* it does effective 1EV output */
X
Xint last_dot = -1; /* last dot location */
X
Xwindow(arg)
X int arg;
X {
X int i;
X
X switch (arg)
X {
X case WIN_OFF: /* final window off */
X case WIN_SUSP: /* temp window off */
X if (WN_scroll) /* if reset/clean up */
X {
X /* full margins, cursor to last line, erase line */
X printf("\033[r\033[%d;0H\033[K", WN_height);
X }
X break;
X
X case WIN_INIT: /* initialize window - find output speed */
X if (out_noterm) win_speed = 0; /* std out is not a terminal */
X else
X {
X for (win_speed = 1; (win_speeds[win_speed] != ttybuf.sg_ospeed) && (win_speed < 13); win_speed++);
X if (win_speed == 13) win_speed = 1;
X }
X w_init(); /* set up screen image buffer */
X if (WN_scroll) vt(VT_CLEAR); /* if split-screen is enabled, clear screen */
X /* (fall through to "resume") */
X
X case WIN_RESUME: /* re-enable window */
X if (WN_scroll) /* set scroll region, cursor to bottom */
X printf("\033[%d;%dr\033[%d;0H", WN_height - WN_scroll + 1, WN_height, WN_height);
X break;
X case WIN_REDRAW: /* force redraw of window */
X redraw_sw = 1;
X break;
X
X case WIN_LINE: /* display one line unless window enabled or ev */
X if (WN_scroll || ev_val) window(WIN_REFR); /* if a real window is set, do it */
X else if (w_setptr(dot, &w_p1)) /* set pointer to dot... and if there's a buffer */
X {
X w_lines(0, &w_p1, &w_p1); /* get to beginning of line */
X window0(1); /* and type 1 line */
X }
X break;
X
X case WIN_REFR: /* if enabled, refresh window; else do ev or es */
X if (WN_scroll) window1(); /* if scrolling enabled, refresh the window */
X else if ((ev_val) || (es_val && search_flag)) /* else if ev or es, do that */
X {
X i = (ev_val) ? ev_val : es_val;
X if (w_setptr(dot, &w_p1)) /* set a pointer at dot... and if there's a buffer */
X window0(i - w_lines(1 - i, &w_p1, &w_p1)); /* go back (i-1) lines and ahead (i) lines */
X }
X break;
X
X case WIN_DISP: /* display buffer independent of whether scroll mode is enabled */
X window1();
X break;
X
X } /* end of switch */
X
X fflush(stdout); /* send output out */
X } /* end of window() */
X/* routine to type n lines with character at "dot" in reverse video */
X/* used for ev, es, and <BS> or <LF> as immediate commands */
X/* starting char position is in w_p1; argument is number of lines */
X
Xwindow0(num)
X int num;
X {
X int wi;
X char wc; /* temp char */
X
X for (wi = w_p1.dot; (num > 0) && (wi < z); wi++) /* for each character */
X {
X wc = w_p1.p->ch[w_p1.c]; /* get character */
X
X if ((char_count >= WN_width) && (wc != CR) && !(spec_chars[wc] & A_L)) /* if about to exceed width */
X {
X if (et_val & ET_TRUNC) goto w0_noprint; /* truncate: don't print this */
X else
X {
X fputs("\033[K\015\012\033(0h\033(B ", stdout); /* <eeol> "NL space" */
X char_count = 2;
X --num; /* one fewer line remaining */
X }
X }
X
X if (wi == dot) /* if this char is at the pointer */
X {
X vt(VT_SETSPEC2); /* set reverse video */
X if (wc == TAB)
X {
X type_char(' '); /* illuminate the first sp of a tab */
X vt(VT_CLRSPEC); /* clear reverse video */
X if (char_count & tabmask) type_char(TAB);
X }
X else /* not a tab */
X {
X if ((wc == CR) && (char_count < WN_width)) /* CR at rh margin: don't display cursor */
X {
X type_char(' '); /* cr: put a space after line */
X vt(VT_EEOL); /* erase to eol */
X }
X type_char(wc); /* type the char, or exec CR */
X if (wc == LF)
X {
X fputs("\033(0", stdout);
X type_char('e');
X fputs("\033(B", stdout);
X }
X vt(VT_CLRSPEC); /* clear reverse video */
X }
X }
X else /* this is not char at pointer */
X {
X if (wc == CR && curr_x < WN_width) vt(VT_EEOL); /* erase to EOL */
X type_char(wc);
X }
X if ((wc == FF) || (wc == VT)) /* FF & VT end a line */
X {
X vt(VT_EEOL); /* erase rest of this line */
X crlf(); /* and leave a blank one */
X if (!(ez_val & EZ_NOVTFF)) --num; /* if FF and VT count as line sep's, count them */
X }
X
X w0_noprint:
X if (++w_p1.c > CELLSIZE-1) w_p1.p = w_p1.p->f, w_p1.c = 0; /* next char */
X if (wc == LF) --num; /* if this is a line feed, count lines */
X }
X
X if (dot == z) fputs("\033[1;7m \033[0m\033[0K", stdout); /* type one space and erase rest of line */
X else fputs("\033[0K", stdout); /* else just erase to EOL */
X }
X/* routine to maintain the screen window */
X/* if scroll mode is enabled, the VT100 screen is split and only the upper part */
X/* is used by this routine; else the whole screen is used. */
X
Xwindow1()
X {
X int i, j, m, lflag;
X
X if (!redraw_sw && (dot == last_dot) && (buff_mod == MAX)) return; /* return if nothing has changed */
X
X block_inter(1); /* disable ^C interrupts */
X if (WN_scroll) printf("\033[1;%dr", window_size); /* scroll mode: redefine scroll region */
X printf("\033[H"); /* home */
X term_y = term_x = 0; /* indicate cursor is at home */
X
X if ((redraw_sw) || (z <= wlp[0]->start)) window1_abs(); /* forced redraw, or z before start of screen */
X
X
X/* check whether pointer is before modified buffer location */
X
X else if (buff_mod >= dot) /* yes */
X {
X
X if (dot < wlp[0]->start) /* if dot is before screen */
X {
X w_setptr(wlp[0]->start, &w_p1); /* get to beginning of screen */
X
X /* check whether screen begins with the last part of a continued line */
X for (j = 0; (wlp[j]->cflag & WF_CONT) && (j < window_size/2); j++);
X if (j < window_size/2) /* if so, does it continue less than halfway down the screen? */
X {
X
X if (j) /* is there a partial line? */
X {
X w_lines(0, &w_p1, &w_p1); /* 0L */
X j -= w_lines(1, &w_p1, NULL); /* now j is number of display lines before screen */
X }
X /* now look for how many lines back "dot" is: if screen starts with partial line, w_p1 has already been moved */
X /* to beginning of the line and j equals the count of extra lines to scroll */
X
X for (i = 0; (dot < w_p1.dot) && (i < window_size/2); ) i -= w_lines(-1, &w_p1, &w_p1);
X if ((dot >= w_p1.dot) && (i < window_size)) /* found point within reason */
X {
X w_scroll(j - i); /* scroll screen down that many lines */
X curr_y = wlp[0]->cflag = wlp[0]->col = curr_x = 0; /* start from top of screen */
X wlp[0]->start = w_p1.dot; /* save starting char position */
X window2(0); /* and rewrite screen */
X }
X
X else window1_abs(); /* farther back than that - redraw */
X }
X
X else window1_abs(); /* continuation was too long: give up and redraw */
X } /* end of "dot is before screen" */
X
X else if (dot <= wlp[last_y]->end) window1_inc(dot); /* on screen - redraw incrementally */
X
X else window1_after(); /* dot is after screen: scroll or redraw */
X } /* end of "dot is before modified point" */
X
X
X/* the modified point in the buffer is before dot */
X
X else
X {
X if (buff_mod < wlp[0]->start) window1_abs(); /* modified point before screen - redraw fully */
X
X else if (buff_mod <= wlp[last_y]->end) /* modified point on screen */
X {
X for (m = 0; buff_mod > wlp[m]->end; m++); /* find line with buff_mod */
X w_setptr(wlp[m]->start, &w_p1); /* set a pointer to start of line with buff_mod */
X j = (m < window_size/2) ? window_size - 1 - m : window_size/2; /* maximum # of lines between buff_mod & dot */
X for (i = 0; (dot >= w_p1.dot) && (w_p1.dot < z) && (i <= j); )
X i += (lflag = w_lines(1, &w_p1, &w_p1) ) ? lflag : 1; /* count lines from buff_mod to first line after dot */
X if (i > j) window1_abs(); /* too far - redraw */
X else
X {
X if (lflag && (dot == z)) i++; /* if at end, following a LF */
X w_setptr(wlp[m]->start, &w_p1); /* pointer to start of area to redraw */
X if (i >= window_size - m) /* if there are not enough blank lines on screen */
X w_scroll(i = i - window_size + m), curr_y = m - i, curs_y -= i; /* scroll up the difference */
X else curr_y = m;
X curr_x = (wlp[curr_y]->cflag & WF_CONT) ? 2 : wlp[curr_y]->col; /* line starts at left unless continuation */
X if ((curr_y > curs_y) && (curs_y >= 0)) w_rmcurs(); /* remove old cursor if it won't be written over */
X window2(0); /* rewrite newly cleared region */
X for (curr_x = 0; ++curr_y < window_size; ) /* clear rest of screen if needed */
X {
X wlp[curr_y]->cflag = 0;
X if (wlp[curr_y]->n) wlp[curr_y]->n = 0, vtm(VT_EEOL);
X }
X }
X } /* end "modified point on screen */
X
X else window1_after(); /* modified point after screen: scroll or redraw as appropriate */
X }
X/* done redrawing: do cleanup work */
X
X if (WN_scroll)
X {
X printf("\033[%d;%dr", window_size+1, WN_height); /* reset margins */
X printf("\033[%d;0H", WN_height); /* cursor to bottom */
X }
X else printf("\033[H"); /* no split screen: set home */
X
X fflush(stdout); /* flush output */
X WN_origin = wlp[0]->start; /* save first char pos on screen */
X redraw_sw = 0; /* mark screen as updated */
X buff_mod = MAX;
X last_dot = dot;
X block_inter(0); /* reenable interrupts */
X }
X/* routine to redraw screen absolutely */
X
Xwindow1_abs()
X {
X int i, j;
X
X curr_y = wlp[0]->col = curr_x = 0; /* indicate where refresh starts */
X set_pointer(dot, &w_p1); /* make a text buffer, if none, and refresh the display */
X w_lines(0, &w_p1, &w_p1); /* do 0L */
X if ((i = w_lines(window_size/2, &w_p1, NULL)) == 0) i = 1; /* check how many lines after dot */
X if (i > window_size/2) i = window_size/2; /* limit amount after dot */
X for (j = 0; (j < window_size - i) && (w_p1.dot > 0); ) /* find start of display area */
X j -= w_lines(-1, &w_p1, &w_p1);
X if (j > window_size - i) w_lines(1, &w_p1, &w_p1); /* if too far back, move up one line */
X
X wlp[0]->start = w_p1.dot; /* indicate where first window line starts */
X window2(0); /* refresh the whole display */
X
X for (curr_x = 0; ++curr_y < window_size; ) /* blank out lines not written by window2 */
X if (wlp[curr_y]->n || redraw_sw) wlp[curr_y]->n = 0, vtm(VT_EEOL);
X }
X
X
X
X
X/* redraw screen incrementally */
X
Xwindow1_inc(wd)
X int wd; /* argument is earliest change */
X {
X short temp_y;
X
X/* find the line containing the character at wd */
X
X for (temp_y = 0; wd > wlp[temp_y]->end; temp_y++);
X
X if ((curs_y != temp_y) || (buff_mod == MAX) || curs_crflag) /* if the cursor line won't be rewritten */
X w_rmcurs(); /* remove the old cursor */
X curr_y = temp_y; /* and go to work on the beginning of the line with dot */
X curr_x = (wlp[curr_y]->cflag & WF_CONT) ? 2 : wlp[curr_y]->col; /* line starts at left unless continuation */
X
X w_setptr(wlp[curr_y]->start, &w_p1); /* make a pointer there */
X window2(buff_mod == MAX); /* if buffer not modified, redraw only the line with dot */
X
X if (buff_mod < MAX) /* if buffer has changed, erase display lines beyond end of buffer */
X for (curr_x = 0; ++curr_y < window_size; )
X if ( ((wlp[curr_y]->start >= z) || (wlp[curr_y]->start <= wlp[curr_y-1]->end)) && (wlp[curr_y]->n || redraw_sw) )
X wlp[curr_y]->n = 0, vtm(VT_EEOL), wlp[curr_y]->cflag = 0;
X }
X/* routine to move window downwards: scroll up or redraw as appropriate */
X
Xwindow1_after()
X {
X int i, lflag;
X
X w_rmcurs(); /* remove old cursor */
X w_setptr(wlp[window_size-1]->start, &w_p1); /* set pointer to start of last line on screen */
X
X for (i = 0; (dot >= w_p1.dot) && (w_p1.dot < z) && (i <= window_size/2); )
X i += (lflag = w_lines(1, &w_p1, &w_p1)) ? lflag : 1; /* fwd one line at a time until > dot or end of buffer */
X
X if (i <= window_size/2) /* found within n lines */
X {
X if (lflag && (dot == z)) ++i; /* if dot is at end of buffer after a LF */
X if (i >= window_size - last_y) /* if there are not enough blank lines on screen */
X w_scroll(i - window_size + last_y), curr_y = window_size - i; /* scroll up the difference */
X else curr_y = last_y;
X
X while (curr_y && (wlp[curr_y]->cflag & WF_CONT)) --curr_y; /* get to start of cont'd lines */
X w_setptr(wlp[curr_y]->start, &w_p1); /* pointer to start of area to redraw */
X curr_x = wlp[curr_y]->col; /* redraw starts at line's first column */
X window2(0); /* rewrite newly cleared region */
X }
X
X else window1_abs(); /* move down is too far: redraw fully */
X }
X
X
X
X/* routine to remove the existing cursor */
X
Xw_rmcurs()
X {
X if (curs_c) /* if there was a cursor */
X {
X w_move(curs_y, curs_x); /* go remove the old cursor */
X if (curs_c & W_MARK) fputs("\033(0", stdout); /* if prev char was a spec char */
X putchar(*curs_p = curs_c); /* put back the char that was there */
X if (curs_c & W_MARK) fputs("\033(B", stdout);
X ++term_x; /* and keep the terminal cursor loc. happy */
X }
X }
X/* routine to do actual display refresh */
X/* called with w_p1 at starting char, curr_y, curr_x at starting coordinate */
X/* rewrites to end of screen if arg = 0, or only until line with cursor if arg = 1 */
X
Xwindow2(arg)
X int arg;
X {
X register int wdot;
X register char wc; /* temp char */
X register short dflag; /* nonzero if this is char at dot */
X short cr_found; /* indicates a cr found on this line */
X
X cr_found = 0; /* clear "cr" flag in first line written */
X for (wdot = w_p1.dot; (curr_y < window_size) && (wdot < z); wdot++) /* for each character */
X {
X wc = w_p1.p->ch[w_p1.c] & 0177; /* get character */
X if (dflag = (wdot == dot)) if (arg) arg = -1; /* save "this is char at dot", "on line with dot" */
X
X if (wc < ' ') switch (wc) /* dispatch control characters */
X {
X case CR:
X if (dflag) /* if cursor on this CR */
X {
X if (curr_x < WN_width) w_makecurs(' ', 1), w_type(' ', 1); /* display a space, unless at end */
X else curs_crflag = curs_c = 0; /* else set "no cursor displayed" */
X }
X /* trim remainder of line if this is first cr and old line was longer */
X if (!cr_found && ((curr_x < wlp[curr_y]->n) || redraw_sw))
X {
X wlp[curr_y]->n = curr_x;
X if (curr_x < WN_width) vtm(VT_EEOL);
X }
X cr_found = 1; /* set cr flag */
X wlp[curr_y]->cflag &= ~WF_BEG; /* this line is not continued */
X while (curr_y && (wlp[curr_y]->cflag & WF_CONT)) --curr_y; /* if line is a continuation, scan up */
X curr_x = 0;
X break;
X
X case TAB:
X if (curr_x >= WN_width)
X {
X if (et_val & ET_TRUNC) goto noprint;
X if (w_overflow(wdot)) goto w2_exit; /* extend line */
X }
X if (dflag) w_makecurs(' ', 0);
X w_type(' ', dflag); /* type one space */
X if (dflag)
X {
X vt(VT_CLRSPEC); /* end reverse video */
X dflag = 0;
X }
X while ((curr_x & tabmask) && (curr_x < WN_width)) w_type(' ', 0); /* finish tab */
X break;
X case LF:
X while ((curr_y < window_size) && (wlp[curr_y]->cflag & WF_BEG)) ++curr_y; /* last screen row of this line */
X wlp[curr_y]->end = wdot; /* save char position that ended this line */
X if (dflag) /* if this LF is at dot */
X { /* put cursor there, save char that was there */
X w_makecurs( (curr_x < wlp[curr_y]->n) ? wlp[curr_y]->ch[curr_x] : ' ', 0);
X fputs("\033(0", stdout); /* put in a "LF" char */
X w_type('e', 1);
X fputs("\033(B", stdout);
X } /* if no cr found and not in last column, erase rest of line */
X if (!cr_found && (curr_x < wlp[curr_y]->n))
X {
X wlp[curr_y]->n = curr_x;
X if (curr_x < WN_width) vtm(VT_EEOL);
X }
X if (dflag) --curr_x; /* put the cursor back before the artificial LF char, if any */
X if (curr_y >= window_size-1) /* if at end of screen, exit, but... */
X {
X if (dflag) vt(VT_CLRSPEC); /* if cursor is here, clear reverse video first */
X goto w2_exit;
X }
X
X if ((wlp[curr_y]->cflag & WF_CONT) && (wlp[curr_y]->end - wlp[curr_y]->start == 1)) /* if a now-empty cont. line, */
X { /* flush it */
X if (curr_y > 0) wlp[curr_y-1]->cflag &= ~WF_BEG; /* remove "cont'd" flag from prev line */
X arg = 0; /* and force redraw of rest of screen */
X if (curs_y == curr_y) curs_c = 0; /* if cursor was on this line, it will disappear */
X }
X else ++curr_y; /* down one line if not absorbing blank contin. line */
X
X wlp[curr_y]->start = wdot + 1; /* assume line starts with next char */
X wlp[curr_y]->col = curr_x; /* save starting column */
X cr_found = wlp[curr_y]->cflag = 0; /* clear line continuation flags */
X if (curr_x) w_ebol(); /* if not at left margin, erase beginning of line */
X if (arg == -1) /* finished line with dot... quit if spec'd */
X {
X if (dflag) /* but first, if at cursor, clear reverse video */
X {
X vt(VT_CLRSPEC);
X dflag = 0;
X }
X return;
X }
X break;
X
X case ESC:
X if (curr_x >= WN_width)
X {
X if (et_val & ET_TRUNC) goto noprint;
X if (w_overflow(wdot)) goto w2_exit; /* extend line */
X }
X if (dflag) w_makecurs('$', 0);
X w_type('$', dflag);
X break;
X default: /* all other control chars print as ^X */
X if (curr_x >= WN_width - 1)
X {
X if (et_val & ET_TRUNC) goto noprint;
X if (w_overflow(wdot)) goto w2_exit;
X }
X if (dflag) w_makecurs('^', 0);
X w_type('^', dflag); /* ^ */
X if (dflag)
X {
X vt(VT_CLRSPEC); /* if at cursor, clear reverse video */
X dflag = 0;
X }
X w_type(wc | 0100, 0);
X break;
X } /* end "switch" */
X else /* a printing character */
X {
X if (curr_x >= WN_width)
X {
X if (et_val & ET_TRUNC) goto noprint;
X if (w_overflow(wdot)) goto w2_exit; /* extend line */
X }
X if (dflag) w_makecurs(wc, 0);
X w_type(wc, dflag);
X }
X
X if (dflag)
X {
X vt(VT_CLRSPEC); /* if at cursor, clear reverse video */
X }
X
X if ((wc == FF) || (wc == VT)) /* these chars leave a display line blank */
X {
X if (redraw_sw || (curr_x < wlp[curr_y]->n))
X {
X wlp[curr_y]->n = curr_x;
X if (curr_x < WN_width) vtm(VT_EEOL); /* erase rest of line */
X }
X wlp[curr_y]->end = wdot;
X if (curr_y >= window_size-1) goto w2_exit; /* quit if overflow screen */
X wlp[++curr_y]->start = wdot + 1;
X cr_found = wlp[curr_y]->cflag = 0; /* init new line */
X if (curr_x -= 2) w_ebol(); /* back up over ^X; if not at left margin, erase beginning of line */
X wlp[curr_y]->col = curr_x; /* save starting column */
X }
X noprint:
X if (++ w_p1.c > CELLSIZE - 1) w_p1.p = w_p1.p->f, w_p1.c = 0; /* next char in buffer */
X } /* end of "for all characters" */
X
X if (dot == z)
X {
X if (curr_x < WN_width) w_makecurs(' ', 1), w_type(' ', 1), vt(VT_CLRSPEC); /* display a space, unless at end */
X else curs_crflag = curs_c = 0; /* else set "no cursor displayed" */
X }
X
X /* clear rest of line if needed */
X if (!cr_found && (redraw_sw || (curr_x < wlp[curr_y]->n)))
X {
X wlp[curr_y]->n = curr_x;
X if (curr_x < WN_width) vtm(VT_EEOL);
X }
X wlp[curr_y]->end = wdot; /* save char at end of last line */
X w2_exit:
X last_y = curr_y; /* record last used line on screen */
X }
X/* routine to move cursor to current location and then call vt */
X
Xvtm(arg)
X int arg;
X {
X w_move(curr_y, curr_x);
X vt(arg);
X }
X
X
X
X
X/* routine to set reverse video and save cursor location */
X/* first argument is char at cursor, 2nd is value for curs_crflag */
X
Xw_makecurs(wc, crflag)
X char wc;
X short crflag;
X {
X curs_y = curr_y, curs_x = curr_x, curs_c = wc; /* save cursor coord and char */
X curs_p = &wlp[curr_y]->ch[curr_x]; /* save location of cursor spot in window image */
X curs_crflag = crflag; /* save crflag */
X vt(VT_SETSPEC2); /* set flag and reverse video */
X }
X
X
X
X
X/* routine to handle line overflow */
X/* returns nonzero if at end of screen, zero otherwise */
X/* arg is current character position */
X
Xint w_overflow(wd)
X {
X wlp[curr_y]->end = wd-1; /* last character was end of this line */
X if (wlp[curr_y]->n > curr_x)
X {
X wlp[curr_y]->n = curr_x;
X if (curr_x < WN_width) vtm(VT_EEOL); /* if old line was wider, erase */
X }
X if (curr_y >= window_size-1) return(1);
X wlp[curr_y]->cflag |= WF_BEG; /* mark this line as "continued" */
X wlp[++curr_y]->cflag = WF_CONT; /* next line is a continuation line */
X wlp[curr_y]->start = wd; /* char about to be printed is this line's first */
X wlp[curr_y]->col = curr_x = 0; /* new line starts at left margin */
X fputs("\033(0", stdout); /* alternate char set */
X w_type('h', W_MARK); /* "NL" space */
X w_type(' ', W_MARK);
X fputs("\033(B", stdout);
X return(0);
X }
X/* routine to type one character: arguments are char and a */
X/* "mark" bit. If mark is set, the char is always retyped */
X
Xw_type(c, m)
X char c;
X int m;
X {
X register char *p;
X
X p = &wlp[curr_y]->ch[curr_x]; /* pointer to char image */
X if ((c != *p) || (m) || (redraw_sw) || (curr_x >= wlp[curr_y]->n))
X {
X w_move(curr_y, curr_x);
X putchar(c);
X *p = (m) ? c | W_MARK : c;
X ++term_x;
X }
X ++curr_x;
X if (wlp[curr_y]->n < curr_x) wlp[curr_y]->n = curr_x; /* if we've lengthened the line, record that fact */
X }
X
X
X
X
X/* initialize display image */
X
Xw_init()
X {
X short i, j;
X
X for (i = 0; i < window_size; i++) /* for each row */
X {
X wlp[i] = &w_image[i]; /* set pointer to this line's data */
X w_image[i].n = w_image[i].cflag = 0; /* no chars used, cr flag clear */
X for (j = 0; j < W_MAX_H; w_image[i].ch[j++] = ' '); /* clear line */
X }
X }
X
X
X
X
X/* put character followed by appropriate number of nulls for "other control function" */
X/* if argument is 0, output filler chars only */
X
Xputchar_d(c)
X char c;
X {
X int i;
X
X if (c) putchar(c); /* output character */
X for (i = 0; i < win_dlyc[win_speed]; i++) putchar('\0'); /* output filler */
X }
X/* put out appropriate number of filler chars for display function that scrolls (LF, etc.) */
X
Xscroll_dly()
X {
X int i;
X
X for (i = 0; i < win_dlys[win_speed]; i++) putchar('\0'); /* output filler */
X }
X
X
X
X/* move terminal cursor to stated y, x position */
X/* uses incremental moves or absolute cursor position, whichever is shorter */
X
Xw_move(y, x)
X short y, x;
X {
X register short i;
X
X /* if practical, use CR to get to left margin */
X if ((curr_x == 0) && (term_x != 0)) putchar(CR), term_x = 0;
X if ((y == term_y) && (term_x < WN_width)) /* if term x is beyond last char, use abs positioning */
X {
X if (x == term_x) return;
X if (x > term_x)
X {
X if (x - term_x == 1) fputs("\033[C", stdout);
X else printf("\033[%dC", x - term_x);
X }
X else
X {
X if ((i = term_x - x) < 4) for (; i > 0; i--) putchar('\b'); /* use BS */
X else printf("\033[%dD", term_x - x); /* use incremental jump */
X }
X term_x = x;
X }
X else
X {
X if ((x == term_x) && (term_x < WN_width))
X {
X if (y > term_y)
X {
X if ((i = y - term_y) < 4) for (; i >0; i--) putchar(LF); /* use LF */
X else printf("\033[%dB", i); /* use incremental jump */
X }
X else if ((i = term_y - y) == 1) fputs("\033[A", stdout); /* move 1 */
X else printf("\033[%dA", i);
X term_y = y;
X }
X else printf("\033[%d;%dH", (term_y = y) + 1, (term_x = x) + 1); /* absolute jump */
X }
X }
X/* scroll screen: argument is count: + up, - down */
X
Xw_scroll(count)
X int count;
X {
X register int i, ic;
X struct w_line *p[W_MAX_V]; /* temp copy of pointer array */
X
X if (count > 0) /* scrolling up */
X {
X w_move(window_size-1, 0); /* cursor to bottom of window */
X for (i = 0; i < count; i++)
X {
X putchar(LF), wlp[i]->n = 0; /* scroll terminal, blank out image line */
X }
X }
X else /* scroll down */
X {
X w_move(0, 0); /* cursor to top */
X for (i = 0; i > count; i--)
X {
X fputs("\033M", stdout), wlp[window_size-1+i]->n = 0;
X }
X }
X for (i = 0; i < window_size; i++) p[i] = wlp[(window_size + i + count) % window_size]; /* rearrange */
X for (i = 0; i < window_size; i++) wlp[i] = p[i];
X }
X
X
X
X/* clear line to left of curr_x */
X/* if some chars nonblank, does erase from start of line */
X
Xw_ebol()
X {
X short i, j;
X
X for (j = i = 0; i < curr_x; i++) if (wlp[curr_y]->ch[i] != ' ') wlp[curr_y]->ch[i] = ' ', j++;
X if (j || redraw_sw) w_move(curr_y, curr_x-1), vt(VT_EBOL);
X }
X
X
X
X/* routine to set a pointer to a given location (like set_pointer) */
X/* returns nonzero if a text buffer exists, otherwise 0 */
X
Xint w_setptr(loc, pp)
X register int loc; /* location */
X register struct qp *pp; /* address of pointer */
X {
X register int i;
X
X if (buff.f)
X {
X for (i = loc / CELLSIZE, pp->p = buff.f; i > 0; i--) pp->p = pp->p->f;
X pp->c = loc % CELLSIZE;
X pp->dot = loc;
X }
X return( (int) buff.f);
X }
X/* routine to move N lines (back, forward, or 0) */
X/* w_lines(n, &source, &dest) where n is the line count, source */
X/* points to a qp at the current pointer, dest, if nonzero, */
X/* it points to a qp where the result is to go. */
X/* routine returns actual number of display lines */
X
Xstruct qp w_lines_p; /* to compute # of display lines in -N lines */
X
Xint w_lines(n, ps, pd)
X int n; /* number of lines */
X register struct qp *ps, *pd; /* source, destination qp's */
X {
X register struct buffcell *tp; /* local copy of the qp */
X register int tc, tdot, tn;
X int tcnt, tl; /* chars/line and display line count */
X char tch;
X
X tdot = ps->dot;
X tp = ps->p;
X tc = ps->c;
X
X if (n > 0) /* argument is positive */
X {
X for (tcnt = tl = tn = 0; (tn < n) && (tdot < z); tdot++) /* forward over N line separators */
X {
X if (spec_chars[ tch = tp->ch[tc] ] & A_L) ++tl, ++tn; /* count separators */
X else if (!(et_val & ET_TRUNC)) /* if text lines can overflow screen lines */
X {
X if (!(tch & 0140)) /* if character is a control char */
X {
X if (tch == CR) /* CR resets count */
X {
X if (tcnt > WN_width) ++tl;
X tcnt = 0;
X }
X else if (tch == TAB) tcnt = (tcnt | tabmask) +1; /* tab to next tab stop */
X else if (tch == ESC) ++tcnt; /* ESC takes one space */
X else tcnt += 2; /* normal control chars take 2 spaces */
X }
X else ++tcnt; /* not a control char: takes one space */
X if (tcnt > WN_width) ++tl, tcnt = 2; /* if overflow, one more line */
X }
X
X if (++tc > CELLSIZE-1) tp = tp->f, tc = 0; /* next character position */
X }
X if (tl > tn) tn = tl; /* if counting display lines and there's more of them, return that */
X }
X else /* argument is zero or negative */
X {
X for (tn = 0; (tn >= n) && (tdot > 0); ) /* back up over (n+1) line feeds */
X {
X --tdot;
X if (--tc < 0) tp = tp->b, tc = CELLSIZE -1;
X if (spec_chars[tp->ch[tc]] & A_L) --tn;
X }
X if (tn < n) /* if stopped on a line sep, fwd over it */
X {
X ++tn;
X ++tdot;
X if (++tc > CELLSIZE-1) tp = tp->f, tc = 0;
X }
X
X if (!(et_val & ET_TRUNC) && (n != 0)) /* if text line can overflow display line */
X {
X w_lines_p.dot = tdot, w_lines_p.p = tp, w_lines_p.c = tc; /* then count the number of display */
X tn = -w_lines(-n, &w_lines_p, 0); /* lines in the N text lines we just backed up over */
X }
X }
X
X if (pd) pd->dot = tdot, pd->p = tp, pd->c = tc; /* if an "after" pointer given, update it */
X return(tn);
X }
X
END_OF_te_window.c
if test 33018 -ne `wc -c <te_window.c`; then
echo shar: \"te_window.c\" unpacked with wrong size!?
fi
# end of overwriting check
fi
echo shar: End of archive 4 \(of 4\).
cp /dev/null ark4isdone
DONE=true
for I in 1 2 3 4 ; do
if test ! -f ark${I}isdone ; then
echo shar: You still need to run archive ${I}.
DONE=false
fi
done
if test "$DONE" = "true" ; then
echo You have unpacked all 4 archives.
echo "See the *.doc files"
rm -f ark[1-9]isdone
fi
## End of shell archive.
exit 0