position.c revision 60786
160786Sps/* 260786Sps * Copyright (C) 1984-2000 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 * 760786Sps * For more information about less, or for information on how to 860786Sps * contact the author, see the README file. 960786Sps */ 1060786Sps 1160786Sps 1260786Sps/* 1360786Sps * Routines dealing with the "position" table. 1460786Sps * This is a table which tells the position (in the input file) of the 1560786Sps * first char on each currently displayed line. 1660786Sps * 1760786Sps * {{ The position table is scrolled by moving all the entries. 1860786Sps * Would be better to have a circular table 1960786Sps * and just change a couple of pointers. }} 2060786Sps */ 2160786Sps 2260786Sps#include "less.h" 2360786Sps#include "position.h" 2460786Sps 2560786Spsstatic POSITION *table = NULL; /* The position table */ 2660786Spsstatic int table_size; 2760786Sps 2860786Spsextern int sc_width, sc_height; 2960786Sps 3060786Sps/* 3160786Sps * Return the starting file position of a line displayed on the screen. 3260786Sps * The line may be specified as a line number relative to the top 3360786Sps * of the screen, but is usually one of these special cases: 3460786Sps * the top (first) line on the screen 3560786Sps * the second line on the screen 3660786Sps * the bottom line on the screen 3760786Sps * the line after the bottom line on the screen 3860786Sps */ 3960786Sps public POSITION 4060786Spsposition(where) 4160786Sps int where; 4260786Sps{ 4360786Sps switch (where) 4460786Sps { 4560786Sps case BOTTOM: 4660786Sps where = sc_height - 2; 4760786Sps break; 4860786Sps case BOTTOM_PLUS_ONE: 4960786Sps where = sc_height - 1; 5060786Sps break; 5160786Sps case MIDDLE: 5260786Sps where = (sc_height - 1) / 2; 5360786Sps } 5460786Sps return (table[where]); 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{ 6460786Sps register 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{ 8160786Sps register 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{ 9760786Sps register 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 { 11960786Sps get_scrpos(&scrpos); 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{ 13960786Sps register 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{ 16360786Sps register int i; 16460786Sps 16560786Sps for (i = s; i <= e; i++) 16660786Sps if (table[i] != NULL_POSITION) 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 18060786Spsget_scrpos(scrpos) 18160786Sps struct scrpos *scrpos; 18260786Sps{ 18360786Sps register int i; 18460786Sps 18560786Sps /* 18660786Sps * Find the first line on the screen which has something on it, 18760786Sps * and return the screen line number and the file position. 18860786Sps */ 18960786Sps for (i = 0; i < sc_height; i++) 19060786Sps if (table[i] != NULL_POSITION) 19160786Sps { 19260786Sps scrpos->ln = i+1; 19360786Sps scrpos->pos = table[i]; 19460786Sps return; 19560786Sps } 19660786Sps /* 19760786Sps * The screen is empty. 19860786Sps */ 19960786Sps scrpos->pos = NULL_POSITION; 20060786Sps} 20160786Sps 20260786Sps/* 20360786Sps * Adjust a screen line number to be a simple positive integer 20460786Sps * in the range { 0 .. sc_height-2 }. 20560786Sps * (The bottom line, sc_height-1, is reserved for prompts, etc.) 20660786Sps * The given "sline" may be in the range { 1 .. sc_height-1 } 20760786Sps * to refer to lines relative to the top of the screen (starting from 1), 20860786Sps * or it may be in { -1 .. -(sc_height-1) } to refer to lines 20960786Sps * relative to the bottom of the screen. 21060786Sps */ 21160786Sps public int 21260786Spsadjsline(sline) 21360786Sps int sline; 21460786Sps{ 21560786Sps /* 21660786Sps * Negative screen line number means 21760786Sps * relative to the bottom of the screen. 21860786Sps */ 21960786Sps if (sline < 0) 22060786Sps sline += sc_height; 22160786Sps /* 22260786Sps * Can't be less than 1 or greater than sc_height-1. 22360786Sps */ 22460786Sps if (sline <= 0) 22560786Sps sline = 1; 22660786Sps if (sline >= sc_height) 22760786Sps sline = sc_height - 1; 22860786Sps /* 22960786Sps * Return zero-based line number, not one-based. 23060786Sps */ 23160786Sps return (sline-1); 23260786Sps} 233