home *** CD-ROM | disk | FTP | other *** search
/ TopWare Tools / TOOLS.iso / tools / top1242 / display.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-01-06  |  31.5 KB  |  1,349 lines

  1. /*
  2. * The functions in this file handle redisplay. The
  3. * redisplay system knows almost nothing about the editing
  4. * process; the editing functions do, however, set some
  5. * hints to eliminate a lot of the grinding. There is more
  6. * that can be done; the "vtputc" interface is a real
  7. * pig.  The MEMMAP
  8. * changes things around for memory mapped video. With
  9. * both off, the terminal is a VT52.
  10. */
  11.  
  12. #include    <sys/types.h>
  13. #include    <sys/stat.h>
  14. #include    "def.h"
  15.  
  16. D32 get_long ();
  17. D16 get_int ();
  18. void writ_echo ();
  19. void uline ();
  20. void ucopy ();
  21. void modeline ();
  22. void bin_to_text ();
  23. uint fill_buf ();
  24. uint get_currow ();
  25. uint get_curcol ();
  26. #if MSDOS
  27. void    mem_line ();
  28. #endif
  29.  
  30. extern    char    MSG_prn_to[];
  31. extern    char    MSG_disp_r_n[];
  32. extern    char    MSG_11lX[];
  33. extern    char    MSG_11lo[];
  34. extern    char    MSG_11ld[];
  35. extern    char    MSG_03o[];
  36. extern    char    MSG_06o[];
  37. extern    char    MSG_011lo[];
  38. extern    char    MSG_03u[];
  39. extern    char    MSG_05u[];
  40. extern    char    MSG_010lu[];
  41. extern    char    MSG_02X[];
  42. extern    char    MSG_04X[];
  43. extern    char    MSG_08lX[];
  44. extern    char    MSG_prog_name[];
  45. extern    char    MSG_disp_b_lst[];
  46. extern    char    MSG_file[];
  47. extern    char    MSG_RO[];
  48. extern    char    MSG_WL[];
  49. extern    char    MSG_RW[];
  50. extern    char    MSG_AU[];
  51. extern    char    MSG_NOT_AU[];
  52. extern    char    MSG_curs_asc[];
  53. extern    char    MSG_curs_ebc[];
  54. extern    char    MSG_curs_hex[];
  55. extern    char    MSG_curs_bin[];
  56. extern    char    MSG_curs_dec[];
  57. extern    char    MSG_curs_oct[];
  58. extern    char    MSG_siz_8[];
  59. extern    char    MSG_siz_16[];
  60. extern    char    MSG_siz_32[];
  61. extern    char    MSG_siz_null[];
  62. extern    char    MSG_int_shift[];
  63. extern    char    MSG_mot_shift[];
  64. extern    char    MSG_print1[];
  65. extern    char    MSG_print2[];
  66. #if RUNCHK
  67. extern    char    ERR_disp_1[];
  68. extern    char    ERR_disp_2[];
  69. extern    char    ERR_disp_3[];
  70. extern    char    ERR_disp_4[];
  71. extern    char    ERR_disp_5[];
  72. extern    char    ERR_disp_6[];
  73. #endif
  74.  
  75. extern char ebcdic_table[];
  76.  
  77. extern  bool    mem_map;
  78.  
  79. /*
  80. * You can change these back to the types
  81. * implied by the name if you get tight for space. If you
  82. * make both of them "int" you get better code on the VAX.
  83. * They do nothing if this is not Gosling redisplay, except
  84. * for change the size of a structure that isn't used.
  85. * A bit of a cheat.
  86. */
  87. #define XCHAR   int
  88. #define XSHORT  int
  89.  
  90. /*
  91. * A video structure always holds
  92. * an array of characters whose length is equal to
  93. * the longest line possible. Only some of this is
  94. * used if "ncol" isn't the same as "NCOL".
  95. */
  96. typedef struct vid
  97. {
  98.     short   v_hash;             /* Hash code, for compares.     */
  99.     short   v_flag;             /* Flag word.                   */
  100.     short   v_color;            /* Color of the line.           */
  101.     XSHORT v_cost;      /* Cost of display.     */
  102.     char    v_text[NMAXCOL];       /* The actual characters.       */
  103. }                   VIDEO;
  104.  
  105. #define VFCHG   0x0001          /* Changed.                     */
  106. #define VFHBAD  0x0002          /* Hash and cost are bad.       */
  107.  
  108. /*
  109. * SCORE structures hold the optimal
  110. * trace trajectory, and the cost of redisplay, when
  111. * the dynamic programming redisplay code is used.
  112. * If no fancy redisplay, this isn't used. The trace index
  113. * fields can be "char", and the score a "short", but
  114. * this makes the code worse on the VAX.
  115. */
  116. typedef struct
  117. {
  118.     XCHAR s_itrace;             /* "i" index for track back.    */
  119.     XCHAR s_jtrace;             /* "j" index for trace back.    */
  120.     XSHORT s_cost;              /* Display cost.                */
  121. }               SCORE;
  122.  
  123. int     sgarbf = TRUE;          /* TRUE if screen is garbage.   */
  124. int     vtrow = 0;              /* Virtual cursor row.          */
  125. int     vtcol = 0;              /* Virtual cursor column.       */
  126. int     tthue = CNONE;          /* Current color.               */
  127. int     ttrow = HUGE;           /* Physical cursor row.         */
  128. int     ttcol = HUGE;           /* Physical cursor column.      */
  129. int     tttop = HUGE;           /* Top of scroll region.        */
  130. int     ttbot = HUGE;           /* Bottom of scroll region.     */
  131. char    file_off_bad = FALSE;   /* Have file offsets been changed */
  132.  
  133. VIDEO * vscreen[NMAXROW];       /* Edge vector, virtual.        */
  134. VIDEO * pscreen[NMAXROW];       /* Edge vector, physical.       */
  135. VIDEO video[2 * (NMAXROW)];     /* Actual screen data.          */
  136. VIDEO blanks;                   /* Blank line image.            */
  137.  
  138. /*
  139. * Initialize the data structures used
  140. * by the display code. The edge vectors used
  141. * to access the screens are set up. The operating
  142. * system's terminal I/O channel is set up. Fill the
  143. * "blanks" array with ASCII blanks. The rest is done
  144. * at compile time. The original window is marked
  145. * as needing full update, and the physical screen
  146. * is marked as garbage, so all the right stuff happens
  147. * on the first call to redisplay.
  148. */
  149. void vtinit ()
  150. {
  151.     register    VIDEO * vp;
  152.     register int    i;
  153.  
  154.     ttopen ();
  155.     ttinit ();
  156.     vp = &video[0];
  157.     for (i = 0; i < NMAXROW; ++i)
  158.     {
  159.         vscreen[i] = vp;
  160.         ++vp;
  161.         pscreen[i] = vp;
  162.         ++vp;
  163.     }
  164.     blanks.v_color = CTEXT;
  165.     for (i = 0; i < NMAXCOL; ++i)
  166.         blanks.v_text[i] = ' ';
  167. }
  168.  
  169. /*
  170. * Tidy up the virtual display system
  171. * in anticipation of a return back to the host
  172. * operating system. Right now all we do is position
  173. * the cursor to the last line, erase the line, and
  174. * close the terminal channel.
  175. */
  176. void vttidy ()
  177. {
  178.     ttcolor (CTEXT);
  179.     ttnowindow ();              /* No scroll window.    */
  180.     ttmove (nrow - 1, 0);       /* Echo line.           */
  181.     tteeol ();
  182.     tttidy ();
  183.     ttflush ();
  184.     ttclose ();
  185. }
  186.  
  187. /*
  188. * Move the virtual cursor to an origin
  189. * 0 spot on the virtual display screen. I could
  190. * store the column as a character pointer to the spot
  191. * on the line, which would make "vtputc" a little bit
  192. * more efficient. No checking for errors.
  193. */
  194. void vtmove (row, col)
  195. int row, col;
  196. {
  197.     vtrow = row;
  198.     vtcol = col;
  199. }
  200.  
  201. /*
  202. * Write a character to the virtual display,
  203. * dealing with long lines and the display of unprintable
  204. * things like control characters. Also expand tabs every 8
  205. * columns. This code only puts printing characters into
  206. * the virtual display image. Special care must be taken when
  207. * expanding tabs. On a screen whose width is not a multiple
  208. * of 8, it is possible for the virtual cursor to hit the
  209. * right margin before the next tab stop is reached. This
  210. * makes the tab code loop if you are not careful.
  211. * Three guesses how we found this.
  212. */
  213. void vtputc (c)
  214. register char   c;
  215. {
  216.     register    VIDEO * vp;
  217.  
  218.     vp = vscreen[vtrow];
  219.     if (vtcol >= ncol)
  220.         vp -> v_text[ncol - 1] = '$';
  221.     else
  222.         if (ISCTRL (c) != FALSE)
  223.         {
  224.             vtputc ('^');
  225.             vtputc ((char) (c ^ 0x40));
  226.         }
  227.         else
  228.         {
  229.             vp -> v_text[vtcol] = c;
  230.             vtcol++;
  231.         }
  232.  
  233. }
  234. /*
  235. * Write an entire screen line in the correct format.    pvr
  236. *
  237. * This code only puts printing characters into
  238. * the virtual display image.
  239. * Return TRUE if something was printed to the line.
  240. */
  241. #define REGI  register
  242. bool vtputd (wp, row)
  243. WINDOW * wp;
  244. int     row;                    /* line # to print to v screen */
  245.  
  246. {
  247.     REGI VIDEO * vp;
  248.     REGI char   mode;
  249.     REGI A32    row_offst;
  250.     REGI uint   chrs_per_row,
  251.         lin_offset,
  252.         i,
  253.         chrs_in_lin;
  254.     LINE * cur_line;
  255.     static char w_buf[128];      /* temp buffer for data */
  256.  
  257.     vp = vscreen[vtrow];        /* point to VIDEO structure to print into */
  258.     mode = R_TYPE(wp);          /* get type of format structure */
  259.  
  260.     /* get number of bytes per row */
  261.     chrs_per_row = R_BYTES(wp);
  262.  
  263.     /* determine the offset from begining of the buffer for this line */
  264.     row_offst = WIND_POS(wp) + (row * chrs_per_row);
  265.  
  266.     /* search for and point to first character in buffer to be printed */
  267.     cur_line = wp -> w_linep;   /* start with current first window line */
  268.     while (TRUE)
  269.     {                       /* find line with desired character */
  270.         if (cur_line == wp -> w_bufp -> b_linep)
  271.         {                   /* at end of buffer? */
  272.             return (FALSE);
  273.         }
  274.         if (cur_line -> l_file_offset > row_offst)
  275.         {
  276.             /* if less than current line */
  277.             cur_line = cur_line -> l_bp;/* step back */
  278.         }
  279.         else
  280.             if ((cur_line -> l_file_offset + cur_line -> l_used) <= row_offst)
  281.             {
  282.                 cur_line = cur_line -> l_fp;/* step ahead */
  283.             }
  284.             else
  285.                 break;
  286.     }
  287.  
  288.     lin_offset = row_offst - cur_line -> l_file_offset;/* offset into line */
  289.  
  290.     /* get index into the current line to start reading the current row's data */
  291.     /* copy line text into buffer */
  292.     chrs_in_lin = fill_buf (wp, cur_line, lin_offset, w_buf, chrs_per_row);
  293.  
  294.     /* limit line length to screen width, used in TEXT mode only */
  295.     if (chrs_in_lin > NCOL)
  296.         chrs_in_lin = NCOL;
  297.  
  298.     /* Clear the line to spaces */
  299.     for (i = 0; i < NCOL; i++)
  300.     {
  301.         vp -> v_text[i] = ' ';
  302.     }
  303.     switch (mode)
  304.     {
  305.     case TEXT:
  306.         break;
  307.     case ASCII:
  308.     case EBCDIC:
  309.     case BINARY:
  310.     case HEX:
  311.         /* print the row offset from the start of the file in HEX */
  312.         sprintf (vp -> v_text, MSG_11lX, row_offst);/* to vid buf */
  313.         break;
  314.     case OCTAL:
  315.         /* print the row offset from the start of the file */
  316.         sprintf (vp -> v_text, MSG_11lo, row_offst);/* to vid buf */
  317.         break;
  318.     case DECIMAL:
  319.         /* print the row offset from the start of the file */
  320.         sprintf (vp -> v_text, MSG_11ld, row_offst);/* to vid buf */
  321.         break;
  322. #if RUNCHK
  323.     default:
  324.         writ_echo (ERR_disp_1);
  325.         break;
  326. #endif
  327.     }
  328.  
  329.     /* print the binary data to the text line */
  330.     bin_to_text (w_buf, vp -> v_text, chrs_in_lin,
  331.         wp -> w_fmt_ptr);
  332.  
  333.     vtcol = NCOL;
  334.     return (TRUE);
  335. }
  336.  
  337. /*
  338. *   Print the contents of then binary data buffer bin_buf
  339. *   into the proper mode of text into txt_buf.
  340. *   Process 'len' bytes.
  341. *
  342. *   input:
  343. *           bin_buf     pointer to buffer of binary data to process.
  344. *           txt_buf     pointer to output buffer to print text result into.
  345. *           len         length in bytes of data in bin_buf to process.
  346. *           fmt_ptr     pointer to a ROW_FMT to use to format the data
  347. *                       conversion and printing process.
  348. *   output:
  349. *           none.
  350. */
  351.  
  352. void bin_to_text (bin_buf, txt_buf, len, fmt_ptr)
  353.  
  354. char   *bin_buf,
  355. *txt_buf;
  356. uint    len;
  357. ROW_FMT *fmt_ptr;
  358.  
  359. {
  360.     uchar   i,
  361.         ch,
  362.         k,
  363.         j,
  364.         mode,
  365.         size,
  366.         *posn;
  367.     uint    temp_int;
  368.     ulong   temp_long;
  369.  
  370.     mode = fmt_ptr -> r_type;   /* get type of format structure */
  371.     size = fmt_ptr -> r_size;   /* get size of format structure */
  372.     posn = fmt_ptr -> r_positions;/* pointer to array of display positions */
  373.  
  374.     switch (mode)
  375.     {
  376.     case TEXT:
  377.     case ASCII:
  378.         for (i = 0; i < len; i++)
  379.         {
  380.             ch = bin_buf[i];
  381.             if ((ch >= ' ') && (ch < 0x7f))
  382.                 txt_buf[posn[0] + i] = ch;
  383.             else
  384.                 txt_buf[posn[0] + i] = '.';
  385.         }
  386.         break;
  387.  
  388.     case EBCDIC:
  389.         for (i = 0; i < len; i++)
  390.         {
  391.             txt_buf[posn[0] + i] =
  392.                 0xff & ebcdic_table[0xff & bin_buf[i]];
  393.         }
  394.         break;
  395.  
  396.     case OCTAL:
  397.         switch (size)
  398.         {
  399.         case BYTES:     /* print octal bytes */
  400.             for (i = 0; i < len; i++)
  401.             {
  402.                 sprintf (&txt_buf[
  403.                                     posn[i]], MSG_03o, 0xff & bin_buf[i]);
  404.             }
  405.             break;
  406.  
  407.         case WORDS:     /* print octal words */
  408.             k = 0;
  409.             for (i = 0; i < len;
  410.                 i += 2)
  411.             {
  412.                 temp_int = get_int (&bin_buf[i]);
  413.                 sprintf (&txt_buf[posn[k++]], MSG_06o, temp_int);
  414.             }
  415.             break;
  416.  
  417.         case DWORDS:    /* print octal double words */
  418.             k = 0;
  419.             for (i = 0; i < len;
  420.                 i += 4)
  421.             {
  422.                 temp_long = get_long (&bin_buf[i]);
  423.                 sprintf (&txt_buf[posn[k++]], MSG_011lo, temp_long);
  424.             }
  425.             break;
  426.         }
  427.         break;
  428.  
  429.     case DECIMAL:
  430.         switch (size)
  431.         {
  432.         case BYTES:     /* print decimal bytes */
  433.             for (i = 0; i < len; i++)
  434.             {
  435.                 sprintf (&txt_buf[
  436.                                     posn[i]], MSG_03u, 0xff & bin_buf[i]);
  437.             }
  438.             break;
  439.  
  440.         case WORDS:     /* print decimal words */
  441.             k = 0;
  442.             for (i = 0; i < len;
  443.                 i += 2)
  444.             {
  445.                 temp_int = get_int (&bin_buf[i]);
  446.                 sprintf (&txt_buf[
  447.                                     posn[k++]], MSG_05u, temp_int);
  448.             }
  449.             break;
  450.  
  451.         case DWORDS:    /* print decimal double words */
  452.             k = 0;
  453.             for (i = 0; i < len; i += 4)
  454.             {
  455.                 temp_long = get_long (&bin_buf[i]);
  456.                 sprintf (&txt_buf[
  457.                                     posn[k++]], MSG_010lu, temp_long);
  458.             }
  459.             break;
  460.         }
  461.         break;
  462.  
  463.     case HEX:
  464.         switch (size)
  465.         {
  466.         case BYTES:     /* print hex bytes and ascii chars */
  467.             for (i = 0; i < len; i++)
  468.             {
  469.                 if ((bin_buf[i] >= ' ') && (bin_buf[i] < 0x7f))
  470.                     txt_buf[posn[i + 16]] = 0xff & bin_buf[i];
  471.                 else
  472.                     txt_buf[posn[i + 16]] = '.';
  473.                 sprintf (&txt_buf[posn[i]], MSG_02X, 0xff & bin_buf[i]);
  474.             }
  475.             break;
  476.  
  477.         case WORDS:     /* print hex words */
  478.             k = 0;
  479.             for (i = 0; i < len; i += 2)
  480.             {
  481.                 temp_int = get_int (&bin_buf[i]);
  482.                 sprintf (&txt_buf[
  483.                                     posn[k++]], MSG_04X, temp_int);
  484.             }
  485.             break;
  486.  
  487.         case DWORDS:    /* print hex double words */
  488.             k = 0;
  489.             for (i = 0; i < len; i += 4)
  490.             {
  491.                 temp_long = get_long (&bin_buf[i]);
  492.                 sprintf (&txt_buf[
  493.                                     posn[k++]], MSG_08lX, temp_long);
  494.             }
  495.             break;
  496.         }
  497.         break;
  498.  
  499.     case BINARY:
  500.         switch (size)
  501.         {
  502.         case BYTES:     /* print binary bits */
  503.             for (i = 0; i < len; i++)
  504.             {
  505.                 ch = bin_buf[i];/* get char to convert */
  506.                 for (k = 0; k < 8; k++)
  507.                 {
  508.                     if (ch & 0x80)
  509.                         txt_buf[posn[i] + k]
  510.                             = '1';
  511.                     else
  512.                         txt_buf[posn[i] + k]
  513.                             = '0';
  514.                     ch = ch << 1;/* slide next bit into place */
  515.                 }
  516.             }
  517.             break;
  518.  
  519.         case WORDS:
  520.             j = 0;
  521.             for (i = 0; i < len; i += 2)
  522.             {
  523.                 temp_int = get_int (&bin_buf[i]);
  524.  
  525.                 for (k = 0; k < 16; k++)
  526.                 {
  527.                     if (temp_int & 0x8000)
  528.                         txt_buf[posn[j] + k]
  529.                             = '1';
  530.                     else
  531.                         txt_buf[posn[j] + k]
  532.                             = '0';
  533.                     temp_int = temp_int << 1;
  534.                     /* slide next bit into place */
  535.                 }
  536.                 j++;
  537.             }
  538.             break;
  539.  
  540.         case DWORDS:
  541.             j = 0;
  542.             for (i = 0; i < len; i += 4)
  543.             {
  544.                 temp_long = get_long (&bin_buf[i]);
  545.                 for (k = 0; k < 32; k++)
  546.                 {
  547.                     if (temp_long & 0x80000000)
  548.                         txt_buf[posn[j] + k]
  549.                             = '1';
  550.                     else
  551.                         txt_buf[posn[j] + k]
  552.                             = '0';
  553.                     temp_long = temp_long << 1;
  554.                     /* slide next bit into place */
  555.                 }
  556.                 j++;
  557.             }
  558.             break;
  559.         }
  560.         break;
  561. #if RUNCHK
  562.     default:
  563.         writ_echo (ERR_disp_2);
  564.         break;
  565. #endif
  566.     }
  567.     len *= (fmt_ptr -> r_chr_per_u + 1);
  568.     /* Clean up any garbage characters left by the sprintf's */
  569.     for (i = 0; i < NCOL; i++)
  570.     {
  571.         if (txt_buf[i] == 0)
  572.             txt_buf[i] = ' ';
  573.     }
  574. }
  575.  
  576. /*
  577. *   Get an int from the buffer.
  578. *   Perform the Intel byte shuffle if necessary
  579. */
  580.  
  581. D16 get_int (w_buf)
  582. uchar  *w_buf;
  583.  
  584. {
  585.     int     temp_int;
  586.  
  587.     if (curwp -> w_intel_mode)
  588.     {
  589.         temp_int = 0xff & w_buf[1];
  590.         temp_int <<= 8;
  591.         temp_int |= 0xff & w_buf[0];
  592.     }
  593.     else
  594.     {
  595.         temp_int = 0xff & w_buf[0];
  596.         temp_int <<= 8;
  597.         temp_int |= 0xff & w_buf[1];
  598.     }
  599.     return (temp_int);
  600. }
  601.  
  602. /*
  603. *   Get an long from the buffer.
  604. *   Perform the Intel byte shuffle if necessary
  605. */
  606.  
  607. D32 get_long (w_buf)
  608. uchar  *w_buf;
  609.  
  610. {
  611.     long    temp_long;
  612.  
  613.     if (curwp -> w_intel_mode)
  614.     {
  615.         temp_long = 0xff & w_buf[3];
  616.         temp_long <<= 8;
  617.         temp_long |= 0xff & w_buf[2];
  618.         temp_long <<= 8;
  619.         temp_long |= 0xff & w_buf[1];
  620.         temp_long <<= 8;
  621.         temp_long |= 0xff & w_buf[0];
  622.     }
  623.     else
  624.     {
  625.         temp_long = 0xff & w_buf[0];
  626.         temp_long <<= 8;
  627.         temp_long |= 0xff & w_buf[1];
  628.         temp_long <<= 8;
  629.         temp_long |= 0xff & w_buf[2];
  630.         temp_long <<= 8;
  631.         temp_long |= 0xff & w_buf[3];
  632.     }
  633.     return (temp_long);
  634. }
  635.  
  636.  
  637. /*
  638. *   Copy a length of bytes from the buffer LINEs into the designated
  639. *   buffer.   If the current LINE does not have enough bytes then
  640. *   advance to the next.   Return the actual number of bytes copied.
  641. *   The number copied would be less than the number requested if
  642. *   end of file is reached.
  643. */
  644.  
  645. uint    fill_buf (wp, lin, lin_off, w_buff, cnt)
  646. WINDOW  *wp;
  647. LINE    *lin;
  648. uint    lin_off,
  649. cnt;
  650. char    *w_buff;
  651. {
  652.     REGI uint   src,
  653.         dest,
  654.         i;
  655.  
  656.     src = lin_off;              /* initialize source line index */
  657.     dest = 0;                   /* initialize destination buffer index */
  658.  
  659.     while (TRUE)
  660.     {
  661.         while (src < lin -> l_used)
  662.         {
  663.             w_buff[dest++] = lin -> l_text[src++];/* copy byte */
  664.  
  665.             if (dest == cnt)
  666.             {               /* if done */
  667.                 return (cnt);   /* then leave */
  668.             }
  669.         }
  670.         if (R_TYPE(wp) == TEXT)
  671.             return (dest);   /* in text mode don't advance to next line */
  672.  
  673.         lin = lin -> l_fp;      /* move to the next line */
  674.         if (lin == wp -> w_bufp -> b_linep)
  675.         {                   /* if past last line */
  676.             {
  677.             for (i = dest; i < cnt; ++i)
  678.                 w_buff[i] = 0;/* fill rest of buffer with zeros */
  679.             return (dest);  /* return number of chars copied */
  680.         }
  681.     }
  682.     src = 0;                /* start next LINE at first byte */
  683. }
  684. return (0);
  685. }
  686.  
  687. /*
  688. * Erase from the end of the
  689. * software cursor to the end of the
  690. * line on which the software cursor is
  691. * located. The display routines will decide
  692. * if a hardware erase to end of line command
  693. * should be used to display this.
  694. */
  695. void vteeol ()
  696. {
  697.     register    VIDEO * vp;
  698.  
  699.     vp = vscreen[vtrow];
  700.     while (vtcol < ncol)
  701.         vp -> v_text[vtcol++] = ' ';
  702. }
  703.  
  704. /*
  705. * Make sure that the display is
  706. * right. This is a three part process. First,
  707. * scan through all of the windows looking for dirty
  708. * ones. Check the framing, and refresh the screen.
  709. * Second, make the
  710. * virtual and physical screens the same.
  711. */
  712. void update ()
  713. {
  714.     register    WINDOW * wp;
  715.     register    VIDEO * vp1;
  716.     register    VIDEO * vp2;
  717.     register uint    i;
  718.     register int    hflag;
  719.  
  720.     hflag = FALSE;              /* Not hard.            */
  721.     wp = wheadp;
  722.     while (wp != NULL)
  723.     {
  724.         /* is this window to be displayed in linked mode */
  725.         if ((curbp -> b_flag & BFLINK) &&
  726.             (wp -> w_bufp == curbp))
  727.         {                   /* move dot to current window's dot position */
  728.             wp -> w_dotp = curwp -> w_dotp;
  729.             wp -> w_doto = curwp -> w_doto;
  730.             move_ptr (wp, 0L, TRUE, TRUE, TRUE); /* insure dot is aligned */
  731.             wind_on_dot (wp);   /* move window to new dot position */
  732.         }
  733.  
  734.         if (wp -> w_flag != 0)
  735.  
  736.         {                   /* Need update.         */
  737.             move_ptr (wp, 0L, FALSE, TRUE, TRUE); /* window on row boundary */
  738.             move_ptr (wp, 0L, TRUE, TRUE, TRUE); /* dot on unit boundary */
  739.             if ((wp -> w_flag & WFFORCE) == 0)
  740.             {
  741.                 wind_on_dot (wp);/* position window on dot */
  742.             }
  743.             i = get_currow (wp); /* Redo this one line, mabey.    */
  744.             if ((wp -> w_flag & ~WFMODE) == WFEDIT)
  745.             {
  746.                 vscreen[i] -> v_color = CTEXT;
  747.                 vscreen[i] -> v_flag |= (VFCHG | VFHBAD);
  748.                 vtmove (i, 0);
  749.                 vtputd (wp, i - wp -> w_toprow);/* print line to the screen */
  750.             }
  751.             else
  752.                 if ((wp -> w_flag & ~WFMODE) == WFMOVE)
  753.                 {
  754.                     while (i < wp -> w_toprow + wp -> w_ntrows)
  755.                     {
  756.                         /* paint entire window */
  757.                         vscreen[i] -> v_color = CTEXT;
  758.                         vscreen[i] -> v_flag |= (VFCHG | VFHBAD);
  759.                         vtmove (i, 0);
  760.                         /* print line to the screen */
  761.                         if (!vtputd (wp, i - wp -> w_toprow))
  762.                             vteeol ();
  763.                         ++i;
  764.                     }
  765.                 }
  766.                 else
  767.                     if ((wp -> w_flag & (WFEDIT | WFHARD)) != 0)
  768.                     {
  769.                         hflag = TRUE;
  770.                         i = wp -> w_toprow;
  771.                         while (i < wp -> w_toprow + wp -> w_ntrows)
  772.                         {
  773.                             /* paint entire window */
  774.                             vscreen[i] -> v_color = CTEXT;
  775.                             vscreen[i] -> v_flag |= (VFCHG | VFHBAD);
  776.                             vtmove (i, 0);
  777.                             /* print line to the screen */
  778.                             if (!vtputd (wp, i - wp -> w_toprow))
  779.                                 vteeol ();
  780.                             ++i;
  781.                         }
  782.                     }
  783.             if ((wp -> w_flag & WFMODE) ||
  784.                 (wp -> w_flag & WFMOVE) ||
  785.                 (wp -> w_flag & WFHARD))
  786.                 modeline (wp);
  787.             wp -> w_flag = 0;
  788.         }
  789.         wp = wp -> w_wndp;
  790.     }
  791.     if (sgarbf != FALSE)
  792.     {                       /* Screen is garbage.   */
  793.         sgarbf = FALSE;         /* Erase-page clears    */
  794.         epresf = FALSE;         /* the message area.    */
  795.         tttop = HUGE;           /* Forget where you set */
  796.         ttbot = HUGE;           /* scroll region.       */
  797.         tthue = CNONE;          /* Color unknown.       */
  798.         ttmove (0, 0);
  799.         tteeop ();
  800. #if MSDOS
  801.         if (mem_map)
  802.         {
  803.             for (i = 0; i < nrow; ++i)
  804.             {
  805.                 mem_line (i, vscreen[i]);
  806.             }
  807.         }
  808.         else
  809.         {
  810. #endif
  811.             for (i = 0; i < nrow; ++i)
  812.             {
  813.                 uline (i, vscreen[i], &blanks);
  814.                 ucopy (vscreen[i], pscreen[i]);
  815.             }
  816. #if MSDOS
  817.         }
  818. #endif
  819.         ttmove (get_currow (curwp), get_curcol (curwp));
  820.         ttflush ();
  821.         return;
  822.     }
  823.     for (i = 0; i < nrow; ++i)
  824.     {                       /* Easy update.         */
  825.         vp1 = vscreen[i];
  826.         vp2 = pscreen[i];
  827.         if ((vp1 -> v_flag & VFCHG) != 0)
  828.         {
  829. #if MSDOS
  830.             if (mem_map)
  831.                 mem_line (i, vp1);
  832.             else
  833. #endif
  834.                 {
  835.                     uline (i, vp1, vp2);
  836.                     ucopy (vp1, vp2);
  837.                 }
  838.         }
  839.     }
  840.     ttmove (get_currow (curwp), get_curcol (curwp));
  841.     ttflush ();
  842. }
  843. /*
  844. *   Get the window relative row in which the cursor will
  845. *   appear. pvr
  846. */
  847. uint    get_currow (wp)
  848. WINDOW * wp;
  849. {
  850.     A32    row;
  851.     /* number of bytes from start of window */
  852.     row = DOT_POS(wp) - WIND_POS(wp);
  853.     /* number of rows down in window */
  854.     row /= R_BYTES(wp);
  855.     row += wp -> w_toprow;
  856. #if RUNCHK
  857.     if (row < wp -> w_toprow)
  858.         printf (ERR_disp_3);
  859.     if (row > (wp -> w_ntrows + wp -> w_toprow))
  860.         printf (ERR_disp_4);
  861. #endif
  862.     return (row & 0xffff);
  863. }
  864.  
  865. /*
  866. *   Get the window relative column in which the cursor will
  867. *   appear. pvr
  868. */
  869. uint    get_curcol (wp)
  870. WINDOW * wp;
  871. {
  872.     long    offset,
  873.     index;
  874.     uint    b_per_u, pos;
  875.  
  876.     b_per_u = R_B_PER_U(wp);
  877.     /* dot offset from start of buffer */
  878.     offset = DOT_POS(wp);
  879.     offset -= wp -> w_disp_shift;
  880.     offset &= ~(b_per_u - 1);
  881.     /* calculate mod of the current file position */
  882.     index = offset & (R_BYTES(wp) - 1);
  883.     index /= b_per_u;
  884.     /* limit to window width */
  885.     if (index >= NCOL)
  886.         index = NCOL;
  887.     pos = wp -> w_fmt_ptr -> r_positions[index] + wp -> w_unit_offset;
  888.     return (pos);
  889. }
  890. #if MSDOS
  891. void    mem_line (row, vvp)
  892. int     row;
  893. VIDEO * vvp;
  894. {
  895.     vvp -> v_flag &= ~VFCHG;    /* Changes done.        */
  896.     ttcolor (vvp -> v_color);
  897.     putline (row + 1, 1, ncol, &vvp -> v_text[0]);
  898. }
  899. #endif
  900. /*
  901. * Update a saved copy of a line,
  902. * kept in a VIDEO structure. The "vvp" is
  903. * the one in the "vscreen". The "pvp" is the one
  904. * in the "pscreen". This is called to make the
  905. * virtual and physical screens the same when
  906. * display has done an update.
  907. */
  908. void ucopy (vvp, pvp)
  909. register    VIDEO * vvp;
  910. register    VIDEO * pvp;
  911. {
  912.     register int    i;
  913.  
  914.     vvp -> v_flag &= ~VFCHG;    /* Changes done.        */
  915.     pvp -> v_flag = vvp -> v_flag;/* Update model.        */
  916.     pvp -> v_hash = vvp -> v_hash;
  917.     pvp -> v_cost = vvp -> v_cost;
  918.     pvp -> v_color = vvp -> v_color;
  919.     for (i = 0; i < ncol; ++i)
  920.         pvp -> v_text[i] = vvp -> v_text[i];
  921. }
  922.  
  923. /*
  924. * Update a single line. This routine only
  925. * uses basic functionality (no insert and delete character,
  926. * but erase to end of line). The "vvp" points at the VIDEO
  927. * structure for the line on the virtual screen, and the "pvp"
  928. * is the same for the physical screen. Avoid erase to end of
  929. * line when updating CMODE color lines, because of the way that
  930. * reverse video works on most terminals.
  931. */
  932. void uline (row, vvp, pvp)
  933. int row;
  934. VIDEO * vvp;
  935. VIDEO * pvp;
  936. {
  937.     register char  *cp1;
  938.     register char  *cp2;
  939.     register char  *cp3;
  940.     register char  *cp4;
  941.     register char  *cp5;
  942.     register int    nbflag;
  943.  
  944.     if (vvp -> v_color != pvp -> v_color)
  945.     {                       /* Wrong color, do a    */
  946.         ttmove (row, 0);        /* full redraw.         */
  947.         ttcolor (vvp -> v_color);
  948.         cp1 = &vvp -> v_text[0];
  949.         cp2 = &vvp -> v_text[ncol];
  950.         while (cp1 != cp2)
  951.         {
  952.             ttputc (*cp1++);
  953.             ++ttcol;
  954.         }
  955.         return;
  956.     }
  957.     cp1 = &vvp -> v_text[0];    /* Compute left match.  */
  958.     cp2 = &pvp -> v_text[0];
  959.     while (cp1 != &vvp -> v_text[ncol] && cp1[0] == cp2[0])
  960.     {
  961.         ++cp1;
  962.         ++cp2;
  963.     }
  964.     if (cp1 == &vvp -> v_text[ncol])/* All equal.           */
  965.         return;
  966.     nbflag = FALSE;
  967.     cp3 = &vvp -> v_text[ncol]; /* Compute right match. */
  968.     cp4 = &pvp -> v_text[ncol];
  969.     while (cp3[-1] == cp4[-1])
  970.     {
  971.         --cp3;
  972.         --cp4;
  973.         if (cp3[0] != ' ')      /* Note non-blanks in   */
  974.             nbflag = TRUE;      /* the right match.     */
  975.     }
  976.     cp5 = cp3;                  /* Is erase good?       */
  977.     if (nbflag == FALSE && vvp -> v_color == CTEXT)
  978.     {
  979.         while (cp5 != cp1 && cp5[-1] == ' ')
  980.             --cp5;
  981.         /* Alcyon hack */
  982.         if ((int) (cp3 - cp5) <= tceeol)
  983.             cp5 = cp3;
  984.     }
  985.     /* Alcyon hack */
  986.     ttmove (row, (int) (cp1 - &vvp -> v_text[0]));
  987.     ttcolor (vvp -> v_color);
  988.     while (cp1 != cp5)
  989.     {
  990.         ttputc (*cp1++);
  991.         ++ttcol;
  992.     }
  993.     if (cp5 != cp3)             /* Do erase.            */
  994.         tteeol ();
  995. }
  996.  
  997. /*
  998. * Redisplay the mode line for
  999. * the window pointed to by the "wp".
  1000. * This is the only routine that has any idea
  1001. * of how the modeline is formatted. You can
  1002. * change the modeline format by hacking at
  1003. * this routine. Called by "update" any time
  1004. * there is a dirty window.
  1005. */
  1006.  
  1007. void modeline (wp)
  1008. register    WINDOW * wp;
  1009. {
  1010.     register char  *cp,
  1011.     mode,
  1012.     size,
  1013.     u_posn,
  1014.     *s;
  1015.     register char   c;
  1016.     register int    n;
  1017.     register    BUFFER * bp;
  1018.     register    A32 posn;
  1019.  
  1020.     static char posn_buf[30] =
  1021.     {
  1022.         0
  1023.     };                          /* krw */
  1024.  
  1025.     mode = wp -> w_fmt_ptr -> r_type;/* get type of format structure */
  1026.     size = wp -> w_fmt_ptr -> r_size;/* get size of format structure */
  1027.  
  1028.     n = wp -> w_toprow + wp -> w_ntrows;/* Location.            */
  1029.     vscreen[n] -> v_color = CMODE;/* Mode line color.     */
  1030.     vscreen[n] -> v_flag |= (VFCHG | VFHBAD);/* Recompute, display.  */
  1031.     vtmove (n, 0);              /* Seek to right line.  */
  1032.     bp = wp -> w_bufp;
  1033.  
  1034.     cp = MSG_prog_name;               /* Program name.  pvr    */
  1035.     n = 5;
  1036.     while ((c = *cp++) != 0)
  1037.     {
  1038.         vtputc (c);
  1039.         ++n;
  1040.     }
  1041.  
  1042.     if ((bp -> b_flag & BFBAD) != 0)/* "?" if trashed.      */
  1043.         vtputc ('?');
  1044.     else
  1045.         vtputc (' ');
  1046.  
  1047.     if ((bp -> b_flag & BFCHG) != 0)/* "*" if changed.      */
  1048.         vtputc ('*');
  1049.     else
  1050.         vtputc (' ');
  1051.  
  1052.     if (insert_mode)            /* "I" if insert mode  */
  1053.         vtputc ('I');
  1054.     else
  1055.         vtputc ('O');
  1056.  
  1057.     if (bp == blistp)
  1058.     {                       /* special list */
  1059.         cp = MSG_disp_b_lst;
  1060.         while ((c = *cp++) != 0)
  1061.         {
  1062.             vtputc (c);
  1063.             ++n;
  1064.         }
  1065.         goto pad;
  1066.     }
  1067.  
  1068.     /* Buffer name */
  1069.     vtputc (' ');
  1070.     ++n;
  1071.     cp = &bp -> b_bname[0];
  1072.     while ((c = *cp++) != 0)
  1073.     {
  1074.         vtputc (c);
  1075.         ++n;
  1076.     }
  1077.     while ((int) (cp - &bp -> b_bname[0]) < NBUFN)
  1078.     {
  1079.         vtputc (' ');
  1080.         n++;
  1081.         cp++;
  1082.     }
  1083.  
  1084.     /* File name.           */
  1085.     vtputc (' ');
  1086.     ++n;
  1087.     cp = MSG_file;
  1088.     while ((c = *cp++) != 0)
  1089.     {
  1090.         vtputc (c);
  1091.         ++n;
  1092.     }
  1093.     cp = &bp -> b_fname[0];
  1094.     while ((c = *cp++) != 0)
  1095.     {
  1096.         vtputc (c);
  1097.         ++n;
  1098.     }
  1099.     cp--;
  1100.     while ((int) (cp - &bp -> b_fname[0]) < NFILE)
  1101.     {
  1102.         vtputc (' ');
  1103.         n++;
  1104.         cp++;
  1105.     }
  1106.  
  1107.     if (bp -> b_flag & BFVIEW)
  1108.         s = MSG_RO;
  1109.     else if (bp -> b_flag & BFSLOCK)
  1110.         s = MSG_WL;
  1111.     else
  1112.         s = MSG_RW;
  1113.  
  1114.     while (*s)
  1115.     {                       /* krw */
  1116.         vtputc (*s++);
  1117.         ++n;
  1118.     }
  1119.  
  1120.     if (auto_update && !(bp -> b_flag & BFVIEW) && bp -> b_bname[0])/* jam */
  1121.         s = MSG_AU;
  1122.     else
  1123.         s = MSG_NOT_AU;
  1124.     for (; *s && n < NCOL;)
  1125.     {
  1126.         vtputc (*s++);
  1127.         ++n;
  1128.     }
  1129.  
  1130.     /* Insert current dot position into mode line. */
  1131.     posn = DOT_POS(wp);
  1132.     u_posn = R_CHR_PER_U(wp) - wp -> w_unit_offset - 1;
  1133.     if (u_posn < 0)
  1134.         u_posn = 0;
  1135.     switch (mode)
  1136.     {
  1137.     case TEXT:
  1138.     case ASCII:
  1139.         sprintf (posn_buf, MSG_curs_asc, posn);
  1140.         break;
  1141.     case EBCDIC:
  1142.         sprintf (posn_buf, MSG_curs_ebc, posn);
  1143.         break;
  1144.     case HEX:
  1145.         sprintf (posn_buf, MSG_curs_hex, posn, u_posn);
  1146.         break;
  1147.     case BINARY:
  1148.         sprintf (posn_buf, MSG_curs_bin, posn, u_posn);
  1149.         break;
  1150.     case DECIMAL:
  1151.         sprintf (posn_buf, MSG_curs_dec, posn, u_posn);
  1152.         break;
  1153.     case OCTAL:
  1154.         sprintf (posn_buf, MSG_curs_oct, posn, u_posn);
  1155.         break;
  1156. #if RUNCHK
  1157.     default:
  1158.         writ_echo (ERR_disp_5);
  1159.         break;
  1160. #endif
  1161.     }
  1162.  
  1163.     cp = posn_buf;
  1164.     while ((c = *cp++) != 0)
  1165.     {
  1166.         vtputc (c);
  1167.         ++n;
  1168.     }
  1169.  
  1170.  
  1171.     if ((mode == HEX) ||
  1172.         (mode == DECIMAL) ||
  1173.         (mode == OCTAL))
  1174.     {
  1175.         switch (size)
  1176.         {
  1177.         case BYTES:
  1178.             sprintf (posn_buf, MSG_siz_8);
  1179.             break;
  1180.         case WORDS:
  1181.             sprintf (posn_buf, MSG_siz_16);
  1182.             break;
  1183.         case DWORDS:
  1184.             sprintf (posn_buf, MSG_siz_32);
  1185.             break;
  1186. #if RUNCHK
  1187.         default:
  1188.             writ_echo (ERR_disp_6);
  1189.             break;
  1190. #endif
  1191.         }
  1192.     }
  1193.     else
  1194.         sprintf (posn_buf, MSG_siz_null);
  1195.  
  1196.     cp = posn_buf;
  1197.     while ((c = *cp++) != 0)
  1198.     {
  1199.         vtputc (c);
  1200.         ++n;
  1201.     }
  1202.  
  1203.     if (wp -> w_intel_mode)
  1204.         sprintf (posn_buf, MSG_int_shift, wp -> w_disp_shift);
  1205.     else
  1206.         sprintf (posn_buf, MSG_mot_shift, wp -> w_disp_shift);
  1207.     cp = posn_buf;
  1208.     while ((c = *cp++) != 0)
  1209.     {
  1210.         vtputc (c);
  1211.         ++n;
  1212.     }
  1213.  
  1214.  
  1215.     /* pad out */
  1216. pad:
  1217.     while (n < ncol)
  1218.     {
  1219.         vtputc (' ');
  1220.         ++n;
  1221.     }
  1222. }
  1223.  
  1224. /*
  1225. * write text to the echo line
  1226. */
  1227. void    writ_echo (buf)
  1228. char    *buf;
  1229. {
  1230.     int     i;
  1231.     char    *vpp;
  1232.     bool    fill_spac;
  1233.  
  1234.     fill_spac = FALSE;
  1235.     vpp = vscreen[nrow - 1] -> v_text;
  1236.     vscreen[nrow - 1] -> v_color = CTEXT;
  1237.     vscreen[nrow - 1] -> v_flag |= VFCHG;
  1238.     epresf = TRUE;
  1239.  
  1240.     for (i = 0; i < NCOL; i++)
  1241.     {
  1242.         if (buf[i] == 0)
  1243.             fill_spac = TRUE;
  1244.         if (fill_spac)
  1245.             vpp[i] = ' ';
  1246.         else
  1247.             vpp[i] = buf[i];
  1248.     }
  1249. #if MSDOS
  1250.     if (mem_map)
  1251.     {
  1252.         mem_line (nrow - 1, vscreen[nrow - 1]);
  1253.     }
  1254.     else
  1255. #endif
  1256.         {
  1257.             uline (nrow - 1, vscreen[nrow - 1], pscreen[nrow - 1]);
  1258.             uline (nrow - 1, vscreen[nrow - 1], &blanks);
  1259.             ucopy (vscreen[nrow - 1], pscreen[nrow - 1]);
  1260.             ttflush ();
  1261.         }
  1262. }
  1263.  
  1264. /*
  1265. * Print the current buffer from mark to dot using the
  1266. * current window's display format.
  1267. * Prompt for file name or io device to print to.
  1268. */
  1269.  
  1270. bool    print ()
  1271. {
  1272.     LINE    *dot_l_sav, *mark_l_sav, *wind_l_sav;
  1273.     int     dot_off_sav, mark_off_sav, wind_off_sav, i;
  1274.     char   s;
  1275.     char    fname[NFILEN];
  1276.     register int    nline;
  1277.     char    buf[NFILEN], buf1[NFILEN];
  1278.  
  1279.     /* save the original window state */
  1280.     dot_l_sav = curwp -> w_dotp;
  1281.     dot_off_sav = curwp -> w_doto;
  1282.     mark_l_sav = curwp -> w_markp;
  1283.     mark_off_sav = curwp -> w_marko;
  1284.     wind_l_sav = curwp -> w_linep;
  1285.     wind_off_sav = curwp -> w_loff;
  1286.  
  1287.     /* if mark is not set then set it to location zero */
  1288.     if (curwp -> w_markp == NULL)
  1289.     {
  1290.         curwp -> w_markp = curwp -> w_bufp -> b_linep -> l_fp;
  1291.         curwp -> w_marko = 0;
  1292.     }
  1293.  
  1294.     nline = 0;
  1295.     if ((s = ereply (MSG_prn_to, fname, NFILEN, NULL)) == ABORT)
  1296.         return (s);
  1297.     adjustcase (fname);
  1298.     if ((s = ffwopen (fname, S_IREAD | S_IWRITE)) != FIOSUC)/* Open writes message. */
  1299.         return (FALSE);
  1300.  
  1301.     sprintf (buf, MSG_print1, fname);
  1302.     writ_echo (buf);
  1303.     /* make dot before mark */
  1304.     if (DOT_POS(curwp) > MARK_POS(curwp))
  1305.         swapmark ();    /* make mark first */
  1306.  
  1307.     while (DOT_POS(curwp) <= MARK_POS(curwp))
  1308.     {
  1309.         /* check if we should quit */
  1310.         if (ttkeyready ())
  1311.         {
  1312.             if (ttgetc () == CTL_G)   /* quit if abort was hit */
  1313.                 break;
  1314.         }
  1315.         nline++;
  1316.         /* move window so that first line is on dot */
  1317.         move_ptr (curwp, DOT_POS(curwp), FALSE, TRUE, FALSE);
  1318.  
  1319.         if (vtputd (curwp, 0))   /* print line into video buffer */
  1320.         {
  1321.             for (i = NCOL; (vscreen[vtrow] -> v_text[i] < '!') ||
  1322.                 (vscreen[vtrow] -> v_text[i] > '~'); i--)
  1323.                 ;
  1324.             i++;
  1325.             if ((s = ffputline (vscreen[vtrow] -> v_text, i)) != FIOSUC)
  1326.                 break;
  1327.             if ((s = ffputline (MSG_disp_r_n, 2)) != FIOSUC)
  1328.                 break;
  1329.         }
  1330.         else
  1331.             break;
  1332.         forwline (0, 1, KRANDOM);   /* advance to next line */
  1333.     }
  1334.     ffclose ();
  1335.     sprintf (buf1, MSG_print2, R_POS_FMT(curwp));
  1336.     sprintf (buf, buf1, (long) nline);
  1337.     writ_echo (buf);
  1338.  
  1339.     /* restore the original window state */
  1340.     curwp -> w_dotp = dot_l_sav;
  1341.     curwp -> w_doto = dot_off_sav;
  1342.     curwp -> w_markp = mark_l_sav;
  1343.     curwp -> w_marko = mark_off_sav;
  1344.     curwp -> w_linep = wind_l_sav;
  1345.     curwp -> w_loff = wind_off_sav;
  1346.     curwp -> w_flag |= WFHARD;  /* insure that window is still presentable */
  1347.     return (TRUE);
  1348. }
  1349.