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