home *** CD-ROM | disk | FTP | other *** search
- /*
- * 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[];
-
- #include "lintfunc.dec"
-
- 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 n;
- {
- 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 n;
- {
- 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 at last byte of buffer then do not step */
- if (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, *line_guess;
- int *l_off;
- char shift;
- bool no_limit;
-
- no_limit = TRUE;
- if (dot)
- { /* move dot position */
- l_off = &wp -> w_doto;
- line = &wp -> w_dotp;
- align = R_SIZE(wp); /* bytes -1 in a unit */
- }
- else
- { /* move window position */
- l_off = &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 (dest_pos < 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 ()
- {
- long f_off;
- long index;
-
- 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)
- {
- 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)
- {
- 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)
- register int n;
- {
- 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)
- register int n;
- {
- 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)
- {
- 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:
- 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);
- }
-
-