Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!mnetor!seismo!umcp-cs!chris From: chris@umcp-cs.UUCP (Chris Torek) Newsgroups: net.unix-wizards Subject: Re: -ltermcap Message-ID: <2724@umcp-cs.UUCP> Date: Mon, 4-Aug-86 00:33:59 EDT Article-I.D.: umcp-cs.2724 Posted: Mon Aug 4 00:33:59 1986 Date-Received: Mon, 4-Aug-86 07:12:17 EDT References: <2773@mit-eddie.MIT.EDU> <2565@rsch.wisc.edu> Reply-To: chris@maryland.UUCP (Chris Torek) Organization: University of Maryland, Dept. of Computer Sci. Lines: 180 >In article <2773@mit-eddie.MIT.EDU> shawn@mit-eddie.MIT.EDU >(Shawn F. Mckay) writes: >>One would think I could say something like: >> >>char buff[20]; >> tgetstr ("cl", buff); In article <2565@rsch.wisc.edu> dave@rsch.wisc.edu (Dave Cohrs) replies: >Read the termcap(3) man page more carefully. ... So you want to do: > > char buff[20]; > char *bufptr = buff; > (void) tgetstr("cl", &bufptr); Closer; but it is worse than that. Termcap's design is quite messy and error-prone. I once outlined a better design, but have never bothered to implement it. Termcap first requires that you copy the terminal capability string into a buffer. It then interprets the copied string into another buffer. Both buffers are `owned' by you but `taken over' by termcap; the first must last through all tget* calls, and the second as long as you wish to use the decoded strings. The following is pretty much the minimum code required to obtain just the clear screen entry: #ifdef this_works_but_is_not_a_good_idea_anyway char *getenv(); char * get_clear_screen() { char tbuf[1024]; /* used only during interpretation */ static char expbuf[1024]; /* stores interpreted strings */ char *ep; /* pointer into expbuf */ char *term; if ((term = getenv("TERM")) == NULL) return (NULL); /* terminal type unavailable */ /* -1 => no termcap file; 0 => termcap file but $TERM not found */ if (tgetent(tbuf, term) != 1) return (NULL); /* failed for some reason */ ep = expbuf; return (tgetstr("cl", &ep)); } #endif #include #include #include /* * Before you can use `cl', you must also set `ospeed' and `PC': */ extern short ospeed; extern char PC; /* * ospeed should be set to the output speed of the terminal, as * returned by gtty() / ioctl(TIOCGETP). PC should be set to * the terminal's pad character (result from tgetstr("pc")), * or the default, NUL ('\0'). Note that tgetstr("pc") either * returns NULL (in which case PC should be '\0') or a pointer * which must be dereferenced to get the pad character. * * For this reason, the `get_clear_screen' routine defined above * is pretty much useless anyway. Instead, you need something * more like this: */ static char tbuf[1024]; /* for intermediate results */ static char expbuf[1024]; /* for expanded (decoded) strings */ static char *expp; /* pointer into expbuf */ static int started_tc; /* true => got termcap started */ static int no_tc; /* true => termcap unavailable */ char *getenv(); #define start_tc() if (started_tc) /*void*/; else fire_up_termcap() /* * Set things up so that tgetent() et al. are OK */ static void fire_up_termcap() { char *term; struct sgttyb sg; started_tc++; /* well, soon */ if ((term = getenv("TERM")) == NULL || tgetent(tbuf, term) != 1) { no_tc++; /* no termcap available */ return; } expp = expbuf; /* init expansion pointer *? if (ioctl(0, TIOCGETP, &sg)) ospeed = B1200; /* just a guess */ else ospeed = sg.sg_ospeed; } /* * Wrapper for tgetstr(). */ char * get_termcap_string(name) char *name; { start_tc(); return (no_tc ? NULL : tgetstr(name, &expp)); } /* * Get the clear screen entry, and set up the pad character so that * we can use it. */ char * get_clear_screen() { char *p; if ((p = get_termcap_string("pc")) != NULL) PC = *p; return (get_termcap_string("cl")); } /* * This can now be printed via * * int outc(c) int c; { return (putchar(c)); } * ... * p = get_clear_screen(); * tputs(p, 1, outc); * */ /* * For good measure, some interface routines for other termcap things, * and an `outc' routine: */ int outc(c) int c; { return (putchar(c)); } /* * Wrapper for tgetnum(). */ int get_termcap_number(name) char *name; { start_tc(); return (no_tc ? -1 : tgetnum(name)); } /* * Wrapper for tgetflag(). */ int get_termcap_flag(name) char *name; { start_tc(); return (no_tc ? 0 : tgetflag(name)); } -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 1516) UUCP: seismo!umcp-cs!chris CSNet: chris@umcp-cs ARPA: chris@mimsy.umd.edu