Commit | Line | Data |
---|---|---|
bfe13c81 KB |
1 | /* |
2 | * Copyright (c) 1988 Mark Nudleman | |
3 | * Copyright (c) 1988 Regents of the University of California. | |
4 | * All rights reserved. | |
5 | * | |
bfe13c81 KB |
6 | * Redistribution and use in source and binary forms are permitted |
7 | * provided that the above copyright notice and this paragraph are | |
8 | * duplicated in all such forms and that any documentation, | |
9 | * advertising materials, and other materials related to such | |
10 | * distribution and use acknowledge that the software was developed | |
a942b40b KB |
11 | * by Mark Nudleman and the University of California, Berkeley. The |
12 | * name of Mark Nudleman or the | |
bfe13c81 KB |
13 | * University may not be used to endorse or promote products derived |
14 | * from this software without specific prior written permission. | |
15 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR | |
16 | * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED | |
17 | * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. | |
18 | */ | |
19 | ||
20 | #ifndef lint | |
a942b40b | 21 | static char sccsid[] = "@(#)output.c 5.4 (Berkeley) %G%"; |
bfe13c81 KB |
22 | #endif /* not lint */ |
23 | ||
24 | /* | |
25 | * High level routines dealing with the output to the screen. | |
26 | */ | |
27 | ||
28 | #include "less.h" | |
29 | ||
30 | public int errmsgs; /* Count of messages displayed by error() */ | |
31 | ||
32 | extern int sigs; | |
33 | extern int sc_width, sc_height; | |
34 | extern int ul_width, ue_width; | |
35 | extern int so_width, se_width; | |
36 | extern int bo_width, be_width; | |
37 | extern int tabstop; | |
38 | extern int twiddle; | |
39 | extern int screen_trashed; | |
40 | extern int any_display; | |
41 | extern char *line; | |
42 | extern char *first_cmd; | |
43 | ||
44 | /* | |
45 | * Display the line which is in the line buffer. | |
46 | */ | |
47 | public void | |
48 | put_line() | |
49 | { | |
50 | register char *p; | |
51 | register int c; | |
52 | register int column; | |
53 | extern int auto_wrap, ignaw; | |
54 | ||
55 | if (sigs) | |
56 | { | |
57 | /* | |
58 | * Don't output if a signal is pending. | |
59 | */ | |
60 | screen_trashed = 1; | |
61 | return; | |
62 | } | |
63 | ||
64 | if (line == NULL) | |
65 | line = (twiddle) ? "~" : ""; | |
66 | ||
67 | column = 0; | |
68 | for (p = line; *p != '\0'; p++) | |
69 | { | |
70 | switch (c = *p) | |
71 | { | |
72 | case UL_CHAR: | |
73 | ul_enter(); | |
74 | column += ul_width; | |
75 | break; | |
76 | case UE_CHAR: | |
77 | ul_exit(); | |
78 | column += ue_width; | |
79 | break; | |
80 | case BO_CHAR: | |
81 | bo_enter(); | |
82 | column += bo_width; | |
83 | break; | |
84 | case BE_CHAR: | |
85 | bo_exit(); | |
86 | column += be_width; | |
87 | break; | |
88 | case '\t': | |
89 | do | |
90 | { | |
91 | putchr(' '); | |
92 | column++; | |
93 | } while ((column % tabstop) != 0); | |
94 | break; | |
95 | case '\b': | |
96 | putbs(); | |
97 | column--; | |
98 | break; | |
99 | default: | |
100 | if (c & 0200) | |
101 | { | |
102 | /* | |
103 | * Control characters arrive here as the | |
104 | * normal character [carat_char(c)] with | |
105 | * the 0200 bit set. See pappend(). | |
106 | */ | |
107 | putchr('^'); | |
108 | putchr(c & 0177); | |
109 | column += 2; | |
110 | } else | |
111 | { | |
112 | putchr(c); | |
113 | column++; | |
114 | } | |
115 | } | |
116 | } | |
117 | if (column < sc_width || !auto_wrap || ignaw) | |
118 | putchr('\n'); | |
119 | } | |
120 | ||
121 | /* | |
122 | * Is a given character a "control" character? | |
123 | * {{ ASCII DEPENDENT }} | |
124 | */ | |
125 | public int | |
126 | control_char(c) | |
127 | int c; | |
128 | { | |
129 | return (c < ' ' || c == '\177'); | |
130 | } | |
131 | ||
132 | /* | |
133 | * Return the printable character used to identify a control character | |
134 | * (printed after a carat; e.g. '\3' => "^C"). | |
135 | * {{ ASCII DEPENDENT }} | |
136 | */ | |
137 | public int | |
138 | carat_char(c) | |
139 | int c; | |
140 | { | |
141 | return ((c == '\177') ? '?' : (c | 0100)); | |
142 | } | |
143 | ||
144 | ||
145 | static char obuf[1024]; | |
146 | static char *ob = obuf; | |
147 | ||
148 | /* | |
149 | * Flush buffered output. | |
150 | */ | |
151 | public void | |
152 | flush() | |
153 | { | |
154 | register int n; | |
155 | ||
156 | n = ob - obuf; | |
157 | if (n == 0) | |
158 | return; | |
159 | if (write(1, obuf, n) != n) | |
160 | screen_trashed = 1; | |
161 | ob = obuf; | |
162 | } | |
163 | ||
bfe13c81 KB |
164 | /* |
165 | * Output a character. | |
166 | */ | |
167 | public void | |
168 | putchr(c) | |
169 | int c; | |
170 | { | |
171 | if (ob >= &obuf[sizeof(obuf)]) | |
172 | flush(); | |
173 | *ob++ = c; | |
174 | } | |
175 | ||
176 | /* | |
177 | * Output a string. | |
178 | */ | |
179 | public void | |
180 | putstr(s) | |
181 | register char *s; | |
182 | { | |
183 | while (*s != '\0') | |
184 | putchr(*s++); | |
185 | } | |
186 | ||
187 | /* | |
188 | * Output a message in the lower left corner of the screen | |
189 | * and wait for carriage return. | |
190 | */ | |
191 | ||
192 | static char return_to_continue[] = " (press RETURN)"; | |
193 | ||
194 | public void | |
195 | error(s) | |
196 | char *s; | |
197 | { | |
198 | register int c; | |
199 | static char buf[2]; | |
200 | ||
201 | errmsgs++; | |
202 | if (!any_display) | |
203 | { | |
204 | /* | |
205 | * Nothing has been displayed yet. | |
206 | * Output this message on error output (file | |
207 | * descriptor 2) and don't wait for a keystroke | |
208 | * to continue. | |
209 | * | |
210 | * This has the desirable effect of producing all | |
211 | * error messages on error output if standard output | |
212 | * is directed to a file. It also does the same if | |
213 | * we never produce any real output; for example, if | |
214 | * the input file(s) cannot be opened. If we do | |
215 | * eventually produce output, code in edit() makes | |
216 | * sure these messages can be seen before they are | |
217 | * overwritten or scrolled away. | |
218 | */ | |
219 | write(2, s, strlen(s)); | |
220 | write(2, "\n", 1); | |
221 | return; | |
222 | } | |
223 | ||
224 | lower_left(); | |
225 | clear_eol(); | |
226 | so_enter(); | |
227 | putstr(s); | |
228 | putstr(return_to_continue); | |
229 | so_exit(); | |
230 | ||
bfe13c81 KB |
231 | c = getchr(); |
232 | if (c != '\n' && c != '\r' && c != ' ' && c != READ_INTR) | |
233 | { | |
234 | buf[0] = c; | |
235 | first_cmd = buf; | |
236 | } | |
bfe13c81 KB |
237 | lower_left(); |
238 | ||
239 | if (strlen(s) + sizeof(return_to_continue) + | |
240 | so_width + se_width + 1 > sc_width) | |
241 | /* | |
242 | * Printing the message has probably scrolled the screen. | |
243 | * {{ Unless the terminal doesn't have auto margins, | |
244 | * in which case we just hammered on the right margin. }} | |
245 | */ | |
246 | repaint(); | |
247 | ||
248 | flush(); | |
249 | } | |
250 | ||
251 | static char intr_to_abort[] = "... (interrupt to abort)"; | |
252 | ||
253 | public void | |
254 | ierror(s) | |
255 | char *s; | |
256 | { | |
257 | ||
258 | lower_left(); | |
259 | clear_eol(); | |
260 | so_enter(); | |
261 | putstr(s); | |
262 | putstr(intr_to_abort); | |
263 | so_exit(); | |
264 | flush(); | |
265 | } |