jump.c revision 170256
160786Sps/* 2170256Sdelphij * Copyright (C) 1984-2007 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 which jump to a new location in the file. 1460786Sps */ 1560786Sps 1660786Sps#include "less.h" 1760786Sps#include "position.h" 1860786Sps 1960786Spsextern int hit_eof; 2060786Spsextern int jump_sline; 2160786Spsextern int squished; 2260786Spsextern int screen_trashed; 2360786Spsextern int sc_width, sc_height; 2460786Spsextern int show_attn; 25161475Sdelphijextern int top_scroll; 2660786Sps 2760786Sps/* 2860786Sps * Jump to the end of the file. 2960786Sps */ 3060786Sps public void 3160786Spsjump_forw() 3260786Sps{ 3360786Sps POSITION pos; 3460786Sps 3560786Sps if (ch_end_seek()) 3660786Sps { 3760786Sps error("Cannot seek to end of file", NULL_PARG); 3860786Sps return; 3960786Sps } 4060786Sps /* 4160786Sps * Position the last line in the file at the last screen line. 4260786Sps * Go back one line from the end of the file 4360786Sps * to get to the beginning of the last line. 4460786Sps */ 4560786Sps pos = back_line(ch_tell()); 4660786Sps if (pos == NULL_POSITION) 4760786Sps jump_loc((POSITION)0, sc_height-1); 4860786Sps else 4960786Sps jump_loc(pos, sc_height-1); 5060786Sps} 5160786Sps 5260786Sps/* 5360786Sps * Jump to line n in the file. 5460786Sps */ 5560786Sps public void 56128345Stjrjump_back(linenum) 57128345Stjr LINENUM linenum; 5860786Sps{ 5960786Sps POSITION pos; 6060786Sps PARG parg; 6160786Sps 6260786Sps /* 6360786Sps * Find the position of the specified line. 6460786Sps * If we can seek there, just jump to it. 6560786Sps * If we can't seek, but we're trying to go to line number 1, 6660786Sps * use ch_beg_seek() to get as close as we can. 6760786Sps */ 68128345Stjr pos = find_pos(linenum); 6960786Sps if (pos != NULL_POSITION && ch_seek(pos) == 0) 7060786Sps { 7160786Sps if (show_attn) 7260786Sps set_attnpos(pos); 7360786Sps jump_loc(pos, jump_sline); 74128345Stjr } else if (linenum <= 1 && ch_beg_seek() == 0) 7560786Sps { 7660786Sps jump_loc(ch_tell(), jump_sline); 7760786Sps error("Cannot seek to beginning of file", NULL_PARG); 7860786Sps } else 7960786Sps { 80128345Stjr parg.p_linenum = linenum; 81128345Stjr error("Cannot seek to line number %n", &parg); 8260786Sps } 8360786Sps} 8460786Sps 8560786Sps/* 8660786Sps * Repaint the screen. 8760786Sps */ 8860786Sps public void 8960786Spsrepaint() 9060786Sps{ 9160786Sps struct scrpos scrpos; 9260786Sps /* 9360786Sps * Start at the line currently at the top of the screen 9460786Sps * and redisplay the screen. 9560786Sps */ 9660786Sps get_scrpos(&scrpos); 9760786Sps pos_clear(); 9860786Sps jump_loc(scrpos.pos, scrpos.ln); 9960786Sps} 10060786Sps 10160786Sps/* 10260786Sps * Jump to a specified percentage into the file. 10360786Sps */ 10460786Sps public void 105170256Sdelphijjump_percent(percent, fraction) 10660786Sps int percent; 107170256Sdelphij long fraction; 10860786Sps{ 10960786Sps POSITION pos, len; 11060786Sps 11160786Sps /* 11260786Sps * Determine the position in the file 11360786Sps * (the specified percentage of the file's length). 11460786Sps */ 11560786Sps if ((len = ch_length()) == NULL_POSITION) 11660786Sps { 11760786Sps ierror("Determining length of file", NULL_PARG); 11860786Sps ch_end_seek(); 11960786Sps } 12060786Sps if ((len = ch_length()) == NULL_POSITION) 12160786Sps { 12260786Sps error("Don't know length of file", NULL_PARG); 12360786Sps return; 12460786Sps } 125170256Sdelphij pos = percent_pos(len, percent, fraction); 12660786Sps if (pos >= len) 12760786Sps pos = len-1; 12860786Sps 12960786Sps jump_line_loc(pos, jump_sline); 13060786Sps} 13160786Sps 13260786Sps/* 13360786Sps * Jump to a specified position in the file. 13460786Sps * Like jump_loc, but the position need not be 13560786Sps * the first character in a line. 13660786Sps */ 13760786Sps public void 13860786Spsjump_line_loc(pos, sline) 13960786Sps POSITION pos; 14060786Sps int sline; 14160786Sps{ 14260786Sps int c; 14360786Sps 14460786Sps if (ch_seek(pos) == 0) 14560786Sps { 14660786Sps /* 14760786Sps * Back up to the beginning of the line. 14860786Sps */ 14960786Sps while ((c = ch_back_get()) != '\n' && c != EOI) 15060786Sps ; 15160786Sps if (c == '\n') 15260786Sps (void) ch_forw_get(); 15360786Sps pos = ch_tell(); 15460786Sps } 15560786Sps if (show_attn) 15660786Sps set_attnpos(pos); 15760786Sps jump_loc(pos, sline); 15860786Sps} 15960786Sps 16060786Sps/* 16160786Sps * Jump to a specified position in the file. 16260786Sps * The position must be the first character in a line. 16360786Sps * Place the target line on a specified line on the screen. 16460786Sps */ 16560786Sps public void 16660786Spsjump_loc(pos, sline) 16760786Sps POSITION pos; 16860786Sps int sline; 16960786Sps{ 17060786Sps register int nline; 17160786Sps POSITION tpos; 17260786Sps POSITION bpos; 17360786Sps 17460786Sps /* 17560786Sps * Normalize sline. 17660786Sps */ 17760786Sps sline = adjsline(sline); 17860786Sps 17960786Sps if ((nline = onscreen(pos)) >= 0) 18060786Sps { 18160786Sps /* 18260786Sps * The line is currently displayed. 18360786Sps * Just scroll there. 18460786Sps */ 18560786Sps nline -= sline; 18660786Sps if (nline > 0) 18760786Sps forw(nline, position(BOTTOM_PLUS_ONE), 1, 0, 0); 18860786Sps else 18960786Sps back(-nline, position(TOP), 1, 0); 19060786Sps if (show_attn) 19160786Sps repaint_hilite(1); 19260786Sps return; 19360786Sps } 19460786Sps 19560786Sps /* 19660786Sps * Line is not on screen. 19760786Sps * Seek to the desired location. 19860786Sps */ 19960786Sps if (ch_seek(pos)) 20060786Sps { 20160786Sps error("Cannot seek to that file position", NULL_PARG); 20260786Sps return; 20360786Sps } 20460786Sps 20560786Sps /* 20660786Sps * See if the desired line is before or after 20760786Sps * the currently displayed screen. 20860786Sps */ 20960786Sps tpos = position(TOP); 21060786Sps bpos = position(BOTTOM_PLUS_ONE); 21160786Sps if (tpos == NULL_POSITION || pos >= tpos) 21260786Sps { 21360786Sps /* 21460786Sps * The desired line is after the current screen. 21560786Sps * Move back in the file far enough so that we can 21660786Sps * call forw() and put the desired line at the 21760786Sps * sline-th line on the screen. 21860786Sps */ 21960786Sps for (nline = 0; nline < sline; nline++) 22060786Sps { 22160786Sps if (bpos != NULL_POSITION && pos <= bpos) 22260786Sps { 22360786Sps /* 22460786Sps * Surprise! The desired line is 22560786Sps * close enough to the current screen 22660786Sps * that we can just scroll there after all. 22760786Sps */ 22860786Sps forw(sc_height-sline+nline-1, bpos, 1, 0, 0); 22960786Sps if (show_attn) 23060786Sps repaint_hilite(1); 23160786Sps return; 23260786Sps } 23360786Sps pos = back_line(pos); 23460786Sps if (pos == NULL_POSITION) 23560786Sps { 23660786Sps /* 23760786Sps * Oops. Ran into the beginning of the file. 23860786Sps * Exit the loop here and rely on forw() 23960786Sps * below to draw the required number of 24060786Sps * blank lines at the top of the screen. 24160786Sps */ 24260786Sps break; 24360786Sps } 24460786Sps } 24560786Sps lastmark(); 24660786Sps hit_eof = 0; 24760786Sps squished = 0; 24860786Sps screen_trashed = 0; 24960786Sps forw(sc_height-1, pos, 1, 0, sline-nline); 25060786Sps } else 25160786Sps { 25260786Sps /* 25360786Sps * The desired line is before the current screen. 25460786Sps * Move forward in the file far enough so that we 25560786Sps * can call back() and put the desired line at the 25660786Sps * sline-th line on the screen. 25760786Sps */ 25860786Sps for (nline = sline; nline < sc_height - 1; nline++) 25960786Sps { 26060786Sps pos = forw_line(pos); 26160786Sps if (pos == NULL_POSITION) 26260786Sps { 26360786Sps /* 26460786Sps * Ran into end of file. 26560786Sps * This shouldn't normally happen, 26660786Sps * but may if there is some kind of read error. 26760786Sps */ 26860786Sps break; 26960786Sps } 27060786Sps if (pos >= tpos) 27160786Sps { 27260786Sps /* 27360786Sps * Surprise! The desired line is 27460786Sps * close enough to the current screen 27560786Sps * that we can just scroll there after all. 27660786Sps */ 27760786Sps back(nline+1, tpos, 1, 0); 27860786Sps if (show_attn) 27960786Sps repaint_hilite(1); 28060786Sps return; 28160786Sps } 28260786Sps } 28360786Sps lastmark(); 284170256Sdelphij if (!top_scroll) 285161475Sdelphij clear(); 286161475Sdelphij else 287161475Sdelphij home(); 28860786Sps screen_trashed = 0; 28960786Sps add_back_pos(pos); 29060786Sps back(sc_height-1, pos, 1, 0); 29160786Sps } 29260786Sps} 293