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