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