home *** CD-ROM | disk | FTP | other *** search
- /*
- * The functions in this file handle redisplay. The
- * redisplay system knows almost nothing about the editing
- * process; the editing functions do, however, set some
- * hints to eliminate a lot of the grinding. There is more
- * that can be done; the "vtputc" interface is a real
- * pig. Two conditional compilation flags; the GOSLING
- * flag enables dynamic programming redisplay, using the
- * algorithm published by Jim Gosling in SIGOA. The MEMMAP
- * changes things around for memory mapped video. With
- * both off, the terminal is a VT52.
- */
-
- #define LINT_ARGS 1 /* enable lint type checking */
- #include "def.h"
-
- D32 get_long ();
- D16 get_int ();
- void writ_echo ();
- void uline ();
- void ucopy ();
- void modeline ();
- void bin_to_text ();
- uint fill_buf ();
- uint get_currow ();
- uint get_curcol ();
- #if MSDOS
- void mem_line ();
- #endif
-
- extern char MSG_prn_to[];
- extern char MSG_disp_r_n[];
- extern char MSG_11lX[];
- extern char MSG_11lo[];
- extern char MSG_11ld[];
- extern char MSG_03o[];
- extern char MSG_06o[];
- extern char MSG_011lo[];
- extern char MSG_03u[];
- extern char MSG_05u[];
- extern char MSG_010lu[];
- extern char MSG_02X[];
- extern char MSG_04X[];
- extern char MSG_08lX[];
- extern char MSG_prog_name[];
- extern char MSG_disp_b_lst[];
- extern char MSG_file[];
- extern char MSG_RO[];
- extern char MSG_WL[];
- extern char MSG_RW[];
- extern char MSG_AU[];
- extern char MSG_NOT_AU[];
- extern char MSG_curs_asc[];
- extern char MSG_curs_ebc[];
- extern char MSG_curs_hex[];
- extern char MSG_curs_bin[];
- extern char MSG_curs_dec[];
- extern char MSG_curs_oct[];
- extern char MSG_siz_8[];
- extern char MSG_siz_16[];
- extern char MSG_siz_32[];
- extern char MSG_siz_null[];
- extern char MSG_int_shift[];
- extern char MSG_mot_shift[];
- extern char MSG_print1[];
- extern char MSG_print2[];
- #if RUNCHK
- extern char ERR_disp_1[];
- extern char ERR_disp_2[];
- extern char ERR_disp_3[];
- extern char ERR_disp_4[];
- extern char ERR_disp_5[];
- extern char ERR_disp_6[];
- #endif
-
- #include "lintfunc.dec"
- extern char ebcdic_table[];
-
- extern bool mem_map;
-
- /*
- * You can change these back to the types
- * implied by the name if you get tight for space. If you
- * make both of them "int" you get better code on the VAX.
- * They do nothing if this is not Gosling redisplay, except
- * for change the size of a structure that isn't used.
- * A bit of a cheat.
- */
- #define XCHAR int
- #define XSHORT int
-
- /*
- * A video structure always holds
- * an array of characters whose length is equal to
- * the longest line possible. Only some of this is
- * used if "ncol" isn't the same as "NCOL".
- */
- typedef struct vid
- {
- short v_hash; /* Hash code, for compares. */
- short v_flag; /* Flag word. */
- short v_color; /* Color of the line. */
- XSHORT v_cost; /* Cost of display. */
- char v_text[NCOL]; /* The actual characters. */
- } VIDEO;
-
- #define VFCHG 0x0001 /* Changed. */
- #define VFHBAD 0x0002 /* Hash and cost are bad. */
-
- /*
- * SCORE structures hold the optimal
- * trace trajectory, and the cost of redisplay, when
- * the dynamic programming redisplay code is used.
- * If no fancy redisplay, this isn't used. The trace index
- * fields can be "char", and the score a "short", but
- * this makes the code worse on the VAX.
- */
- typedef struct
- {
- XCHAR s_itrace; /* "i" index for track back. */
- XCHAR s_jtrace; /* "j" index for trace back. */
- XSHORT s_cost; /* Display cost. */
- } SCORE;
-
- int sgarbf = TRUE; /* TRUE if screen is garbage. */
- int vtrow = 0; /* Virtual cursor row. */
- int vtcol = 0; /* Virtual cursor column. */
- int tthue = CNONE; /* Current color. */
- int ttrow = HUGE; /* Physical cursor row. */
- int ttcol = HUGE; /* Physical cursor column. */
- int tttop = HUGE; /* Top of scroll region. */
- int ttbot = HUGE; /* Bottom of scroll region. */
- char file_off_bad = FALSE; /* Have file offsets been changed */
-
- VIDEO * vscreen[NROW]; /* Edge vector, virtual. */
- VIDEO * pscreen[NROW]; /* Edge vector, physical. */
- VIDEO video[2 * (NROW)]; /* Actual screen data. */
- VIDEO blanks; /* Blank line image. */
-
- #if GOSLING
- /*
- * This matrix is written as an array because
- * we do funny things in the "setscores" routine, which
- * is very compute intensive, to make the subscripts go away.
- * It would be "SCORE score[NROW][NROW]" in old speak.
- * Look at "setscores" to understand what is up.
- */
- SCORE score[NROW * NROW];
- #endif
-
- /*
- * Initialize the data structures used
- * by the display code. The edge vectors used
- * to access the screens are set up. The operating
- * system's terminal I/O channel is set up. Fill the
- * "blanks" array with ASCII blanks. The rest is done
- * at compile time. The original window is marked
- * as needing full update, and the physical screen
- * is marked as garbage, so all the right stuff happens
- * on the first call to redisplay.
- */
- void vtinit ()
- {
- register VIDEO * vp;
- register int i;
-
- ttopen ();
- ttinit ();
- vp = &video[0];
- for (i = 0; i < NROW; ++i)
- {
- vscreen[i] = vp;
- ++vp;
- pscreen[i] = vp;
- ++vp;
- }
- blanks.v_color = CTEXT;
- for (i = 0; i < NCOL; ++i)
- blanks.v_text[i] = ' ';
- }
-
- /*
- * Tidy up the virtual display system
- * in anticipation of a return back to the host
- * operating system. Right now all we do is position
- * the cursor to the last line, erase the line, and
- * close the terminal channel.
- */
- void vttidy ()
- {
- ttcolor (CTEXT);
- ttnowindow (); /* No scroll window. */
- ttmove (nrow - 1, 0); /* Echo line. */
- tteeol ();
- tttidy ();
- ttflush ();
- ttclose ();
- }
-
- /*
- * Move the virtual cursor to an origin
- * 0 spot on the virtual display screen. I could
- * store the column as a character pointer to the spot
- * on the line, which would make "vtputc" a little bit
- * more efficient. No checking for errors.
- */
- void vtmove (row, col)
- {
- vtrow = row;
- vtcol = col;
- }
-
- /*
- * Write a character to the virtual display,
- * dealing with long lines and the display of unprintable
- * things like control characters. Also expand tabs every 8
- * columns. This code only puts printing characters into
- * the virtual display image. Special care must be taken when
- * expanding tabs. On a screen whose width is not a multiple
- * of 8, it is possible for the virtual cursor to hit the
- * right margin before the next tab stop is reached. This
- * makes the tab code loop if you are not careful.
- * Three guesses how we found this.
- */
- void vtputc (c)
- register int c;
- {
- register VIDEO * vp;
-
- vp = vscreen[vtrow];
- if (vtcol >= ncol)
- vp -> v_text[ncol - 1] = '$';
- else
- if (ISCTRL (c) != FALSE)
- {
- vtputc ('^');
- vtputc (c ^ 0x40);
- }
- else
- {
- vp -> v_text[vtcol] = c;
- vtcol++;
- }
-
- }
- /*
- * Write an entire screen line in the correct format. pvr
- *
- * This code only puts printing characters into
- * the virtual display image.
- * Return TRUE if something was printed to the line.
- */
- #define REGI register
- bool vtputd (wp, row)
- WINDOW * wp;
- int row; /* line # to print to v screen */
-
- {
- REGI VIDEO * vp;
- REGI char *lin_ptr,
- ch,
- mode;
- REGI A32 row_offst;
- REGI uint chrs_per_row,
- lin_offset,
- crs,
- i,
- j,
- k,
- chrs_in_lin;
- LINE * cur_line;
- REGI uchar tempc;
- REGI D32 temp_long;
- REGI D16 temp_int;
- static char w_buf[128]; /* temp buffer for data */
- REGI char *fmnt_ptr; /* pointer to format structure */
-
- vp = vscreen[vtrow]; /* point to VIDEO structure to print into */
- mode = R_TYPE(wp); /* get type of format structure */
-
- /* get number of bytes per row */
- chrs_per_row = R_BYTES(wp);
-
- /* determine the offset from begining of the buffer for this line */
- row_offst = WIND_POS(wp) + (row * chrs_per_row);
-
- /* search for and point to first character in buffer to be printed */
- cur_line = wp -> w_linep; /* start with current first window line */
- while (TRUE)
- { /* find line with desired character */
- if (cur_line == wp -> w_bufp -> b_linep)
- { /* at end of buffer? */
- return (FALSE);
- }
- if (cur_line -> l_file_offset > row_offst)
- {
- /* if less than current line */
- cur_line = cur_line -> l_bp;/* step back */
- }
- else
- if ((cur_line -> l_file_offset + cur_line -> l_used) <= row_offst)
- {
- cur_line = cur_line -> l_fp;/* step ahead */
- }
- else
- break;
- }
-
- lin_offset = row_offst - cur_line -> l_file_offset;/* offset into line */
-
- /* get index into the current line to start reading the current row's data */
- /* copy line text into buffer */
- chrs_in_lin = fill_buf (wp, cur_line, lin_offset, w_buf, chrs_per_row);
-
- /* limit line length to screen width, used in TEXT mode only */
- if (chrs_in_lin > NCOL)
- chrs_in_lin = NCOL;
-
- /* Clear the line to spaces */
- for (i = 0; i < NCOL; i++)
- {
- vp -> v_text[i] = ' ';
- }
- switch (mode)
- {
- case TEXT:
- break;
- case ASCII:
- case EBCDIC:
- case BINARY:
- case HEX:
- /* print the row offset from the start of the file in HEX */
- sprintf (vp -> v_text, MSG_11lX, row_offst);/* to vid buf */
- break;
- case OCTAL:
- /* print the row offset from the start of the file */
- sprintf (vp -> v_text, MSG_11lo, row_offst);/* to vid buf */
- break;
- case DECIMAL:
- /* print the row offset from the start of the file */
- sprintf (vp -> v_text, MSG_11ld, row_offst);/* to vid buf */
- break;
- #if RUNCHK
- default:
- writ_echo (ERR_disp_1);
- break;
- #endif
- }
-
- /* print the binary data to the text line */
- bin_to_text (w_buf, vp -> v_text, chrs_in_lin,
- wp -> w_fmt_ptr);
-
- vtcol = NCOL;
- return (TRUE);
- }
-
- /*
- * Print the contents of then binary data buffer bin_buf
- * into the proper mode of text into txt_buf.
- * Process 'len' bytes.
- *
- * input:
- * bin_buf pointer to buffer of binary data to process.
- * txt_buf pointer to output buffer to print text result into.
- * len length in bytes of data in bin_buf to process.
- * fmt_ptr pointer to a ROW_FMT to use to format the data
- * conversion and printing process.
- * output:
- * none.
- */
-
- void bin_to_text (bin_buf, txt_buf, len, fmt_ptr)
-
- char *bin_buf,
- *txt_buf;
- uint len;
- ROW_FMT *fmt_ptr;
-
- {
- uchar i,
- ch,
- k,
- j,
- mode,
- size,
- *posn;
- uint temp_int;
- ulong temp_long;
-
- mode = fmt_ptr -> r_type; /* get type of format structure */
- size = fmt_ptr -> r_size; /* get size of format structure */
- posn = fmt_ptr -> r_positions;/* pointer to array of display positions */
-
- switch (mode)
- {
- case TEXT:
- case ASCII:
- for (i = 0; i < len; i++)
- {
- ch = bin_buf[i];
- if ((ch >= ' ') && (ch < 0x7f))
- txt_buf[posn[0] + i] = ch;
- else
- txt_buf[posn[0] + i] = '.';
- }
- break;
-
- case EBCDIC:
- for (i = 0; i < len; i++)
- {
- txt_buf[posn[0] + i] =
- 0xff & ebcdic_table[0xff & bin_buf[i]];
- }
- break;
-
- case OCTAL:
- switch (size)
- {
- case BYTES: /* print octal bytes */
- for (i = 0; i < len; i++)
- {
- sprintf (&txt_buf[
- posn[i]], MSG_03o, 0xff & bin_buf[i]);
- }
- break;
-
- case WORDS: /* print octal words */
- k = 0;
- for (i = 0; i < len;
- i += 2)
- {
- temp_int = get_int (&bin_buf[i]);
- sprintf (&txt_buf[posn[k++]], MSG_06o, temp_int);
- }
- break;
-
- case DWORDS: /* print octal double words */
- k = 0;
- for (i = 0; i < len;
- i += 4)
- {
- temp_long = get_long (&bin_buf[i]);
- sprintf (&txt_buf[posn[k++]], MSG_011lo, temp_long);
- }
- break;
- }
- break;
-
- case DECIMAL:
- switch (size)
- {
- case BYTES: /* print decimal bytes */
- for (i = 0; i < len; i++)
- {
- sprintf (&txt_buf[
- posn[i]], MSG_03u, 0xff & bin_buf[i]);
- }
- break;
-
- case WORDS: /* print decimal words */
- k = 0;
- for (i = 0; i < len;
- i += 2)
- {
- temp_int = get_int (&bin_buf[i]);
- sprintf (&txt_buf[
- posn[k++]], MSG_05u, temp_int);
- }
- break;
-
- case DWORDS: /* print decimal double words */
- k = 0;
- for (i = 0; i < len; i += 4)
- {
- temp_long = get_long (&bin_buf[i]);
- sprintf (&txt_buf[
- posn[k++]], MSG_010lu, temp_long);
- }
- break;
- }
- break;
-
- case HEX:
- switch (size)
- {
- case BYTES: /* print hex bytes and ascii chars */
- for (i = 0; i < len; i++)
- {
- if ((bin_buf[i] >= ' ') && (bin_buf[i] < 0x7f))
- txt_buf[posn[i + 16]] = 0xff & bin_buf[i];
- else
- txt_buf[posn[i + 16]] = '.';
- sprintf (&txt_buf[posn[i]], MSG_02X, 0xff & bin_buf[i]);
- }
- break;
-
- case WORDS: /* print hex words */
- k = 0;
- for (i = 0; i < len; i += 2)
- {
- temp_int = get_int (&bin_buf[i]);
- sprintf (&txt_buf[
- posn[k++]], MSG_04X, temp_int);
- }
- break;
-
- case DWORDS: /* print hex double words */
- k = 0;
- for (i = 0; i < len; i += 4)
- {
- temp_long = get_long (&bin_buf[i]);
- sprintf (&txt_buf[
- posn[k++]], MSG_08lX, temp_long);
- }
- break;
- }
- break;
-
- case BINARY:
- switch (size)
- {
- case BYTES: /* print binary bits */
- for (i = 0; i < len; i++)
- {
- ch = bin_buf[i];/* get char to convert */
- for (k = 0; k < 8; k++)
- {
- if (ch & 0x80)
- txt_buf[posn[i] + k]
- = '1';
- else
- txt_buf[posn[i] + k]
- = '0';
- ch = ch << 1;/* slide next bit into place */
- }
- }
- break;
-
- case WORDS:
- j = 0;
- for (i = 0; i < len; i += 2)
- {
- temp_int = get_int (&bin_buf[i]);
-
- for (k = 0; k < 16; k++)
- {
- if (temp_int & 0x8000)
- txt_buf[posn[j] + k]
- = '1';
- else
- txt_buf[posn[j] + k]
- = '0';
- temp_int = temp_int << 1;
- /* slide next bit into place */
- }
- j++;
- }
- break;
-
- case DWORDS:
- j = 0;
- for (i = 0; i < len; i += 4)
- {
- temp_long = get_long (&bin_buf[i]);
- for (k = 0; k < 32; k++)
- {
- if (temp_long & 0x80000000)
- txt_buf[posn[j] + k]
- = '1';
- else
- txt_buf[posn[j] + k]
- = '0';
- temp_long = temp_long << 1;
- /* slide next bit into place */
- }
- j++;
- }
- break;
- }
- break;
- #if RUNCHK
- default:
- writ_echo (ERR_disp_2);
- break;
- #endif
- }
- len *= (fmt_ptr -> r_chr_per_u + 1);
- /* Clean up any garbage characters left by the sprintf's */
- for (i = 0; i < NCOL; i++)
- {
- if (txt_buf[i] == 0)
- txt_buf[i] = ' ';
- }
- }
-
- /*
- * Get an int from the buffer.
- * Perform the Intel byte shuffle if necessary
- */
-
- D16 get_int (w_buf)
- uchar *w_buf;
-
- {
- int temp_int;
-
- if (curwp -> w_intel_mode)
- {
- temp_int = 0xff & w_buf[1];
- temp_int <<= 8;
- temp_int |= 0xff & w_buf[0];
- }
- else
- {
- temp_int = 0xff & w_buf[0];
- temp_int <<= 8;
- temp_int |= 0xff & w_buf[1];
- }
- return (temp_int);
- }
-
- /*
- * Get an long from the buffer.
- * Perform the Intel byte shuffle if necessary
- */
-
- D32 get_long (w_buf)
- uchar *w_buf;
-
- {
- long temp_long;
-
- if (curwp -> w_intel_mode)
- {
- temp_long = 0xff & w_buf[3];
- temp_long <<= 8;
- temp_long |= 0xff & w_buf[2];
- temp_long <<= 8;
- temp_long |= 0xff & w_buf[1];
- temp_long <<= 8;
- temp_long |= 0xff & w_buf[0];
- }
- else
- {
- temp_long = 0xff & w_buf[0];
- temp_long <<= 8;
- temp_long |= 0xff & w_buf[1];
- temp_long <<= 8;
- temp_long |= 0xff & w_buf[2];
- temp_long <<= 8;
- temp_long |= 0xff & w_buf[3];
- }
- return (temp_long);
- }
-
-
- /*
- * Copy a length of bytes from the buffer LINEs into the designated
- * buffer. If the current LINE does not have enough bytes then
- * advance to the next. Return the actual number of bytes copied.
- * The number copied would be less than the number requested if
- * end of file is reached.
- */
-
- uint fill_buf (wp, lin, lin_off, w_buff, cnt)
- WINDOW *wp;
- LINE *lin;
- uint lin_off,
- cnt;
- char *w_buff;
- {
- REGI uint src,
- dest,
- i;
-
- src = lin_off; /* initialize source line index */
- dest = 0; /* initialize destination buffer index */
-
- while (TRUE)
- {
- while (src < lin -> l_used)
- {
- w_buff[dest++] = lin -> l_text[src++];/* copy byte */
-
- if (dest == cnt)
- { /* if done */
- return (cnt); /* then leave */
- }
- }
- if (R_TYPE(curwp) == TEXT)
- return (dest); /* in text mode don't advance to next line */
-
- lin = lin -> l_fp; /* move to the next line */
- if (lin == wp -> w_bufp -> b_linep)
- { /* if past last line */
- {
- for (i = dest; i < cnt; ++i)
- w_buff[i] = 0;/* fill rest of buffer with zeros */
- return (dest); /* return number of chars copied */
- }
- }
- src = 0; /* start next LINE at first byte */
- }
- }
-
- /*
- * Erase from the end of the
- * software cursor to the end of the
- * line on which the software cursor is
- * located. The display routines will decide
- * if a hardware erase to end of line command
- * should be used to display this.
- */
- void vteeol ()
- {
- register VIDEO * vp;
-
- vp = vscreen[vtrow];
- while (vtcol < ncol)
- vp -> v_text[vtcol++] = ' ';
- }
-
- /*
- * Make sure that the display is
- * right. This is a three part process. First,
- * scan through all of the windows looking for dirty
- * ones. Check the framing, and refresh the screen.
- * Second, make the
- * virtual and physical screens the same.
- */
- void update ()
- {
- register LINE * lp;
- register WINDOW * wp;
- register VIDEO * vp1;
- register VIDEO * vp2;
- register uint i;
- register int j,
- k;
- register int c;
- register int hflag;
- register int offs;
- register int size;
-
- hflag = FALSE; /* Not hard. */
- wp = wheadp;
- while (wp != NULL)
- {
- /* is this window to be displayed in linked mode */
- if ((curbp -> b_flag & BFLINK) &&
- (wp -> w_bufp == curbp))
- { /* move dot to current window's dot position */
- wp -> w_dotp = curwp -> w_dotp;
- wp -> w_doto = curwp -> w_doto;
- move_ptr (wp, 0L, TRUE, TRUE, TRUE); /* insure dot is aligned */
- wind_on_dot (wp); /* move window to new dot position */
- }
-
- if (wp -> w_flag != 0)
-
- { /* Need update. */
- move_ptr (wp, 0L, FALSE, TRUE, TRUE); /* window on row boundary */
- move_ptr (wp, 0L, TRUE, TRUE, TRUE); /* dot on unit boundary */
- if ((wp -> w_flag & WFFORCE) == 0)
- {
- wind_on_dot (wp);/* position window on dot */
- }
- i = get_currow (wp); /* Redo this one line, mabey. */
- if ((wp -> w_flag & ~WFMODE) == WFEDIT)
- {
- vscreen[i] -> v_color = CTEXT;
- vscreen[i] -> v_flag |= (VFCHG | VFHBAD);
- vtmove (i, 0);
- vtputd (wp, i - wp -> w_toprow);/* print line to the screen */
- }
- else
- if ((wp -> w_flag & ~WFMODE) == WFMOVE)
- {
- while (i < wp -> w_toprow + wp -> w_ntrows)
- {
- /* paint entire window */
- vscreen[i] -> v_color = CTEXT;
- vscreen[i] -> v_flag |= (VFCHG | VFHBAD);
- vtmove (i, 0);
- /* print line to the screen */
- if (!vtputd (wp, i - wp -> w_toprow))
- vteeol ();
- ++i;
- }
- }
- else
- if ((wp -> w_flag & (WFEDIT | WFHARD)) != 0)
- {
- hflag = TRUE;
- i = wp -> w_toprow;
- while (i < wp -> w_toprow + wp -> w_ntrows)
- {
- /* paint entire window */
- vscreen[i] -> v_color = CTEXT;
- vscreen[i] -> v_flag |= (VFCHG | VFHBAD);
- vtmove (i, 0);
- /* print line to the screen */
- if (!vtputd (wp, i - wp -> w_toprow))
- vteeol ();
- ++i;
- }
- }
- if ((wp -> w_flag & WFMODE) ||
- (wp -> w_flag & WFMOVE) ||
- (wp -> w_flag & WFHARD))
- modeline (wp);
- wp -> w_flag = 0;
- }
- wp = wp -> w_wndp;
- }
- if (sgarbf != FALSE)
- { /* Screen is garbage. */
- sgarbf = FALSE; /* Erase-page clears */
- epresf = FALSE; /* the message area. */
- tttop = HUGE; /* Forget where you set */
- ttbot = HUGE; /* scroll region. */
- tthue = CNONE; /* Color unknown. */
- ttmove (0, 0);
- tteeop ();
- #if MSDOS
- if (mem_map)
- {
- for (i = 0; i < nrow; ++i)
- {
- mem_line (i, vscreen[i]);
- }
- }
- else
- {
- #endif
- for (i = 0; i < nrow; ++i)
- {
- uline (i, vscreen[i], &blanks);
- ucopy (vscreen[i], pscreen[i]);
- }
- #if MSDOS
- }
- #endif
- ttmove (get_currow (curwp), get_curcol (curwp));
- ttflush ();
- return;
- }
- #if GOSLING
- if (hflag != FALSE)
- { /* Hard update? */
- for (i = 0; i < nrow; ++i)
- { /* Compute hash data. */
- hash (vscreen[i]);
- hash (pscreen[i]);
- }
- offs = 0; /* Get top match. */
- while (offs != nrow)
- {
- vp1 = vscreen[offs];
- vp2 = pscreen[offs];
- if (vp1 -> v_color != vp2 -> v_color
- || vp1 -> v_hash != vp2 -> v_hash)
- break;
- #if MSDOS
- if (mem_map)
- mem_line (offs, vp1);
- else
- #endif
- {
- uline (offs, vp1, vp2);
- ucopy (vp1, vp2);
- }
- ++offs;
- }
- if (offs == nrow - 1)
- { /* Might get it all. */
- ttmove (get_currow (curwp), get_curcol (curwp));
- ttflush ();
- return;
- }
- size = nrow; /* Get bottom match. */
- while (size != offs)
- {
- vp1 = vscreen[size - 1];
- vp2 = pscreen[size - 1];
- if (vp1 -> v_color != vp2 -> v_color
- || vp1 -> v_hash != vp2 -> v_hash)
- break;
- #if MSDOS
- if (mem_map)
- mem_line (size - 1, vp1);
- else
- #endif
- {
- uline (size - 1, vp1, vp2);
- ucopy (vp1, vp2);
- }
- --size;
- }
- if ((size -= offs) == 0)/* Get screen size. */
- abort ();
- setscores (offs, size); /* Do hard update. */
- traceback (offs, size, size, size);
- for (i = 0; i < size; ++i)
- ucopy (vscreen[offs + i], pscreen[offs + i]);
- ttmove (get_currow (curwp), get_curcol (curwp));
- ttflush ();
- return;
- }
- #endif
- for (i = 0; i < nrow; ++i)
- { /* Easy update. */
- vp1 = vscreen[i];
- vp2 = pscreen[i];
- if ((vp1 -> v_flag & VFCHG) != 0)
- {
- #if MSDOS
- if (mem_map)
- mem_line (i, vp1);
- else
- #endif
- {
- uline (i, vp1, vp2);
- ucopy (vp1, vp2);
- }
- }
- }
- ttmove (get_currow (curwp), get_curcol (curwp));
- ttflush ();
- }
- /*
- * Get the window relative row in which the cursor will
- * appear. pvr
- */
- uint get_currow (wp)
- WINDOW * wp;
- {
- A32 row;
- /* number of bytes from start of window */
- row = DOT_POS(wp) - WIND_POS(wp);
- /* number of rows down in window */
- row /= R_BYTES(wp);
- row += wp -> w_toprow;
- #if RUNCHK
- if (row < wp -> w_toprow)
- printf (ERR_disp_3);
- if (row > (wp -> w_ntrows + wp -> w_toprow))
- printf (ERR_disp_4);
- #endif
- return (row & 0xffff);
- }
-
- /*
- * Get the window relative column in which the cursor will
- * appear. pvr
- */
- uint get_curcol (wp)
- WINDOW * wp;
- {
- long offset,
- index;
- uint b_per_u, pos;
-
- b_per_u = R_B_PER_U(wp);
- /* dot offset from start of buffer */
- offset = DOT_POS(wp);
- offset -= wp -> w_disp_shift;
- offset &= ~(b_per_u - 1);
- /* calculate mod of the current file position */
- index = offset & (R_BYTES(wp) - 1);
- index /= b_per_u;
- /* limit to window width */
- if (index >= NCOL)
- index = NCOL;
- pos = wp -> w_fmt_ptr -> r_positions[index] + wp -> w_unit_offset;
- return (pos);
- }
- #if MSDOS
- void mem_line (row, vvp)
- int row;
- VIDEO * vvp;
- {
- vvp -> v_flag &= ~VFCHG; /* Changes done. */
- ttcolor (vvp -> v_color);
- putline (row + 1, 1, ncol, &vvp -> v_text[0]);
- }
- #endif
- /*
- * Update a saved copy of a line,
- * kept in a VIDEO structure. The "vvp" is
- * the one in the "vscreen". The "pvp" is the one
- * in the "pscreen". This is called to make the
- * virtual and physical screens the same when
- * display has done an update.
- */
- void ucopy (vvp, pvp)
- register VIDEO * vvp;
- register VIDEO * pvp;
- {
- register int i;
-
- vvp -> v_flag &= ~VFCHG; /* Changes done. */
- pvp -> v_flag = vvp -> v_flag;/* Update model. */
- pvp -> v_hash = vvp -> v_hash;
- pvp -> v_cost = vvp -> v_cost;
- pvp -> v_color = vvp -> v_color;
- for (i = 0; i < ncol; ++i)
- pvp -> v_text[i] = vvp -> v_text[i];
- }
-
- /*
- * Update a single line. This routine only
- * uses basic functionality (no insert and delete character,
- * but erase to end of line). The "vvp" points at the VIDEO
- * structure for the line on the virtual screen, and the "pvp"
- * is the same for the physical screen. Avoid erase to end of
- * line when updating CMODE color lines, because of the way that
- * reverse video works on most terminals.
- */
- void uline (row, vvp, pvp)
- VIDEO * vvp;
- VIDEO * pvp;
- {
- register char *cp1;
- register char *cp2;
- register char *cp3;
- register char *cp4;
- register char *cp5;
- register int nbflag;
-
- if (vvp -> v_color != pvp -> v_color)
- { /* Wrong color, do a */
- ttmove (row, 0); /* full redraw. */
- ttcolor (vvp -> v_color);
- cp1 = &vvp -> v_text[0];
- cp2 = &vvp -> v_text[ncol];
- while (cp1 != cp2)
- {
- ttputc (*cp1++);
- ++ttcol;
- }
- return;
- }
- cp1 = &vvp -> v_text[0]; /* Compute left match. */
- cp2 = &pvp -> v_text[0];
- while (cp1 != &vvp -> v_text[ncol] && cp1[0] == cp2[0])
- {
- ++cp1;
- ++cp2;
- }
- if (cp1 == &vvp -> v_text[ncol])/* All equal. */
- return;
- nbflag = FALSE;
- cp3 = &vvp -> v_text[ncol]; /* Compute right match. */
- cp4 = &pvp -> v_text[ncol];
- while (cp3[-1] == cp4[-1])
- {
- --cp3;
- --cp4;
- if (cp3[0] != ' ') /* Note non-blanks in */
- nbflag = TRUE; /* the right match. */
- }
- cp5 = cp3; /* Is erase good? */
- if (nbflag == FALSE && vvp -> v_color == CTEXT)
- {
- while (cp5 != cp1 && cp5[-1] == ' ')
- --cp5;
- /* Alcyon hack */
- if ((int) (cp3 - cp5) <= tceeol)
- cp5 = cp3;
- }
- /* Alcyon hack */
- ttmove (row, (int) (cp1 - &vvp -> v_text[0]));
- ttcolor (vvp -> v_color);
- while (cp1 != cp5)
- {
- ttputc (*cp1++);
- ++ttcol;
- }
- if (cp5 != cp3) /* Do erase. */
- tteeol ();
- }
-
- /*
- * Redisplay the mode line for
- * the window pointed to by the "wp".
- * This is the only routine that has any idea
- * of how the modeline is formatted. You can
- * change the modeline format by hacking at
- * this routine. Called by "update" any time
- * there is a dirty window.
- */
-
- void modeline (wp)
- register WINDOW * wp;
- {
- register char *cp,
- mode,
- size,
- u_posn,
- *s;
- register int c;
- register int n;
- register BUFFER * bp;
- register A32 posn;
-
- static char posn_buf[30] =
- {0
- }; /* krw */
-
- mode = wp -> w_fmt_ptr -> r_type;/* get type of format structure */
- size = wp -> w_fmt_ptr -> r_size;/* get size of format structure */
-
- n = wp -> w_toprow + wp -> w_ntrows;/* Location. */
- vscreen[n] -> v_color = CMODE;/* Mode line color. */
- vscreen[n] -> v_flag |= (VFCHG | VFHBAD);/* Recompute, display. */
- vtmove (n, 0); /* Seek to right line. */
- bp = wp -> w_bufp;
-
- cp = MSG_prog_name; /* Program name. pvr */
- n = 5;
- while ((c = *cp++) != 0)
- {
- vtputc (c);
- ++n;
- }
-
- if ((bp -> b_flag & BFBAD) != 0)/* "?" if trashed. */
- vtputc ('?');
- else
- vtputc (' ');
-
- if ((bp -> b_flag & BFCHG) != 0)/* "*" if changed. */
- vtputc ('*');
- else
- vtputc (' ');
-
- if (insert_mode) /* "I" if insert mode */
- vtputc ('I');
- else
- vtputc ('O');
-
- if (bp == blistp)
- { /* special list */
- cp = MSG_disp_b_lst;
- while ((c = *cp++) != 0)
- {
- vtputc (c);
- ++n;
- }
- goto pad;
- }
-
- /* Buffer name */
- vtputc (' ');
- ++n;
- cp = &bp -> b_bname[0];
- while ((c = *cp++) != 0)
- {
- vtputc (c);
- ++n;
- }
- while ((int) (cp - &bp -> b_bname[0]) < NBUFN)
- {
- vtputc (' ');
- n++;
- cp++;
- }
-
- /* File name. */
- vtputc (' ');
- ++n;
- cp = MSG_file;
- while ((c = *cp++) != 0)
- {
- vtputc (c);
- ++n;
- }
- cp = &bp -> b_fname[0];
- while ((c = *cp++) != 0)
- {
- vtputc (c);
- ++n;
- }
- cp--;
- while ((int) (cp - &bp -> b_fname[0]) < NFILE)
- {
- vtputc (' ');
- n++;
- cp++;
- }
-
- if (bp -> b_flag & BFVIEW)
- s = MSG_RO;
- else if (bp -> b_flag & BFSLOCK)
- s = MSG_WL;
- else
- s = MSG_RW;
-
- while (*s)
- { /* krw */
- vtputc (*s++);
- ++n;
- }
-
- if (auto_update && !(bp -> b_flag & BFVIEW) && bp -> b_bname[0])/* jam */
- s = MSG_AU;
- else
- s = MSG_NOT_AU;
- for (; *s && n < NCOL;)
- {
- vtputc (*s++);
- ++n;
- }
-
- /* Insert current dot position into mode line. */
- posn = DOT_POS(wp);
- u_posn = R_CHR_PER_U(wp) - wp -> w_unit_offset - 1;
- if (u_posn < 0)
- u_posn = 0;
- switch (mode)
- {
- case TEXT:
- case ASCII:
- sprintf (posn_buf, MSG_curs_asc, posn);
- break;
- case EBCDIC:
- sprintf (posn_buf, MSG_curs_ebc, posn);
- break;
- case HEX:
- sprintf (posn_buf, MSG_curs_hex, posn, u_posn);
- break;
- case BINARY:
- sprintf (posn_buf, MSG_curs_bin, posn, u_posn);
- break;
- case DECIMAL:
- sprintf (posn_buf, MSG_curs_dec, posn, u_posn);
- break;
- case OCTAL:
- sprintf (posn_buf, MSG_curs_oct, posn, u_posn);
- break;
- #if RUNCHK
- default:
- writ_echo (ERR_disp_5);
- break;
- #endif
- }
-
- cp = posn_buf;
- while ((c = *cp++) != 0)
- {
- vtputc (c);
- ++n;
- }
-
-
- if ((mode == HEX) ||
- (mode == DECIMAL) ||
- (mode == OCTAL))
- {
- switch (size)
- {
- case BYTES:
- sprintf (posn_buf, MSG_siz_8);
- break;
- case WORDS:
- sprintf (posn_buf, MSG_siz_16);
- break;
- case DWORDS:
- sprintf (posn_buf, MSG_siz_32);
- break;
- #if RUNCHK
- default:
- writ_echo (ERR_disp_6);
- break;
- #endif
- }
- }
- else
- sprintf (posn_buf, MSG_siz_null);
-
- cp = posn_buf;
- while ((c = *cp++) != 0)
- {
- vtputc (c);
- ++n;
- }
-
- if (wp -> w_intel_mode)
- sprintf (posn_buf, MSG_int_shift, wp -> w_disp_shift);
- else
- sprintf (posn_buf, MSG_mot_shift, wp -> w_disp_shift);
- cp = posn_buf;
- while ((c = *cp++) != 0)
- {
- vtputc (c);
- ++n;
- }
-
-
- /* pad out */
- pad:
- while (n < ncol)
- {
- vtputc (' ');
- ++n;
- }
- }
-
- /*
- * write text to the echo line
- */
- void writ_echo (buf)
- char *buf;
- {
- int i, len;
- char *vpp;
- bool fill_spac;
-
- fill_spac = FALSE;
- vpp = vscreen[nrow - 1] -> v_text;
- vscreen[nrow - 1] -> v_color = CTEXT;
- vscreen[nrow - 1] -> v_flag |= VFCHG;
- epresf = TRUE;
-
- for (i = 0; i < NCOL; i++)
- {
- if (buf[i] == 0)
- fill_spac = TRUE;
- if (fill_spac)
- vpp[i] = ' ';
- else
- vpp[i] = buf[i];
- }
- #if MSDOS
- if (mem_map)
- {
- mem_line (nrow - 1, vscreen[nrow - 1]);
- }
- else
- #endif
- {
- uline (nrow - 1, vscreen[nrow - 1], pscreen[nrow - 1]);
- /* uline (nrow - 1, vscreen[nrow - 1], &blanks); */
- ucopy (vscreen[nrow - 1], pscreen[nrow - 1]);
- ttflush ();
- }
- }
-
- #if GOSLING
- /*
- * Compute the hash code for
- * the line pointed to by the "vp". Recompute
- * it if necessary. Also set the approximate redisplay
- * cost. The validity of the hash code is marked by
- * a flag bit. The cost understand the advantages
- * of erase to end of line. Tuned for the VAX
- * by Bob McNamara; better than it used to be on
- * just about any machine.
- */
- void hash (vp)
- register VIDEO * vp;
- {
- register int i;
- register int n;
- register char *s;
-
- if ((vp -> v_flag & VFHBAD) != 0)
- { /* Hash bad. */
- s = &vp -> v_text[ncol - 1];
- for (i = ncol; i != 0; --i, --s)
- if (*s != ' ')
- break;
- n = ncol - i; /* Erase cheaper? */
- if (n > tceeol)
- n = tceeol;
- vp -> v_cost = i + n; /* Bytes + blanks. */
- for (n = 0; i != 0; --i, --s)
- n = (n << 5) + n + *s;
- vp -> v_hash = n; /* Hash code. */
- vp -> v_flag &= ~VFHBAD;/* Flag as all done. */
- }
- }
-
- /*
- * Compute the Insert-Delete
- * cost matrix. The dynamic programming algorithm
- * described by James Gosling is used. This code assumes
- * that the line above the echo line is the last line involved
- * in the scroll region. This is easy to arrange on the VT100
- * because of the scrolling region. The "offs" is the origin 0
- * offset of the first row in the virtual/physical screen that
- * is being updated; the "size" is the length of the chunk of
- * screen being updated. For a full screen update, use offs=0
- * and size=nrow-1.
- *
- * Older versions of this code implemented the score matrix by
- * a two dimensional array of SCORE nodes. This put all kinds of
- * multiply instructions in the code! This version is written to
- * use a linear array and pointers, and contains no multiplication
- * at all. The code has been carefully looked at on the VAX, with
- * only marginal checking on other machines for efficiency. In
- * fact, this has been tuned twice! Bob McNamara tuned it even
- * more for the VAX, which is a big issue for him because of
- * the 66 line X displays.
- *
- * On some machines, replacing the "for (i=1; i<=size; ++i)" with
- * i = 1; do
- { }while (++i <=size)" will make the code quite a
- * bit better; but it looks ugly.
- */
- void setscores (offs, size)
- {
- register SCORE * sp;
- register int tempcost;
- register int bestcost;
- register int j;
- register int i;
- register VIDEO ** vp;
- register VIDEO ** pp;
- register SCORE * sp1;
- register VIDEO ** vbase;
- register VIDEO ** pbase;
-
- vbase = &vscreen[offs - 1]; /* By hand CSE's. */
- pbase = &pscreen[offs - 1];
- score[0].s_itrace = 0; /* [0, 0] */
- score[0].s_jtrace = 0;
- score[0].s_cost = 0;
- sp = &score[1]; /* Row 0, inserts. */
- tempcost = 0;
- vp = &vbase[1];
- for (j = 1; j <= size; ++j)
- {
- sp -> s_itrace = 0;
- sp -> s_jtrace = j - 1;
- tempcost += tcinsl;
- tempcost += (*vp) -> v_cost;
- sp -> s_cost = tempcost;
- ++vp;
- ++sp;
- }
- sp = &score[NROW]; /* Column 0, deletes. */
- tempcost = 0;
- for (i = 1; i <= size; ++i)
- {
- sp -> s_itrace = i - 1;
- sp -> s_jtrace = 0;
- tempcost += tcdell;
- sp -> s_cost = tempcost;
- sp += NROW;
- }
- sp1 = &score[NROW + 1]; /* [1, 1]. */
- pp = &pbase[1];
- for (i = 1; i <= size; ++i)
- {
- sp = sp1;
- vp = &vbase[1];
- for (j = 1; j <= size; ++j)
- {
- sp -> s_itrace = i - 1;
- sp -> s_jtrace = j;
- bestcost = (sp - NROW) -> s_cost;
- if (j != size) /* Cd(A[i])=0 @ Dis. */
- bestcost += tcdell;
- tempcost = (sp - 1) -> s_cost;
- tempcost += (*vp) -> v_cost;
- if (i != size) /* Ci(B[j])=0 @ Dsj. */
- tempcost += tcinsl;
- if (tempcost < bestcost)
- {
- sp -> s_itrace = i;
- sp -> s_jtrace = j - 1;
- bestcost = tempcost;
- }
- tempcost = (sp - NROW - 1) -> s_cost;
- if ((*pp) -> v_color != (*vp) -> v_color
- || (*pp) -> v_hash != (*vp) -> v_hash)
- tempcost += (*vp) -> v_cost;
- if (tempcost < bestcost)
- {
- sp -> s_itrace = i - 1;
- sp -> s_jtrace = j - 1;
- bestcost = tempcost;
- }
- sp -> s_cost = bestcost;
- ++sp; /* Next column. */
- ++vp;
- }
- ++pp;
- sp1 += NROW; /* Next row. */
- }
- }
-
- /*
- * Trace back through the dynamic programming cost
- * matrix, and update the screen using an optimal sequence
- * of redraws, insert lines, and delete lines. The "offs" is
- * the origin 0 offset of the chunk of the screen we are about to
- * update. The "i" and "j" are always started in the lower right
- * corner of the matrix, and imply the size of the screen.
- * A full screen traceback is called with offs=0 and i=j=nrow-1.
- * There is some do-it-yourself double subscripting here,
- * which is acceptable because this routine is much less compute
- * intensive then the code that builds the score matrix!
- */
- void traceback (offs, size, i, j)
- {
- register int itrace;
- register int jtrace;
- register int k;
- register int ninsl;
- register int ndraw;
- register int ndell;
-
- if (i == 0 && j == 0) /* End of update. */
- return;
- itrace = score[(NROW * i) + j].s_itrace;
- jtrace = score[(NROW * i) + j].s_jtrace;
- if (itrace == i)
- { /* [i, j-1] */
- ninsl = 0; /* Collect inserts. */
- if (i != size)
- ninsl = 1;
- ndraw = 1;
- while (itrace != 0 || jtrace != 0)
- {
- if (score[(NROW * itrace) + jtrace].s_itrace != itrace)
- break;
- jtrace = score[(NROW * itrace) + jtrace].s_jtrace;
- if (i != size)
- ++ninsl;
- ++ndraw;
- }
- traceback (offs, size, itrace, jtrace);
- if (ninsl != 0)
- {
- ttcolor (CTEXT);
- ttinsl (offs + j - ninsl, offs + size - 1, ninsl);
- }
- do
- { /* B[j], A[j] blank. */
- k = offs + j - ndraw;
- uline (k, vscreen[k], &blanks);
- } while (--ndraw);
- return;
- }
- if (jtrace == j)
- { /* [i-1, j] */
- ndell = 0; /* Collect deletes. */
- if (j != size)
- ndell = 1;
- while (itrace != 0 || jtrace != 0)
- {
- if (score[(NROW * itrace) + jtrace].s_jtrace != jtrace)
- break;
- itrace = score[(NROW * itrace) + jtrace].s_itrace;
- if (j != size)
- ++ndell;
- }
- if (ndell != 0)
- {
- ttcolor (CTEXT);
- ttdell (offs + i - ndell, offs + size - 1, ndell);
- }
- traceback (offs, size, itrace, jtrace);
- return;
- }
- traceback (offs, size, itrace, jtrace);
- k = offs + j - 1;
- uline (k, vscreen[k], pscreen[offs + i - 1]);
- }
- #endif
-
- /*
- * Print the current buffer from mark to dot using the
- * current window's display format.
- * Prompt for file name or io device to print to.
- */
-
- bool print ()
- {
- LINE *dot_l_sav, *mark_l_sav, *wind_l_sav;
- int dot_off_sav, mark_off_sav, wind_off_sav, i;
- char s;
- char fname[NFILEN];
- register int nline;
- char buf[80], buf1[60];
-
- /* save the original window state */
- dot_l_sav = curwp -> w_dotp;
- dot_off_sav = curwp -> w_doto;
- mark_l_sav = curwp -> w_markp;
- mark_off_sav = curwp -> w_marko;
- wind_l_sav = curwp -> w_linep;
- wind_off_sav = curwp -> w_loff;
-
- /* if mark is not set then set it to location zero */
- if (curwp -> w_markp == NULL)
- {
- curwp -> w_markp = curwp -> w_bufp -> b_linep -> l_fp;
- curwp -> w_marko = 0;
- }
-
- nline = 0;
- if ((s = ereply (MSG_prn_to, fname, NFILEN, NULL)) == ABORT)
- return (s);
- adjustcase (fname);
- if ((s = ffwopen (fname)) != FIOSUC)/* Open writes message. */
- return (FALSE);
-
- sprintf (buf, MSG_print1, fname);
- writ_echo (buf);
- /* make dot before mark */
- if (DOT_POS(curwp) > MARK_POS(curwp))
- swapmark (); /* make mark first */
-
- while (DOT_POS(curwp) <= MARK_POS(curwp))
- {
- /* check if we should quit */
- if (ttkeyready ())
- {
- ttgetc (); /* through away char that was struck */
- break;
- }
- nline++;
- /* move window so that first line is on dot */
- move_ptr (curwp, DOT_POS(curwp), FALSE, TRUE, FALSE);
-
- if (vtputd (curwp, 0)) /* print line into video buffer */
- {
- for (i = NCOL; (vscreen[vtrow] -> v_text[i] < '!') ||
- (vscreen[vtrow] -> v_text[i] > '~'); i--)
- ;
- i++;
- if ((s = ffputline (vscreen[vtrow] -> v_text, i)) != FIOSUC)
- break;
- if ((s = ffputline (MSG_disp_r_n, 2)) != FIOSUC)
- break;
- }
- else
- break;
- forwline (0, 1, KRANDOM); /* advance to next line */
- }
- ffclose ();
- sprintf (buf1, MSG_print2, R_POS_FMT(curwp));
- sprintf (buf, buf1, (long) nline);
- writ_echo (buf);
-
- /* restore the original window state */
- curwp -> w_dotp = dot_l_sav;
- curwp -> w_doto = dot_off_sav;
- curwp -> w_markp = mark_l_sav;
- curwp -> w_marko = mark_off_sav;
- curwp -> w_linep = wind_l_sav;
- curwp -> w_loff = wind_off_sav;
- curwp -> w_flag |= WFHARD; /* insure that window is still presentable */
- return (TRUE);
- }
-