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