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