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

basic.c

/*
*      Basic cursor motion commands.
* The routines in this file are the basic
* command functions for moving the cursor around on
* the screen, setting mark, and swapping dot with
* mark. Only moves between lines, which might make the
* current buffer framing bad, are hard.
*/

#include    "def.h"

bool move_ptr ();
bool forwchar ();
bool wind_on_dot ();
bool backline ();

extern char MSG_mark_set[];
extern char MSG_no_mark[];
extern char MSG_go_b_n[];
extern char MSG_bad_num[];
#if RUNCHK
extern char ERR_bas_1[];
#endif
extern char MSG_lX[];
extern char MSG_lO[];
extern char MSG_lD[];


extern bool rplc_mode;

/*  pvr
* Move cursor backwards. Do the
* right thing if the count is less than
* 0. Error if you try to move back from
* the beginning of the buffer.
*/
bool
backchar (f, n, k)
    register int f, n, k;
{
    if (n < 0)
      return (forwchar (f, -n, KRANDOM));

    while (n--)
    {
      if (curwp->w_unit_offset == 0)
      {
          if (!move_ptr (curwp, -(long) R_B_PER_U (curwp),
                     TRUE, TRUE, TRUE))
            return (FALSE);

          /* step to previous unit */
          curwp->w_unit_offset = R_CHR_PER_U (curwp) - 1;

          /* if before first line in window then move window */
          wind_on_dot (curwp);
      }
      else
          curwp->w_unit_offset--;
    }
    curwp->w_flag |= WFMODE;  /* update mode line */
    return (TRUE);
}

/*  pvr
* Move cursor forwards. Do the
* right thing if the count is less than
* 0. Error if you try to move forward
* from the end of the buffer.
*/
bool
forwchar (f, n, k)
    register int f, n, k;
{
    if (n < 0)
      return (backchar (f, -n, KRANDOM));

    curwp->w_flag |= WFMODE;  /* update mode line */
    while (n--)
    {
      if (curwp->w_unit_offset >= (R_CHR_PER_U (curwp) - 1))
      {
          /* move to the mext unit */
          curwp->w_unit_offset = 0;

          if (!move_ptr (curwp, (long) R_B_PER_U (curwp),
                     TRUE, TRUE, TRUE))
          {
            /* I am at the the end of the buffer */
            return (FALSE);
          }

          /* if after the last line in window then move window */
          wind_on_dot (curwp);
      }
      else if                 /* if at last byte of buffer then do not step  */
          (DOT_POS (curwp) < BUF_SIZE (curwp))
          curwp->w_unit_offset++;   /* step within unit */
    }
    return (TRUE);
}

/*  pvr
*   This function moves the specified pointer by the ammount specified
*   in 'len'.   Move the dot pointer is 'dot' is true, else move
*   the window pointer.  Do the fix up if 'fix' is TRUE.
*   This is a relative move if 'rel' is TRUE, else it is an
*   absolute move.
*/

bool
move_ptr (wp, len, dot, fix, rel)
    WINDOW *wp;
    long len;
    bool dot, fix, rel;
{
    A32 cur_pos, dest_pos, fix_val, last_pos;
    long rel_pos;
    A32 last_fixed_pos, align;
    LINE **line;
    int *l_off;
    char shift;
    bool no_limit;

    no_limit = TRUE;
    if (dot)
    {                   /* move dot position */
      l_off = (int *) &wp->w_doto;
      line = &wp->w_dotp;
      align = R_SIZE (wp);    /* bytes -1 in a unit */
    }
    else
    {                   /* move window position */
      l_off = (int *) &wp->w_loff;
      line = &wp->w_linep;
      align = R_ALIGN (wp) - 1;     /* interval of bytes to align window */
    }

    /* get the current position in the buffer */
    cur_pos = (*line)->l_file_offset + *l_off;

    if (rel)
    {
      rel_pos = len;
      dest_pos = len + cur_pos;     /* destination position */
    }
    else
    {
      rel_pos = len - cur_pos;/* relative move amount */
      dest_pos = len;         /* destination position */
    }
    if (fix)
    {
      shift = wp->w_disp_shift;

      /* limit at begining */
      if ((long) dest_pos < (long) shift)
      {
          rel_pos = shift - cur_pos;
          no_limit = FALSE;
      }
      else
      {
          /* calculate fixed up destination position */
          fix_val = dest_pos &= ~align;
          fix_val += shift;

          /* calculate the last position in the buffer */
          last_pos = BUF_SIZE (wp);
          if (last_pos < (last_fixed_pos = (last_pos & ~align) + shift))
            last_pos = last_fixed_pos - align - 1;

          /* if we are going to limit at the end of the buffer */
          if (last_pos < fix_val)
          {
            fix_val = last_pos;
            no_limit = FALSE;
          }
          rel_pos = fix_val - cur_pos;
      }
    }
    while (TRUE)
    {
      if (rel_pos < 0)  /* move  backward through buffer */
      {
          /* current line? */
          if (*l_off + rel_pos >= 0)
          {
            *l_off += (short) rel_pos;
            return (no_limit);
          }
          /* are we at the first line */
          if ((*line)->l_bp->l_size != 0)
          {             /* no, so step back */
            rel_pos += *l_off;
            (*line) = (*line)->l_bp;      /* move back one line */
            *l_off = (*line)->l_used;
          }
          else
          {             /* yes, limit at the begining */
            *l_off = 0;
            return (FALSE);
          }
      }
      else
          /* move forward through buffer */
      {
          /* is in current line? */
          if (((A32) (*l_off) + rel_pos) < ((A32) ((*line)->l_used)))
          {
            *l_off += (short) rel_pos;
            return (no_limit);
          }
          if ((*line)->l_fp->l_size != 0)
          {
            rel_pos -= (*line)->l_used - *l_off;
            *l_off = 0;
            (*line) = (*line)->l_fp;      /* move forward one line */
          }
          else
          {
            *l_off = (*line)->l_used;     /* at last line so limit it */
            return (FALSE);
          }
      }
    }
}

