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