Logo Search packages:      
Sourcecode: beav version File versions  Download package

display.c

/*
* 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.  The MEMMAP
* changes things around for memory mapped video. With
* both off, the terminal is a VT52.
*/

#include    <sys/types.h>
#include    <sys/stat.h>
#include    "def.h"

D64 get_double ();
D32 get_long ();
D16 get_int ();
void writ_echo ();
void modeline ();
void bin_to_text ();
uint fill_buf ();
uint get_currow ();
uint get_curcol ();
#ifndef NOPROTO
struct vid;
void ucopy (struct vid *vvp, struct vid *pvp);
void uline (int row, struct vid *vvp, struct vid *pvp);
#else
void uline ();
void ucopy ();
#endif
#if MSDOS
void mem_line (int row, struct vid *vvp);
#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_116e[];
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_flt[];
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[];
extern char MSG_cnt_al_w[];
#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

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.            */
    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;        /* Edge vector, virtual.            */
VIDEO **pscreen;        /* Edge vector, physical.        */
VIDEO *video;                 /* Actual screen data.          */
VIDEO blanks;                 /* Blank line image.                */

/*
* 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;

    /* allocate memory for screen images */
    if (((vscreen = (VIDEO **) malloc (sizeof (VIDEO *) * nrow)) == NULL) ||
      ((pscreen = (VIDEO **) malloc (sizeof (VIDEO *) * nrow)) == NULL) ||
      ((video = (VIDEO *) malloc (sizeof (VIDEO) * 2 * nrow)) == NULL))
    {
      err_echo (MSG_cnt_al_w);
      exit (1);         /* can't continue */
    }

    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] = ' ';
}

/*
*     Free memory used by the screen buffers
*/
void
vtfree ()
{
    /* release old screen memory */
    free (video);
    free (pscreen);
    free (vscreen);
}

/*
* 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)
    int 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 char c;
{
    register VIDEO *vp;

    vp = vscreen[vtrow];
    if (vtcol >= ncol)
      vp->v_text[ncol - 1] = '$';
    else if (ISCTRL (c) != FALSE)
    {
      vtputc ('^');
      vtputc ((char) (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 uchar mode;
    REGI A32 row_offst;
    REGI uint chrs_per_row, lin_offset, i, chrs_in_lin;
    LINE *cur_line;
    static char w_buf[128];   /* temp buffer for data */

    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;
#if   FLOAT_DISP
    case FLOAT:
#endif
    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;
#if   FLOAT_DISP
    case FLOAT:
      {
          /*
            *     The Intel floating point representation is;
            *           bit 0  - 52       significand (53 bits)
            *           bit 53 - 62       biased exponent (11 bits)
            *           bit   63                sign
            *     maximum range;    10^-308 <= X <= 10^+308
            *     obviously, not all patterns are legal floating point numbers.
            *     There can be up to 16 decimal digits of significand.
            *     There are only 3 decimal digits of exponent (308 max).
            */
          k = 0;
          for (i = 0; i < len; i += sizeof (D64))
          {
            D64 temp_d;

            temp_d = get_double (&bin_buf[i]);
            sprintf (&txt_buf[posn[k++]], MSG_116e, temp_d);
          }
      }
      break;
#endif
    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 = temp_int << 8;
      temp_int |= 0xff & w_buf[0];
    }
    else
    {
      temp_int = 0xff & w_buf[0];
      temp_int = 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 = temp_long << 8;
      temp_long |= 0xff & w_buf[2];
      temp_long = temp_long << 8;
      temp_long |= 0xff & w_buf[1];
      temp_long = temp_long << 8;
      temp_long |= 0xff & w_buf[0];
    }
    else
    {
      temp_long = 0xff & w_buf[0];
      temp_long = temp_long << 8;
      temp_long |= 0xff & w_buf[1];
      temp_long = temp_long << 8;
      temp_long |= 0xff & w_buf[2];
      temp_long = temp_long << 8;
      temp_long |= 0xff & w_buf[3];
    }
    return (temp_long);
}

#if   FLOAT_DISP
/*
*   Get an double from the buffer.
*   Perform the Intel byte shuffle if necessary
*/

D64
get_double (w_buf)
    uchar *w_buf;
{
    uchar temp_doub[sizeof (D64)];
    D64 *dp;
    int i, siz;

    dp = (D64 *) temp_doub;
    siz = sizeof (D64);

    if (curwp->w_intel_mode)
    {
      for (i = 0; i <= siz - 1; i++)
      {
          temp_doub[i] = 0xff & w_buf[i];
      }
    }
    else
    {
      for (i = 0; i <= 7; i++)
      {
          temp_doub[(siz - 1) - i] = 0xff & w_buf[i];
      }
    }
    return (*dp);
}

#endif

/*
*   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 (wp) == 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 WINDOW *wp;
    register VIDEO *vp1;
    register VIDEO *vp2;
    register uint i;
    register int hflag;

    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;
    }
    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_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)
    int row;
    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, size, u_posn, *s;
    uchar mode;
    register char 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;
#if   FLOAT_DISP
    case FLOAT:
#endif
      sprintf (posn_buf, MSG_curs_flt, 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;
    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 ();
    }
}

/*
* 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[NFILEN], buf1[NFILEN];

    /* 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, S_IREAD | S_IWRITE)) != 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 ())
      {
          if (ttgetc () == CTL_G)   /* quit if abort was hit */
            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);
}

Generated by  Doxygen 1.6.0   Back to index