position.c revision 195941
1258945Sroberto/* 2258945Sroberto * Copyright (C) 1984-2009 Mark Nudelman 3258945Sroberto * 4258945Sroberto * You may distribute under the terms of either the GNU General Public 5258945Sroberto * License or the Less License, as specified in the README file. 6258945Sroberto * 7258945Sroberto * For more information about less, or for information on how to 8258945Sroberto * contact the author, see the README file. 9258945Sroberto */ 10258945Sroberto 11258945Sroberto 12258945Sroberto/* 13258945Sroberto * Routines dealing with the "position" table. 14258945Sroberto * This is a table which tells the position (in the input file) of the 15258945Sroberto * first char on each currently displayed line. 16258945Sroberto * 17258945Sroberto * {{ The position table is scrolled by moving all the entries. 18258945Sroberto * Would be better to have a circular table 19258945Sroberto * and just change a couple of pointers. }} 20258945Sroberto */ 21258945Sroberto 22258945Sroberto#include "less.h" 23258945Sroberto#include "position.h" 24258945Sroberto 25258945Srobertostatic POSITION *table = NULL; /* The position table */ 26258945Srobertostatic int table_size; 27258945Sroberto 28258945Srobertoextern int sc_width, sc_height; 29258945Sroberto 30258945Sroberto/* 31258945Sroberto * Return the starting file position of a line displayed on the screen. 32258945Sroberto * The line may be specified as a line number relative to the top 33258945Sroberto * of the screen, but is usually one of these special cases: 34258945Sroberto * the top (first) line on the screen 35258945Sroberto * the second line on the screen 36280849Scy * the bottom line on the screen 37280849Scy * the line after the bottom line on the screen 38280849Scy */ 39280849Scy public POSITION 40258945Srobertoposition(where) 41280849Scy int where; 42258945Sroberto{ 43258945Sroberto switch (where) 44258945Sroberto { 45258945Sroberto case BOTTOM: 46258945Sroberto where = sc_height - 2; 47258945Sroberto break; 48258945Sroberto case BOTTOM_PLUS_ONE: 49258945Sroberto where = sc_height - 1; 50258945Sroberto break; 51258945Sroberto case MIDDLE: 52258945Sroberto where = (sc_height - 1) / 2; 53258945Sroberto } 54258945Sroberto return (table[where]); 55258945Sroberto} 56258945Sroberto 57258945Sroberto/* 58258945Sroberto * Add a new file position to the bottom of the position table. 59258945Sroberto */ 60258945Sroberto public void 61258945Srobertoadd_forw_pos(pos) 62258945Sroberto POSITION pos; 63258945Sroberto{ 64258945Sroberto register int i; 65258945Sroberto 66258945Sroberto /* 67258945Sroberto * Scroll the position table up. 68258945Sroberto */ 69258945Sroberto for (i = 1; i < sc_height; i++) 70258945Sroberto table[i-1] = table[i]; 71258945Sroberto table[sc_height - 1] = pos; 72258945Sroberto} 73258945Sroberto 74258945Sroberto/* 75258945Sroberto * Add a new file position to the top of the position table. 76258945Sroberto */ 77258945Sroberto public void 78258945Srobertoadd_back_pos(pos) 79258945Sroberto POSITION pos; 80258945Sroberto{ 81258945Sroberto register int i; 82258945Sroberto 83258945Sroberto /* 84258945Sroberto * Scroll the position table down. 85258945Sroberto */ 86258945Sroberto for (i = sc_height - 1; i > 0; i--) 87258945Sroberto table[i] = table[i-1]; 88258945Sroberto table[0] = pos; 89258945Sroberto} 90258945Sroberto 91258945Sroberto/* 92258945Sroberto * Initialize the position table, done whenever we clear the screen. 93258945Sroberto */ 94258945Sroberto public void 95258945Srobertopos_clear() 96258945Sroberto{ 97258945Sroberto register int i; 98258945Sroberto 99258945Sroberto for (i = 0; i < sc_height; i++) 100258945Sroberto table[i] = NULL_POSITION; 101258945Sroberto} 102258945Sroberto 103258945Sroberto/* 104258945Sroberto * Allocate or reallocate the position table. 105258945Sroberto */ 106280849Scy public void 107258945Srobertopos_init() 108258945Sroberto{ 109258945Sroberto struct scrpos scrpos; 110258945Sroberto 111280849Scy if (sc_height <= table_size) 112258945Sroberto return; 113258945Sroberto /* 114258945Sroberto * If we already have a table, remember the first line in it 115258945Sroberto * before we free it, so we can copy that line to the new table. 116258945Sroberto */ 117280849Scy if (table != NULL) 118258945Sroberto { 119258945Sroberto get_scrpos(&scrpos); 120258945Sroberto free((char*)table); 121258945Sroberto } else 122258945Sroberto scrpos.pos = NULL_POSITION; 123258945Sroberto table = (POSITION *) ecalloc(sc_height, sizeof(POSITION)); 124280849Scy table_size = sc_height; 125258945Sroberto pos_clear(); 126258945Sroberto if (scrpos.pos != NULL_POSITION) 127258945Sroberto table[scrpos.ln-1] = scrpos.pos; 128280849Scy} 129280849Scy 130258945Sroberto/* 131280849Scy * See if the byte at a specified position is currently on the screen. 132258945Sroberto * Check the position table to see if the position falls within its range. 133258945Sroberto * Return the position table entry if found, -1 if not. 134258945Sroberto */ 135258945Sroberto public int 136258945Srobertoonscreen(pos) 137258945Sroberto POSITION pos; 138258945Sroberto{ 139258945Sroberto register int i; 140258945Sroberto 141258945Sroberto if (pos < table[0]) 142258945Sroberto return (-1); 143258945Sroberto for (i = 1; i < sc_height; i++) 144258945Sroberto if (pos < table[i]) 145258945Sroberto return (i-1); 146258945Sroberto return (-1); 147258945Sroberto} 148258945Sroberto 149258945Sroberto/* 150258945Sroberto * See if the entire screen is empty. 151258945Sroberto */ 152258945Sroberto public int 153258945Srobertoempty_screen() 154258945Sroberto{ 155258945Sroberto return (empty_lines(0, sc_height-1)); 156258945Sroberto} 157258945Sroberto 158258945Sroberto public int 159258945Srobertoempty_lines(s, e) 160258945Sroberto int s; 161258945Sroberto int e; 162258945Sroberto{ 163258945Sroberto register int i; 164258945Sroberto 165258945Sroberto for (i = s; i <= e; i++) 166258945Sroberto if (table[i] != NULL_POSITION) 167258945Sroberto return (0); 168258945Sroberto return (1); 169258945Sroberto} 170258945Sroberto 171258945Sroberto/* 172258945Sroberto * Get the current screen position. 173258945Sroberto * The screen position consists of both a file position and 174258945Sroberto * a screen line number where the file position is placed on the screen. 175258945Sroberto * Normally the screen line number is 0, but if we are positioned 176258945Sroberto * such that the top few lines are empty, we may have to set 177258945Sroberto * the screen line to a number > 0. 178280849Scy */ 179280849Scy public void 180280849Scyget_scrpos(scrpos) 181280849Scy struct scrpos *scrpos; 182280849Scy{ 183280849Scy register int i; 184280849Scy 185280849Scy /* 186280849Scy * Find the first line on the screen which has something on it, 187280849Scy * and return the screen line number and the file position. 188280849Scy */ 189280849Scy for (i = 0; i < sc_height; i++) 190280849Scy if (table[i] != NULL_POSITION) 191280849Scy { 192280849Scy scrpos->ln = i+1; 193280849Scy scrpos->pos = table[i]; 194280849Scy return; 195258945Sroberto } 196280849Scy /* 197280849Scy * The screen is empty. 198280849Scy */ 199280849Scy scrpos->pos = NULL_POSITION; 200280849Scy} 201280849Scy 202280849Scy/* 203280849Scy * Adjust a screen line number to be a simple positive integer 204280849Scy * in the range { 0 .. sc_height-2 }. 205280849Scy * (The bottom line, sc_height-1, is reserved for prompts, etc.) 206280849Scy * The given "sline" may be in the range { 1 .. sc_height-1 } 207280849Scy * to refer to lines relative to the top of the screen (starting from 1), 208280849Scy * or it may be in { -1 .. -(sc_height-1) } to refer to lines 209280849Scy * relative to the bottom of the screen. 210 */ 211 public int 212adjsline(sline) 213 int sline; 214{ 215 /* 216 * Negative screen line number means 217 * relative to the bottom of the screen. 218 */ 219 if (sline < 0) 220 sline += sc_height; 221 /* 222 * Can't be less than 1 or greater than sc_height-1. 223 */ 224 if (sline <= 0) 225 sline = 1; 226 if (sline >= sc_height) 227 sline = sc_height - 1; 228 /* 229 * Return zero-based line number, not one-based. 230 */ 231 return (sline-1); 232} 233