160786Sps/* 2240121Sdelphij * Copyright (C) 1984-2012 Mark Nudelman 360786Sps * 460786Sps * You may distribute under the terms of either the GNU General Public 560786Sps * License or the Less License, as specified in the README file. 660786Sps * 7240121Sdelphij * For more information, see the README file. 860786Sps */ 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 3960786Spsposition(where) 4060786Sps int where; 4160786Sps{ 4260786Sps switch (where) 4360786Sps { 4460786Sps case BOTTOM: 4560786Sps where = sc_height - 2; 4660786Sps break; 4760786Sps case BOTTOM_PLUS_ONE: 4860786Sps where = sc_height - 1; 4960786Sps break; 5060786Sps case MIDDLE: 5160786Sps where = (sc_height - 1) / 2; 5260786Sps } 5360786Sps return (table[where]); 5460786Sps} 5560786Sps 5660786Sps/* 5760786Sps * Add a new file position to the bottom of the position table. 5860786Sps */ 5960786Sps public void 6060786Spsadd_forw_pos(pos) 6160786Sps POSITION pos; 6260786Sps{ 6360786Sps register int i; 6460786Sps 6560786Sps /* 6660786Sps * Scroll the position table up. 6760786Sps */ 6860786Sps for (i = 1; i < sc_height; i++) 6960786Sps table[i-1] = table[i]; 7060786Sps table[sc_height - 1] = pos; 7160786Sps} 7260786Sps 7360786Sps/* 7460786Sps * Add a new file position to the top of the position table. 7560786Sps */ 7660786Sps public void 7760786Spsadd_back_pos(pos) 7860786Sps POSITION pos; 7960786Sps{ 8060786Sps register int i; 8160786Sps 8260786Sps /* 8360786Sps * Scroll the position table down. 8460786Sps */ 8560786Sps for (i = sc_height - 1; i > 0; i--) 8660786Sps table[i] = table[i-1]; 8760786Sps table[0] = pos; 8860786Sps} 8960786Sps 9060786Sps/* 9160786Sps * Initialize the position table, done whenever we clear the screen. 9260786Sps */ 9360786Sps public void 9460786Spspos_clear() 9560786Sps{ 9660786Sps register int i; 9760786Sps 9860786Sps for (i = 0; i < sc_height; i++) 9960786Sps table[i] = NULL_POSITION; 10060786Sps} 10160786Sps 10260786Sps/* 10360786Sps * Allocate or reallocate the position table. 10460786Sps */ 10560786Sps public void 10660786Spspos_init() 10760786Sps{ 10860786Sps struct scrpos scrpos; 10960786Sps 11060786Sps if (sc_height <= table_size) 11160786Sps return; 11260786Sps /* 11360786Sps * If we already have a table, remember the first line in it 11460786Sps * before we free it, so we can copy that line to the new table. 11560786Sps */ 11660786Sps if (table != NULL) 11760786Sps { 11860786Sps get_scrpos(&scrpos); 11960786Sps free((char*)table); 12060786Sps } else 12160786Sps scrpos.pos = NULL_POSITION; 12260786Sps table = (POSITION *) ecalloc(sc_height, sizeof(POSITION)); 12360786Sps table_size = sc_height; 12460786Sps pos_clear(); 12560786Sps if (scrpos.pos != NULL_POSITION) 12660786Sps table[scrpos.ln-1] = scrpos.pos; 12760786Sps} 12860786Sps 12960786Sps/* 13060786Sps * See if the byte at a specified position is currently on the screen. 13160786Sps * Check the position table to see if the position falls within its range. 13260786Sps * Return the position table entry if found, -1 if not. 13360786Sps */ 13460786Sps public int 13560786Spsonscreen(pos) 13660786Sps POSITION pos; 13760786Sps{ 13860786Sps register int i; 13960786Sps 14060786Sps if (pos < table[0]) 14160786Sps return (-1); 14260786Sps for (i = 1; i < sc_height; i++) 14360786Sps if (pos < table[i]) 14460786Sps return (i-1); 14560786Sps return (-1); 14660786Sps} 14760786Sps 14860786Sps/* 14960786Sps * See if the entire screen is empty. 15060786Sps */ 15160786Sps public int 15260786Spsempty_screen() 15360786Sps{ 15460786Sps return (empty_lines(0, sc_height-1)); 15560786Sps} 15660786Sps 15760786Sps public int 15860786Spsempty_lines(s, e) 15960786Sps int s; 16060786Sps int e; 16160786Sps{ 16260786Sps register int i; 16360786Sps 16460786Sps for (i = s; i <= e; i++) 165251154Sdelphij if (table[i] != NULL_POSITION && table[i] != 0) 16660786Sps return (0); 16760786Sps return (1); 16860786Sps} 16960786Sps 17060786Sps/* 17160786Sps * Get the current screen position. 17260786Sps * The screen position consists of both a file position and 17360786Sps * a screen line number where the file position is placed on the screen. 17460786Sps * Normally the screen line number is 0, but if we are positioned 17560786Sps * such that the top few lines are empty, we may have to set 17660786Sps * the screen line to a number > 0. 17760786Sps */ 17860786Sps public void 17960786Spsget_scrpos(scrpos) 18060786Sps struct scrpos *scrpos; 18160786Sps{ 18260786Sps register int i; 18360786Sps 18460786Sps /* 18560786Sps * Find the first line on the screen which has something on it, 18660786Sps * and return the screen line number and the file position. 18760786Sps */ 18860786Sps for (i = 0; i < sc_height; i++) 18960786Sps if (table[i] != NULL_POSITION) 19060786Sps { 19160786Sps scrpos->ln = i+1; 19260786Sps scrpos->pos = table[i]; 19360786Sps return; 19460786Sps } 19560786Sps /* 19660786Sps * The screen is empty. 19760786Sps */ 19860786Sps scrpos->pos = NULL_POSITION; 19960786Sps} 20060786Sps 20160786Sps/* 20260786Sps * Adjust a screen line number to be a simple positive integer 20360786Sps * in the range { 0 .. sc_height-2 }. 20460786Sps * (The bottom line, sc_height-1, is reserved for prompts, etc.) 20560786Sps * The given "sline" may be in the range { 1 .. sc_height-1 } 20660786Sps * to refer to lines relative to the top of the screen (starting from 1), 20760786Sps * or it may be in { -1 .. -(sc_height-1) } to refer to lines 20860786Sps * relative to the bottom of the screen. 20960786Sps */ 21060786Sps public int 21160786Spsadjsline(sline) 21260786Sps int sline; 21360786Sps{ 21460786Sps /* 21560786Sps * Negative screen line number means 21660786Sps * relative to the bottom of the screen. 21760786Sps */ 21860786Sps if (sline < 0) 21960786Sps sline += sc_height; 22060786Sps /* 22160786Sps * Can't be less than 1 or greater than sc_height-1. 22260786Sps */ 22360786Sps if (sline <= 0) 22460786Sps sline = 1; 22560786Sps if (sline >= sc_height) 22660786Sps sline = sc_height - 1; 22760786Sps /* 22860786Sps * Return zero-based line number, not one-based. 22960786Sps */ 23060786Sps return (sline-1); 23160786Sps} 232