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