/********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1986 Wayne A. Christopher, U. C. Berkeley CAD Group $Id$ **********/ /* * Routines to handle "more"d output. There are some serious system * dependencies in here, and it isn't clear that versions of this stuff * can be written for every possible machine... */ #include "ngspice.h" #include "config.h" #include #ifdef HAVE_ASPRINTF #ifdef HAVE_LIBIBERTY_H /* asprintf */ #include #elif defined(__MINGW32__) || defined(__SUNPRO_C) /* we have asprintf, but not libiberty.h */ #include extern int asprintf(char **out, const char *fmt, ...); extern int vasprintf(char **out, const char *fmt, va_list ap); #endif #endif #ifdef HAVE_SGTTY_H #include #endif #ifdef HAVE_SYS_IOCTL_H #include #endif #if 0 /* Bad interaction with bool type in bool.h because curses also defines this symbol. */ #ifdef HAVE_TERMCAP #include #include #endif #endif #ifdef HAVE_TERMCAP_H #include #elif HAVE_NCURSES_TERMCAP_H #include #endif #include #include "variable.h" #include "terminal.h" /* out_printf doesn't handle double arguments correctly, so we sprintf into this buf and call out_send w/ it */ char out_pbuf[8*BSIZE_SP]; bool out_moremode = TRUE; bool out_isatty = TRUE; #ifndef TCL_MODULE #ifdef HAVE_TERMCAP static char *motion_chars; static char *clear_chars; static char *home_chars; static char *cleol_chars; #endif /* HAVE_TERMCAP */ #define DEF_SCRHEIGHT 24 #define DEF_SCRWIDTH 80 static int xsize, ysize; static int xpos, ypos; static bool noprint, nopause; /* Start output... */ void out_init(void) { #ifdef TIOCGWINSZ struct winsize ws; #endif noprint = nopause = FALSE; if (cp_getvar("nomoremode", CP_BOOL, NULL)) out_moremode = FALSE; else out_moremode = TRUE; if (!out_moremode || !cp_interactive) out_isatty = FALSE; if (!out_isatty) return; xsize = ysize = 0; /* Figure out the screen size. We try, in order, TIOCGSIZE, * tgetent(), and cp_getvar(height). Default is 24 x 80. */ #ifdef TIOCGWINSZ if (!xsize || !ysize) { (void) ioctl(fileno(stdout), TIOCGWINSZ, (char *) &ws); xsize = ws.ws_col; ysize = ws.ws_row; } #endif if (!xsize) (void) cp_getvar("width", CP_NUM, (char *) &xsize); if (!ysize) (void) cp_getvar("height", CP_NUM, (char *) &ysize); if (!xsize) xsize = DEF_SCRWIDTH; if (!ysize) ysize = DEF_SCRHEIGHT; ysize -= 2; /* Fudge room... */ xpos = ypos = 0; return; } /* Putc may not be buffered (sp?), so we do it ourselves. */ static char staticbuf[BUFSIZ]; struct { int count; char *ptr; } ourbuf = { BUFSIZ, staticbuf }; /* send buffer out */ void outbufputc(void) { if (ourbuf.count != BUFSIZ) { fputs(staticbuf, cp_out); memset(staticbuf, 0, BUFSIZ-ourbuf.count); ourbuf.count = BUFSIZ; ourbuf.ptr = staticbuf; } } static void bufputc(char c) { if (--ourbuf.count >= 0) { *ourbuf.ptr++ = c; } else { /* Flush and reset the buffer */ outbufputc(); /* and store the character. */ ourbuf.count--; *ourbuf.ptr++ = c; } } /* prompt for a return */ void promptreturn(void) { char buf[16]; moe: fprintf(cp_out, "\n\t-- hit return for more, ? for help -- "); if (!fgets(buf, 16, cp_in)) { clearerr(cp_in); *buf = 'q'; } switch (*buf) { case '\n': break; case 'q': noprint = TRUE; break; case 'c': nopause = TRUE; break; case ' ': break; case '?': fprintf(cp_out, "\nPossible responses:\n\ \t : Print another screenful\n\ \tq : Discard the rest of the output\n\ \tc : Continuously print the rest of the output\n\ \t? : Print this help message\n"); goto moe; default: fprintf(cp_out, "Character %d is no good\n", *buf); goto moe; } } /* Print a string to the output. If this would cause the screen to scroll, * print "more". */ void out_send(char *string) { if (noprint) return; if (!out_isatty || nopause) { fputs(string, cp_out); return; } while (*string) { switch (*string) { case '\n': xpos = 0; ypos++; break; case '\f': ypos = ysize; xpos = 0; break; case '\t': xpos = xpos / 8 + 1; xpos *= 8; break; default: xpos++; break; } while (xpos >= xsize) { xpos -= xsize; ypos++; } if (ypos >= ysize) { outbufputc(); /* out goes buffer */ promptreturn(); (void) fflush(cp_out); ypos = xpos = 0; } bufputc(*string); /* we need to buffer these */ string++; } (void) outbufputc(); return; } /* Printf some stuff using more mode. */ void out_printf(char *fmt, ...) { #if defined(HAVE_ASPRINTF) /* seems the best solution */ char * tbuf; va_list ap; va_start (ap, fmt); vasprintf(&tbuf, fmt, ap); va_end (ap); out_send(tbuf); FREE(tbuf); #elif defined(HAVE_SNPRINTF) /* the second best */ va_list ap; va_start (ap, fmt); vsnprintf(out_pbuf, sizeof(out_pbuf), fmt, ap); va_end (ap); out_send(out_pbuf); #else /* guaranteed a bug for long messages */ va_list ap; va_start (ap, fmt); vsprintf(out_pbuf, fmt, ap); va_end (ap); out_send(out_pbuf); #endif return; } #ifdef HAVE_TERMCAP static int outfn(int c) { putc(c, stdout); return c; } #endif /* HAVE_TERMCAP */ void tcap_init(void) { char *s; #ifdef HAVE_TERMCAP char tbuf[1025]; static char buf2[100]; char *charbuf; charbuf = buf2; if ((s = getenv("TERM"))) { if (tgetent(tbuf, s) != -1) { xsize = tgetnum("co"); ysize = tgetnum("li"); if ((xsize <= 0) || (ysize <= 0)) xsize = ysize = 0; clear_chars = (char *) tgetstr("cl", &charbuf); motion_chars = (char *) tgetstr("cm", &charbuf); home_chars = (char *) tgetstr("ho", &charbuf); cleol_chars = (char *) tgetstr("ce", &charbuf); } } #endif if (!xsize) { if ((s = getenv("COLS"))) xsize = atoi(s); if (xsize <= 0) xsize = 0; } if (!ysize) { if ((s = getenv("LINES"))) ysize = atoi(s); if (ysize <= 0) ysize = 0; } } void term_clear(void) { #ifdef HAVE_TERMCAP if (*clear_chars) tputs(clear_chars, 1, outfn); else fputs("\n", stdout); #endif } void term_home(void) { #ifdef HAVE_TERMCAP if (*home_chars) tputs(home_chars, 1, outfn); else if (*motion_chars) tputs(tgoto(motion_chars, 1, 1), 1, outfn); else fputs("\n", stdout); #endif } void term_cleol(void) { #ifdef HAVE_TERMCAP if (*cleol_chars) tputs(cleol_chars, 1, outfn); #endif } #else void out_init(void) {} void outbufputc(void) {} void promptreturn(void) {} void term_clear(void) {} void term_home(void) {} void term_cleol(void) {} void tcap_init(void) {} void out_send(char *string) {fprintf(cp_out,string);} void out_printf(char *fmt, ...) { va_list ap; va_start (ap, fmt); vfprintf(cp_out, fmt, ap); va_end (ap); } #endif /* TCL_MODULE */