position.c revision 1.3 1 1.3 tron /* $NetBSD: position.c,v 1.3 2011/07/03 20:14:13 tron Exp $ */
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.3 tron scrpos.pos = scrpos.ln = 0; /* XXX: GCC */
113 1.1 tron
114 1.1 tron if (sc_height <= table_size)
115 1.1 tron return;
116 1.1 tron /*
117 1.1 tron * If we already have a table, remember the first line in it
118 1.1 tron * before we free it, so we can copy that line to the new table.
119 1.1 tron */
120 1.1 tron if (table != NULL)
121 1.1 tron {
122 1.1 tron get_scrpos(&scrpos);
123 1.1 tron free((char*)table);
124 1.1 tron } else
125 1.1 tron scrpos.pos = NULL_POSITION;
126 1.1 tron table = (POSITION *) ecalloc(sc_height, sizeof(POSITION));
127 1.1 tron table_size = sc_height;
128 1.1 tron pos_clear();
129 1.1 tron if (scrpos.pos != NULL_POSITION)
130 1.1 tron table[scrpos.ln-1] = scrpos.pos;
131 1.1 tron }
132 1.1 tron
133 1.1 tron /*
134 1.1 tron * See if the byte at a specified position is currently on the screen.
135 1.1 tron * Check the position table to see if the position falls within its range.
136 1.1 tron * Return the position table entry if found, -1 if not.
137 1.1 tron */
138 1.1 tron public int
139 1.1 tron onscreen(pos)
140 1.1 tron POSITION pos;
141 1.1 tron {
142 1.1 tron register int i;
143 1.1 tron
144 1.1 tron if (pos < table[0])
145 1.1 tron return (-1);
146 1.1 tron for (i = 1; i < sc_height; i++)
147 1.1 tron if (pos < table[i])
148 1.1 tron return (i-1);
149 1.1 tron return (-1);
150 1.1 tron }
151 1.1 tron
152 1.1 tron /*
153 1.1 tron * See if the entire screen is empty.
154 1.1 tron */
155 1.1 tron public int
156 1.1 tron empty_screen()
157 1.1 tron {
158 1.1 tron return (empty_lines(0, sc_height-1));
159 1.1 tron }
160 1.1 tron
161 1.1 tron public int
162 1.1 tron empty_lines(s, e)
163 1.1 tron int s;
164 1.1 tron int e;
165 1.1 tron {
166 1.1 tron register int i;
167 1.1 tron
168 1.1 tron for (i = s; i <= e; i++)
169 1.1 tron if (table[i] != NULL_POSITION)
170 1.1 tron return (0);
171 1.1 tron return (1);
172 1.1 tron }
173 1.1 tron
174 1.1 tron /*
175 1.1 tron * Get the current screen position.
176 1.1 tron * The screen position consists of both a file position and
177 1.1 tron * a screen line number where the file position is placed on the screen.
178 1.1 tron * Normally the screen line number is 0, but if we are positioned
179 1.1 tron * such that the top few lines are empty, we may have to set
180 1.1 tron * the screen line to a number > 0.
181 1.1 tron */
182 1.1 tron public void
183 1.1 tron get_scrpos(scrpos)
184 1.1 tron struct scrpos *scrpos;
185 1.1 tron {
186 1.1 tron register int i;
187 1.1 tron
188 1.1 tron /*
189 1.1 tron * Find the first line on the screen which has something on it,
190 1.1 tron * and return the screen line number and the file position.
191 1.1 tron */
192 1.1 tron for (i = 0; i < sc_height; i++)
193 1.1 tron if (table[i] != NULL_POSITION)
194 1.1 tron {
195 1.1 tron scrpos->ln = i+1;
196 1.1 tron scrpos->pos = table[i];
197 1.1 tron return;
198 1.1 tron }
199 1.1 tron /*
200 1.1 tron * The screen is empty.
201 1.1 tron */
202 1.1 tron scrpos->pos = NULL_POSITION;
203 1.1 tron }
204 1.1 tron
205 1.1 tron /*
206 1.1 tron * Adjust a screen line number to be a simple positive integer
207 1.1 tron * in the range { 0 .. sc_height-2 }.
208 1.1 tron * (The bottom line, sc_height-1, is reserved for prompts, etc.)
209 1.1 tron * The given "sline" may be in the range { 1 .. sc_height-1 }
210 1.1 tron * to refer to lines relative to the top of the screen (starting from 1),
211 1.1 tron * or it may be in { -1 .. -(sc_height-1) } to refer to lines
212 1.1 tron * relative to the bottom of the screen.
213 1.1 tron */
214 1.1 tron public int
215 1.1 tron adjsline(sline)
216 1.1 tron int sline;
217 1.1 tron {
218 1.1 tron /*
219 1.1 tron * Negative screen line number means
220 1.1 tron * relative to the bottom of the screen.
221 1.1 tron */
222 1.1 tron if (sline < 0)
223 1.1 tron sline += sc_height;
224 1.1 tron /*
225 1.1 tron * Can't be less than 1 or greater than sc_height-1.
226 1.1 tron */
227 1.1 tron if (sline <= 0)
228 1.1 tron sline = 1;
229 1.1 tron if (sline >= sc_height)
230 1.1 tron sline = sc_height - 1;
231 1.1 tron /*
232 1.1 tron * Return zero-based line number, not one-based.
233 1.1 tron */
234 1.1 tron return (sline-1);
235 1.1 tron }
236