xref: /netbsd/distrib/utils/more/output.c (revision bf9ec67e)
1 /*	$NetBSD: output.c,v 1.5 1999/10/19 23:09:45 dan Exp $	*/
2 
3 /*
4  * Copyright (c) 1988 Mark Nudleman
5  * Copyright (c) 1988, 1993
6  *	The Regents of the University of California.  All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. All advertising materials mentioning features or use of this software
17  *    must display the following acknowledgement:
18  *	This product includes software developed by the University of
19  *	California, Berkeley and its contributors.
20  * 4. Neither the name of the University nor the names of its contributors
21  *    may be used to endorse or promote products derived from this software
22  *    without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34  * SUCH DAMAGE.
35  */
36 
37 #include <sys/cdefs.h>
38 #ifndef lint
39 #if 0
40 static char sccsid[] = "@(#)output.c	8.2 (Berkeley) 4/27/95";
41 #else
42 __RCSID("$NetBSD: output.c,v 1.5 1999/10/19 23:09:45 dan Exp $");
43 #endif
44 #endif /* not lint */
45 
46 /*
47  * High level routines dealing with the output to the screen.
48  */
49 
50 #include <stdio.h>
51 #include <string.h>
52 #include <unistd.h>
53 #include <stdlib.h>
54 
55 #include "less.h"
56 #include "extern.h"
57 
58 int errmsgs;	/* Count of messages displayed by error() */
59 
60 /* display the line which is in the line buffer. */
61 void
62 put_line()
63 {
64 	char *p;
65 	int c;
66 	int column;
67 
68 	if (sigs)
69 	{
70 		/*
71 		 * Don't output if a signal is pending.
72 		 */
73 		screen_trashed = 1;
74 		return;
75 	}
76 
77 	if (line == NULL)
78 		line = "";
79 
80 	column = 0;
81 	for (p = line;  *p != '\0';  p++)
82 	{
83 		switch (c = *p)
84 		{
85 		case UL_CHAR:
86 			ul_enter();
87 			column += ul_width +1;
88 			break;
89 		case UE_CHAR:
90 			ul_exit();
91 			column += ue_width;
92 			break;
93 		case BO_CHAR:
94 			bo_enter();
95 			column += bo_width +1;
96 			break;
97 		case BE_CHAR:
98 			bo_exit();
99 			column += be_width;
100 			break;
101 		case '\t':
102 			do
103 			{
104 				putchr(' ');
105 				column++;
106 			} while ((column % tabstop) != 0);
107 			break;
108 		case '\b':
109 			putbs();
110 			column--;
111 			break;
112 		default:
113 			if (c & 0200)
114 			{
115 				/*
116 				 * Control characters arrive here as the
117 				 * normal character [CARAT_CHAR(c)] with
118 				 * the 0200 bit set.  See pappend().
119 				 */
120 				putchr('^');
121 				putchr(c & 0177);
122 				column += 2;
123 			} else
124 			{
125 				putchr(c);
126 				column++;
127 			}
128 		}
129 	}
130 	if (column < sc_width || !auto_wrap || ignaw)
131 		putchr('\n');
132 }
133 
134 static char obuf[1024];
135 static char *ob = obuf;
136 
137 /*
138  * Flush buffered output.
139  */
140 void
141 flush()
142 {
143 	int n;
144 
145 	n = ob - obuf;
146 	if (n == 0)
147 		return;
148 	if (write(1, obuf, n) != n)
149 		screen_trashed = 1;
150 	ob = obuf;
151 }
152 
153 /*
154  * Purge any pending output.
155  */
156 void
157 purge()
158 {
159 
160 	ob = obuf;
161 }
162 
163 /*
164  * Output a character.
165  */
166 int
167 putchr(c)
168 	int c;
169 {
170 	if (ob >= &obuf[sizeof(obuf)])
171 		flush();
172 	*ob++ = c;
173 }
174 
175 /*
176  * Output a string.
177  */
178 void
179 putstr(s)
180 	char *s;
181 {
182 	while (*s != '\0')
183 		putchr(*s++);
184 }
185 
186 int cmdstack;
187 static char return_to_continue[] = "(press RETURN)";
188 
189 /*
190  * Output a message in the lower left corner of the screen
191  * and wait for carriage return.
192  */
193 void
194 error(s)
195 	char *s;
196 {
197 	int ch;
198 
199 	++errmsgs;
200 	if (!any_display) {
201 		/*
202 		 * Nothing has been displayed yet.  Output this message on
203 		 * error output (file descriptor 2) and don't wait for a
204 		 * keystroke to continue.
205 		 *
206 		 * This has the desirable effect of producing all error
207 		 * messages on error output if standard output is directed
208 		 * to a file.  It also does the same if we never produce
209 		 * any real output; for example, if the input file(s) cannot
210 		 * be opened.  If we do eventually produce output, code in
211 		 * edit() makes sure these messages can be seen before they
212 		 * are overwritten or scrolled away.
213 		 */
214 		if (s != NULL) {
215 			(void)write(2, s, strlen(s));
216 			(void)write(2, "\n", 1);
217 		}
218 		return;
219 	}
220 
221 	lower_left();
222 	clear_eol();
223 	so_enter();
224 	if (s != NULL) {
225 		putstr(s);
226 		putstr("  ");
227 	}
228 	putstr(return_to_continue);
229 	so_exit();
230 
231 	if ((ch = getchr()) != '\n') {
232 		if (ch == 'q')
233 			quit();
234 		cmdstack = ch;
235 	}
236 	lower_left();
237 
238 	if ((s != NULL ? strlen(s) : 0) + sizeof(return_to_continue) +
239 		so_width + se_width + 1 > sc_width)
240 		/*
241 		 * Printing the message has probably scrolled the screen.
242 		 * {{ Unless the terminal doesn't have auto margins,
243 		 *    in which case we just hammered on the right margin. }}
244 		 */
245 		repaint();
246 	flush();
247 }
248 
249 static char intr_to_abort[] = "... (interrupt to abort)";
250 
251 void
252 ierror(s)
253 	char *s;
254 {
255 	lower_left();
256 	clear_eol();
257 	so_enter();
258 	putstr(s);
259 	putstr(intr_to_abort);
260 	so_exit();
261 	flush();
262 }
263