xref: /original-bsd/usr.bin/more/output.c (revision 00695d63)
1 /*
2  * Copyright (c) 1988 Mark Nudleman
3  * Copyright (c) 1988, 1993
4  *	The Regents of the University of California.  All rights reserved.
5  *
6  * %sccs.include.redist.c%
7  */
8 
9 #ifndef lint
10 static char sccsid[] = "@(#)output.c	8.2 (Berkeley) 04/27/95";
11 #endif /* not lint */
12 
13 /*
14  * High level routines dealing with the output to the screen.
15  */
16 
17 #include <stdio.h>
18 #include <less.h>
19 
20 int errmsgs;	/* Count of messages displayed by error() */
21 
22 extern int sigs;
23 extern int sc_width, sc_height;
24 extern int ul_width, ue_width;
25 extern int so_width, se_width;
26 extern int bo_width, be_width;
27 extern int tabstop;
28 extern int screen_trashed;
29 extern int any_display;
30 extern char *line;
31 
32 /* display the line which is in the line buffer. */
33 put_line()
34 {
35 	register char *p;
36 	register int c;
37 	register int column;
38 	extern int auto_wrap, ignaw;
39 
40 	if (sigs)
41 	{
42 		/*
43 		 * Don't output if a signal is pending.
44 		 */
45 		screen_trashed = 1;
46 		return;
47 	}
48 
49 	if (line == NULL)
50 		line = "";
51 
52 	column = 0;
53 	for (p = line;  *p != '\0';  p++)
54 	{
55 		switch (c = *p)
56 		{
57 		case UL_CHAR:
58 			ul_enter();
59 			column += ul_width +1;
60 			break;
61 		case UE_CHAR:
62 			ul_exit();
63 			column += ue_width;
64 			break;
65 		case BO_CHAR:
66 			bo_enter();
67 			column += bo_width +1;
68 			break;
69 		case BE_CHAR:
70 			bo_exit();
71 			column += be_width;
72 			break;
73 		case '\t':
74 			do
75 			{
76 				putchr(' ');
77 				column++;
78 			} while ((column % tabstop) != 0);
79 			break;
80 		case '\b':
81 			putbs();
82 			column--;
83 			break;
84 		default:
85 			if (c & 0200)
86 			{
87 				/*
88 				 * Control characters arrive here as the
89 				 * normal character [CARAT_CHAR(c)] with
90 				 * the 0200 bit set.  See pappend().
91 				 */
92 				putchr('^');
93 				putchr(c & 0177);
94 				column += 2;
95 			} else
96 			{
97 				putchr(c);
98 				column++;
99 			}
100 		}
101 	}
102 	if (column < sc_width || !auto_wrap || ignaw)
103 		putchr('\n');
104 }
105 
106 static char obuf[1024];
107 static char *ob = obuf;
108 
109 /*
110  * Flush buffered output.
111  */
112 flush()
113 {
114 	register int n;
115 
116 	n = ob - obuf;
117 	if (n == 0)
118 		return;
119 	if (write(1, obuf, n) != n)
120 		screen_trashed = 1;
121 	ob = obuf;
122 }
123 
124 /*
125  * Purge any pending output.
126  */
127 purge()
128 {
129 
130 	ob = obuf;
131 }
132 
133 /*
134  * Output a character.
135  */
136 putchr(c)
137 	int c;
138 {
139 	if (ob >= &obuf[sizeof(obuf)])
140 		flush();
141 	*ob++ = c;
142 }
143 
144 /*
145  * Output a string.
146  */
147 putstr(s)
148 	register char *s;
149 {
150 	while (*s != '\0')
151 		putchr(*s++);
152 }
153 
154 int cmdstack;
155 static char return_to_continue[] = "(press RETURN)";
156 
157 /*
158  * Output a message in the lower left corner of the screen
159  * and wait for carriage return.
160  */
161 error(s)
162 	char *s;
163 {
164 	int ch;
165 
166 	++errmsgs;
167 	if (!any_display) {
168 		/*
169 		 * Nothing has been displayed yet.  Output this message on
170 		 * error output (file descriptor 2) and don't wait for a
171 		 * keystroke to continue.
172 		 *
173 		 * This has the desirable effect of producing all error
174 		 * messages on error output if standard output is directed
175 		 * to a file.  It also does the same if we never produce
176 		 * any real output; for example, if the input file(s) cannot
177 		 * be opened.  If we do eventually produce output, code in
178 		 * edit() makes sure these messages can be seen before they
179 		 * are overwritten or scrolled away.
180 		 */
181 		if (s != NULL) {
182 			(void)write(2, s, strlen(s));
183 			(void)write(2, "\n", 1);
184 		}
185 		return;
186 	}
187 
188 	lower_left();
189 	clear_eol();
190 	so_enter();
191 	if (s != NULL) {
192 		putstr(s);
193 		putstr("  ");
194 	}
195 	putstr(return_to_continue);
196 	so_exit();
197 
198 	if ((ch = getchr()) != '\n') {
199 		if (ch == 'q')
200 			quit();
201 		cmdstack = ch;
202 	}
203 	lower_left();
204 
205 	if ((s != NULL ? strlen(s) : 0) + sizeof(return_to_continue) +
206 		so_width + se_width + 1 > sc_width)
207 		/*
208 		 * Printing the message has probably scrolled the screen.
209 		 * {{ Unless the terminal doesn't have auto margins,
210 		 *    in which case we just hammered on the right margin. }}
211 		 */
212 		repaint();
213 	flush();
214 }
215 
216 static char intr_to_abort[] = "... (interrupt to abort)";
217 
218 ierror(s)
219 	char *s;
220 {
221 	lower_left();
222 	clear_eol();
223 	so_enter();
224 	putstr(s);
225 	putstr(intr_to_abort);
226 	so_exit();
227 	flush();
228 }
229