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