xref: /minix3/external/bsd/less/dist/mark.c (revision 84d9c625bfea59e274550651111ae9edfdc40fbd)
1*84d9c625SLionel Sambuc /*	$NetBSD: mark.c,v 1.3 2013/09/04 19:44:21 tron Exp $	*/
2f7cf2976SLionel Sambuc 
3f7cf2976SLionel Sambuc /*
4*84d9c625SLionel Sambuc  * Copyright (C) 1984-2012  Mark Nudelman
5f7cf2976SLionel Sambuc  *
6f7cf2976SLionel Sambuc  * You may distribute under the terms of either the GNU General Public
7f7cf2976SLionel Sambuc  * License or the Less License, as specified in the README file.
8f7cf2976SLionel Sambuc  *
9*84d9c625SLionel Sambuc  * For more information, see the README file.
10f7cf2976SLionel Sambuc  */
11f7cf2976SLionel Sambuc 
12f7cf2976SLionel Sambuc 
13f7cf2976SLionel Sambuc #include "less.h"
14f7cf2976SLionel Sambuc 
15f7cf2976SLionel Sambuc extern IFILE curr_ifile;
16f7cf2976SLionel Sambuc extern int sc_height;
17f7cf2976SLionel Sambuc extern int jump_sline;
18f7cf2976SLionel Sambuc 
19f7cf2976SLionel Sambuc /*
20f7cf2976SLionel Sambuc  * A mark is an ifile (input file) plus a position within the file.
21f7cf2976SLionel Sambuc  */
22f7cf2976SLionel Sambuc struct mark {
23f7cf2976SLionel Sambuc 	IFILE m_ifile;
24f7cf2976SLionel Sambuc 	struct scrpos m_scrpos;
25f7cf2976SLionel Sambuc };
26f7cf2976SLionel Sambuc 
27f7cf2976SLionel Sambuc /*
28f7cf2976SLionel Sambuc  * The table of marks.
29f7cf2976SLionel Sambuc  * Each mark is identified by a lowercase or uppercase letter.
30f7cf2976SLionel Sambuc  * The final one is lmark, for the "last mark"; addressed by the apostrophe.
31f7cf2976SLionel Sambuc  */
32f7cf2976SLionel Sambuc #define	NMARKS		((2*26)+1)	/* a-z, A-Z, lastmark */
33f7cf2976SLionel Sambuc #define	LASTMARK	(NMARKS-1)
34f7cf2976SLionel Sambuc static struct mark marks[NMARKS];
35f7cf2976SLionel Sambuc 
36f7cf2976SLionel Sambuc /*
37f7cf2976SLionel Sambuc  * Initialize the mark table to show no marks are set.
38f7cf2976SLionel Sambuc  */
39f7cf2976SLionel Sambuc 	public void
init_mark()40f7cf2976SLionel Sambuc init_mark()
41f7cf2976SLionel Sambuc {
42f7cf2976SLionel Sambuc 	int i;
43f7cf2976SLionel Sambuc 
44f7cf2976SLionel Sambuc 	for (i = 0;  i < NMARKS;  i++)
45f7cf2976SLionel Sambuc 		marks[i].m_scrpos.pos = NULL_POSITION;
46f7cf2976SLionel Sambuc }
47f7cf2976SLionel Sambuc 
48f7cf2976SLionel Sambuc /*
49f7cf2976SLionel Sambuc  * See if a mark letter is valid (between a and z).
50f7cf2976SLionel Sambuc  */
51f7cf2976SLionel Sambuc 	static struct mark *
getumark(c)52f7cf2976SLionel Sambuc getumark(c)
53f7cf2976SLionel Sambuc 	int c;
54f7cf2976SLionel Sambuc {
55f7cf2976SLionel Sambuc 	if (c >= 'a' && c <= 'z')
56f7cf2976SLionel Sambuc 		return (&marks[c-'a']);
57f7cf2976SLionel Sambuc 
58f7cf2976SLionel Sambuc 	if (c >= 'A' && c <= 'Z')
59f7cf2976SLionel Sambuc 		return (&marks[c-'A'+26]);
60f7cf2976SLionel Sambuc 
61f7cf2976SLionel Sambuc 	error("Invalid mark letter", NULL_PARG);
62f7cf2976SLionel Sambuc 	return (NULL);
63f7cf2976SLionel Sambuc }
64f7cf2976SLionel Sambuc 
65f7cf2976SLionel Sambuc /*
66f7cf2976SLionel Sambuc  * Get the mark structure identified by a character.
67f7cf2976SLionel Sambuc  * The mark struct may come either from the mark table
68f7cf2976SLionel Sambuc  * or may be constructed on the fly for certain characters like ^, $.
69f7cf2976SLionel Sambuc  */
70f7cf2976SLionel Sambuc 	static struct mark *
getmark(c)71f7cf2976SLionel Sambuc getmark(c)
72f7cf2976SLionel Sambuc 	int c;
73f7cf2976SLionel Sambuc {
74f7cf2976SLionel Sambuc 	register struct mark *m;
75f7cf2976SLionel Sambuc 	static struct mark sm;
76f7cf2976SLionel Sambuc 
77f7cf2976SLionel Sambuc 	switch (c)
78f7cf2976SLionel Sambuc 	{
79f7cf2976SLionel Sambuc 	case '^':
80f7cf2976SLionel Sambuc 		/*
81f7cf2976SLionel Sambuc 		 * Beginning of the current file.
82f7cf2976SLionel Sambuc 		 */
83f7cf2976SLionel Sambuc 		m = &sm;
84f7cf2976SLionel Sambuc 		m->m_scrpos.pos = ch_zero();
85f7cf2976SLionel Sambuc 		m->m_scrpos.ln = 0;
86f7cf2976SLionel Sambuc 		m->m_ifile = curr_ifile;
87f7cf2976SLionel Sambuc 		break;
88f7cf2976SLionel Sambuc 	case '$':
89f7cf2976SLionel Sambuc 		/*
90f7cf2976SLionel Sambuc 		 * End of the current file.
91f7cf2976SLionel Sambuc 		 */
92f7cf2976SLionel Sambuc 		if (ch_end_seek())
93f7cf2976SLionel Sambuc 		{
94f7cf2976SLionel Sambuc 			error("Cannot seek to end of file", NULL_PARG);
95f7cf2976SLionel Sambuc 			return (NULL);
96f7cf2976SLionel Sambuc 		}
97f7cf2976SLionel Sambuc 		m = &sm;
98f7cf2976SLionel Sambuc 		m->m_scrpos.pos = ch_tell();
99f7cf2976SLionel Sambuc 		m->m_scrpos.ln = sc_height-1;
100f7cf2976SLionel Sambuc 		m->m_ifile = curr_ifile;
101f7cf2976SLionel Sambuc 		break;
102f7cf2976SLionel Sambuc 	case '.':
103f7cf2976SLionel Sambuc 		/*
104f7cf2976SLionel Sambuc 		 * Current position in the current file.
105f7cf2976SLionel Sambuc 		 */
106f7cf2976SLionel Sambuc 		m = &sm;
107f7cf2976SLionel Sambuc 		get_scrpos(&m->m_scrpos);
108f7cf2976SLionel Sambuc 		m->m_ifile = curr_ifile;
109f7cf2976SLionel Sambuc 		break;
110f7cf2976SLionel Sambuc 	case '\'':
111f7cf2976SLionel Sambuc 		/*
112f7cf2976SLionel Sambuc 		 * The "last mark".
113f7cf2976SLionel Sambuc 		 */
114f7cf2976SLionel Sambuc 		m = &marks[LASTMARK];
115f7cf2976SLionel Sambuc 		break;
116f7cf2976SLionel Sambuc 	default:
117f7cf2976SLionel Sambuc 		/*
118f7cf2976SLionel Sambuc 		 * Must be a user-defined mark.
119f7cf2976SLionel Sambuc 		 */
120f7cf2976SLionel Sambuc 		m = getumark(c);
121f7cf2976SLionel Sambuc 		if (m == NULL)
122f7cf2976SLionel Sambuc 			break;
123f7cf2976SLionel Sambuc 		if (m->m_scrpos.pos == NULL_POSITION)
124f7cf2976SLionel Sambuc 		{
125f7cf2976SLionel Sambuc 			error("Mark not set", NULL_PARG);
126f7cf2976SLionel Sambuc 			return (NULL);
127f7cf2976SLionel Sambuc 		}
128f7cf2976SLionel Sambuc 		break;
129f7cf2976SLionel Sambuc 	}
130f7cf2976SLionel Sambuc 	return (m);
131f7cf2976SLionel Sambuc }
132f7cf2976SLionel Sambuc 
133f7cf2976SLionel Sambuc /*
134f7cf2976SLionel Sambuc  * Is a mark letter is invalid?
135f7cf2976SLionel Sambuc  */
136f7cf2976SLionel Sambuc 	public int
badmark(c)137f7cf2976SLionel Sambuc badmark(c)
138f7cf2976SLionel Sambuc 	int c;
139f7cf2976SLionel Sambuc {
140f7cf2976SLionel Sambuc 	return (getmark(c) == NULL);
141f7cf2976SLionel Sambuc }
142f7cf2976SLionel Sambuc 
143f7cf2976SLionel Sambuc /*
144f7cf2976SLionel Sambuc  * Set a user-defined mark.
145f7cf2976SLionel Sambuc  */
146f7cf2976SLionel Sambuc 	public void
setmark(c)147f7cf2976SLionel Sambuc setmark(c)
148f7cf2976SLionel Sambuc 	int c;
149f7cf2976SLionel Sambuc {
150f7cf2976SLionel Sambuc 	register struct mark *m;
151f7cf2976SLionel Sambuc 	struct scrpos scrpos;
152f7cf2976SLionel Sambuc 
153f7cf2976SLionel Sambuc 	m = getumark(c);
154f7cf2976SLionel Sambuc 	if (m == NULL)
155f7cf2976SLionel Sambuc 		return;
156f7cf2976SLionel Sambuc 	get_scrpos(&scrpos);
157f7cf2976SLionel Sambuc 	m->m_scrpos = scrpos;
158f7cf2976SLionel Sambuc 	m->m_ifile = curr_ifile;
159f7cf2976SLionel Sambuc }
160f7cf2976SLionel Sambuc 
161f7cf2976SLionel Sambuc /*
162f7cf2976SLionel Sambuc  * Set lmark (the mark named by the apostrophe).
163f7cf2976SLionel Sambuc  */
164f7cf2976SLionel Sambuc 	public void
lastmark()165f7cf2976SLionel Sambuc lastmark()
166f7cf2976SLionel Sambuc {
167f7cf2976SLionel Sambuc 	struct scrpos scrpos;
168f7cf2976SLionel Sambuc 
169f7cf2976SLionel Sambuc 	if (ch_getflags() & CH_HELPFILE)
170f7cf2976SLionel Sambuc 		return;
171f7cf2976SLionel Sambuc 	get_scrpos(&scrpos);
172f7cf2976SLionel Sambuc 	if (scrpos.pos == NULL_POSITION)
173f7cf2976SLionel Sambuc 		return;
174f7cf2976SLionel Sambuc 	marks[LASTMARK].m_scrpos = scrpos;
175f7cf2976SLionel Sambuc 	marks[LASTMARK].m_ifile = curr_ifile;
176f7cf2976SLionel Sambuc }
177f7cf2976SLionel Sambuc 
178f7cf2976SLionel Sambuc /*
179f7cf2976SLionel Sambuc  * Go to a mark.
180f7cf2976SLionel Sambuc  */
181f7cf2976SLionel Sambuc 	public void
gomark(c)182f7cf2976SLionel Sambuc gomark(c)
183f7cf2976SLionel Sambuc 	int c;
184f7cf2976SLionel Sambuc {
185f7cf2976SLionel Sambuc 	register struct mark *m;
186f7cf2976SLionel Sambuc 	struct scrpos scrpos;
187f7cf2976SLionel Sambuc 
188f7cf2976SLionel Sambuc 	m = getmark(c);
189f7cf2976SLionel Sambuc 	if (m == NULL)
190f7cf2976SLionel Sambuc 		return;
191f7cf2976SLionel Sambuc 
192f7cf2976SLionel Sambuc 	/*
193f7cf2976SLionel Sambuc 	 * If we're trying to go to the lastmark and
194f7cf2976SLionel Sambuc 	 * it has not been set to anything yet,
195f7cf2976SLionel Sambuc 	 * set it to the beginning of the current file.
196f7cf2976SLionel Sambuc 	 */
197f7cf2976SLionel Sambuc 	if (m == &marks[LASTMARK] && m->m_scrpos.pos == NULL_POSITION)
198f7cf2976SLionel Sambuc 	{
199f7cf2976SLionel Sambuc 		m->m_ifile = curr_ifile;
200f7cf2976SLionel Sambuc 		m->m_scrpos.pos = ch_zero();
201f7cf2976SLionel Sambuc 		m->m_scrpos.ln = jump_sline;
202f7cf2976SLionel Sambuc 	}
203f7cf2976SLionel Sambuc 
204f7cf2976SLionel Sambuc 	/*
205f7cf2976SLionel Sambuc 	 * If we're using lmark, we must save the screen position now,
206f7cf2976SLionel Sambuc 	 * because if we call edit_ifile() below, lmark will change.
207f7cf2976SLionel Sambuc 	 * (We save the screen position even if we're not using lmark.)
208f7cf2976SLionel Sambuc 	 */
209f7cf2976SLionel Sambuc 	scrpos = m->m_scrpos;
210f7cf2976SLionel Sambuc 	if (m->m_ifile != curr_ifile)
211f7cf2976SLionel Sambuc 	{
212f7cf2976SLionel Sambuc 		/*
213f7cf2976SLionel Sambuc 		 * Not in the current file; edit the correct file.
214f7cf2976SLionel Sambuc 		 */
215f7cf2976SLionel Sambuc 		if (edit_ifile(m->m_ifile))
216f7cf2976SLionel Sambuc 			return;
217f7cf2976SLionel Sambuc 	}
218f7cf2976SLionel Sambuc 
219f7cf2976SLionel Sambuc 	jump_loc(scrpos.pos, scrpos.ln);
220f7cf2976SLionel Sambuc }
221f7cf2976SLionel Sambuc 
222f7cf2976SLionel Sambuc /*
223f7cf2976SLionel Sambuc  * Return the position associated with a given mark letter.
224f7cf2976SLionel Sambuc  *
225f7cf2976SLionel Sambuc  * We don't return which screen line the position
226f7cf2976SLionel Sambuc  * is associated with, but this doesn't matter much,
227f7cf2976SLionel Sambuc  * because it's always the first non-blank line on the screen.
228f7cf2976SLionel Sambuc  */
229f7cf2976SLionel Sambuc 	public POSITION
markpos(c)230f7cf2976SLionel Sambuc markpos(c)
231f7cf2976SLionel Sambuc 	int c;
232f7cf2976SLionel Sambuc {
233f7cf2976SLionel Sambuc 	register struct mark *m;
234f7cf2976SLionel Sambuc 
235f7cf2976SLionel Sambuc 	m = getmark(c);
236f7cf2976SLionel Sambuc 	if (m == NULL)
237f7cf2976SLionel Sambuc 		return (NULL_POSITION);
238f7cf2976SLionel Sambuc 
239f7cf2976SLionel Sambuc 	if (m->m_ifile != curr_ifile)
240f7cf2976SLionel Sambuc 	{
241f7cf2976SLionel Sambuc 		error("Mark not in current file", NULL_PARG);
242f7cf2976SLionel Sambuc 		return (NULL_POSITION);
243f7cf2976SLionel Sambuc 	}
244f7cf2976SLionel Sambuc 	return (m->m_scrpos.pos);
245f7cf2976SLionel Sambuc }
246f7cf2976SLionel Sambuc 
247f7cf2976SLionel Sambuc /*
248f7cf2976SLionel Sambuc  * Clear the marks associated with a specified ifile.
249f7cf2976SLionel Sambuc  */
250f7cf2976SLionel Sambuc 	public void
unmark(ifile)251f7cf2976SLionel Sambuc unmark(ifile)
252f7cf2976SLionel Sambuc 	IFILE ifile;
253f7cf2976SLionel Sambuc {
254f7cf2976SLionel Sambuc 	int i;
255f7cf2976SLionel Sambuc 
256f7cf2976SLionel Sambuc 	for (i = 0;  i < NMARKS;  i++)
257f7cf2976SLionel Sambuc 		if (marks[i].m_ifile == ifile)
258f7cf2976SLionel Sambuc 			marks[i].m_scrpos.pos = NULL_POSITION;
259f7cf2976SLionel Sambuc }
260