=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/less/input.c,v retrieving revision 1.4 retrieving revision 1.5 diff -u -r1.4 -r1.5 --- src/usr.bin/less/input.c 2003/04/13 18:26:25 1.4 +++ src/usr.bin/less/input.c 2011/09/16 18:12:09 1.5 @@ -1,5 +1,5 @@ /* - * Copyright (C) 1984-2002 Mark Nudelman + * Copyright (C) 1984-2011 Mark Nudelman * * You may distribute under the terms of either the GNU General Public * License or the Less License, as specified in the README file. @@ -27,6 +27,7 @@ extern int quit_if_one_screen; extern int sigs; extern int ignore_eoi; +extern int status_col; extern POSITION start_attnpos; extern POSITION end_attnpos; #if HILITE_SEARCH @@ -45,18 +46,21 @@ forw_line(curr_pos) POSITION curr_pos; { + POSITION base_pos; POSITION new_pos; register int c; int blankline; int endline; + int backchars; +get_forw_line: if (curr_pos == NULL_POSITION) { null_line(); return (NULL_POSITION); } #if HILITE_SEARCH - if (hilite_search == OPT_ONPLUS) + if (hilite_search == OPT_ONPLUS || is_filtering() || status_col) /* * If we are ignoring EOI (command F), only prepare * one line ahead, to avoid getting stuck waiting for @@ -73,10 +77,59 @@ return (NULL_POSITION); } - prewind(); - plinenum(curr_pos); - (void) ch_seek(curr_pos); + /* + * Step back to the beginning of the line. + */ + base_pos = curr_pos; + for (;;) + { + if (ABORT_SIGS()) + { + null_line(); + return (NULL_POSITION); + } + c = ch_back_get(); + if (c == EOI) + break; + if (c == '\n') + { + (void) ch_forw_get(); + break; + } + --base_pos; + } + /* + * Read forward again to the position we should start at. + */ + prewind(); + plinenum(base_pos); + (void) ch_seek(base_pos); + new_pos = base_pos; + while (new_pos < curr_pos) + { + if (ABORT_SIGS()) + { + null_line(); + return (NULL_POSITION); + } + c = ch_forw_get(); + backchars = pappend(c, new_pos); + new_pos++; + if (backchars > 0) + { + pshift_all(); + new_pos -= backchars; + while (--backchars >= 0) + (void) ch_back_get(); + } + } + (void) pflushmbc(); + pshift_all(); + + /* + * Read the first character to display. + */ c = ch_forw_get(); if (c == EOI) { @@ -85,6 +138,9 @@ } blankline = (c == '\n' || c == '\r'); + /* + * Read each character in the line and append to the line buffer. + */ for (;;) { if (ABORT_SIGS()) @@ -97,15 +153,24 @@ /* * End of the line. */ + backchars = pflushmbc(); new_pos = ch_tell(); - endline = TRUE; + if (backchars > 0 && !chopline && hshift == 0) + { + new_pos -= backchars + 1; + endline = FALSE; + } else + endline = TRUE; break; } + if (c != '\r') + blankline = 0; /* * Append the char to the line and get the next char. */ - if (pappend(c, ch_tell()-1)) + backchars = pappend(c, ch_tell()-1); + if (backchars > 0) { /* * The char won't fit in the line; the line @@ -116,6 +181,11 @@ { do { + if (ABORT_SIGS()) + { + null_line(); + return (NULL_POSITION); + } c = ch_forw_get(); } while (c != '\n' && c != EOI); new_pos = ch_tell(); @@ -123,15 +193,31 @@ quit_if_one_screen = FALSE; } else { - new_pos = ch_tell() - 1; + new_pos = ch_tell() - backchars; endline = FALSE; } break; } c = ch_forw_get(); } - pdone(endline); + pdone(endline, 1); + +#if HILITE_SEARCH + if (is_filtered(base_pos)) + { + /* + * We don't want to display this line. + * Get the next line. + */ + curr_pos = new_pos; + goto get_forw_line; + } + + if (status_col && is_hilited(base_pos, ch_tell()-1, 1, NULL)) + set_status_col('*'); +#endif + if (squeeze && blankline) { /* @@ -164,17 +250,19 @@ back_line(curr_pos) POSITION curr_pos; { - POSITION new_pos, begin_new_pos; + POSITION new_pos, begin_new_pos, base_pos; int c; int endline; + int backchars; +get_back_line: if (curr_pos == NULL_POSITION || curr_pos <= ch_zero()) { null_line(); return (NULL_POSITION); } #if HILITE_SEARCH - if (hilite_search == OPT_ONPLUS) + if (hilite_search == OPT_ONPLUS || is_filtering() || status_col) prep_hilite((curr_pos < 3*size_linebuf) ? 0 : curr_pos - 3*size_linebuf, curr_pos, -1); #endif @@ -189,9 +277,9 @@ /* * Find out if the "current" line was blank. */ - (void) ch_forw_get(); /* Skip the newline */ - c = ch_forw_get(); /* First char of "current" line */ - (void) ch_back_get(); /* Restore our position */ + (void) ch_forw_get(); /* Skip the newline */ + c = ch_forw_get(); /* First char of "current" line */ + (void) ch_back_get(); /* Restore our position */ (void) ch_back_get(); if (c == '\n' || c == '\r') @@ -233,7 +321,7 @@ * This is the newline ending the previous line. * We have hit the beginning of the line. */ - new_pos = ch_tell() + 1; + base_pos = ch_tell() + 1; break; } if (c == EOI) @@ -243,7 +331,7 @@ * This must be the first line in the file. * This must, of course, be the beginning of the line. */ - new_pos = ch_tell(); + base_pos = ch_tell(); break; } } @@ -257,16 +345,17 @@ * are much longer than the screen width, * but I don't know of any better way. }} */ + new_pos = base_pos; if (ch_seek(new_pos)) { null_line(); return (NULL_POSITION); } endline = FALSE; - loop: - begin_new_pos = new_pos; prewind(); plinenum(new_pos); + loop: + begin_new_pos = new_pos; (void) ch_seek(new_pos); do @@ -280,10 +369,17 @@ new_pos++; if (c == '\n') { + backchars = pflushmbc(); + if (backchars > 0 && !chopline && hshift == 0) + { + backchars++; + goto shift; + } endline = TRUE; break; } - if (pappend(c, ch_tell()-1)) + backchars = pappend(c, ch_tell()-1); + if (backchars > 0) { /* * Got a full printable line, but we haven't @@ -296,14 +392,33 @@ quit_if_one_screen = FALSE; break; } - pdone(0); - (void) ch_back_get(); - new_pos--; + shift: + pshift_all(); + while (backchars-- > 0) + { + (void) ch_back_get(); + new_pos--; + } goto loop; } } while (new_pos < curr_pos); - pdone(endline); + pdone(endline, 0); + +#if HILITE_SEARCH + if (is_filtered(base_pos)) + { + /* + * We don't want to display this line. + * Get the previous line. + */ + curr_pos = begin_new_pos; + goto get_back_line; + } + + if (status_col && is_hilited(base_pos, ch_tell()-1, 1, NULL)) + set_status_col('*'); +#endif return (begin_new_pos); }