/*  pvr
*   Move the window so that the dot is within it's
*   area.   Return TRUE if window was moved.
*/

bool
wind_on_dot (wp)

    WINDOW *wp;
{
    long diff, incr;
    A32 d_offs, w_start, bytes, align;

    /* number of bytes in a row */
    bytes = R_BYTES (wp);
    /* number of bytes to align on */
    align = R_ALIGN (wp);
    /* offset of window from start of the buffer */
    w_start = WIND_POS (wp);
    /* offset of dot from start of the buffer */
    d_offs = DOT_POS (wp);
    /* calculate the amount to move that is 1/3 of the window */
    incr = bytes * wp->w_ntrows / 3;
    /* if dot is before first line in window */
    if ((diff = (d_offs - w_start)) < 0)  /* diff used later */
    {
      move_ptr (wp, diff - incr, FALSE, TRUE, TRUE);
      wp->w_flag |= WFHARD;
      return (TRUE);
    }
    /* if dot is after the last line in window */
    if (0 < (diff -= (wp->w_ntrows * bytes - 1)))
    {
      if (align != 1)
          diff = (diff & ~(align - 1)) + align;
      move_ptr (wp, diff + incr, FALSE, TRUE, TRUE);
      wp->w_flag |= WFHARD;
      return (TRUE);
    }
    /* is window aligned? */
    if (w_start != ((w_start & ~(align - 1)) + wp->w_disp_shift))
    {                   /* if no then move into alignment */
      move_ptr (wp, 0L, FALSE, TRUE, TRUE);
      wp->w_flag |= WFHARD;
      return (TRUE);
    }
    return (FALSE);
}

/*  pvr
* Go to the beginning of the
* buffer. Setting WFHARD is conservative,
* but almost always the case.
*/
bool
gotobob ()
{
    move_ptr (curwp, 0L, TRUE, TRUE, FALSE);    /* move dot */
    move_ptr (curwp, 0L, FALSE, TRUE, FALSE);   /* move window */
    curwp->w_unit_offset = 0;
    curwp->w_flag |= WFHARD;
    return (TRUE);
}

/*  pvr
* Go to the end of the buffer.
* Setting WFHARD is conservative, but
* almost always the case.
* Dot is one byte past the end of the buffer.
*/
bool
gotoeob ()
{
    move_ptr (curwp, BUF_SIZE (curwp), TRUE, TRUE, FALSE);  /* move dot */
    curwp->w_unit_offset = 0;
    wind_on_dot (curwp);
    return (TRUE);
}

/*  pvr
* Move forward by full lines.
* If the number of lines to move is less
* than zero, call the backward line function to
* actually do it. The last command controls how
* the goal column is set.
*/
bool
forwline (f, n, k)
    int f, n, k;
{
    if (n < 0)
      return (backline (f, -n, KRANDOM));

    if (rplc_mode)
    {
      next_pat ();
    }
    else
    {
      /* move dot */
      if (!move_ptr (curwp, (long) R_BYTES (curwp) * n,
                   TRUE, TRUE, TRUE))
          curwp->w_unit_offset = 0;
      wind_on_dot (curwp);
      curwp->w_flag |= WFMODE;/* update mode line */
    }
    return (TRUE);
}

/*  pvr
* This function is like "forwline", but
* goes backwards. The scheme is exactly the same.
* Check for arguments that are less than zero and
* call your alternate. Figure out the new line and
* call "movedot" to perform the motion.
*/
bool
backline (f, n, k)
    int f, n, k;
{
    if (n < 0)
      return (forwline (f, -n, KRANDOM));

    if (rplc_mode)
    {
      next_pat ();
    }
    else
    {
      if (!move_ptr (curwp, -((long) (R_BYTES (curwp) * n)),
                   TRUE, TRUE, TRUE))
          curwp->w_unit_offset = 0;

      /* is dot before the top of window? */
      wind_on_dot (curwp);
      curwp->w_flag |= WFMODE;/* update mode line */
    }
    return (TRUE);
}

