1 /**********
2 Copyright 1990 Regents of the University of California. All rights reserved.
3 Author: 1986 Wayne A. Christopher, U. C. Berkeley CAD Group
4 **********/
5
6 /*
7 * Routines to handle "more"d output. There are some serious system
8 * dependencies in here, and it isn't clear that versions of this stuff
9 * can be written for every possible machine...
10 */
11 #include "ngspice/ngspice.h"
12
13 #include <stdarg.h>
14
15
16 #ifdef HAVE_SGTTY_H
17 #include <sgtty.h>
18 #endif
19
20 #ifdef HAVE_SYS_IOCTL_H
21 #include <sys/ioctl.h>
22 #endif
23
24
25 #ifdef HAVE_TERMCAP
26 #include <curses.h>
27 #include <term.h>
28 #endif
29
30
31 #ifdef HAVE_TERMCAP_H
32 #include <termcap.h>
33 #elif HAVE_NCURSES_TERMCAP_H
34 #include <ncurses/termcap.h>
35 #endif
36
37 #include "ngspice/cpdefs.h"
38
39 #include "variable.h"
40 #include "terminal.h"
41
42
43 bool out_moremode = FALSE;
44 bool out_isatty = TRUE;
45
46 #ifndef TCL_MODULE
47
48 #ifdef HAVE_TERMCAP
49 static char *motion_chars;
50 static char *clear_chars;
51 static char *home_chars;
52 static char *cleol_chars;
53 #endif
54
55 #define DEF_SCRHEIGHT 24
56 #define DEF_SCRWIDTH 80
57
58 static int xsize, ysize;
59 static int xpos, ypos;
60 static bool noprint, nopause;
61
62
63 /* Start output... */
64
65 void
out_init(void)66 out_init(void)
67 {
68 #ifdef TIOCGWINSZ
69 struct winsize ws;
70 #endif
71
72 noprint = nopause = FALSE;
73
74 if (cp_getvar("moremode", CP_BOOL, NULL, 0))
75 out_moremode = TRUE;
76 else
77 out_moremode = FALSE;
78
79 if (!out_moremode || !cp_interactive)
80 out_isatty = FALSE;
81
82 if (!out_isatty)
83 return;
84
85 xsize = ysize = 0;
86
87 /* Figure out the screen size. We try, in order, TIOCGSIZE,
88 * tgetent(), and cp_getvar(height). Default is 24 x 80.
89 */
90
91 #ifdef TIOCGWINSZ
92 if (!xsize || !ysize) {
93 (void) ioctl(fileno(stdout), TIOCGWINSZ, (char *) &ws);
94 xsize = ws.ws_col;
95 ysize = ws.ws_row;
96 }
97 #endif
98
99 if (!xsize)
100 (void) cp_getvar("width", CP_NUM, &xsize, 0);
101 if (!ysize)
102 (void) cp_getvar("height", CP_NUM, &ysize, 0);
103
104 if (!xsize)
105 xsize = DEF_SCRWIDTH;
106 if (!ysize)
107 ysize = DEF_SCRHEIGHT;
108 ysize -= 2; /* Fudge room... */
109
110 xpos = ypos = 0;
111 }
112
113
114 /* Putc may not be buffered (sp?), so we do it ourselves. */
115
116 static char staticbuf[BUFSIZ];
117
118 struct {
119 int count;
120 char *ptr;
121 } ourbuf = { BUFSIZ, staticbuf };
122
123
124 /* send buffer out */
125 void
outbufputc(void)126 outbufputc(void)
127 {
128 if (ourbuf.count != BUFSIZ) {
129 fputs(staticbuf, cp_out);
130 memset(staticbuf, 0, (size_t) (BUFSIZ - ourbuf.count));
131 ourbuf.count = BUFSIZ;
132 ourbuf.ptr = staticbuf;
133 }
134
135 }
136
137
138 static void
bufputc(char c)139 bufputc(char c)
140 {
141 if (--ourbuf.count >= 0) {
142 *ourbuf.ptr++ = c;
143 } else {
144 /* Flush and reset the buffer */
145 outbufputc();
146 /* and store the character. */
147 ourbuf.count--;
148 *ourbuf.ptr++ = c;
149 }
150 }
151
152
153 /* prompt for a return */
154 void
promptreturn(void)155 promptreturn(void)
156 {
157 char buf[16];
158
159 moe:
160 fprintf(cp_out, "\n\t-- hit return for more, ? for help -- ");
161
162 if (!fgets(buf, 16, cp_in)) {
163 clearerr(cp_in);
164 *buf = 'q';
165 }
166
167 switch (*buf) {
168 case '\n':
169 break;
170 case 'q':
171 noprint = TRUE;
172 break;
173 case 'c':
174 nopause = TRUE;
175 break;
176 case ' ':
177 break;
178 case '?':
179 fprintf(cp_out,
180 "\nPossible responses:\n\
181 \t<cr> : Print another screenful\n\
182 \tq <cr> : Discard the rest of the output\n\
183 \tc <cr> : Continuously print the rest of the output\n\
184 \t? <cr> : Print this help message\n");
185 goto moe;
186 default:
187 fprintf(cp_out, "Character %d is no good\n", *buf);
188 goto moe;
189 }
190 }
191
192
193 /* Print a string to the output. If this would cause the screen to scroll,
194 * print "more".
195 */
196
197 void
out_send(char * string)198 out_send(char *string)
199 {
200 if (noprint)
201 return;
202
203 if (!out_isatty || nopause) {
204 fputs(string, cp_out);
205 return;
206 }
207
208 while (*string) {
209 switch (*string) {
210 case '\n':
211 xpos = 0;
212 ypos++;
213 break;
214 case '\f':
215 ypos = ysize;
216 xpos = 0;
217 break;
218 case '\t':
219 xpos = xpos / 8 + 1;
220 xpos *= 8;
221 break;
222 default:
223 xpos++;
224 break;
225 }
226
227 while (xpos >= xsize) {
228 xpos -= xsize;
229 ypos++;
230 }
231
232 if (ypos >= ysize) {
233 outbufputc(); /* out goes buffer */
234 promptreturn();
235 (void) fflush(cp_out);
236 ypos = xpos = 0;
237 }
238
239 bufputc(*string); /* we need to buffer these */
240 string++;
241 }
242
243 (void) outbufputc();
244 }
245
246
247 /* Printf some stuff using more mode. */
248
249 void
out_vprintf(const char * fmt,va_list ap)250 out_vprintf(const char *fmt, va_list ap)
251 {
252 char *tbuf = tvprintf(fmt, ap);
253 out_send(tbuf);
254 FREE(tbuf);
255 }
256
257
258 void
out_printf(char * fmt,...)259 out_printf(char *fmt, ...)
260 {
261 va_list ap;
262 va_start(ap, fmt);
263 out_vprintf(fmt, ap);
264 va_end(ap);
265 }
266
267
268 #ifdef HAVE_TERMCAP
269 static int
outfn(int c)270 outfn(int c)
271 {
272 putc(c, stdout);
273 return c;
274 }
275 #endif
276
277
278 void
tcap_init(void)279 tcap_init(void)
280 {
281 char *s;
282 #ifdef HAVE_TERMCAP
283 char tbuf[1025];
284 static char buf2[100];
285 char *charbuf;
286
287 charbuf = buf2;
288
289 if ((s = getenv("TERM")) != NULL)
290 if (tgetent(tbuf, s) != -1) {
291 xsize = tgetnum("co");
292 ysize = tgetnum("li");
293 if ((xsize <= 0) || (ysize <= 0))
294 xsize = ysize = 0;
295 clear_chars = tgetstr("cl", &charbuf);
296 motion_chars = tgetstr("cm", &charbuf);
297 home_chars = tgetstr("ho", &charbuf);
298 cleol_chars = tgetstr("ce", &charbuf);
299 }
300 #endif
301
302 if (!xsize) {
303 if ((s = getenv("COLS")) != NULL)
304 xsize = atoi(s);
305 if (xsize <= 0)
306 xsize = DEF_SCRWIDTH;
307 }
308
309 if (!ysize) {
310 if ((s = getenv("LINES")) != NULL)
311 ysize = atoi(s);
312 if (ysize <= 0)
313 ysize = DEF_SCRHEIGHT;
314 }
315 }
316
317
318 void
term_clear(void)319 term_clear(void)
320 {
321 #ifdef HAVE_TERMCAP
322 if (*clear_chars)
323 tputs(clear_chars, 1, outfn);
324 else
325 fputs("\n", stdout);
326 #endif
327 }
328
329
330 void
term_home(void)331 term_home(void)
332 {
333 #ifdef HAVE_TERMCAP
334 if (*home_chars)
335 tputs(home_chars, 1, outfn);
336 else if (*motion_chars)
337 tputs(tgoto(motion_chars, 1, 1), 1, outfn);
338 else
339 fputs("\n", stdout);
340 #endif
341 }
342
343
344 void
term_cleol(void)345 term_cleol(void)
346 {
347 #ifdef HAVE_TERMCAP
348 if (*cleol_chars)
349 tputs(cleol_chars, 1, outfn);
350 #endif
351 }
352
353 #else
354
out_init(void)355 void out_init(void) {}
outbufputc(void)356 void outbufputc(void) {}
promptreturn(void)357 void promptreturn(void) {}
term_clear(void)358 void term_clear(void) {}
term_home(void)359 void term_home(void) {}
term_cleol(void)360 void term_cleol(void) {}
tcap_init(void)361 void tcap_init(void) {}
362
363
364 void
out_send(char * string)365 out_send(char *string)
366 {
367 fprintf(cp_out, "%s", string);
368 }
369
370
371 void
out_vprintf(const char * fmt,va_list ap)372 out_vprintf(const char *fmt, va_list ap)
373 {
374 vfprintf(cp_out, fmt, ap);
375 }
376
377
378 void
out_printf(char * fmt,...)379 out_printf(char *fmt, ...)
380 {
381 va_list ap;
382 va_start(ap, fmt);
383 out_vprintf(fmt, ap);
384 va_end(ap);
385 }
386
387 #endif /* TCL_MODULE */
388