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