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