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