position.c revision 251154
11573Srgrimes/* 21573Srgrimes * Copyright (C) 1984-2012 Mark Nudelman 31573Srgrimes * 41573Srgrimes * You may distribute under the terms of either the GNU General Public 51573Srgrimes * License or the Less License, as specified in the README file. 61573Srgrimes * 71573Srgrimes * For more information, see the README file. 81573Srgrimes */ 91573Srgrimes 101573Srgrimes 111573Srgrimes/* 121573Srgrimes * Routines dealing with the "position" table. 131573Srgrimes * This is a table which tells the position (in the input file) of the 141573Srgrimes * first char on each currently displayed line. 151573Srgrimes * 161573Srgrimes * {{ The position table is scrolled by moving all the entries. 171573Srgrimes * Would be better to have a circular table 181573Srgrimes * and just change a couple of pointers. }} 191573Srgrimes */ 201573Srgrimes 211573Srgrimes#include "less.h" 221573Srgrimes#include "position.h" 231573Srgrimes 241573Srgrimesstatic POSITION *table = NULL; /* The position table */ 251573Srgrimesstatic int table_size; 261573Srgrimes 271573Srgrimesextern int sc_width, sc_height; 281573Srgrimes 291573Srgrimes/* 301573Srgrimes * Return the starting file position of a line displayed on the screen. 311573Srgrimes * The line may be specified as a line number relative to the top 321573Srgrimes * of the screen, but is usually one of these special cases: 3350476Speter * the top (first) line on the screen 341573Srgrimes * the second line on the screen 35200019Sbrueffer * the bottom line on the screen 361573Srgrimes * the line after the bottom line on the screen 371573Srgrimes */ 381573Srgrimes public POSITION 39189356Sdasposition(where) 40189356Sdas int where; 411573Srgrimes{ 4259460Sphantom switch (where) 4359460Sphantom { 441573Srgrimes case BOTTOM: 45189356Sdas where = sc_height - 2; 4684306Sru break; 471573Srgrimes case BOTTOM_PLUS_ONE: 48103012Stjr where = sc_height - 1; 491573Srgrimes break; 50103012Stjr case MIDDLE: 511573Srgrimes where = (sc_height - 1) / 2; 52103012Stjr } 531573Srgrimes return (table[where]); 54103012Stjr} 5515931Speter 5615931Speter/* 57189356Sdas * Add a new file position to the bottom of the position table. 58200019Sbrueffer */ 5984306Sru public void 601573Srgrimesadd_forw_pos(pos) 61103012Stjr POSITION pos; 621573Srgrimes{ 63103012Stjr register int i; 641573Srgrimes 65103012Stjr /* 661573Srgrimes * Scroll the position table up. 67103012Stjr */ 6815931Speter for (i = 1; i < sc_height; i++) 6915931Speter table[i-1] = table[i]; 70189356Sdas table[sc_height - 1] = pos; 71189356Sdas} 721573Srgrimes 731573Srgrimes/* 741573Srgrimes * Add a new file position to the top of the position table. 751573Srgrimes */ 761573Srgrimes public void 771573Srgrimesadd_back_pos(pos) 78108037Sru POSITION pos; 79108037Sru{ 801573Srgrimes register int i; 811573Srgrimes 82108037Sru /* 831573Srgrimes * Scroll the position table down. 84107619Sru */ 851573Srgrimes for (i = sc_height - 1; i > 0; i--) 861573Srgrimes table[i] = table[i-1]; 871573Srgrimes table[0] = pos; 881573Srgrimes} 891573Srgrimes 901573Srgrimes/* 91189356Sdas * Initialize the position table, done whenever we clear the screen. 92189356Sdas */ 93189356Sdas public void 94189356Sdaspos_clear() 951573Srgrimes{ 961573Srgrimes register int i; 971573Srgrimes 981573Srgrimes for (i = 0; i < sc_height; i++) 991573Srgrimes table[i] = NULL_POSITION; 1001573Srgrimes} 10115931Speter 10215931Speter/* 10315931Speter * Allocate or reallocate the position table. 10415931Speter */ 10515931Speter public void 10615931Speterpos_init() 10749082Shoek{ 10815931Speter struct scrpos scrpos; 1091573Srgrimes 1101573Srgrimes if (sc_height <= table_size) 1111573Srgrimes return; 1121573Srgrimes /* 1131573Srgrimes * If we already have a table, remember the first line in it 1141573Srgrimes * before we free it, so we can copy that line to the new table. 11515931Speter */ 116108037Sru if (table != NULL) 117108037Sru { 11815931Speter get_scrpos(&scrpos); 11915931Speter free((char*)table); 120108037Sru } else 12170553Sben scrpos.pos = NULL_POSITION; 12270553Sben table = (POSITION *) ecalloc(sc_height, sizeof(POSITION)); 12370553Sben table_size = sc_height; 12415931Speter pos_clear(); 12515931Speter if (scrpos.pos != NULL_POSITION) 12615931Speter table[scrpos.ln-1] = scrpos.pos; 12778180Sschweikh} 12815931Speter 12915931Speter/* 13015931Speter * See if the byte at a specified position is currently on the screen. 13187735Sru * Check the position table to see if the position falls within its range. 13215931Speter * Return the position table entry if found, -1 if not. 13379199Sru */ 13479199Sru public int 13579199Sruonscreen(pos) 13615931Speter POSITION pos; 137108037Sru{ 138108037Sru register int i; 1391573Srgrimes 1401573Srgrimes if (pos < table[0]) 141108037Sru return (-1); 14277794Simp for (i = 1; i < sc_height; i++) 14377794Simp if (pos < table[i]) 14477794Simp return (i-1); 14577794Simp return (-1); 14677794Simp} 14777794Simp 14877794Simp/* 14977794Simp * See if the entire screen is empty. 15077794Simp */ 15177794Simp public int 15277794Simpempty_screen() 153234530Sdas{ 154234530Sdas return (empty_lines(0, sc_height-1)); 155234530Sdas} 15615931Speter 157108037Sru public int 158108037Sruempty_lines(s, e) 1591573Srgrimes int s; 1601573Srgrimes int e; 161108037Sru{ 162234530Sdas register int i; 163234530Sdas 164234530Sdas for (i = s; i <= e; i++) 165234530Sdas if (table[i] != NULL_POSITION && table[i] != 0) 1661573Srgrimes return (0); 1671573Srgrimes return (1); 1681573Srgrimes} 1691573Srgrimes 1701573Srgrimes/* 1711573Srgrimes * Get the current screen position. 1721573Srgrimes * The screen position consists of both a file position and 1731573Srgrimes * a screen line number where the file position is placed on the screen. 1741573Srgrimes * Normally the screen line number is 0, but if we are positioned 1751573Srgrimes * such that the top few lines are empty, we may have to set 17679199Sru * the screen line to a number > 0. 17779199Sru */ 17879199Sru public void 1791573Srgrimesget_scrpos(scrpos) 1801573Srgrimes struct scrpos *scrpos; 1811573Srgrimes{ 1821573Srgrimes register int i; 1831573Srgrimes 1841573Srgrimes /* 1851573Srgrimes * Find the first line on the screen which has something on it, 18621674Sjkh * and return the screen line number and the file position. 18721674Sjkh */ 18879199Sru for (i = 0; i < sc_height; i++) 18921674Sjkh if (table[i] != NULL_POSITION) 19021674Sjkh { 19121674Sjkh scrpos->ln = i+1; 19221674Sjkh scrpos->pos = table[i]; 19321674Sjkh return; 19421674Sjkh } 19521674Sjkh /* 1961573Srgrimes * The screen is empty. 19787735Sru */ 19887113Sfenner scrpos->pos = NULL_POSITION; 19987113Sfenner} 20079199Sru 20178180Sschweikh/* 20279199Sru * Adjust a screen line number to be a simple positive integer 2031573Srgrimes * in the range { 0 .. sc_height-2 }. 20479199Sru * (The bottom line, sc_height-1, is reserved for prompts, etc.) 2051573Srgrimes * The given "sline" may be in the range { 1 .. sc_height-1 } 20678180Sschweikh * to refer to lines relative to the top of the screen (starting from 1), 2071573Srgrimes * or it may be in { -1 .. -(sc_height-1) } to refer to lines 2081573Srgrimes * relative to the bottom of the screen. 209187809Sdas */ 2101573Srgrimes public int 2111573Srgrimesadjsline(sline) 2121573Srgrimes int sline; 2131573Srgrimes{ 2141573Srgrimes /* 2151573Srgrimes * Negative screen line number means 2161573Srgrimes * relative to the bottom of the screen. 2171573Srgrimes */ 2181573Srgrimes if (sline < 0) 2191573Srgrimes sline += sc_height; 2201573Srgrimes /* 2211573Srgrimes * Can't be less than 1 or greater than sc_height-1. 22287113Sfenner */ 2231573Srgrimes if (sline <= 0) 22479199Sru sline = 1; 2251573Srgrimes if (sline >= sc_height) 2261573Srgrimes sline = sc_height - 1; 2271573Srgrimes /* 2281573Srgrimes * Return zero-based line number, not one-based. 2291573Srgrimes */ 2301573Srgrimes return (sline-1); 2311573Srgrimes} 2321573Srgrimes