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