Annotation of src/usr.bin/less/position.c, Revision 1.2
1.1 etheisen 1: /*
2: * Copyright (c) 1984,1985,1989,1994,1995 Mark Nudelman
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms, with or without
6: * modification, are permitted provided that the following conditions
7: * are met:
8: * 1. Redistributions of source code must retain the above copyright
9: * notice, this list of conditions and the following disclaimer.
10: * 2. Redistributions in binary form must reproduce the above copyright
11: * notice in the documentation and/or other materials provided with
12: * the distribution.
13: *
14: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY
15: * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE
18: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
20: * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
21: * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22: * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
23: * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
24: * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25: */
26:
27:
28: /*
29: * Routines dealing with the "position" table.
30: * This is a table which tells the position (in the input file) of the
31: * first char on each currently displayed line.
32: *
33: * {{ The position table is scrolled by moving all the entries.
34: * Would be better to have a circular table
35: * and just change a couple of pointers. }}
36: */
37:
38: #include "less.h"
39: #include "position.h"
40:
41: static POSITION *table = NULL; /* The position table */
42: static int table_size;
43:
44: extern int sc_width, sc_height;
45:
46: /*
47: * Return the starting file position of a line displayed on the screen.
48: * The line may be specified as a line number relative to the top
49: * of the screen, but is usually one of these special cases:
50: * the top (first) line on the screen
51: * the second line on the screen
52: * the bottom line on the screen
53: * the line after the bottom line on the screen
54: */
55: public POSITION
56: position(where)
57: int where;
58: {
1.2 ! millert 59: if (where >= table_size)
! 60: where = BOTTOM;
! 61:
1.1 etheisen 62: switch (where)
63: {
64: case BOTTOM:
65: where = sc_height - 2;
66: break;
67: case BOTTOM_PLUS_ONE:
68: where = sc_height - 1;
69: break;
70: case MIDDLE:
71: where = (sc_height - 1) / 2;
72: }
73: return (table[where]);
74: }
75:
76: /*
77: * Add a new file position to the bottom of the position table.
78: */
79: public void
80: add_forw_pos(pos)
81: POSITION pos;
82: {
83: register int i;
84:
85: /*
86: * Scroll the position table up.
87: */
88: for (i = 1; i < sc_height; i++)
89: table[i-1] = table[i];
90: table[sc_height - 1] = pos;
91: }
92:
93: /*
94: * Add a new file position to the top of the position table.
95: */
96: public void
97: add_back_pos(pos)
98: POSITION pos;
99: {
100: register int i;
101:
102: /*
103: * Scroll the position table down.
104: */
105: for (i = sc_height - 1; i > 0; i--)
106: table[i] = table[i-1];
107: table[0] = pos;
108: }
109:
110: /*
111: * Initialize the position table, done whenever we clear the screen.
112: */
113: public void
114: pos_clear()
115: {
116: register int i;
117:
118: for (i = 0; i < sc_height; i++)
119: table[i] = NULL_POSITION;
120: }
121:
122: /*
123: * Allocate or reallocate the position table.
124: */
125: public void
126: pos_init()
127: {
128: struct scrpos scrpos;
129:
130: if (sc_height <= table_size)
131: return;
132: /*
133: * If we already have a table, remember the first line in it
134: * before we free it, so we can copy that line to the new table.
135: */
136: if (table != NULL)
137: {
138: get_scrpos(&scrpos);
139: free((char*)table);
140: } else
141: scrpos.pos = NULL_POSITION;
142: table = (POSITION *) ecalloc(sc_height, sizeof(POSITION));
143: table_size = sc_height;
144: pos_clear();
145: if (scrpos.pos != NULL_POSITION)
146: table[scrpos.ln-1] = scrpos.pos;
147: }
148:
149: /*
150: * See if the byte at a specified position is currently on the screen.
151: * Check the position table to see if the position falls within its range.
152: * Return the position table entry if found, -1 if not.
153: */
154: public int
155: onscreen(pos)
156: POSITION pos;
157: {
158: register int i;
159:
160: if (pos < table[0])
161: return (-1);
162: for (i = 1; i < sc_height; i++)
163: if (pos < table[i])
164: return (i-1);
165: return (-1);
166: }
167:
168: /*
169: * See if the entire screen is empty.
170: */
171: public int
172: empty_screen()
173: {
174: return (empty_lines(0, sc_height-1));
175: }
176:
177: public int
178: empty_lines(s, e)
179: int s;
180: int e;
181: {
182: register int i;
183:
184: for (i = s; i <= e; i++)
185: if (table[i] != NULL_POSITION)
186: return (0);
187: return (1);
188: }
189:
190: /*
191: * Get the current screen position.
192: * The screen position consists of both a file position and
193: * a screen line number where the file position is placed on the screen.
194: * Normally the screen line number is 0, but if we are positioned
195: * such that the top few lines are empty, we may have to set
196: * the screen line to a number > 0.
197: */
198: public void
199: get_scrpos(scrpos)
200: struct scrpos *scrpos;
201: {
202: register int i;
203:
204: /*
205: * Find the first line on the screen which has something on it,
206: * and return the screen line number and the file position.
207: */
208: for (i = 0; i < sc_height; i++)
209: if (table[i] != NULL_POSITION)
210: {
211: scrpos->ln = i+1;
212: scrpos->pos = table[i];
213: return;
214: }
215: /*
216: * The screen is empty.
217: */
218: scrpos->pos = NULL_POSITION;
219: }
220:
221: /*
222: * Adjust a screen line number to be a simple positive integer
223: * in the range { 0 .. sc_height-2 }.
224: * (The bottom line, sc_height-1, is reserved for prompts, etc.)
225: * The given "sline" may be in the range { 1 .. sc_height-1 }
226: * to refer to lines relative to the top of the screen (starting from 1),
227: * or it may be in { -1 .. -(sc_height-1) } to refer to lines
228: * relative to the bottom of the screen.
229: */
230: public int
231: adjsline(sline)
232: int sline;
233: {
234: /*
235: * Negative screen line number means
236: * relative to the bottom of the screen.
237: */
238: if (sline < 0)
239: sline += sc_height;
240: /*
241: * Can't be less than 1 or greater than sc_height-1.
242: */
243: if (sline <= 0)
244: sline = 1;
245: if (sline >= sc_height)
246: sline = sc_height - 1;
247: /*
248: * Return zero-based line number, not one-based.
249: */
250: return (sline-1);
251: }