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