move the repaint routine into v_event with other event routines
[nvi.git] / vi / v_mark.c
blob9d8cac4a50fd9e43a01fa88fc806c255cee44a66
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.
7 * See the LICENSE file for redistribution information.
8 */
10 #include "config.h"
12 #ifndef lint
13 static const char sccsid[] = "$Id: v_mark.c,v 10.9 1996/12/04 09:47:59 bostic Exp $ (Berkeley) $Date: 1996/12/04 09:47:59 $";
14 #endif /* not lint */
16 #include <sys/types.h>
17 #include <sys/queue.h>
18 #include <sys/time.h>
20 #include <bitstring.h>
21 #include <limits.h>
22 #include <stdlib.h>
23 #include <stdio.h>
25 #include "../common/common.h"
26 #include "vi.h"
28 enum which {BQMARK, FQMARK};
29 static int mark __P((SCR *, VICMD *, int, enum which));
32 * v_mark -- m[a-z]
33 * Set a mark.
35 * PUBLIC: int v_mark __P((SCR *, VICMD *));
37 int
38 v_mark(sp, vp)
39 SCR *sp;
40 VICMD *vp;
42 return (mark_set(sp, vp->character, &vp->m_start, 1));
46 * v_bmark -- `['`a-z]
47 * Move to a mark.
49 * Moves to a mark, setting both row and column.
51 * !!!
52 * Although not commonly known, the "'`" and "'`" forms are historically
53 * valid. The behavior is determined by the first character, so "`'" is
54 * the same as "``". Remember this fact -- you'll be amazed at how many
55 * people don't know it and will be delighted that you are able to tell
56 * them.
58 * PUBLIC: int v_bmark __P((SCR *, VICMD *));
60 int
61 v_bmark(sp, vp)
62 SCR *sp;
63 VICMD *vp;
65 return (mark(sp, vp, 1, BQMARK));
69 * v_fmark -- '['`a-z]
70 * Move to a mark.
72 * Move to the first nonblank character of the line containing the mark.
74 * PUBLIC: int v_fmark __P((SCR *, VICMD *));
76 int
77 v_fmark(sp, vp)
78 SCR *sp;
79 VICMD *vp;
81 return (mark(sp, vp, 1, FQMARK));
85 * v_mmark -- <mouse>
86 * Move to a mouse mark.
88 * PUBLIC: int v_mmark __P((SCR *, VICMD *));
90 int
91 v_mmark(sp, vp)
92 SCR *sp;
93 VICMD *vp;
95 (void)vs_pos(sp,
96 vp->ev.e_lno, vp->ev.e_cno, &vp->m_stop.lno, &vp->m_stop.cno);
97 return (mark(sp, vp, 0, BQMARK));
101 * mark --
102 * Mark commands.
104 static int
105 mark(sp, vp, getmark, cmd)
106 SCR *sp;
107 VICMD *vp;
108 int getmark;
109 enum which cmd;
111 dir_t dir;
112 MARK m;
113 size_t len;
115 if (getmark && mark_get(sp, vp->character, &vp->m_stop, M_BERR))
116 return (1);
119 * !!!
120 * Historically, BQMARKS for character positions that no longer
121 * existed acted as FQMARKS.
123 * FQMARKS move to the first non-blank.
125 switch (cmd) {
126 case BQMARK:
127 if (db_get(sp, vp->m_stop.lno, DBG_FATAL, NULL, &len))
128 return (1);
129 if (vp->m_stop.cno < len ||
130 vp->m_stop.cno == len && len == 0)
131 break;
133 if (ISMOTION(vp))
134 F_SET(vp, VM_LMODE);
135 cmd = FQMARK;
136 /* FALLTHROUGH */
137 case FQMARK:
138 vp->m_stop.cno = 0;
139 if (nonblank(sp, vp->m_stop.lno, &vp->m_stop.cno))
140 return (1);
141 break;
142 default:
143 abort();
146 /* Non-motion commands move to the end of the range. */
147 if (!ISMOTION(vp)) {
148 vp->m_final = vp->m_stop;
149 return (0);
153 * !!!
154 * If a motion component to a BQMARK, the cursor has to move.
156 if (cmd == BQMARK &&
157 vp->m_stop.lno == vp->m_start.lno &&
158 vp->m_stop.cno == vp->m_start.cno) {
159 v_nomove(sp);
160 return (1);
164 * If the motion is in the reverse direction, switch the start and
165 * stop MARK's so that it's in a forward direction. (There's no
166 * reason for this other than to make the tests below easier. The
167 * code in vi.c:vi() would have done the switch.) Both forward
168 * and backward motions can happen for any kind of search command.
170 if (vp->m_start.lno > vp->m_stop.lno ||
171 vp->m_start.lno == vp->m_stop.lno &&
172 vp->m_start.cno > vp->m_stop.cno) {
173 m = vp->m_start;
174 vp->m_start = vp->m_stop;
175 vp->m_stop = m;
176 dir = BACKWARD;
177 } else
178 dir = FORWARD;
181 * Yank cursor motion, when associated with marks as motion commands,
182 * historically behaved as follows:
184 * ` motion ' motion
185 * Line change? Line change?
186 * Y N Y N
187 * -------------- ---------------
188 * FORWARD: | NM NM | NM NM
189 * | |
190 * BACKWARD: | M M | M NM(1)
192 * where NM means the cursor didn't move, and M means the cursor
193 * moved to the mark.
195 * As the cursor was usually moved for yank commands associated
196 * with backward motions, this implementation regularizes it by
197 * changing the NM at position (1) to be an M. This makes mark
198 * motions match search motions, which is probably A Good Thing.
200 * Delete cursor motion was always to the start of the text region,
201 * regardless. Ignore other motion commands.
203 #ifdef HISTORICAL_PRACTICE
204 if (ISCMD(vp->rkp, 'y')) {
205 if ((cmd == BQMARK ||
206 cmd == FQMARK && vp->m_start.lno != vp->m_stop.lno) &&
207 (vp->m_start.lno > vp->m_stop.lno ||
208 vp->m_start.lno == vp->m_stop.lno &&
209 vp->m_start.cno > vp->m_stop.cno))
210 vp->m_final = vp->m_stop;
211 } else if (ISCMD(vp->rkp, 'd'))
212 if (vp->m_start.lno > vp->m_stop.lno ||
213 vp->m_start.lno == vp->m_stop.lno &&
214 vp->m_start.cno > vp->m_stop.cno)
215 vp->m_final = vp->m_stop;
216 #else
217 vp->m_final = vp->m_start;
218 #endif
221 * Forward marks are always line oriented, and it's set in the
222 * vcmd.c table.
224 if (cmd == FQMARK)
225 return (0);
228 * BQMARK'S moving backward and starting at column 0, and ones moving
229 * forward and ending at column 0 are corrected to the last column of
230 * the previous line. Otherwise, adjust the starting/ending point to
231 * the character before the current one (this is safe because we know
232 * the search had to move to succeed).
234 * Mark motions become line mode opertions if they start at the first
235 * nonblank and end at column 0 of another line.
237 if (vp->m_start.lno < vp->m_stop.lno && vp->m_stop.cno == 0) {
238 if (db_get(sp, --vp->m_stop.lno, DBG_FATAL, NULL, &len))
239 return (1);
240 vp->m_stop.cno = len ? len - 1 : 0;
241 len = 0;
242 if (nonblank(sp, vp->m_start.lno, &len))
243 return (1);
244 if (vp->m_start.cno <= len)
245 F_SET(vp, VM_LMODE);
246 } else
247 --vp->m_stop.cno;
249 return (0);