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