1 /* $OpenBSD: position.c,v 1.4 2001/11/19 19:02:14 mpech Exp $ */ 2 3 /* 4 * Copyright (c) 1984,1985,1989,1994,1995 Mark Nudelman 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice in the documentation and/or other materials provided with 14 * the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY 17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 22 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 30 /* 31 * Routines dealing with the "position" table. 32 * This is a table which tells the position (in the input file) of the 33 * first char on each currently displayed line. 34 * 35 * {{ The position table is scrolled by moving all the entries. 36 * Would be better to have a circular table 37 * and just change a couple of pointers. }} 38 */ 39 40 #include "less.h" 41 #include "position.h" 42 43 static POSITION *table = NULL; /* The position table */ 44 static int table_size; 45 46 extern int sc_width, sc_height; 47 48 /* 49 * Return the starting file position of a line displayed on the screen. 50 * The line may be specified as a line number relative to the top 51 * of the screen, but is usually one of these special cases: 52 * the top (first) line on the screen 53 * the second line on the screen 54 * the bottom line on the screen 55 * the line after the bottom line on the screen 56 */ 57 public POSITION 58 position(where) 59 int where; 60 { 61 if (where >= table_size) 62 where = BOTTOM; 63 64 switch (where) 65 { 66 case BOTTOM: 67 where = sc_height - 2; 68 break; 69 case BOTTOM_PLUS_ONE: 70 where = sc_height - 1; 71 break; 72 case MIDDLE: 73 where = (sc_height - 1) / 2; 74 } 75 return (table[where]); 76 } 77 78 /* 79 * Add a new file position to the bottom of the position table. 80 */ 81 public void 82 add_forw_pos(pos) 83 POSITION pos; 84 { 85 int i; 86 87 /* 88 * Scroll the position table up. 89 */ 90 for (i = 1; i < sc_height; i++) 91 table[i-1] = table[i]; 92 table[sc_height - 1] = pos; 93 } 94 95 /* 96 * Add a new file position to the top of the position table. 97 */ 98 public void 99 add_back_pos(pos) 100 POSITION pos; 101 { 102 int i; 103 104 /* 105 * Scroll the position table down. 106 */ 107 for (i = sc_height - 1; i > 0; i--) 108 table[i] = table[i-1]; 109 table[0] = pos; 110 } 111 112 /* 113 * Initialize the position table, done whenever we clear the screen. 114 */ 115 public void 116 pos_clear() 117 { 118 int i; 119 120 for (i = 0; i < sc_height; i++) 121 table[i] = NULL_POSITION; 122 } 123 124 /* 125 * Allocate or reallocate the position table. 126 */ 127 public void 128 pos_init() 129 { 130 struct scrpos scrpos; 131 132 if (sc_height <= table_size) 133 return; 134 /* 135 * If we already have a table, remember the first line in it 136 * before we free it, so we can copy that line to the new table. 137 */ 138 if (table != NULL) 139 { 140 get_scrpos(&scrpos); 141 free((char*)table); 142 } else 143 scrpos.pos = NULL_POSITION; 144 table = (POSITION *) ecalloc(sc_height, sizeof(POSITION)); 145 table_size = sc_height; 146 pos_clear(); 147 if (scrpos.pos != NULL_POSITION) 148 table[scrpos.ln-1] = scrpos.pos; 149 } 150 151 /* 152 * See if the byte at a specified position is currently on the screen. 153 * Check the position table to see if the position falls within its range. 154 * Return the position table entry if found, -1 if not. 155 */ 156 public int 157 onscreen(pos) 158 POSITION pos; 159 { 160 int i; 161 162 if (pos < table[0]) 163 return (-1); 164 for (i = 1; i < sc_height; i++) 165 if (pos < table[i]) 166 return (i-1); 167 return (-1); 168 } 169 170 /* 171 * See if the entire screen is empty. 172 */ 173 public int 174 empty_screen() 175 { 176 return (empty_lines(0, sc_height-1)); 177 } 178 179 public int 180 empty_lines(s, e) 181 int s; 182 int e; 183 { 184 int i; 185 186 for (i = s; i <= e; i++) 187 if (table[i] != NULL_POSITION) 188 return (0); 189 return (1); 190 } 191 192 /* 193 * Get the current screen position. 194 * The screen position consists of both a file position and 195 * a screen line number where the file position is placed on the screen. 196 * Normally the screen line number is 0, but if we are positioned 197 * such that the top few lines are empty, we may have to set 198 * the screen line to a number > 0. 199 */ 200 public void 201 get_scrpos(scrpos) 202 struct scrpos *scrpos; 203 { 204 int i; 205 206 /* 207 * Find the first line on the screen which has something on it, 208 * and return the screen line number and the file position. 209 */ 210 for (i = 0; i < sc_height; i++) 211 if (table[i] != NULL_POSITION) 212 { 213 scrpos->ln = i+1; 214 scrpos->pos = table[i]; 215 return; 216 } 217 /* 218 * The screen is empty. 219 */ 220 scrpos->pos = NULL_POSITION; 221 } 222 223 /* 224 * Adjust a screen line number to be a simple positive integer 225 * in the range { 0 .. sc_height-2 }. 226 * (The bottom line, sc_height-1, is reserved for prompts, etc.) 227 * The given "sline" may be in the range { 1 .. sc_height-1 } 228 * to refer to lines relative to the top of the screen (starting from 1), 229 * or it may be in { -1 .. -(sc_height-1) } to refer to lines 230 * relative to the bottom of the screen. 231 */ 232 public int 233 adjsline(sline) 234 int sline; 235 { 236 /* 237 * Negative screen line number means 238 * relative to the bottom of the screen. 239 */ 240 if (sline < 0) 241 sline += sc_height; 242 /* 243 * Can't be less than 1 or greater than sc_height-1. 244 */ 245 if (sline <= 0) 246 sline = 1; 247 if (sline >= sc_height) 248 sline = sc_height - 1; 249 /* 250 * Return zero-based line number, not one-based. 251 */ 252 return (sline-1); 253 } 254