/************************************************************************* *** line.c (JJB TEMPLAR) *** *** Date modifications begun: 7/8/89. *** *** Last modified: 9/8/89. *** *************************************************************************/ /*** Routines to manipulate the "line buffer". The line buffer holds a *** *** line of output as it is being built in preparation for output to *** *** the screen. We keep track of the PRINTABLE length of the line as *** *** it is being built (well, sort of). *** *************************************************************************/ #include "less.h" static char linebuf[1024]; /* Buffer which holds the current output line */ static char *curr; /* Pointer into linebuf */ static int column; /* Printable length, accounting for backspaces, etc. */ char *line; /* Pointer to the current line. Usually points to linebuf. */ extern int sc_width, sc_height; void prewind() /*=====================================================*/ { /* Rewind line buffer. */ line = curr = linebuf; column = 0; } #define NEW_COLUMN(nc) if ((nc) > sc_width+50) return(1); else column = (nc); int pappend(c) /*====================================================*/ register int c; /* Append char to buffer, return !success. */ { if (!c) { /* Add zero to string */ *curr = 0; return(0); } /* check if much buffer left */ if (curr - linebuf > sizeof(linebuf) - 12) return(1); /* Used to expand tabs. Let console worry about that. May cause probs * if auto-wrap was on (which it isn't), and will frack the l_start * stuff a little. (Actually put out ^I at the moment). */ /* Let the ESC codesd pass through OK. */ /* Deal with ctrl-characters at the put_line level, one of the benefits * of which is that the high bit isn't required to flag carats */ /* Ordinary character. Just put it in the buffer */ NEW_COLUMN(column+1); *curr++ = c; return(0); } LONG forw_raw_line(curr_pos) /*=======================================*/ LONG curr_pos; /* Similar to forw_line(), but for "raw lines". */ { register char *p; register int c; LONG new_pos; if ((curr_pos == NULL_POSITION) || ch_seek(curr_pos) || ((c = ch_forw_get()) == EOF)) return(NULL_POSITION); /* Can't go forward */ p = linebuf; for (;;) { if ((c == '\n') || (c == EOF)) { new_pos = ch_tell(); break; } if (p >= &linebuf[sizeof(linebuf)-1]) { /* Overflowed the input buffer. Pretend the line ended here. */ new_pos = ch_tell() - 1; break; } *p++ = c; c = ch_forw_get(); } *p = 0; line = linebuf; return(new_pos); } LONG back_raw_line(curr_pos) /*=======================================*/ LONG curr_pos; /* As above, but backwards. */ { register char *p; register int c; LONG new_pos; if ((curr_pos == NULL_POSITION) || (curr_pos <= 0) || ch_seek(curr_pos-1)) return(NULL_POSITION); p = &linebuf[sizeof(linebuf)]; *(--p) = 0; for (;;) { c = ch_back_get(); if (c == '\n') { /* Newline ending previous line */ new_pos = ch_tell() + 1; break; } if (c == EOF) { /* Hit beginning of file */ new_pos = 0; break; } if (p <= linebuf) { /* Overflowed the input buffer */ new_pos = ch_tell() + 1; break; } *(--p) = c; } line = p; return(new_pos); }