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