Annotation of src/usr.bin/less/position.c, Revision 1.11
1.1 etheisen 1: /*
1.7 shadchin 2: * Copyright (C) 1984-2012 Mark Nudelman
1.10 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.5 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.7 shadchin 9: * For more information, see the README file.
1.8 nicm 10: */
1.1 etheisen 11:
12: /*
13: * Routines dealing with the "position" table.
14: * This is a table which tells the position (in the input file) of the
15: * first char on each currently displayed line.
16: *
17: * {{ The position table is scrolled by moving all the entries.
1.8 nicm 18: * Would be better to have a circular table
19: * and just change a couple of pointers. }}
1.1 etheisen 20: */
21:
22: #include "less.h"
23: #include "position.h"
24:
1.8 nicm 25: static off_t *table = NULL; /* The position table */
1.1 etheisen 26: static int table_size;
27:
28: extern int sc_width, sc_height;
29:
30: /*
31: * Return the starting file position of a line displayed on the screen.
32: * The line may be specified as a line number relative to the top
33: * of the screen, but is usually one of these special cases:
34: * the top (first) line on the screen
35: * the second line on the screen
36: * the bottom line on the screen
37: * the line after the bottom line on the screen
38: */
1.8 nicm 39: off_t
40: position(int where)
1.1 etheisen 41: {
1.8 nicm 42: switch (where) {
1.1 etheisen 43: case BOTTOM:
44: where = sc_height - 2;
45: break;
46: case BOTTOM_PLUS_ONE:
47: where = sc_height - 1;
48: break;
49: case MIDDLE:
50: where = (sc_height - 1) / 2;
51: }
52: return (table[where]);
53: }
54:
55: /*
56: * Add a new file position to the bottom of the position table.
57: */
1.8 nicm 58: void
59: add_forw_pos(off_t pos)
1.1 etheisen 60: {
1.8 nicm 61: int i;
1.1 etheisen 62:
63: /*
64: * Scroll the position table up.
65: */
1.11 ! deraadt 66: for (i = 1; i < sc_height; i++)
1.1 etheisen 67: table[i-1] = table[i];
68: table[sc_height - 1] = pos;
69: }
70:
71: /*
72: * Add a new file position to the top of the position table.
73: */
1.8 nicm 74: void
75: add_back_pos(off_t pos)
1.1 etheisen 76: {
1.8 nicm 77: int i;
1.1 etheisen 78:
79: /*
80: * Scroll the position table down.
81: */
1.11 ! deraadt 82: for (i = sc_height - 1; i > 0; i--)
1.1 etheisen 83: table[i] = table[i-1];
84: table[0] = pos;
85: }
86:
87: /*
88: * Initialize the position table, done whenever we clear the screen.
89: */
1.8 nicm 90: void
91: pos_clear(void)
1.1 etheisen 92: {
1.8 nicm 93: int i;
1.1 etheisen 94:
1.11 ! deraadt 95: for (i = 0; i < sc_height; i++)
1.8 nicm 96: table[i] = -1;
1.1 etheisen 97: }
98:
99: /*
100: * Allocate or reallocate the position table.
101: */
1.8 nicm 102: void
103: pos_init(void)
1.1 etheisen 104: {
105: struct scrpos scrpos;
106:
107: if (sc_height <= table_size)
108: return;
109: /*
110: * If we already have a table, remember the first line in it
111: * before we free it, so we can copy that line to the new table.
112: */
1.8 nicm 113: if (table != NULL) {
1.1 etheisen 114: get_scrpos(&scrpos);
1.8 nicm 115: free(table);
116: } else {
117: scrpos.pos = -1;
118: }
119: table = ecalloc(sc_height, sizeof (off_t));
1.1 etheisen 120: table_size = sc_height;
121: pos_clear();
1.8 nicm 122: if (scrpos.pos != -1)
1.1 etheisen 123: table[scrpos.ln-1] = scrpos.pos;
124: }
125:
126: /*
127: * See if the byte at a specified position is currently on the screen.
128: * Check the position table to see if the position falls within its range.
129: * Return the position table entry if found, -1 if not.
130: */
1.8 nicm 131: int
132: onscreen(off_t pos)
1.1 etheisen 133: {
1.9 tedu 134: int i;
1.1 etheisen 135:
136: if (pos < table[0])
137: return (-1);
1.11 ! deraadt 138: for (i = 1; i < sc_height; i++)
1.1 etheisen 139: if (pos < table[i])
140: return (i-1);
141: return (-1);
142: }
143:
144: /*
145: * See if the entire screen is empty.
146: */
1.8 nicm 147: int
148: empty_screen(void)
1.1 etheisen 149: {
150: return (empty_lines(0, sc_height-1));
151: }
152:
1.8 nicm 153: int
154: empty_lines(int s, int e)
1.1 etheisen 155: {
1.8 nicm 156: int i;
1.1 etheisen 157:
1.11 ! deraadt 158: for (i = s; i <= e; i++)
1.8 nicm 159: if (table[i] != -1 && table[i] != 0)
1.1 etheisen 160: return (0);
161: return (1);
162: }
163:
164: /*
165: * Get the current screen position.
166: * The screen position consists of both a file position and
167: * a screen line number where the file position is placed on the screen.
168: * Normally the screen line number is 0, but if we are positioned
169: * such that the top few lines are empty, we may have to set
170: * the screen line to a number > 0.
171: */
1.8 nicm 172: void
173: get_scrpos(struct scrpos *scrpos)
1.1 etheisen 174: {
1.8 nicm 175: int i;
1.1 etheisen 176:
177: /*
178: * Find the first line on the screen which has something on it,
179: * and return the screen line number and the file position.
180: */
1.11 ! deraadt 181: for (i = 0; i < sc_height; i++)
1.8 nicm 182: if (table[i] != -1) {
1.1 etheisen 183: scrpos->ln = i+1;
184: scrpos->pos = table[i];
185: return;
186: }
187: /*
188: * The screen is empty.
189: */
1.8 nicm 190: scrpos->pos = -1;
1.1 etheisen 191: }
192:
193: /*
194: * Adjust a screen line number to be a simple positive integer
195: * in the range { 0 .. sc_height-2 }.
196: * (The bottom line, sc_height-1, is reserved for prompts, etc.)
197: * The given "sline" may be in the range { 1 .. sc_height-1 }
198: * to refer to lines relative to the top of the screen (starting from 1),
199: * or it may be in { -1 .. -(sc_height-1) } to refer to lines
200: * relative to the bottom of the screen.
201: */
1.8 nicm 202: int
203: adjsline(int sline)
1.1 etheisen 204: {
205: /*
206: * Negative screen line number means
207: * relative to the bottom of the screen.
208: */
209: if (sline < 0)
210: sline += sc_height;
211: /*
212: * Can't be less than 1 or greater than sc_height-1.
213: */
214: if (sline <= 0)
215: sline = 1;
216: if (sline >= sc_height)
217: sline = sc_height - 1;
218: /*
219: * Return zero-based line number, not one-based.
220: */
221: return (sline-1);
222: }