Annotation of src/usr.bin/less/mark.c, Revision 1.2
1.2 ! niklas 1: /* $OpenBSD$ */
! 2:
1.1 etheisen 3: /*
4: * Copyright (c) 1984,1985,1989,1994,1995 Mark Nudelman
5: * All rights reserved.
6: *
7: * Redistribution and use in source and binary forms, with or without
8: * modification, are permitted provided that the following conditions
9: * are met:
10: * 1. Redistributions of source code must retain the above copyright
11: * notice, this list of conditions and the following disclaimer.
12: * 2. Redistributions in binary form must reproduce the above copyright
13: * notice in the documentation and/or other materials provided with
14: * the distribution.
15: *
16: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY
17: * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE
20: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
22: * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23: * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24: * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25: * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26: * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27: */
28:
29:
30: #include "less.h"
31: #include "position.h"
32:
33: extern IFILE curr_ifile;
34: extern int sc_height;
35: extern int jump_sline;
36:
37: /*
38: * A mark is an ifile (input file) plus a position within the file.
39: */
40: struct mark {
41: IFILE m_ifile;
42: struct scrpos m_scrpos;
43: };
44:
45: /*
46: * The table of marks.
47: * Each mark is identified by a lowercase or uppercase letter.
48: */
49: #define NMARKS (2*26) /* a-z, A-Z */
50: static struct mark marks[NMARKS];
51:
52: /*
53: * Special mark for the "last mark"; addressed by the apostrophe.
54: */
55: static struct mark lmark;
56:
57: /*
58: * Initialize the mark table to show no marks are set.
59: */
60: public void
61: init_mark()
62: {
63: int i;
64:
65: for (i = 0; i < NMARKS; i++)
66: marks[i].m_scrpos.pos = NULL_POSITION;
67: lmark.m_scrpos.pos = NULL_POSITION;
68: }
69:
70: /*
71: * See if a mark letter is valid (between a and z).
72: */
73: static struct mark *
74: getumark(c)
75: int c;
76: {
77: if (c >= 'a' && c <= 'z')
78: return (&marks[c-'a']);
79:
80: if (c >= 'A' && c <= 'Z')
81: return (&marks[c-'A'+26]);
82:
83: error("Invalid mark letter", NULL_PARG);
84: return (NULL);
85: }
86:
87: /*
88: * Get the mark structure identified by a character.
89: * The mark struct may come either from the mark table
90: * or may be constructed on the fly for certain characters like ^, $.
91: */
92: static struct mark *
93: getmark(c)
94: int c;
95: {
96: register struct mark *m;
97: static struct mark sm;
98:
99: switch (c)
100: {
101: case '^':
102: /*
103: * Beginning of the current file.
104: */
105: m = &sm;
106: m->m_scrpos.pos = ch_zero();
107: m->m_scrpos.ln = 0;
108: m->m_ifile = curr_ifile;
109: break;
110: case '$':
111: /*
112: * End of the current file.
113: */
114: if (ch_end_seek())
115: {
116: error("Cannot seek to end of file", NULL_PARG);
117: return (NULL);
118: }
119: m = &sm;
120: m->m_scrpos.pos = ch_tell();
121: m->m_scrpos.ln = sc_height-1;
122: m->m_ifile = curr_ifile;
123: break;
124: case '.':
125: /*
126: * Current position in the current file.
127: */
128: m = &sm;
129: m->m_scrpos.pos = ch_tell();
130: m->m_scrpos.ln = 0;
131: m->m_ifile = curr_ifile;
132: break;
133: case '\'':
134: /*
135: * The "last mark".
136: */
137: m = &lmark;
138: break;
139: default:
140: /*
141: * Must be a user-defined mark.
142: */
143: m = getumark(c);
144: if (m == NULL)
145: break;
146: if (m->m_scrpos.pos == NULL_POSITION)
147: {
148: error("Mark not set", NULL_PARG);
149: return (NULL);
150: }
151: break;
152: }
153: return (m);
154: }
155:
156: /*
157: * Is a mark letter is invalid?
158: */
159: public int
160: badmark(c)
161: int c;
162: {
163: return (getmark(c) == NULL);
164: }
165:
166: /*
167: * Set a user-defined mark.
168: */
169: public void
170: setmark(c)
171: int c;
172: {
173: register struct mark *m;
174: struct scrpos scrpos;
175:
176: m = getumark(c);
177: if (m == NULL)
178: return;
179: get_scrpos(&scrpos);
180: m->m_scrpos = scrpos;
181: m->m_ifile = curr_ifile;
182: }
183:
184: /*
185: * Set lmark (the mark named by the apostrophe).
186: */
187: public void
188: lastmark()
189: {
190: struct scrpos scrpos;
191:
192: get_scrpos(&scrpos);
193: if (scrpos.pos == NULL_POSITION)
194: return;
195: lmark.m_scrpos = scrpos;
196: lmark.m_ifile = curr_ifile;
197: }
198:
199: /*
200: * Go to a mark.
201: */
202: public void
203: gomark(c)
204: int c;
205: {
206: register struct mark *m;
207: struct scrpos scrpos;
208:
209: m = getmark(c);
210: if (m == NULL)
211: return;
212:
213: /*
214: * If we're trying to go to the lastmark and
215: * it has not been set to anything yet,
216: * set it to the beginning of the current file.
217: */
218: if (m == &lmark && m->m_scrpos.pos == NULL_POSITION)
219: {
220: m->m_ifile = curr_ifile;
221: m->m_scrpos.pos = ch_zero();
222: m->m_scrpos.ln = jump_sline;
223: }
224:
225: /*
226: * If we're using lmark, we must save the screen position now,
227: * because if we call edit_ifile() below, lmark will change.
228: * (We save the screen position even if we're not using lmark.)
229: */
230: scrpos = m->m_scrpos;
231: if (m->m_ifile != curr_ifile)
232: {
233: /*
234: * Not in the current file; edit the correct file.
235: */
236: if (edit_ifile(m->m_ifile))
237: return;
238: }
239:
240: jump_loc(scrpos.pos, scrpos.ln);
241: }
242:
243: /*
244: * Return the position associated with a given mark letter.
245: *
246: * We don't return which screen line the position
247: * is associated with, but this doesn't matter much,
248: * because it's always the first non-blank line on the screen.
249: */
250: public POSITION
251: markpos(c)
252: int c;
253: {
254: register struct mark *m;
255:
256: m = getmark(c);
257: if (m == NULL)
258: return (NULL_POSITION);
259:
260: if (m->m_ifile != curr_ifile)
261: {
262: error("Mark not in current file", NULL_PARG);
263: return (NULL_POSITION);
264: }
265: return (m->m_scrpos.pos);
266: }