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