1 /* $NetBSD: v_mark.c,v 1.4 2014/01/26 21:43:45 christos Exp $ */
3 * Copyright (c) 1992, 1993, 1994
4 * The Regents of the University of California. All rights reserved.
5 * Copyright (c) 1992, 1993, 1994, 1995, 1996
6 * Keith Bostic. All rights reserved.
8 * See the LICENSE file for redistribution information.
13 #include <sys/cdefs.h>
16 static const char sccsid
[] = "Id: v_mark.c,v 10.12 2001/06/25 15:19:32 skimo Exp (Berkeley) Date: 2001/06/25 15:19:32 ";
19 __RCSID("$NetBSD: v_mark.c,v 1.4 2014/01/26 21:43:45 christos Exp $");
22 #include <sys/types.h>
23 #include <sys/queue.h>
26 #include <bitstring.h>
31 #include "../common/common.h"
34 enum which
{BQMARK
, FQMARK
};
35 static int mark
__P((SCR
*, VICMD
*, int, enum which
));
41 * PUBLIC: int v_mark __P((SCR *, VICMD *));
44 v_mark(SCR
*sp
, VICMD
*vp
)
46 return (mark_set(sp
, vp
->character
, &vp
->m_start
, 1));
53 * Moves to a mark, setting both row and column.
56 * Although not commonly known, the "'`" and "'`" forms are historically
57 * valid. The behavior is determined by the first character, so "`'" is
58 * the same as "``". Remember this fact -- you'll be amazed at how many
59 * people don't know it and will be delighted that you are able to tell
62 * PUBLIC: int v_bmark __P((SCR *, VICMD *));
65 v_bmark(SCR
*sp
, VICMD
*vp
)
67 return (mark(sp
, vp
, 1, BQMARK
));
74 * Move to the first nonblank character of the line containing the mark.
76 * PUBLIC: int v_fmark __P((SCR *, VICMD *));
79 v_fmark(SCR
*sp
, VICMD
*vp
)
81 return (mark(sp
, vp
, 1, FQMARK
));
85 * v_emark -- <mouse click>
88 * PUBLIC: int v_emark __P((SCR *, VICMD *));
91 v_emark(SCR
*sp
, VICMD
*vp
)
95 smp
= HMAP
+ vp
->ev
.e_lno
;
97 msgq(sp
, M_BERR
, "320|Unknown cursor position.");
100 vp
->m_stop
.lno
= smp
->lno
;
102 vs_colpos(sp
, smp
->lno
, vp
->ev
.e_cno
+ (smp
->soff
- 1) * sp
->cols
);
103 return (mark(sp
, vp
, 0, BQMARK
));
111 mark(SCR
*sp
, VICMD
*vp
, int getmark
, enum which cmd
)
116 if (getmark
&& mark_get(sp
, vp
->character
, &vp
->m_stop
, M_BERR
))
121 * Historically, BQMARKS for character positions that no longer
122 * existed acted as FQMARKS.
124 * FQMARKS move to the first non-blank.
128 if (db_get(sp
, vp
->m_stop
.lno
, DBG_FATAL
, NULL
, &len
))
130 if (vp
->m_stop
.cno
< len
||
131 (vp
->m_stop
.cno
== len
&& len
== 0))
140 if (nonblank(sp
, vp
->m_stop
.lno
, &vp
->m_stop
.cno
))
147 /* Non-motion commands move to the end of the range. */
149 vp
->m_final
= vp
->m_stop
;
155 * If a motion component to a BQMARK, the cursor has to move.
158 vp
->m_stop
.lno
== vp
->m_start
.lno
&&
159 vp
->m_stop
.cno
== vp
->m_start
.cno
) {
165 * If the motion is in the reverse direction, switch the start and
166 * stop MARK's so that it's in a forward direction. (There's no
167 * reason for this other than to make the tests below easier. The
168 * code in vi.c:vi() would have done the switch.) Both forward
169 * and backward motions can happen for any kind of search command.
171 if (vp
->m_start
.lno
> vp
->m_stop
.lno
||
172 (vp
->m_start
.lno
== vp
->m_stop
.lno
&&
173 vp
->m_start
.cno
> vp
->m_stop
.cno
)) {
175 vp
->m_start
= vp
->m_stop
;
180 * Yank cursor motion, when associated with marks as motion commands,
181 * historically behaved as follows:
184 * Line change? Line change?
186 * -------------- ---------------
187 * FORWARD: | NM NM | NM NM
189 * BACKWARD: | M M | M NM(1)
191 * where NM means the cursor didn't move, and M means the cursor
194 * As the cursor was usually moved for yank commands associated
195 * with backward motions, this implementation regularizes it by
196 * changing the NM at position (1) to be an M. This makes mark
197 * motions match search motions, which is probably A Good Thing.
199 * Delete cursor motion was always to the start of the text region,
200 * regardless. Ignore other motion commands.
202 #ifdef HISTORICAL_PRACTICE
203 if (ISCMD(vp
->rkp
, 'y')) {
204 if ((cmd
== BQMARK
||
205 cmd
== FQMARK
&& vp
->m_start
.lno
!= vp
->m_stop
.lno
) &&
206 (vp
->m_start
.lno
> vp
->m_stop
.lno
||
207 vp
->m_start
.lno
== vp
->m_stop
.lno
&&
208 vp
->m_start
.cno
> vp
->m_stop
.cno
))
209 vp
->m_final
= vp
->m_stop
;
210 } else if (ISCMD(vp
->rkp
, 'd'))
211 if (vp
->m_start
.lno
> vp
->m_stop
.lno
||
212 vp
->m_start
.lno
== vp
->m_stop
.lno
&&
213 vp
->m_start
.cno
> vp
->m_stop
.cno
)
214 vp
->m_final
= vp
->m_stop
;
216 vp
->m_final
= vp
->m_start
;
220 * Forward marks are always line oriented, and it's set in the
227 * BQMARK'S moving backward and starting at column 0, and ones moving
228 * forward and ending at column 0 are corrected to the last column of
229 * the previous line. Otherwise, adjust the starting/ending point to
230 * the character before the current one (this is safe because we know
231 * the search had to move to succeed).
233 * Mark motions become line mode opertions if they start at the first
234 * nonblank and end at column 0 of another line.
236 if (vp
->m_start
.lno
< vp
->m_stop
.lno
&& vp
->m_stop
.cno
== 0) {
237 if (db_get(sp
, --vp
->m_stop
.lno
, DBG_FATAL
, NULL
, &len
))
239 vp
->m_stop
.cno
= len
? len
- 1 : 0;
241 if (nonblank(sp
, vp
->m_start
.lno
, &len
))
243 if (vp
->m_start
.cno
<= len
)