jump.c revision 128345
1189251Ssam/* 2189251Ssam * Copyright (C) 1984-2002 Mark Nudelman 3189251Ssam * 4189251Ssam * You may distribute under the terms of either the GNU General Public 5189251Ssam * License or the Less License, as specified in the README file. 6189251Ssam * 7189251Ssam * For more information about less, or for information on how to 8189251Ssam * contact the author, see the README file. 9189251Ssam */ 10189251Ssam 11189251Ssam 12189251Ssam/* 13189251Ssam * Routines which jump to a new location in the file. 14189251Ssam */ 15189251Ssam 16189251Ssam#include "less.h" 17189251Ssam#include "position.h" 18214734Srpaulo 19189251Ssamextern int hit_eof; 20189251Ssamextern int jump_sline; 21189251Ssamextern int squished; 22189251Ssamextern int screen_trashed; 23189251Ssamextern int sc_width, sc_height; 24189251Ssamextern int show_attn; 25214734Srpaulo 26214734Srpaulo/* 27214734Srpaulo * Jump to the end of the file. 28214734Srpaulo */ 29214734Srpaulo public void 30214734Srpaulojump_forw() 31214734Srpaulo{ 32214734Srpaulo POSITION pos; 33189251Ssam 34189251Ssam if (ch_end_seek()) 35214734Srpaulo { 36214734Srpaulo error("Cannot seek to end of file", NULL_PARG); 37214734Srpaulo return; 38214734Srpaulo } 39214734Srpaulo /* 40214734Srpaulo * Position the last line in the file at the last screen line. 41214734Srpaulo * Go back one line from the end of the file 42214734Srpaulo * to get to the beginning of the last line. 43214734Srpaulo */ 44189251Ssam pos = back_line(ch_tell()); 45189251Ssam if (pos == NULL_POSITION) 46189251Ssam jump_loc((POSITION)0, sc_height-1); 47189251Ssam else 48189251Ssam jump_loc(pos, sc_height-1); 49189251Ssam} 50189251Ssam 51189251Ssam/* 52189251Ssam * Jump to line n in the file. 53189251Ssam */ 54189251Ssam public void 55189251Ssamjump_back(linenum) 56189251Ssam LINENUM linenum; 57189251Ssam{ 58189251Ssam POSITION pos; 59189251Ssam PARG parg; 60189251Ssam 61189251Ssam /* 62189251Ssam * Find the position of the specified line. 63189251Ssam * If we can seek there, just jump to it. 64189251Ssam * If we can't seek, but we're trying to go to line number 1, 65189251Ssam * use ch_beg_seek() to get as close as we can. 66189251Ssam */ 67189251Ssam pos = find_pos(linenum); 68189251Ssam if (pos != NULL_POSITION && ch_seek(pos) == 0) 69189251Ssam { 70189251Ssam if (show_attn) 71189251Ssam set_attnpos(pos); 72189251Ssam jump_loc(pos, jump_sline); 73189251Ssam } else if (linenum <= 1 && ch_beg_seek() == 0) 74189251Ssam { 75189251Ssam jump_loc(ch_tell(), jump_sline); 76189251Ssam error("Cannot seek to beginning of file", NULL_PARG); 77189251Ssam } else 78189251Ssam { 79189251Ssam parg.p_linenum = linenum; 80189251Ssam error("Cannot seek to line number %n", &parg); 81189251Ssam } 82189251Ssam} 83189251Ssam 84189251Ssam/* 85189251Ssam * Repaint the screen. 86189251Ssam */ 87189251Ssam public void 88189251Ssamrepaint() 89189251Ssam{ 90189251Ssam struct scrpos scrpos; 91189251Ssam /* 92189251Ssam * Start at the line currently at the top of the screen 93189251Ssam * and redisplay the screen. 94189251Ssam */ 95189251Ssam get_scrpos(&scrpos); 96189251Ssam pos_clear(); 97189251Ssam jump_loc(scrpos.pos, scrpos.ln); 98189251Ssam} 99189251Ssam 100189251Ssam/* 101189251Ssam * Jump to a specified percentage into the file. 102189251Ssam */ 103189251Ssam public void 104189251Ssamjump_percent(percent) 105189251Ssam int percent; 106189251Ssam{ 107189251Ssam POSITION pos, len; 108189251Ssam 109189251Ssam /* 110189251Ssam * Determine the position in the file 111189251Ssam * (the specified percentage of the file's length). 112189251Ssam */ 113189251Ssam if ((len = ch_length()) == NULL_POSITION) 114189251Ssam { 115189251Ssam ierror("Determining length of file", NULL_PARG); 116189251Ssam ch_end_seek(); 117189251Ssam } 118189251Ssam if ((len = ch_length()) == NULL_POSITION) 119189251Ssam { 120189251Ssam error("Don't know length of file", NULL_PARG); 121189251Ssam return; 122189251Ssam } 123189251Ssam pos = percent_pos(len, percent); 124189251Ssam if (pos >= len) 125189251Ssam pos = len-1; 126189251Ssam 127189251Ssam jump_line_loc(pos, jump_sline); 128189251Ssam} 129189251Ssam 130189251Ssam/* 131189251Ssam * Jump to a specified position in the file. 132189251Ssam * Like jump_loc, but the position need not be 133189251Ssam * the first character in a line. 134189251Ssam */ 135189251Ssam public void 136189251Ssamjump_line_loc(pos, sline) 137189251Ssam POSITION pos; 138189251Ssam int sline; 139189251Ssam{ 140189251Ssam int c; 141189251Ssam 142189251Ssam if (ch_seek(pos) == 0) 143189251Ssam { 144189251Ssam /* 145189251Ssam * Back up to the beginning of the line. 146189251Ssam */ 147189251Ssam while ((c = ch_back_get()) != '\n' && c != EOI) 148189251Ssam ; 149189251Ssam if (c == '\n') 150189251Ssam (void) ch_forw_get(); 151189251Ssam pos = ch_tell(); 152189251Ssam } 153189251Ssam if (show_attn) 154189251Ssam set_attnpos(pos); 155189251Ssam jump_loc(pos, sline); 156214734Srpaulo} 157189251Ssam 158189251Ssam/* 159189251Ssam * Jump to a specified position in the file. 160189251Ssam * The position must be the first character in a line. 161189251Ssam * Place the target line on a specified line on the screen. 162189251Ssam */ 163189251Ssam public void 164214734Srpaulojump_loc(pos, sline) 165214734Srpaulo POSITION pos; 166214734Srpaulo int sline; 167214734Srpaulo{ 168189251Ssam register int nline; 169214734Srpaulo POSITION tpos; 170214734Srpaulo POSITION bpos; 171214734Srpaulo 172214734Srpaulo /* 173214734Srpaulo * Normalize sline. 174214734Srpaulo */ 175214734Srpaulo sline = adjsline(sline); 176214734Srpaulo 177214734Srpaulo if ((nline = onscreen(pos)) >= 0) 178189251Ssam { 179189251Ssam /* 180189251Ssam * The line is currently displayed. 181189251Ssam * Just scroll there. 182189251Ssam */ 183189251Ssam nline -= sline; 184189251Ssam if (nline > 0) 185189251Ssam forw(nline, position(BOTTOM_PLUS_ONE), 1, 0, 0); 186189251Ssam else 187189251Ssam back(-nline, position(TOP), 1, 0); 188189251Ssam if (show_attn) 189189251Ssam repaint_hilite(1); 190189251Ssam return; 191189251Ssam } 192189251Ssam 193189251Ssam /* 194189251Ssam * Line is not on screen. 195189251Ssam * Seek to the desired location. 196189251Ssam */ 197189251Ssam if (ch_seek(pos)) 198189251Ssam { 199189251Ssam error("Cannot seek to that file position", NULL_PARG); 200189251Ssam return; 201189251Ssam } 202189251Ssam 203189251Ssam /* 204189251Ssam * See if the desired line is before or after 205189251Ssam * the currently displayed screen. 206189251Ssam */ 207189251Ssam tpos = position(TOP); 208189251Ssam bpos = position(BOTTOM_PLUS_ONE); 209189251Ssam if (tpos == NULL_POSITION || pos >= tpos) 210189251Ssam { 211189251Ssam /* 212189251Ssam * The desired line is after the current screen. 213189251Ssam * Move back in the file far enough so that we can 214189251Ssam * call forw() and put the desired line at the 215189251Ssam * sline-th line on the screen. 216189251Ssam */ 217189251Ssam for (nline = 0; nline < sline; nline++) 218189251Ssam { 219189251Ssam if (bpos != NULL_POSITION && pos <= bpos) 220189251Ssam { 221189251Ssam /* 222189251Ssam * Surprise! The desired line is 223189251Ssam * close enough to the current screen 224189251Ssam * that we can just scroll there after all. 225189251Ssam */ 226189251Ssam forw(sc_height-sline+nline-1, bpos, 1, 0, 0); 227189251Ssam if (show_attn) 228189251Ssam repaint_hilite(1); 229189251Ssam return; 230189251Ssam } 231189251Ssam pos = back_line(pos); 232189251Ssam if (pos == NULL_POSITION) 233189251Ssam { 234189251Ssam /* 235189251Ssam * Oops. Ran into the beginning of the file. 236189251Ssam * Exit the loop here and rely on forw() 237189251Ssam * below to draw the required number of 238189251Ssam * blank lines at the top of the screen. 239189251Ssam */ 240189251Ssam break; 241189251Ssam } 242189251Ssam } 243189251Ssam lastmark(); 244189251Ssam hit_eof = 0; 245189251Ssam squished = 0; 246189251Ssam screen_trashed = 0; 247189251Ssam forw(sc_height-1, pos, 1, 0, sline-nline); 248189251Ssam } else 249189251Ssam { 250189251Ssam /* 251189251Ssam * The desired line is before the current screen. 252189251Ssam * Move forward in the file far enough so that we 253189251Ssam * can call back() and put the desired line at the 254189251Ssam * sline-th line on the screen. 255189251Ssam */ 256189251Ssam for (nline = sline; nline < sc_height - 1; nline++) 257189251Ssam { 258189251Ssam pos = forw_line(pos); 259189251Ssam if (pos == NULL_POSITION) 260189251Ssam { 261189251Ssam /* 262189251Ssam * Ran into end of file. 263189251Ssam * This shouldn't normally happen, 264189251Ssam * but may if there is some kind of read error. 265189251Ssam */ 266189251Ssam break; 267189251Ssam } 268189251Ssam if (pos >= tpos) 269189251Ssam { 270189251Ssam /* 271189251Ssam * Surprise! The desired line is 272189251Ssam * close enough to the current screen 273189251Ssam * that we can just scroll there after all. 274189251Ssam */ 275189251Ssam back(nline+1, tpos, 1, 0); 276189251Ssam if (show_attn) 277189251Ssam repaint_hilite(1); 278189251Ssam return; 279189251Ssam } 280189251Ssam } 281189251Ssam lastmark(); 282189251Ssam clear(); 283189251Ssam screen_trashed = 0; 284189251Ssam add_back_pos(pos); 285189251Ssam back(sc_height-1, pos, 1, 0); 286189251Ssam } 287189251Ssam} 288189251Ssam