/*  pvr
* Scroll forward by a specified number
* of lines, or by a full page if no argument.
* (KRW) Added cursor (dot) weighting to force cursor
*       to same position on new page.
*/
bool
forwpage (f, n, k)
    int f, n, k;
{
    long mov_lines;

    if (rplc_mode)
      next_pat ();
    else
    {
      if (curwp->w_ntrows <= 2)
          mov_lines = 2;
      else
          mov_lines = curwp->w_ntrows - 2;

      /* check if last line is already displayed */
      if (WIND_POS (curwp) + (R_BYTES (curwp) * curwp->w_ntrows) <
          curwp->w_bufp->b_linep->l_bp->l_file_offset +
          curwp->w_bufp->b_linep->l_bp->l_used)
      {
          move_ptr (curwp, (long) (R_BYTES (curwp) * mov_lines),
                  FALSE, TRUE, TRUE);
      }
      /* move dot by same amount */
      if (!move_ptr (curwp, (long) (R_BYTES (curwp) * mov_lines),
                   TRUE, TRUE, TRUE))
          curwp->w_unit_offset = 0;

      curwp->w_flag |= WFHARD;
    }
    return (TRUE);
}

/*  pvr
* This command is like "forwpage",
* but it goes backwards.
*/
bool
backpage (f, n, k)
    int f, n, k;
{
    long mov_lines;

    if (rplc_mode)
      next_pat ();
    else
    {
      if (curwp->w_ntrows <= 2)
          mov_lines = 2;
      else
          mov_lines = curwp->w_ntrows - 2;

      /* move window */
      move_ptr (curwp, -(long) (R_BYTES (curwp) * mov_lines),
              FALSE, TRUE, TRUE);
      /* move dot by same amount */
      if (!move_ptr (curwp, -(long) (R_BYTES (curwp) * mov_lines),
                   TRUE, TRUE, TRUE))
          curwp->w_unit_offset = 0;

      curwp->w_flag |= WFHARD;
    }
    return (TRUE);
}

/*
* Set the mark in the current window
* to the value of dot. A message is written to
* the echo line unless we are running in a keyboard
* macro, when it would be silly.
*/
bool
setmark ()
{

    if (curbp == blistp)      /* jam - hack to do goto/kill */
      pickone ();
    else
    {
      curwp->w_markp = curwp->w_dotp;
      curwp->w_marko = curwp->w_doto;
      if (kbdmop == NULL)
      {
          writ_echo (MSG_mark_set);
      }
    }
    return (TRUE);
}

/*  pvr
* Swap the values of "dot" and "mark" in
* the current window. This is pretty easy, because
* all of the hard work gets done by the standard routine
* that moves the mark about. The only possible
* error is "no mark".
*/
bool
swapmark ()
{
    register short odoto;
    register LINE *odotp;

    if (curwp->w_markp == NULL)
    {
      writ_echo (MSG_no_mark);
      return (FALSE);
    }

    odotp = curwp->w_dotp;
    curwp->w_dotp = curwp->w_markp;
    curwp->w_markp = odotp;
    odoto = curwp->w_doto;
    curwp->w_doto = curwp->w_marko;
    curwp->w_marko = odoto;
    wind_on_dot (curwp);
    curwp->w_flag |= WFMODE;  /* update mode line */
    return (TRUE);
}

/*  pvr
* Go to a specific byte position in buffer.
* If an argument is present, then
* it is the byte number, else prompt for a byte number
* to use.
*/
bool
gotoline (f, n, k)
    int f, n, k;
{
    A32 index;
    register int s;
    char buf[32];

    if (f == FALSE)
    {

      if ((s = ereply (MSG_go_b_n, buf, sizeof (buf), 0) != TRUE))
          return (s);
      switch (R_TYPE (curwp))
      {
      case TEXT:
      case ASCII:
      case EBCDIC:
      case BINARY:
      case HEX:
          sscanf (buf, MSG_lX, &index);
          break;
      case OCTAL:
          sscanf (buf, MSG_lO, &index);
          break;
      case DECIMAL:
#if   FLOAT_DISP
      case FLOAT:
#endif
          sscanf (buf, MSG_lD, &index);
          break;
#if RUNCHK
      default:
          writ_echo (ERR_bas_1);
          break;
#endif
      }
    }

    if (n <= 0)
    {
      writ_echo (MSG_bad_num);
      return (FALSE);
    }

    move_ptr (curwp, index, TRUE, TRUE, FALSE);
    curwp->w_unit_offset = 0;

    curwp->w_flag |= WFMODE;  /* update mode line */

    wind_on_dot (curwp);
    return (TRUE);
}

Generated by  Doxygen 1.6.0   Back to index