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