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. */
put_line()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 */
flush()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 */
purge()127 purge()
128 {
129
130 ob = obuf;
131 }
132
133 /*
134 * Output a character.
135 */
putchr(c)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 */
putstr(s)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 */
error(s)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
ierror(s)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