summaryrefslogtreecommitdiff
path: root/usr.bin/less/output.c
diff options
context:
space:
mode:
authoretheisen <etheisen@cvs.openbsd.org>1996-09-21 05:39:47 +0000
committeretheisen <etheisen@cvs.openbsd.org>1996-09-21 05:39:47 +0000
commit47d3895c0565680e9e7eba725be0896bfd06ce11 (patch)
tree921c411da39dc3da0c9f04e1732558983f372819 /usr.bin/less/output.c
parenta2e06afb07d9a651364258a3d25e37f99d1dae46 (diff)
Import of unmolested less-290.
Diffstat (limited to 'usr.bin/less/output.c')
-rw-r--r--usr.bin/less/output.c363
1 files changed, 363 insertions, 0 deletions
diff --git a/usr.bin/less/output.c b/usr.bin/less/output.c
new file mode 100644
index 00000000000..dbe180073a5
--- /dev/null
+++ b/usr.bin/less/output.c
@@ -0,0 +1,363 @@
+/*
+ * Copyright (c) 1984,1985,1989,1994,1995 Mark Nudelman
+ * 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 in the documentation and/or other materials provided with
+ * the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ */
+
+
+/*
+ * High level routines dealing with the output to the screen.
+ */
+
+#include "less.h"
+
+public int errmsgs; /* Count of messages displayed by error() */
+public int need_clr;
+
+extern int sigs;
+extern int sc_width;
+extern int so_s_width, so_e_width;
+extern int screen_trashed;
+extern int any_display;
+
+/*
+ * Display the line which is in the line buffer.
+ */
+ public void
+put_line()
+{
+ register int c;
+ register int i;
+ int a;
+ int curr_attr;
+
+ if (ABORT_SIGS())
+ {
+ /*
+ * Don't output if a signal is pending.
+ */
+ screen_trashed = 1;
+ return;
+ }
+
+ curr_attr = AT_NORMAL;
+
+ for (i = 0; (c = gline(i, &a)) != '\0'; i++)
+ {
+ if (a != curr_attr)
+ {
+ /*
+ * Changing attributes.
+ * Display the exit sequence for the old attribute
+ * and the enter sequence for the new one.
+ */
+ switch (curr_attr)
+ {
+ case AT_UNDERLINE: ul_exit(); break;
+ case AT_BOLD: bo_exit(); break;
+ case AT_BLINK: bl_exit(); break;
+ case AT_STANDOUT: so_exit(); break;
+ }
+ switch (a)
+ {
+ case AT_UNDERLINE: ul_enter(); break;
+ case AT_BOLD: bo_enter(); break;
+ case AT_BLINK: bl_enter(); break;
+ case AT_STANDOUT: so_enter(); break;
+ }
+ curr_attr = a;
+ }
+ if (curr_attr == AT_INVIS)
+ continue;
+ if (c == '\b')
+ putbs();
+ else
+ putchr(c);
+ }
+
+ switch (curr_attr)
+ {
+ case AT_UNDERLINE: ul_exit(); break;
+ case AT_BOLD: bo_exit(); break;
+ case AT_BLINK: bl_exit(); break;
+ case AT_STANDOUT: so_exit(); break;
+ }
+}
+
+static char obuf[1024];
+static char *ob = obuf;
+
+/*
+ * Flush buffered output.
+ *
+ * If we haven't displayed any file data yet,
+ * output messages on error output (file descriptor 2),
+ * otherwise output on standard output (file descriptor 1).
+ *
+ * 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.
+ */
+ public void
+flush()
+{
+ register int n;
+ register int fd;
+
+#if MSOFTC
+ *ob = '\0';
+ _outtext(obuf);
+ ob = obuf;
+#else
+ n = ob - obuf;
+ if (n == 0)
+ return;
+ fd = (any_display) ? 1 : 2;
+ if (write(fd, obuf, n) != n)
+ screen_trashed = 1;
+ ob = obuf;
+#endif
+}
+
+/*
+ * Output a character.
+ */
+ public int
+putchr(c)
+ int c;
+{
+ if (ob >= &obuf[sizeof(obuf)])
+ flush();
+ if (need_clr)
+ {
+ need_clr = 0;
+ clear_bot();
+ }
+#if MSOFTC
+ if (c == '\n')
+ putchr('\r');
+#endif
+ *ob++ = c;
+ return (c);
+}
+
+/*
+ * Output a string.
+ */
+ public void
+putstr(s)
+ register char *s;
+{
+ while (*s != '\0')
+ putchr(*s++);
+}
+
+
+/*
+ * Output an integer in a given radix.
+ */
+ static int
+iprintnum(num, radix)
+ int num;
+ int radix;
+{
+ register char *s;
+ int r;
+ int neg;
+ char buf[10];
+
+ if (neg = (num < 0))
+ num = -num;
+
+ s = buf;
+ do
+ {
+ *s++ = (num % radix) + '0';
+ } while ((num /= radix) != 0);
+
+ if (neg)
+ *s++ = '-';
+ r = s - buf;
+
+ while (s > buf)
+ putchr(*--s);
+ return (r);
+}
+
+/*
+ * This function implements printf-like functionality
+ * using a more portable argument list mechanism than printf's.
+ */
+ static int
+iprintf(fmt, parg)
+ register char *fmt;
+ PARG *parg;
+{
+ register char *s;
+ register int n;
+ register int col;
+
+ col = 0;
+ while (*fmt != '\0')
+ {
+ if (*fmt != '%')
+ {
+ putchr(*fmt++);
+ col++;
+ } else
+ {
+ ++fmt;
+ switch (*fmt++) {
+ case 's':
+ s = parg->p_string;
+ parg++;
+ while (*s != '\0')
+ {
+ putchr(*s++);
+ col++;
+ }
+ break;
+ case 'd':
+ n = parg->p_int;
+ parg++;
+ col += iprintnum(n, 10);
+ break;
+ }
+ }
+ }
+ return (col);
+}
+
+/*
+ * Output a message in the lower left corner of the screen
+ * and wait for carriage return.
+ */
+ public void
+error(fmt, parg)
+ char *fmt;
+ PARG *parg;
+{
+ int c;
+ int col = 0;
+ static char return_to_continue[] = " (press RETURN)";
+
+ errmsgs++;
+
+ if (any_display)
+ {
+ clear_bot();
+ so_enter();
+ col += so_s_width;
+ }
+
+ col += iprintf(fmt, parg);
+
+ if (!any_display)
+ {
+ putchr('\n');
+ return;
+ }
+
+ putstr(return_to_continue);
+ so_exit();
+ col += sizeof(return_to_continue) + so_e_width;
+
+#if ONLY_RETURN
+ while ((c = getchr()) != '\n' && c != '\r')
+ bell();
+#else
+ c = getchr();
+ if (c != '\n' && c != '\r' && c != ' ' && c != READ_INTR)
+ ungetcc(c);
+#endif
+ lower_left();
+
+ if (col >= 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. }}
+ */
+ screen_trashed = 1;
+
+ flush();
+}
+
+static char intr_to_abort[] = "... (interrupt to abort)";
+
+/*
+ * Output a message in the lower left corner of the screen
+ * and don't wait for carriage return.
+ * Usually used to warn that we are beginning a potentially
+ * time-consuming operation.
+ */
+ public void
+ierror(fmt, parg)
+ char *fmt;
+ PARG *parg;
+{
+ clear_bot();
+ so_enter();
+ (void) iprintf(fmt, parg);
+ putstr(intr_to_abort);
+ so_exit();
+ flush();
+ need_clr = 1;
+}
+
+/*
+ * Output a message in the lower left corner of the screen
+ * and return a single-character response.
+ */
+ public int
+query(fmt, parg)
+ char *fmt;
+ PARG *parg;
+{
+ register int c;
+ int col = 0;
+
+ if (any_display)
+ clear_bot();
+
+ (void) iprintf(fmt, parg);
+ c = getchr();
+
+ if (!any_display)
+ {
+ putchr('\n');
+ return (c);
+ }
+
+ lower_left();
+ if (col >= sc_width)
+ screen_trashed = 1;
+ flush();
+
+ return (c);
+}