/************************************************************************* *** input.c (JJB TEMPLAR) *** *** Date modifications begun: 7/8/89. *** *** Last modified: 27/8/89. *** *************************************************************************/ /*** High level routines dealing with getting lines of input from the *** *** file being viewed. When we speak of "lines" here, we mean *** *** PRINTABLE lines; lines processed with respect to the screen width.*** *** We use the term "raw line" to refer to lines simply delimited by *** *** newlines; not processed with respect to screen width. *** *************************************************************************/ #include "less.h" extern int do_bs; extern int squeeze; extern char *line; int page_break; LONG forw_line(curr_pos) /*===========================================*/ LONG curr_pos; /* Get next line, given old position. */ { LONG new_pos; register int c; if ((curr_pos == NULL_POSITION) || ch_seek(curr_pos)) return(NULL_POSITION); prewind(); if (page_break) { new_pos = curr_pos; goto PAGE_SKIP; } if ((c = ch_forw_get()) == EOF) return(NULL_POSITION); if (c == ' ') { /* Must be first char on line */ page_break = 1; } for (;;) { /* Check for EOF too, since file may not end with '\n' */ if ((c == '\n') || (c == EOF)) { new_pos = ch_tell(); /* End of line */ break; } /* Append the char to the line and get the next char. */ if (pappend(c)) { /* The char won't fit in the line; the line is too long to print in the screen width. End the line here. */ new_pos = ch_tell() - 1; break; } c = ch_forw_get(); } PAGE_SKIP: pappend('\0'); if (squeeze && !(*line) && !page_break) { /* This line is blank. Skip down to the last contiguous blank line and pretend it is the one which we are returning. */ while ((c = ch_forw_get()) == '\n') ; if (c != EOF) ch_back_get(); new_pos = ch_tell(); } return(new_pos); } LONG back_line(curr_pos) /*===========================================*/ LONG curr_pos; /* Get previous line. */ { LONG new_pos, begin_new_pos; register int c; if ((curr_pos == NULL_POSITION) || (curr_pos <= 0) || ch_seek(curr_pos-1)) return (NULL_POSITION); if (page_break) { begin_new_pos = curr_pos; prewind(); goto PAGE_BREAK; } if (squeeze) { /* page_break disables squeeze */ /* Find out if the "current" line was blank. */ ch_forw_get(); /* Skip the newline */ c = ch_forw_get(); /* First char of "current" line */ ch_back_get(); /* Restore our position */ ch_back_get(); if (c == '\n') { /* The "current" line was blank. Skip over any preceeding blank lines, since we skipped them in forw_line(). */ while ((c = ch_back_get()) == '\n') ; if (c == EOF) return (NULL_POSITION); ch_forw_get(); } } /* Scan backwards until we hit the beginning of the line. */ for (;;) { c = ch_back_get(); if (c == '\n') { /* This is the newline ending the previous line. We have hit the beginning of the line. */ new_pos = ch_tell() + 1; break; } if (c == EOF) { /* We have hit the beginning of the file. This must be the first line in the file. This must, of course, be the beginning of the line. */ new_pos = 0; break; } } /* Now scan forwards from the beginning of this line. We keep discarding "printable lines" (based on screen width) until we reach the curr_pos. */ if (ch_seek(new_pos)) return(NULL_POSITION); loop: begin_new_pos = new_pos; prewind(); do { c = ch_forw_get(); new_pos++; if (c == '\n') break; if (pappend(c)) { /* Got a full printable line, but we haven't reached our curr_pos yet. Discard the line and start a new one. */ pappend('\0'); ch_back_get(); new_pos--; goto loop; /* Hey hey hey! */ } } while (new_pos < curr_pos); PAGE_BREAK: pappend('\0'); if (*line == ' ') page_break = 1; return(begin_new_pos); }