1238730Sdelphij/* 2330571Sdelphij * Copyright (C) 1984-2017 Mark Nudelman 3238730Sdelphij * 4238730Sdelphij * You may distribute under the terms of either the GNU General Public 5238730Sdelphij * License or the Less License, as specified in the README file. 6238730Sdelphij * 7238730Sdelphij * For more information, see the README file. 8238730Sdelphij */ 960786Sps 1060786Sps 1160786Sps/* 1260786Sps * Routines dealing with the "position" table. 1360786Sps * This is a table which tells the position (in the input file) of the 1460786Sps * first char on each currently displayed line. 1560786Sps * 1660786Sps * {{ The position table is scrolled by moving all the entries. 1760786Sps * Would be better to have a circular table 1860786Sps * and just change a couple of pointers. }} 1960786Sps */ 2060786Sps 2160786Sps#include "less.h" 2260786Sps#include "position.h" 2360786Sps 2460786Spsstatic POSITION *table = NULL; /* The position table */ 2560786Spsstatic int table_size; 2660786Sps 2760786Spsextern int sc_width, sc_height; 2860786Sps 2960786Sps/* 3060786Sps * Return the starting file position of a line displayed on the screen. 3160786Sps * The line may be specified as a line number relative to the top 3260786Sps * of the screen, but is usually one of these special cases: 3360786Sps * the top (first) line on the screen 3460786Sps * the second line on the screen 3560786Sps * the bottom line on the screen 3660786Sps * the line after the bottom line on the screen 3760786Sps */ 3860786Sps public POSITION 39330571Sdelphijposition(sindex) 40330571Sdelphij int sindex; 4160786Sps{ 42330571Sdelphij switch (sindex) 4360786Sps { 4460786Sps case BOTTOM: 45330571Sdelphij sindex = sc_height - 2; 4660786Sps break; 4760786Sps case BOTTOM_PLUS_ONE: 48330571Sdelphij sindex = sc_height - 1; 4960786Sps break; 5060786Sps case MIDDLE: 51330571Sdelphij sindex = (sc_height - 1) / 2; 52330571Sdelphij break; 5360786Sps } 54330571Sdelphij return (table[sindex]); 5560786Sps} 5660786Sps 5760786Sps/* 5860786Sps * Add a new file position to the bottom of the position table. 5960786Sps */ 6060786Sps public void 6160786Spsadd_forw_pos(pos) 6260786Sps POSITION pos; 6360786Sps{ 64330571Sdelphij int i; 6560786Sps 6660786Sps /* 6760786Sps * Scroll the position table up. 6860786Sps */ 6960786Sps for (i = 1; i < sc_height; i++) 7060786Sps table[i-1] = table[i]; 7160786Sps table[sc_height - 1] = pos; 7260786Sps} 7360786Sps 7460786Sps/* 7560786Sps * Add a new file position to the top of the position table. 7660786Sps */ 7760786Sps public void 7860786Spsadd_back_pos(pos) 7960786Sps POSITION pos; 8060786Sps{ 81330571Sdelphij int i; 8260786Sps 8360786Sps /* 8460786Sps * Scroll the position table down. 8560786Sps */ 8660786Sps for (i = sc_height - 1; i > 0; i--) 8760786Sps table[i] = table[i-1]; 8860786Sps table[0] = pos; 8960786Sps} 9060786Sps 9160786Sps/* 9260786Sps * Initialize the position table, done whenever we clear the screen. 9360786Sps */ 9460786Sps public void 9560786Spspos_clear() 9660786Sps{ 97330571Sdelphij int i; 9860786Sps 9960786Sps for (i = 0; i < sc_height; i++) 10060786Sps table[i] = NULL_POSITION; 10160786Sps} 10260786Sps 10360786Sps/* 10460786Sps * Allocate or reallocate the position table. 10560786Sps */ 10660786Sps public void 10760786Spspos_init() 10860786Sps{ 10960786Sps struct scrpos scrpos; 11060786Sps 11160786Sps if (sc_height <= table_size) 11260786Sps return; 11360786Sps /* 11460786Sps * If we already have a table, remember the first line in it 11560786Sps * before we free it, so we can copy that line to the new table. 11660786Sps */ 11760786Sps if (table != NULL) 11860786Sps { 119330571Sdelphij get_scrpos(&scrpos, TOP); 12060786Sps free((char*)table); 12160786Sps } else 12260786Sps scrpos.pos = NULL_POSITION; 12360786Sps table = (POSITION *) ecalloc(sc_height, sizeof(POSITION)); 12460786Sps table_size = sc_height; 12560786Sps pos_clear(); 12660786Sps if (scrpos.pos != NULL_POSITION) 12760786Sps table[scrpos.ln-1] = scrpos.pos; 12860786Sps} 12960786Sps 13060786Sps/* 13160786Sps * See if the byte at a specified position is currently on the screen. 13260786Sps * Check the position table to see if the position falls within its range. 13360786Sps * Return the position table entry if found, -1 if not. 13460786Sps */ 13560786Sps public int 13660786Spsonscreen(pos) 13760786Sps POSITION pos; 13860786Sps{ 139330571Sdelphij int i; 14060786Sps 14160786Sps if (pos < table[0]) 14260786Sps return (-1); 14360786Sps for (i = 1; i < sc_height; i++) 14460786Sps if (pos < table[i]) 14560786Sps return (i-1); 14660786Sps return (-1); 14760786Sps} 14860786Sps 14960786Sps/* 15060786Sps * See if the entire screen is empty. 15160786Sps */ 15260786Sps public int 15360786Spsempty_screen() 15460786Sps{ 15560786Sps return (empty_lines(0, sc_height-1)); 15660786Sps} 15760786Sps 15860786Sps public int 15960786Spsempty_lines(s, e) 16060786Sps int s; 16160786Sps int e; 16260786Sps{ 163330571Sdelphij int i; 16460786Sps 16560786Sps for (i = s; i <= e; i++) 166242584Sdelphij if (table[i] != NULL_POSITION && table[i] != 0) 16760786Sps return (0); 16860786Sps return (1); 16960786Sps} 17060786Sps 17160786Sps/* 17260786Sps * Get the current screen position. 17360786Sps * The screen position consists of both a file position and 17460786Sps * a screen line number where the file position is placed on the screen. 17560786Sps * Normally the screen line number is 0, but if we are positioned 17660786Sps * such that the top few lines are empty, we may have to set 17760786Sps * the screen line to a number > 0. 17860786Sps */ 17960786Sps public void 180330571Sdelphijget_scrpos(scrpos, where) 18160786Sps struct scrpos *scrpos; 182330571Sdelphij int where; 18360786Sps{ 184330571Sdelphij int i; 185330571Sdelphij int dir; 186330571Sdelphij int last; 18760786Sps 188330571Sdelphij switch (where) 189330571Sdelphij { 190330571Sdelphij case TOP: i = 0; dir = +1; last = sc_height-2; break; 191330571Sdelphij default: i = sc_height-2; dir = -1; last = 0; break; 192330571Sdelphij } 193330571Sdelphij 19460786Sps /* 19560786Sps * Find the first line on the screen which has something on it, 19660786Sps * and return the screen line number and the file position. 19760786Sps */ 198330571Sdelphij for (;; i += dir) 199330571Sdelphij { 20060786Sps if (table[i] != NULL_POSITION) 20160786Sps { 20260786Sps scrpos->ln = i+1; 20360786Sps scrpos->pos = table[i]; 20460786Sps return; 20560786Sps } 206330571Sdelphij if (i == last) break; 207330571Sdelphij } 20860786Sps /* 20960786Sps * The screen is empty. 21060786Sps */ 21160786Sps scrpos->pos = NULL_POSITION; 21260786Sps} 21360786Sps 21460786Sps/* 21560786Sps * Adjust a screen line number to be a simple positive integer 21660786Sps * in the range { 0 .. sc_height-2 }. 21760786Sps * (The bottom line, sc_height-1, is reserved for prompts, etc.) 21860786Sps * The given "sline" may be in the range { 1 .. sc_height-1 } 21960786Sps * to refer to lines relative to the top of the screen (starting from 1), 22060786Sps * or it may be in { -1 .. -(sc_height-1) } to refer to lines 22160786Sps * relative to the bottom of the screen. 22260786Sps */ 22360786Sps public int 224330571Sdelphijsindex_from_sline(sline) 22560786Sps int sline; 22660786Sps{ 22760786Sps /* 22860786Sps * Negative screen line number means 22960786Sps * relative to the bottom of the screen. 23060786Sps */ 23160786Sps if (sline < 0) 23260786Sps sline += sc_height; 23360786Sps /* 234330571Sdelphij * Can't be less than 1 or greater than sc_height. 23560786Sps */ 23660786Sps if (sline <= 0) 23760786Sps sline = 1; 238330571Sdelphij if (sline > sc_height) 239330571Sdelphij sline = sc_height; 24060786Sps /* 24160786Sps * Return zero-based line number, not one-based. 24260786Sps */ 24360786Sps return (sline-1); 24460786Sps} 245