GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.bin/vi/build/../vi/v_mark.c Lines: 0 47 0.0 %
Date: 2017-11-07 Branches: 0 45 0.0 %

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