160786Sps/* 2240121Sdelphij * Copyright (C) 1984-2012 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 * 7240121Sdelphij * For more information, see the README file. 860786Sps */ 960786Sps 1060786Sps 1160786Sps/* 1260786Sps * Routines which jump to a new location in the file. 1360786Sps */ 1460786Sps 1560786Sps#include "less.h" 1660786Sps#include "position.h" 1760786Sps 1860786Spsextern int jump_sline; 1960786Spsextern int squished; 2060786Spsextern int screen_trashed; 2160786Spsextern int sc_width, sc_height; 2260786Spsextern int show_attn; 23161475Sdelphijextern int top_scroll; 2460786Sps 2560786Sps/* 2660786Sps * Jump to the end of the file. 2760786Sps */ 2860786Sps public void 2960786Spsjump_forw() 3060786Sps{ 3160786Sps POSITION pos; 32172468Sdelphij POSITION end_pos; 3360786Sps 3460786Sps if (ch_end_seek()) 3560786Sps { 3660786Sps error("Cannot seek to end of file", NULL_PARG); 3760786Sps return; 3860786Sps } 39191930Sdelphij /* 40191930Sdelphij * Note; lastmark will be called later by jump_loc, but it fails 41191930Sdelphij * because the position table has been cleared by pos_clear below. 42191930Sdelphij * So call it here before calling pos_clear. 43191930Sdelphij */ 44191930Sdelphij lastmark(); 4560786Sps /* 4660786Sps * Position the last line in the file at the last screen line. 4760786Sps * Go back one line from the end of the file 4860786Sps * to get to the beginning of the last line. 4960786Sps */ 50172468Sdelphij pos_clear(); 51172468Sdelphij end_pos = ch_tell(); 52172468Sdelphij pos = back_line(end_pos); 5360786Sps if (pos == NULL_POSITION) 5460786Sps jump_loc((POSITION)0, sc_height-1); 5560786Sps else 56172468Sdelphij { 5760786Sps jump_loc(pos, sc_height-1); 58172468Sdelphij if (position(sc_height-1) != end_pos) 59172468Sdelphij repaint(); 60172468Sdelphij } 6160786Sps} 6260786Sps 6360786Sps/* 6460786Sps * Jump to line n in the file. 6560786Sps */ 6660786Sps public void 67128345Stjrjump_back(linenum) 68128345Stjr LINENUM linenum; 6960786Sps{ 7060786Sps POSITION pos; 7160786Sps PARG parg; 7260786Sps 7360786Sps /* 7460786Sps * Find the position of the specified line. 7560786Sps * If we can seek there, just jump to it. 7660786Sps * If we can't seek, but we're trying to go to line number 1, 7760786Sps * use ch_beg_seek() to get as close as we can. 7860786Sps */ 79128345Stjr pos = find_pos(linenum); 8060786Sps if (pos != NULL_POSITION && ch_seek(pos) == 0) 8160786Sps { 8260786Sps if (show_attn) 8360786Sps set_attnpos(pos); 8460786Sps jump_loc(pos, jump_sline); 85128345Stjr } else if (linenum <= 1 && ch_beg_seek() == 0) 8660786Sps { 8760786Sps jump_loc(ch_tell(), jump_sline); 8860786Sps error("Cannot seek to beginning of file", NULL_PARG); 8960786Sps } else 9060786Sps { 91128345Stjr parg.p_linenum = linenum; 92128345Stjr error("Cannot seek to line number %n", &parg); 9360786Sps } 9460786Sps} 9560786Sps 9660786Sps/* 9760786Sps * Repaint the screen. 9860786Sps */ 9960786Sps public void 10060786Spsrepaint() 10160786Sps{ 10260786Sps struct scrpos scrpos; 10360786Sps /* 10460786Sps * Start at the line currently at the top of the screen 10560786Sps * and redisplay the screen. 10660786Sps */ 10760786Sps get_scrpos(&scrpos); 10860786Sps pos_clear(); 10960786Sps jump_loc(scrpos.pos, scrpos.ln); 11060786Sps} 11160786Sps 11260786Sps/* 11360786Sps * Jump to a specified percentage into the file. 11460786Sps */ 11560786Sps public void 116170256Sdelphijjump_percent(percent, fraction) 11760786Sps int percent; 118170256Sdelphij long fraction; 11960786Sps{ 12060786Sps POSITION pos, len; 12160786Sps 12260786Sps /* 12360786Sps * Determine the position in the file 12460786Sps * (the specified percentage of the file's length). 12560786Sps */ 12660786Sps if ((len = ch_length()) == NULL_POSITION) 12760786Sps { 12860786Sps ierror("Determining length of file", NULL_PARG); 12960786Sps ch_end_seek(); 13060786Sps } 13160786Sps if ((len = ch_length()) == NULL_POSITION) 13260786Sps { 13360786Sps error("Don't know length of file", NULL_PARG); 13460786Sps return; 13560786Sps } 136170256Sdelphij pos = percent_pos(len, percent, fraction); 13760786Sps if (pos >= len) 13860786Sps pos = len-1; 13960786Sps 14060786Sps jump_line_loc(pos, jump_sline); 14160786Sps} 14260786Sps 14360786Sps/* 14460786Sps * Jump to a specified position in the file. 14560786Sps * Like jump_loc, but the position need not be 14660786Sps * the first character in a line. 14760786Sps */ 14860786Sps public void 14960786Spsjump_line_loc(pos, sline) 15060786Sps POSITION pos; 15160786Sps int sline; 15260786Sps{ 15360786Sps int c; 15460786Sps 15560786Sps if (ch_seek(pos) == 0) 15660786Sps { 15760786Sps /* 15860786Sps * Back up to the beginning of the line. 15960786Sps */ 16060786Sps while ((c = ch_back_get()) != '\n' && c != EOI) 16160786Sps ; 16260786Sps if (c == '\n') 16360786Sps (void) ch_forw_get(); 16460786Sps pos = ch_tell(); 16560786Sps } 16660786Sps if (show_attn) 16760786Sps set_attnpos(pos); 16860786Sps jump_loc(pos, sline); 16960786Sps} 17060786Sps 17160786Sps/* 17260786Sps * Jump to a specified position in the file. 17360786Sps * The position must be the first character in a line. 17460786Sps * Place the target line on a specified line on the screen. 17560786Sps */ 17660786Sps public void 17760786Spsjump_loc(pos, sline) 17860786Sps POSITION pos; 17960786Sps int sline; 18060786Sps{ 18160786Sps register int nline; 18260786Sps POSITION tpos; 18360786Sps POSITION bpos; 18460786Sps 18560786Sps /* 18660786Sps * Normalize sline. 18760786Sps */ 18860786Sps sline = adjsline(sline); 18960786Sps 19060786Sps if ((nline = onscreen(pos)) >= 0) 19160786Sps { 19260786Sps /* 19360786Sps * The line is currently displayed. 19460786Sps * Just scroll there. 19560786Sps */ 19660786Sps nline -= sline; 19760786Sps if (nline > 0) 19860786Sps forw(nline, position(BOTTOM_PLUS_ONE), 1, 0, 0); 19960786Sps else 20060786Sps back(-nline, position(TOP), 1, 0); 201191930Sdelphij#if HILITE_SEARCH 20260786Sps if (show_attn) 20360786Sps repaint_hilite(1); 204191930Sdelphij#endif 20560786Sps return; 20660786Sps } 20760786Sps 20860786Sps /* 20960786Sps * Line is not on screen. 21060786Sps * Seek to the desired location. 21160786Sps */ 21260786Sps if (ch_seek(pos)) 21360786Sps { 21460786Sps error("Cannot seek to that file position", NULL_PARG); 21560786Sps return; 21660786Sps } 21760786Sps 21860786Sps /* 21960786Sps * See if the desired line is before or after 22060786Sps * the currently displayed screen. 22160786Sps */ 22260786Sps tpos = position(TOP); 22360786Sps bpos = position(BOTTOM_PLUS_ONE); 22460786Sps if (tpos == NULL_POSITION || pos >= tpos) 22560786Sps { 22660786Sps /* 22760786Sps * The desired line is after the current screen. 22860786Sps * Move back in the file far enough so that we can 22960786Sps * call forw() and put the desired line at the 23060786Sps * sline-th line on the screen. 23160786Sps */ 23260786Sps for (nline = 0; nline < sline; nline++) 23360786Sps { 23460786Sps if (bpos != NULL_POSITION && pos <= bpos) 23560786Sps { 23660786Sps /* 23760786Sps * Surprise! The desired line is 23860786Sps * close enough to the current screen 23960786Sps * that we can just scroll there after all. 24060786Sps */ 24160786Sps forw(sc_height-sline+nline-1, bpos, 1, 0, 0); 242191930Sdelphij#if HILITE_SEARCH 24360786Sps if (show_attn) 24460786Sps repaint_hilite(1); 245191930Sdelphij#endif 24660786Sps return; 24760786Sps } 24860786Sps pos = back_line(pos); 24960786Sps if (pos == NULL_POSITION) 25060786Sps { 25160786Sps /* 25260786Sps * Oops. Ran into the beginning of the file. 25360786Sps * Exit the loop here and rely on forw() 25460786Sps * below to draw the required number of 25560786Sps * blank lines at the top of the screen. 25660786Sps */ 25760786Sps break; 25860786Sps } 25960786Sps } 26060786Sps lastmark(); 26160786Sps squished = 0; 26260786Sps screen_trashed = 0; 26360786Sps forw(sc_height-1, pos, 1, 0, sline-nline); 26460786Sps } else 26560786Sps { 26660786Sps /* 26760786Sps * The desired line is before the current screen. 26860786Sps * Move forward in the file far enough so that we 26960786Sps * can call back() and put the desired line at the 27060786Sps * sline-th line on the screen. 27160786Sps */ 27260786Sps for (nline = sline; nline < sc_height - 1; nline++) 27360786Sps { 27460786Sps pos = forw_line(pos); 27560786Sps if (pos == NULL_POSITION) 27660786Sps { 27760786Sps /* 27860786Sps * Ran into end of file. 27960786Sps * This shouldn't normally happen, 28060786Sps * but may if there is some kind of read error. 28160786Sps */ 28260786Sps break; 28360786Sps } 28460786Sps if (pos >= tpos) 28560786Sps { 28660786Sps /* 28760786Sps * Surprise! The desired line is 28860786Sps * close enough to the current screen 28960786Sps * that we can just scroll there after all. 29060786Sps */ 29160786Sps back(nline+1, tpos, 1, 0); 292191930Sdelphij#if HILITE_SEARCH 29360786Sps if (show_attn) 29460786Sps repaint_hilite(1); 295191930Sdelphij#endif 29660786Sps return; 29760786Sps } 29860786Sps } 29960786Sps lastmark(); 300170256Sdelphij if (!top_scroll) 301161475Sdelphij clear(); 302161475Sdelphij else 303161475Sdelphij home(); 30460786Sps screen_trashed = 0; 30560786Sps add_back_pos(pos); 30660786Sps back(sc_height-1, pos, 1, 0); 30760786Sps } 30860786Sps} 309