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