head 1.14; access; symbols RELENG_4_0_0_RELEASE:1.12 RELENG_4:1.12.0.2 RELENG_4_BP:1.12 RELENG_3_4_0_RELEASE:1.7.2.4 RELENG_3_3_0_RELEASE:1.7.2.4 RELENG_3_2_PAO:1.7.2.1.0.2 RELENG_3_2_PAO_BP:1.7.2.1 RELENG_3_2_0_RELEASE:1.7.2.1 RELENG_3_1_0_RELEASE:1.7 RELENG_3:1.7.0.2 RELENG_3_BP:1.7 RELENG_2_2_8_RELEASE:1.5.6.2 RELENG_3_0_0_RELEASE:1.7 RELENG_2_2_7_RELEASE:1.5.6.2 RELENG_2_2_6_RELEASE:1.5.6.1 RELENG_2_2_5_RELEASE:1.5.6.1 bsd_44_lite_2:1.1.1.2 RELENG_2_2_2_RELEASE:1.5 RELENG_2_2_1_RELEASE:1.5 RELENG_2_2_0_RELEASE:1.5 RELENG_2_1_7_RELEASE:1.5 RELENG_2_1_6_1_RELEASE:1.5 RELENG_2_1_6_RELEASE:1.5 RELENG_2_2:1.5.0.6 RELENG_2_2_BP:1.5 RELENG_2_1_5_RELEASE:1.5 RELENG_2_1_0_RELEASE:1.5 RELENG_2_1_0:1.5.0.4 RELENG_2_1_0_BP:1.5 RELENG_2_0_5_RELEASE:1.5 RELENG_2_0_5:1.5.0.2 RELENG_2_0_5_BP:1.5 RELENG_2_0_5_ALPHA:1.4 RELEASE_2_0:1.4 BETA_2_0:1.4 ALPHA_2_0:1.4.0.2 bsd_44_lite:1.1.1.1 CSRG:1.1.1; locks; comment @ * @; 1.14 date 2000.05.23.04.23.09; author tim; state Exp; branches; next 1.13; 1.13 date 2000.05.23.04.19.07; author tim; state Exp; branches; next 1.12; 1.12 date 99.09.03.22.31.18; author hoek; state Exp; branches; next 1.11; 1.11 date 99.08.28.01.04.18; author peter; state Exp; branches; next 1.10; 1.10 date 99.06.02.03.42.39; author hoek; state Exp; branches; next 1.9; 1.9 date 99.05.30.18.06.56; author hoek; state Exp; branches; next 1.8; 1.8 date 99.04.29.18.03.37; author hoek; state Exp; branches; next 1.7; 1.7 date 98.02.20.04.13.28; author jb; state Exp; branches 1.7.2.1; next 1.6; 1.6 date 97.01.12.13.34.13; author ache; state Exp; branches; next 1.5; 1.5 date 95.05.30.06.32.33; author rgrimes; state Exp; branches 1.5.6.1; next 1.4; 1.4 date 94.10.09.15.40.05; author ache; state Exp; branches; next 1.3; 1.3 date 94.09.22.01.19.09; author ache; state Exp; branches; next 1.2; 1.2 date 94.09.08.21.30.51; author csgr; state Exp; branches; next 1.1; 1.1 date 94.05.27.12.30.45; author rgrimes; state Exp; branches 1.1.1.1; next ; 1.1.1.1 date 94.05.27.12.30.46; author rgrimes; state Exp; branches; next 1.1.1.2; 1.1.1.2 date 97.07.06.06.52.55; author bde; state Exp; branches; next ; 1.5.6.1 date 97.09.15.09.20.52; author jkh; state Exp; branches; next 1.5.6.2; 1.5.6.2 date 98.07.17.04.19.47; author jkh; state Exp; branches; next ; 1.7.2.1 date 99.05.02.18.15.56; author hoek; state Exp; branches; next 1.7.2.2; 1.7.2.2 date 99.07.28.06.09.51; author hoek; state Exp; branches; next 1.7.2.3; 1.7.2.3 date 99.07.28.06.17.11; author hoek; state Exp; branches; next 1.7.2.4; 1.7.2.4 date 99.08.29.15.31.18; author peter; state Exp; branches; next ; desc @@ 1.14 log @Note on prev: This was actually a long-standing bug that existed before rev.1.9 of this file (the rev where the buggy code was introduced to replace other presumably buggy code). I don't know why Nevermind. @ text @/* * Copyright (c) 1988 Mark Nudleman * Copyright (c) 1988, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifndef lint static char sccsid[] = "@@(#)output.c 8.1 (Berkeley) 6/6/93"; #endif /* not lint */ #ifndef lint static const char rcsid[] = "$FreeBSD: src/usr.bin/more/output.c,v 1.12 1999/09/03 22:31:18 hoek Exp $"; #endif /* not lint */ /* * High level routines dealing with the output to the screen. */ #include #include #include #include "less.h" extern int bs_mode; extern int sigs; extern int sc_width, sc_height; extern int ul_width, ue_width; extern int so_width, se_width; extern int bo_width, be_width; extern int tabstop; extern int screen_trashed; extern char *line; extern int horiz_off; extern int mode_flags; static int last_pos_highlighted = 0; /* static markup() * * Output correct markup char; return number of columns eaten-up. * Called by put_line() just before doing any actual output. */ #define ENTER 1 #define ACQUIESCE 0 /* XXX Check actual def'n... */ #define EXIT -1 static markup(ent_ul, ent_bo) int *ent_ul, *ent_bo; { int retr; retr = 0; /* * On some terminals (notably syscons), doing xx_exit() will cause * us to exit all special modes. For an xx_exit() function to * work as expected, it may need to call yy_enter() to restore a * lost mode. We don't need to worry about this right now since * pappend() can only handle one of bold or underline at a time. * This is all guaranteed to be true if we fell back to the ``me'' * capability for any of the xx_exit() functions. */ if (*ent_ul == EXIT) { ul_exit(); retr += ue_width; } if (*ent_bo == EXIT) { bo_exit(); retr += be_width; } if (*ent_ul == ENTER) { ul_enter(); retr += ul_width; } if (*ent_bo == ENTER) { bo_enter(); retr += bo_width; } *ent_ul = *ent_bo = ACQUIESCE; return retr; } /* put_line() * * Display the line which is in the line buffer. The number of output * characters in the line buffer cannot exceed screen columns available. * Output characters in the line buffer that precede horiz_off are skipped. * The caller may depend on this behaviour to ensure that the number of output * characters in the line buffer does not exceed the screen columns * available. * * This routine will get confused if the line buffer has non-sensical * UL_CHAR, UE_CHAR, BO_CHAR, BE_CHAR markups. */ #define MAYPUTCHR(char) \ if (column >= horiz_off) { \ column += markup(&ent_ul, &ent_bo); \ putchr(char); \ } put_line() { register char *p; register int c; register int column; extern int auto_wrap, ignaw; int ent_ul, ent_bo; /* enter or exit ul|bo mode for next char */ if (sigs) { /* * Don't output if a signal is pending. */ screen_trashed = 1; return; } if (line == NULL) line = ""; if (last_pos_highlighted) { clear_eol(); last_pos_highlighted = 0; } column = 0; ent_ul = ent_bo = ACQUIESCE; for (p = line; *p != '\0'; p++) { /* * XXX line.c needs to be rewritten to store markup * information as metadata associated with each character. * This will make several things much nicer, fixing problems, * etc. Until then, this kludge will hold the fort well * enough. */ switch ((char)(c = (unsigned char)*p)) { case UL_CHAR: ent_ul = ENTER; break; case UE_CHAR: if (ent_ul != ENTER) ent_ul = EXIT; else ent_ul = ACQUIESCE; break; case BO_CHAR: ent_bo = ENTER; break; case BE_CHAR: if (ent_bo != ENTER) ent_bo = EXIT; else ent_bo = ACQUIESCE; break; case '\t': do { MAYPUTCHR(' '); column++; } while ((column % tabstop) != 0); break; case '\b': /* * column must be at least one greater than * horiz_off (ie. we must be in the second or * beyond screen column) or we'll just end-up * backspacing up to the previous line. */ if (column > horiz_off) { column += markup(&ent_ul, &ent_bo); putbs(); column--; } break; case '\r': /* treat \r\n sequences like \n if -u flag not set. */ if (bs_mode || p[1] != '\0') { /* -u was set, or this CR is not a CRLF, so * treat this CR like any other control_char */ MAYPUTCHR('^'); column++; MAYPUTCHR(CARAT_CHAR(c)); column++; } break; default: if (c == 0200 || CONTROL_CHAR(c)) { c &= ~0200; MAYPUTCHR('^'); column++; MAYPUTCHR(CARAT_CHAR(c)); column++; } else { MAYPUTCHR(c); column++; } } if (column == sc_width + horiz_off && mode_flags) last_pos_highlighted = 1; } column += markup(&ent_ul, &ent_bo); if (column < sc_width + horiz_off || !auto_wrap || ignaw) putchr('\n'); } static char obuf[2048]; /* just large enough for a full 25*80 screen */ static char *ob = obuf; /* * Flush buffered output. */ flush() { register int n; n = ob - obuf; if (n == 0) return; if (write(1, obuf, n) != n) screen_trashed = 1; ob = obuf; } /* * Purge any pending output. */ purge() { ob = obuf; } /* * Output a character. */ putchr(c) int c; { if (ob >= &obuf[sizeof(obuf)]) flush(); *ob++ = c; } /* * Output a string. */ putstr(s) register char *s; { while (*s != '\0') putchr(*s++); } /* * Output a string, expanding control characters into printable sequences. * Returns the number of characters printed. */ int putxstr(s) char *s; { int c; int retr = 0; for (; c = *s; s++) { if (CONTROL_CHAR(c)) { putchr('^'); retr++; c &= ~0200; c = CARAT_CHAR(c); } putchr(c); } return(retr); } static char intr_to_abort[] = "... (interrupt to abort)"; ierror(s) char *s; { lower_left(); clear_eol(); so_enter(); putstr(s); putstr(intr_to_abort); so_exit(); flush(); } @ 1.13 log @Handle immediate switches from bold to underline or vice-a-versa correctly. @ text @@ 1.12 log @Thorough revamp of how input commands are processed. This allows customization of user keys (documentation pending). The only key whose semantics have changed is the capital 'N' key, which now performs a repeat-search in the opposite direction (just like in vi). This commit is a little bulkier than what I had originally planned. I'm not completely happy with the direction it went, but it's definately an improvement, and the alternative is to continue becoming irrelevant compared to GNU less. (Does anyone even _use_ /usr/bin/more these days?) @ text @d41 1 a41 1 "$FreeBSD: src/usr.bin/more/output.c,v 1.11 1999/08/28 01:04:18 peter Exp $"; d84 18 a101 2 switch (*ent_ul) { case ENTER: a103 5 break; case EXIT: ul_exit(); retr += ue_width; break; d105 1 a105 2 switch (*ent_bo) { case ENTER: a107 5 break; case EXIT: bo_exit(); retr += be_width; break; @ 1.11 log @$Id$ -> $FreeBSD$ @ text @d41 1 a41 1 "$FreeBSD$"; a53 2 int errmsgs; /* Count of messages displayed by error() */ a61 1 extern int any_display; d121 1 a121 1 if (column >= eff_horiz_off) { \ a132 1 int eff_horiz_off; a142 5 if (horiz_off == NO_HORIZ_OFF) eff_horiz_off = 0; else eff_horiz_off = horiz_off; d192 1 a192 1 * eff_horiz_off (ie. we must be in the second or d196 1 a196 1 if (column > eff_horiz_off) { d228 1 a228 1 if (column == sc_width + eff_horiz_off && mode_flags) d232 1 a232 1 if (column < sc_width + eff_horiz_off || !auto_wrap || ignaw) a283 3 int cmdstack; static char return_to_continue[] = "(press RETURN)"; d285 2 a286 2 * Output a message in the lower left corner of the screen * and wait for carriage return. d288 2 a289 1 error(s) d292 2 a293 1 int ch; d295 8 a302 26 ++errmsgs; if (!any_display) { /* * Nothing has been displayed yet. Output this message on * error output (file descriptor 2) and don't wait for a * keystroke to continue. * * This has the desirable effect of producing all error * messages on error output if standard output is directed * to a file. It also does the same if we never produce * any real output; for example, if the input file(s) cannot * be opened. If we do eventually produce output, code in * edit() makes sure these messages can be seen before they * are overwritten or scrolled away. */ (void)write(2, s, strlen(s)); (void)write(2, "\n", 1); return; } lower_left(); clear_eol(); so_enter(); if (s) { putstr(s); putstr(" "); a303 2 putstr(return_to_continue); so_exit(); d305 1 a305 17 if ((ch = getchr()) != '\n') { /* XXX hardcoded */ if (ch == 'q') quit(); cmdstack = ch; } lower_left(); if ((s==NULL)?0:(strlen(s)) + sizeof(return_to_continue) + so_width + se_width + 1 > sc_width) /* * Printing the message has probably scrolled the screen. * {{ Unless the terminal doesn't have auto margins, * in which case we just hammered on the right margin. }} */ repaint(); flush(); @ 1.10 log @Don't print backspaces in first column since they backup to the prev line. @ text @d41 1 a41 1 "$Id: output.c,v 1.9 1999/05/30 18:06:56 hoek Exp $"; @ 1.9 log @General code cleanup [incomplete]. Make the arrow keys work. @ text @d41 1 a41 1 "$Id$"; d199 11 a209 4 /* markup() before putbs() ? */ column += markup(&ent_ul, &ent_bo); putbs(); column--; @ 1.8 log @Remove documentation of CRLF bug from more.1. Sync code with manpage. PR: bin/961 bin/7296 (fix) Submitted by: Garance Alistair Drosehn @ text @d39 5 d51 1 d66 1 d68 1 d71 58 a128 1 /* display the line which is in the line buffer. */ d135 2 d147 5 d161 1 d164 7 d174 1 a174 2 ul_enter(); column += ul_width; d177 4 a180 2 ul_exit(); column += ue_width; d183 1 a183 2 bo_enter(); column += bo_width; d186 4 a189 2 bo_exit(); column += be_width; d194 1 a194 1 putchr(' '); d199 2 d210 4 a213 3 putchr('^');; putchr(CARAT_CHAR(c)); column += 2; d220 4 a223 3 putchr('^'); putchr(CARAT_CHAR(c)); column += 2; d226 1 a226 1 putchr(c); d230 1 a230 1 if (column == sc_width && mode_flags) d233 2 a234 1 if (column < sc_width || !auto_wrap || ignaw) d238 1 a238 1 static char obuf[1024]; d329 1 @ 1.7 log @Add #include to get prototypes for functions that gcc has builtin (and wants to know that the prototypes match). @ text @d50 1 d119 11 @ 1.7.2.1 log @MFC: count crlfs as one character @ text @a49 1 extern int bs_mode; a117 11 break; case '\r': /* treat \r\n sequences like \n if -u flag not set. */ if (bs_mode || p[1] != '\0') { /* -u was set, or this CR is not a CRLF, so * treat this CR like any other control_char */ putchr('^');; putchr(CARAT_CHAR(c)); column += 2; } @ 1.7.2.2 log @commit-notes @ text @a38 5 #ifndef lint static const char rcsid[] = "$Id: output.c,v 1.10 1999/06/02 03:42:39 hoek Exp $"; #endif /* not lint */ a45 1 a59 1 extern int horiz_off; a60 1 d63 1 a63 58 /* static markup() * * Output correct markup char; return number of columns eaten-up. * Called by put_line() just before doing any actual output. */ #define ENTER 1 #define ACQUIESCE 0 /* XXX Check actual def'n... */ #define EXIT -1 static markup(ent_ul, ent_bo) int *ent_ul, *ent_bo; { int retr; retr = 0; switch (*ent_ul) { case ENTER: ul_enter(); retr += ul_width; break; case EXIT: ul_exit(); retr += ue_width; break; } switch (*ent_bo) { case ENTER: bo_enter(); retr += bo_width; break; case EXIT: bo_exit(); retr += be_width; break; } *ent_ul = *ent_bo = ACQUIESCE; return retr; } /* put_line() * * Display the line which is in the line buffer. The number of output * characters in the line buffer cannot exceed screen columns available. * Output characters in the line buffer that precede horiz_off are skipped. * The caller may depend on this behaviour to ensure that the number of output * characters in the line buffer does not exceed the screen columns * available. * * This routine will get confused if the line buffer has non-sensical * UL_CHAR, UE_CHAR, BO_CHAR, BE_CHAR markups. */ #define MAYPUTCHR(char) \ if (column >= eff_horiz_off) { \ column += markup(&ent_ul, &ent_bo); \ putchr(char); \ } a69 2 int ent_ul, ent_bo; /* enter or exit ul|bo mode for next char */ int eff_horiz_off; a79 5 if (horiz_off == NO_HORIZ_OFF) eff_horiz_off = 0; else eff_horiz_off = horiz_off; a88 1 ent_ul = ent_bo = ACQUIESCE; a90 7 /* * XXX line.c needs to be rewritten to store markup * information as metadata associated with each character. * This will make several things much nicer, fixing problems, * etc. Until then, this kludge will hold the fort well * enough. */ d94 2 a95 1 ent_ul = ENTER; d98 2 a99 4 if (ent_ul != ENTER) ent_ul = EXIT; else ent_ul = ACQUIESCE; d102 2 a103 1 ent_bo = ENTER; d106 2 a107 4 if (ent_bo != ENTER) ent_bo = EXIT; else ent_bo = ACQUIESCE; d112 1 a112 1 MAYPUTCHR(' '); d117 2 a118 11 /* * column must be at least one greater than * eff_horiz_off (ie. we must be in the second or * beyond screen column) or we'll just end-up * backspacing up to the previous line. */ if (column > eff_horiz_off) { column += markup(&ent_ul, &ent_bo); putbs(); column--; } d126 3 a128 4 MAYPUTCHR('^'); column++; MAYPUTCHR(CARAT_CHAR(c)); column++; d135 3 a137 4 MAYPUTCHR('^'); column++; MAYPUTCHR(CARAT_CHAR(c)); column++; d140 1 a140 1 MAYPUTCHR(c); d144 1 a144 1 if (column == sc_width + eff_horiz_off && mode_flags) d147 1 a147 2 column += markup(&ent_ul, &ent_bo); if (column < sc_width + eff_horiz_off || !auto_wrap || ignaw) d151 1 a151 1 static char obuf[2048]; /* just large enough for a full 25*80 screen */ a241 1 /* XXX hardcoded */ @ 1.7.2.3 log @[Whoops... used ci -m instead of -F on the last commit...] MFC: misc incidental cleanup, gtags support, better line-number passing to $EDITOR, working arrow keys, $Id$ to manpage @ text @d41 1 a41 1 "$Id: output.c,v 1.7.2.2 1999/07/28 06:09:51 hoek Exp $"; @ 1.7.2.4 log @$Id$ -> $FreeBSD$ @ text @d41 1 a41 1 "$FreeBSD$"; @ 1.6 log @include ctype.h to pick isprint macro @ text @d45 1 @ 1.5 log @Remove trailing whitespace. @ text @d43 1 d45 1 a45 1 #include @ 1.5.6.1 log @MFC: Lots of cosmetics (plus one gripe from bde about a comment in tail's sources, of all places). @ text @a42 1 #include d44 1 a44 1 #include "less.h" @ 1.5.6.2 log @MFC: doc fixes, enhancements to locate & more, new tail functionality. @ text @a44 1 #include @ 1.4 log @Back out part of ctype fixes, unneded with new ctypoe @ text @d234 1 a234 1 if ((s==NULL)?0:(strlen(s)) + sizeof(return_to_continue) + @ 1.3 log @1) Make ctype-aware expect chars in range 0200-0204 treated as controls in any case. 2) Fix bug with incorrect column position when standouts occurse 3) Fix bug when last standouted char cause clearing next line in standout @ text @d88 1 a88 1 switch ((char)(c = *p & 0xff)) @ 1.2 log @From 1.1.5.1 >From Arne Bier while running more(1), if you enter ":a" to get the name of the file being viewed, more dumps core when you hit enter (as prompted). This is due to more(1) attempting to find the length of a NULL string. Submitted by: Geoff. @ text @d57 2 d80 5 d88 1 a88 1 switch (c = *p) d92 1 a92 1 column += ul_width +1; d100 1 a100 1 column += bo_width +1; d118 1 a118 1 if (c & 0200) d120 1 a120 5 /* * Control characters arrive here as the * normal character [CARAT_CHAR(c)] with * the 0200 bit set. See pappend(). */ d122 1 a122 1 putchr(c & 0177); d130 2 @ 1.1 log @Initial revision @ text @d229 1 a229 1 if (strlen(s) + sizeof(return_to_continue) + @ 1.1.1.1 log @BSD 4.4 Lite Usr.bin Sources @ text @@ 1.1.1.2 log @Finish importing Lite2's src/usr.bin, except for ex, diff, grep, mail, pascal and vmstat.sparc. All changed files on the vendor branch should already have been imported. @ text @d36 1 a36 1 static char sccsid[] = "@@(#)output.c 8.2 (Berkeley) 4/27/95"; d207 2 a208 4 if (s != NULL) { (void)write(2, s, strlen(s)); (void)write(2, "\n", 1); } d215 1 a215 1 if (s != NULL) { d229 1 a229 1 if ((s != NULL ? strlen(s) : 0) + sizeof(return_to_continue) + @