summaryrefslogtreecommitdiffstats
path: root/contrib/nvi/vi/v_mark.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/nvi/vi/v_mark.c')
-rw-r--r--contrib/nvi/vi/v_mark.c234
1 files changed, 234 insertions, 0 deletions
diff --git a/contrib/nvi/vi/v_mark.c b/contrib/nvi/vi/v_mark.c
new file mode 100644
index 0000000..447430e
--- /dev/null
+++ b/contrib/nvi/vi/v_mark.c
@@ -0,0 +1,234 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ * Keith Bostic. All rights reserved.
+ *
+ * See the LICENSE file for redistribution information.
+ */
+
+#include "config.h"
+
+#ifndef lint
+static const char sccsid[] = "@(#)v_mark.c 10.8 (Berkeley) 9/20/96";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/time.h>
+
+#include <bitstring.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "../common/common.h"
+#include "vi.h"
+
+/*
+ * v_mark -- m[a-z]
+ * Set a mark.
+ *
+ * PUBLIC: int v_mark __P((SCR *, VICMD *));
+ */
+int
+v_mark(sp, vp)
+ SCR *sp;
+ VICMD *vp;
+{
+ return (mark_set(sp, vp->character, &vp->m_start, 1));
+}
+
+enum which {BQMARK, FQMARK};
+static int mark __P((SCR *, VICMD *, enum which));
+
+
+/*
+ * v_bmark -- `['`a-z]
+ * Move to a mark.
+ *
+ * Moves to a mark, setting both row and column.
+ *
+ * !!!
+ * Although not commonly known, the "'`" and "'`" forms are historically
+ * valid. The behavior is determined by the first character, so "`'" is
+ * the same as "``". Remember this fact -- you'll be amazed at how many
+ * people don't know it and will be delighted that you are able to tell
+ * them.
+ *
+ * PUBLIC: int v_bmark __P((SCR *, VICMD *));
+ */
+int
+v_bmark(sp, vp)
+ SCR *sp;
+ VICMD *vp;
+{
+ return (mark(sp, vp, BQMARK));
+}
+
+/*
+ * v_fmark -- '['`a-z]
+ * Move to a mark.
+ *
+ * Move to the first nonblank character of the line containing the mark.
+ *
+ * PUBLIC: int v_fmark __P((SCR *, VICMD *));
+ */
+int
+v_fmark(sp, vp)
+ SCR *sp;
+ VICMD *vp;
+{
+ return (mark(sp, vp, FQMARK));
+}
+
+/*
+ * mark --
+ * Mark commands.
+ */
+static int
+mark(sp, vp, cmd)
+ SCR *sp;
+ VICMD *vp;
+ enum which cmd;
+{
+ dir_t dir;
+ MARK m;
+ size_t len;
+
+ if (mark_get(sp, vp->character, &vp->m_stop, M_BERR))
+ return (1);
+
+ /*
+ * !!!
+ * Historically, BQMARKS for character positions that no longer
+ * existed acted as FQMARKS.
+ *
+ * FQMARKS move to the first non-blank.
+ */
+ switch (cmd) {
+ case BQMARK:
+ if (db_get(sp, vp->m_stop.lno, DBG_FATAL, NULL, &len))
+ return (1);
+ if (vp->m_stop.cno < len ||
+ vp->m_stop.cno == len && len == 0)
+ break;
+
+ if (ISMOTION(vp))
+ F_SET(vp, VM_LMODE);
+ cmd = FQMARK;
+ /* FALLTHROUGH */
+ case FQMARK:
+ vp->m_stop.cno = 0;
+ if (nonblank(sp, vp->m_stop.lno, &vp->m_stop.cno))
+ return (1);
+ break;
+ default:
+ abort();
+ }
+
+ /* Non-motion commands move to the end of the range. */
+ if (!ISMOTION(vp)) {
+ vp->m_final = vp->m_stop;
+ return (0);
+ }
+
+ /*
+ * !!!
+ * If a motion component to a BQMARK, the cursor has to move.
+ */
+ if (cmd == BQMARK &&
+ vp->m_stop.lno == vp->m_start.lno &&
+ vp->m_stop.cno == vp->m_start.cno) {
+ v_nomove(sp);
+ return (1);
+ }
+
+ /*
+ * If the motion is in the reverse direction, switch the start and
+ * stop MARK's so that it's in a forward direction. (There's no
+ * reason for this other than to make the tests below easier. The
+ * code in vi.c:vi() would have done the switch.) Both forward
+ * and backward motions can happen for any kind of search command.
+ */
+ if (vp->m_start.lno > vp->m_stop.lno ||
+ vp->m_start.lno == vp->m_stop.lno &&
+ vp->m_start.cno > vp->m_stop.cno) {
+ m = vp->m_start;
+ vp->m_start = vp->m_stop;
+ vp->m_stop = m;
+ dir = BACKWARD;
+ } else
+ dir = FORWARD;
+
+ /*
+ * Yank cursor motion, when associated with marks as motion commands,
+ * historically behaved as follows:
+ *
+ * ` motion ' motion
+ * Line change? Line change?
+ * Y N Y N
+ * -------------- ---------------
+ * FORWARD: | NM NM | NM NM
+ * | |
+ * BACKWARD: | M M | M NM(1)
+ *
+ * where NM means the cursor didn't move, and M means the cursor
+ * moved to the mark.
+ *
+ * As the cursor was usually moved for yank commands associated
+ * with backward motions, this implementation regularizes it by
+ * changing the NM at position (1) to be an M. This makes mark
+ * motions match search motions, which is probably A Good Thing.
+ *
+ * Delete cursor motion was always to the start of the text region,
+ * regardless. Ignore other motion commands.
+ */
+#ifdef HISTORICAL_PRACTICE
+ if (ISCMD(vp->rkp, 'y')) {
+ if ((cmd == BQMARK ||
+ cmd == FQMARK && vp->m_start.lno != vp->m_stop.lno) &&
+ (vp->m_start.lno > vp->m_stop.lno ||
+ vp->m_start.lno == vp->m_stop.lno &&
+ vp->m_start.cno > vp->m_stop.cno))
+ vp->m_final = vp->m_stop;
+ } else if (ISCMD(vp->rkp, 'd'))
+ if (vp->m_start.lno > vp->m_stop.lno ||
+ vp->m_start.lno == vp->m_stop.lno &&
+ vp->m_start.cno > vp->m_stop.cno)
+ vp->m_final = vp->m_stop;
+#else
+ vp->m_final = vp->m_start;
+#endif
+
+ /*
+ * Forward marks are always line oriented, and it's set in the
+ * vcmd.c table.
+ */
+ if (cmd == FQMARK)
+ return (0);
+
+ /*
+ * BQMARK'S moving backward and starting at column 0, and ones moving
+ * forward and ending at column 0 are corrected to the last column of
+ * the previous line. Otherwise, adjust the starting/ending point to
+ * the character before the current one (this is safe because we know
+ * the search had to move to succeed).
+ *
+ * Mark motions become line mode opertions if they start at the first
+ * nonblank and end at column 0 of another line.
+ */
+ if (vp->m_start.lno < vp->m_stop.lno && vp->m_stop.cno == 0) {
+ if (db_get(sp, --vp->m_stop.lno, DBG_FATAL, NULL, &len))
+ return (1);
+ vp->m_stop.cno = len ? len - 1 : 0;
+ len = 0;
+ if (nonblank(sp, vp->m_start.lno, &len))
+ return (1);
+ if (vp->m_start.cno <= len)
+ F_SET(vp, VM_LMODE);
+ } else
+ --vp->m_stop.cno;
+
+ return (0);
+}
OpenPOWER on IntegriCloud