source: trunk/third/nvi/vi/v_mark.c @ 14302

Revision 14302, 5.5 KB checked in by ghudson, 25 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r14301, which included commits to RCS files with non-trunk default branches.
Line 
1/*-
2 * Copyright (c) 1992, 1993, 1994
3 *      The Regents of the University of California.  All rights reserved.
4 * Copyright (c) 1992, 1993, 1994, 1995, 1996
5 *      Keith Bostic.  All rights reserved.
6 *
7 * See the LICENSE file for redistribution information.
8 */
9
10#include "config.h"
11
12#ifndef lint
13static const char sccsid[] = "@(#)v_mark.c      10.8 (Berkeley) 9/20/96";
14#endif /* not lint */
15
16#include <sys/types.h>
17#include <sys/queue.h>
18#include <sys/time.h>
19
20#include <bitstring.h>
21#include <limits.h>
22#include <stdlib.h>
23#include <stdio.h>
24
25#include "../common/common.h"
26#include "vi.h"
27
28/*
29 * v_mark -- m[a-z]
30 *      Set a mark.
31 *
32 * PUBLIC: int v_mark __P((SCR *, VICMD *));
33 */
34int
35v_mark(sp, vp)
36        SCR *sp;
37        VICMD *vp;
38{
39        return (mark_set(sp, vp->character, &vp->m_start, 1));
40}
41
42enum which {BQMARK, FQMARK};
43static int mark __P((SCR *, VICMD *, enum which));
44
45
46/*
47 * v_bmark -- `['`a-z]
48 *      Move to a mark.
49 *
50 * Moves to a mark, setting both row and column.
51 *
52 * !!!
53 * Although not commonly known, the "'`" and "'`" forms are historically
54 * valid.  The behavior is determined by the first character, so "`'" is
55 * the same as "``".  Remember this fact -- you'll be amazed at how many
56 * people don't know it and will be delighted that you are able to tell
57 * them.
58 *
59 * PUBLIC: int v_bmark __P((SCR *, VICMD *));
60 */
61int
62v_bmark(sp, vp)
63        SCR *sp;
64        VICMD *vp;
65{
66        return (mark(sp, vp, BQMARK));
67}
68
69/*
70 * v_fmark -- '['`a-z]
71 *      Move to a mark.
72 *
73 * Move to the first nonblank character of the line containing the mark.
74 *
75 * PUBLIC: int v_fmark __P((SCR *, VICMD *));
76 */
77int
78v_fmark(sp, vp)
79        SCR *sp;
80        VICMD *vp;
81{
82        return (mark(sp, vp, FQMARK));
83}
84
85/*
86 * mark --
87 *      Mark commands.
88 */
89static int
90mark(sp, vp, cmd)
91        SCR *sp;
92        VICMD *vp;
93        enum which cmd;
94{
95        dir_t dir;
96        MARK m;
97        size_t len;
98
99        if (mark_get(sp, vp->character, &vp->m_stop, M_BERR))
100                return (1);
101
102        /*
103         * !!!
104         * Historically, BQMARKS for character positions that no longer
105         * existed acted as FQMARKS.
106         *
107         * FQMARKS move to the first non-blank.
108         */
109        switch (cmd) {
110        case BQMARK:
111                if (db_get(sp, vp->m_stop.lno, DBG_FATAL, NULL, &len))
112                        return (1);
113                if (vp->m_stop.cno < len ||
114                    vp->m_stop.cno == len && len == 0)
115                        break;
116
117                if (ISMOTION(vp))
118                        F_SET(vp, VM_LMODE);
119                cmd = FQMARK;
120                /* FALLTHROUGH */
121        case FQMARK:
122                vp->m_stop.cno = 0;
123                if (nonblank(sp, vp->m_stop.lno, &vp->m_stop.cno))
124                        return (1);
125                break;
126        default:
127                abort();
128        }
129
130        /* Non-motion commands move to the end of the range. */
131        if (!ISMOTION(vp)) {
132                vp->m_final = vp->m_stop;
133                return (0);
134        }
135
136        /*
137         * !!!
138         * If a motion component to a BQMARK, the cursor has to move.
139         */
140        if (cmd == BQMARK &&
141            vp->m_stop.lno == vp->m_start.lno &&
142            vp->m_stop.cno == vp->m_start.cno) {
143                v_nomove(sp);
144                return (1);
145        }
146
147        /*
148         * If the motion is in the reverse direction, switch the start and
149         * stop MARK's so that it's in a forward direction.  (There's no
150         * reason for this other than to make the tests below easier.  The
151         * code in vi.c:vi() would have done the switch.)  Both forward
152         * and backward motions can happen for any kind of search command.
153         */
154        if (vp->m_start.lno > vp->m_stop.lno ||
155            vp->m_start.lno == vp->m_stop.lno &&
156            vp->m_start.cno > vp->m_stop.cno) {
157                m = vp->m_start;
158                vp->m_start = vp->m_stop;
159                vp->m_stop = m;
160                dir = BACKWARD;
161        } else
162                dir = FORWARD;
163
164        /*
165         * Yank cursor motion, when associated with marks as motion commands,
166         * historically behaved as follows:
167         *
168         * ` motion                     ' motion
169         *              Line change?            Line change?
170         *              Y       N               Y       N
171         *            --------------          ---------------
172         * FORWARD:  |  NM      NM            | NM      NM
173         *           |                        |
174         * BACKWARD: |  M       M             | M       NM(1)
175         *
176         * where NM means the cursor didn't move, and M means the cursor
177         * moved to the mark.
178         *
179         * As the cursor was usually moved for yank commands associated
180         * with backward motions, this implementation regularizes it by
181         * changing the NM at position (1) to be an M.  This makes mark
182         * motions match search motions, which is probably A Good Thing.
183         *
184         * Delete cursor motion was always to the start of the text region,
185         * regardless.  Ignore other motion commands.
186         */
187#ifdef HISTORICAL_PRACTICE
188        if (ISCMD(vp->rkp, 'y')) {
189                if ((cmd == BQMARK ||
190                    cmd == FQMARK && vp->m_start.lno != vp->m_stop.lno) &&
191                    (vp->m_start.lno > vp->m_stop.lno ||
192                    vp->m_start.lno == vp->m_stop.lno &&
193                    vp->m_start.cno > vp->m_stop.cno))
194                        vp->m_final = vp->m_stop;
195        } else if (ISCMD(vp->rkp, 'd'))
196                if (vp->m_start.lno > vp->m_stop.lno ||
197                    vp->m_start.lno == vp->m_stop.lno &&
198                    vp->m_start.cno > vp->m_stop.cno)
199                        vp->m_final = vp->m_stop;
200#else
201        vp->m_final = vp->m_start;
202#endif
203
204        /*
205         * Forward marks are always line oriented, and it's set in the
206         * vcmd.c table.
207         */
208        if (cmd == FQMARK)
209                return (0);
210
211        /*
212         * BQMARK'S moving backward and starting at column 0, and ones moving
213         * forward and ending at column 0 are corrected to the last column of
214         * the previous line.  Otherwise, adjust the starting/ending point to
215         * the character before the current one (this is safe because we know
216         * the search had to move to succeed).
217         *
218         * Mark motions become line mode opertions if they start at the first
219         * nonblank and end at column 0 of another line.
220         */
221        if (vp->m_start.lno < vp->m_stop.lno && vp->m_stop.cno == 0) {
222                if (db_get(sp, --vp->m_stop.lno, DBG_FATAL, NULL, &len))
223                        return (1);
224                vp->m_stop.cno = len ? len - 1 : 0;
225                len = 0;
226                if (nonblank(sp, vp->m_start.lno, &len))
227                        return (1);
228                if (vp->m_start.cno <= len)
229                        F_SET(vp, VM_LMODE);
230        } else
231                --vp->m_stop.cno;
232
233        return (0);
234}
Note: See TracBrowser for help on using the repository browser.