135209Sbostic /* 235209Sbostic * Copyright (c) 1988 Mark Nudleman 3*62131Sbostic * Copyright (c) 1988, 1993 4*62131Sbostic * The Regents of the University of California. All rights reserved. 535209Sbostic * 642742Sbostic * %sccs.include.redist.c% 735209Sbostic */ 835209Sbostic 935209Sbostic #ifndef lint 10*62131Sbostic static char sccsid[] = "@(#)input.c 8.1 (Berkeley) 06/06/93"; 1135209Sbostic #endif /* not lint */ 1235209Sbostic 1335209Sbostic /* 1435209Sbostic * High level routines dealing with getting lines of input 1535209Sbostic * from the file being viewed. 1635209Sbostic * 1735209Sbostic * When we speak of "lines" here, we mean PRINTABLE lines; 1835209Sbostic * lines processed with respect to the screen width. 1935209Sbostic * We use the term "raw line" to refer to lines simply 2035209Sbostic * delimited by newlines; not processed with respect to screen width. 2135209Sbostic */ 2235209Sbostic 2336251Sbostic #include <sys/types.h> 2436251Sbostic #include <less.h> 2535209Sbostic 2635209Sbostic extern int squeeze; 2735209Sbostic extern int sigs; 2835209Sbostic extern char *line; 2935209Sbostic 3036251Sbostic off_t ch_tell(); 3136251Sbostic 3235209Sbostic /* 3335209Sbostic * Get the next line. 3435209Sbostic * A "current" position is passed and a "new" position is returned. 3535209Sbostic * The current position is the position of the first character of 3635209Sbostic * a line. The new position is the position of the first character 3735209Sbostic * of the NEXT line. The line obtained is the line starting at curr_pos. 3835209Sbostic */ 3936251Sbostic off_t forw_line(curr_pos)4035209Sbosticforw_line(curr_pos) 4136251Sbostic off_t curr_pos; 4235209Sbostic { 4336251Sbostic off_t new_pos; 4435209Sbostic register int c; 4535209Sbostic 4635209Sbostic if (curr_pos == NULL_POSITION || ch_seek(curr_pos)) 4735209Sbostic return (NULL_POSITION); 4835209Sbostic 4935209Sbostic c = ch_forw_get(); 5035209Sbostic if (c == EOI) 5135209Sbostic return (NULL_POSITION); 5235209Sbostic 5335209Sbostic prewind(); 5435209Sbostic for (;;) 5535209Sbostic { 5635209Sbostic if (sigs) 5735209Sbostic return (NULL_POSITION); 5835209Sbostic if (c == '\n' || c == EOI) 5935209Sbostic { 6035209Sbostic /* 6135209Sbostic * End of the line. 6235209Sbostic */ 6335209Sbostic new_pos = ch_tell(); 6435209Sbostic break; 6535209Sbostic } 6635209Sbostic 6735209Sbostic /* 6835209Sbostic * Append the char to the line and get the next char. 6935209Sbostic */ 7035209Sbostic if (pappend(c)) 7135209Sbostic { 7235209Sbostic /* 7335209Sbostic * The char won't fit in the line; the line 7435209Sbostic * is too long to print in the screen width. 7535209Sbostic * End the line here. 7635209Sbostic */ 7735209Sbostic new_pos = ch_tell() - 1; 7835209Sbostic break; 7935209Sbostic } 8035209Sbostic c = ch_forw_get(); 8135209Sbostic } 8235209Sbostic (void) pappend('\0'); 8335209Sbostic 8435209Sbostic if (squeeze && *line == '\0') 8535209Sbostic { 8635209Sbostic /* 8735209Sbostic * This line is blank. 8835209Sbostic * Skip down to the last contiguous blank line 8935209Sbostic * and pretend it is the one which we are returning. 9035209Sbostic */ 9135209Sbostic while ((c = ch_forw_get()) == '\n') 9235209Sbostic if (sigs) 9335209Sbostic return (NULL_POSITION); 9435209Sbostic if (c != EOI) 9535209Sbostic (void) ch_back_get(); 9635209Sbostic new_pos = ch_tell(); 9735209Sbostic } 9835209Sbostic 9935209Sbostic return (new_pos); 10035209Sbostic } 10135209Sbostic 10235209Sbostic /* 10335209Sbostic * Get the previous line. 10435209Sbostic * A "current" position is passed and a "new" position is returned. 10535209Sbostic * The current position is the position of the first character of 10635209Sbostic * a line. The new position is the position of the first character 10735209Sbostic * of the PREVIOUS line. The line obtained is the one starting at new_pos. 10835209Sbostic */ 10936251Sbostic off_t back_line(curr_pos)11035209Sbosticback_line(curr_pos) 11136251Sbostic off_t curr_pos; 11235209Sbostic { 11336251Sbostic off_t new_pos, begin_new_pos; 11435209Sbostic int c; 11535209Sbostic 11636251Sbostic if (curr_pos == NULL_POSITION || curr_pos <= (off_t)0 || 11735209Sbostic ch_seek(curr_pos-1)) 11835209Sbostic return (NULL_POSITION); 11935209Sbostic 12035209Sbostic if (squeeze) 12135209Sbostic { 12235209Sbostic /* 12335209Sbostic * Find out if the "current" line was blank. 12435209Sbostic */ 12535209Sbostic (void) ch_forw_get(); /* Skip the newline */ 12635209Sbostic c = ch_forw_get(); /* First char of "current" line */ 12735209Sbostic (void) ch_back_get(); /* Restore our position */ 12835209Sbostic (void) ch_back_get(); 12935209Sbostic 13035209Sbostic if (c == '\n') 13135209Sbostic { 13235209Sbostic /* 13335209Sbostic * The "current" line was blank. 13435209Sbostic * Skip over any preceeding blank lines, 13535209Sbostic * since we skipped them in forw_line(). 13635209Sbostic */ 13735209Sbostic while ((c = ch_back_get()) == '\n') 13835209Sbostic if (sigs) 13935209Sbostic return (NULL_POSITION); 14035209Sbostic if (c == EOI) 14135209Sbostic return (NULL_POSITION); 14235209Sbostic (void) ch_forw_get(); 14335209Sbostic } 14435209Sbostic } 14535209Sbostic 14635209Sbostic /* 14735209Sbostic * Scan backwards until we hit the beginning of the line. 14835209Sbostic */ 14935209Sbostic for (;;) 15035209Sbostic { 15135209Sbostic if (sigs) 15235209Sbostic return (NULL_POSITION); 15335209Sbostic c = ch_back_get(); 15435209Sbostic if (c == '\n') 15535209Sbostic { 15635209Sbostic /* 15735209Sbostic * This is the newline ending the previous line. 15835209Sbostic * We have hit the beginning of the line. 15935209Sbostic */ 16035209Sbostic new_pos = ch_tell() + 1; 16135209Sbostic break; 16235209Sbostic } 16335209Sbostic if (c == EOI) 16435209Sbostic { 16535209Sbostic /* 16635209Sbostic * We have hit the beginning of the file. 16735209Sbostic * This must be the first line in the file. 16835209Sbostic * This must, of course, be the beginning of the line. 16935209Sbostic */ 17035209Sbostic new_pos = ch_tell(); 17135209Sbostic break; 17235209Sbostic } 17335209Sbostic } 17435209Sbostic 17535209Sbostic /* 17635209Sbostic * Now scan forwards from the beginning of this line. 17735209Sbostic * We keep discarding "printable lines" (based on screen width) 17835209Sbostic * until we reach the curr_pos. 17935209Sbostic * 18035209Sbostic * {{ This algorithm is pretty inefficient if the lines 18135209Sbostic * are much longer than the screen width, 18235209Sbostic * but I don't know of any better way. }} 18335209Sbostic */ 18435209Sbostic if (ch_seek(new_pos)) 18535209Sbostic return (NULL_POSITION); 18635209Sbostic loop: 18735209Sbostic begin_new_pos = new_pos; 18835209Sbostic prewind(); 18935209Sbostic 19035209Sbostic do 19135209Sbostic { 19235209Sbostic c = ch_forw_get(); 19335209Sbostic if (c == EOI || sigs) 19435209Sbostic return (NULL_POSITION); 19535209Sbostic new_pos++; 19635209Sbostic if (c == '\n') 19735209Sbostic break; 19835209Sbostic if (pappend(c)) 19935209Sbostic { 20035209Sbostic /* 20135209Sbostic * Got a full printable line, but we haven't 20235209Sbostic * reached our curr_pos yet. Discard the line 20335209Sbostic * and start a new one. 20435209Sbostic */ 20535209Sbostic (void) pappend('\0'); 20635209Sbostic (void) ch_back_get(); 20735209Sbostic new_pos--; 20835209Sbostic goto loop; 20935209Sbostic } 21035209Sbostic } while (new_pos < curr_pos); 21135209Sbostic 21235209Sbostic (void) pappend('\0'); 21335209Sbostic 21435209Sbostic return (begin_new_pos); 21535209Sbostic } 216