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