home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / compsrcs / misc / volume02 / termcap < prev    next >
Encoding:
Internet Message Format  |  1991-08-27  |  28.3 KB

  1. From mipos3!omepd!littlei!uunet!lll-winken!lll-tis!ames!ncar!husc6!necntc!ncoast!allbery Tue Mar 22 19:36:30 PST 1988
  2. Article 330 of comp.sources.misc:
  3. Path: td2cad!mipos3!omepd!littlei!uunet!lll-winken!lll-tis!ames!ncar!husc6!necntc!ncoast!allbery
  4. From: azadian@hslrswi.UUCP (Norman H. Azadian)
  5. Newsgroups: comp.sources.misc
  6. Subject: v02i077: termcap implementation: works under MS-DOS, 4.xBSD
  7. Message-ID: <8803161213.AA05807@hslrhit.hasler>
  8. Date: 16 Mar 88 12:13:56 GMT
  9. Sender: allbery@ncoast.UUCP
  10. Reply-To: azadian@hslrswi.UUCP (Norman H. Azadian)
  11. Lines: 921
  12. Approved: allbery@ncoast.UUCP
  13. comp.sources.misc: Volume 2, Issue 77
  14. Submitted-By: "Norman H. Azadian" <azadian@hslrswi.UUCP>
  15. Archive-Name: termcap
  16.  
  17. comp.sources.misc: Volume 2, Issue 77
  18. Submitted-By: "Norman H. Azadian" <azadian@hslrswi.UUCP>
  19. Archive-Name: termcap
  20.  
  21. [Also looks like it works under System V, although why you'd want to I don't
  22. know....  Needs either Henry Spenser's strings package or a set of System III
  23. or System V libraries.  ++bsa]
  24.  
  25. This is an implementation of termcap(3X) for PC's using MS-DOS.  Not having
  26. access to the unix sources, I hauled off and wrote my own.  While I was at
  27. it I developed complete /etc/termcap profiles for the PC.  The color monitor
  28. profile is completely untested, and the monochrome one is only partially
  29. tested.  I am using this termcap package with less, which I have ported
  30. to the PC and hacked up.  Since I hope someday to distribute my "improved"
  31. less, this termcap package is a necessary pre-requisite.
  32.  
  33.  
  34. #--------------------------------CUT HERE-------------------------------------
  35. #! /bin/sh
  36. #
  37. # This is a shell archive.  Save this into a file, edit it
  38. # and delete all lines above this comment.  Then give this
  39. # file to sh by executing the command "sh file".  The files
  40. # will be extracted into the current directory owned by
  41. # you with default permissions.
  42. #
  43. # The files contained herein are:
  44. #
  45. # -rw-r--r--  1 azadian      1079 Mar 16 12:59 README
  46. # -rw-r--r--  1 azadian      3370 Mar 16 11:52 termcap.pc
  47. # -rw-r--r--  1 azadian     20209 Mar 16 12:13 termcap.c
  48. #
  49. echo 'x - README'
  50. if test -f README; then echo 'shar: not overwriting README'; else
  51. sed 's/^X//' << '________This_Is_The_END________' > README
  52. XI wrote termcap(3X) for use on my PC clone under MS-DOS.  Additionally, I
  53. Xhave developed complete termcap profiles for the PC, starting with the
  54. Xtermcap provided by Darren Friedlein.
  55. X
  56. XTermcap.c was written with the Aztec C compiler (4.1), but it also works
  57. Xwith the 4.3bsd C compiler.  A simple test program is provided at the end
  58. Xof termcap.c.  Pay no attention to the printd() calls, they're part of my
  59. Xdebugging package, and they are effectively neutered by defining DEBUG as 0.
  60. X
  61. XI made good use of some of the functions from Henry Spencer's excellent
  62. Xstandard string library.  If you don't have it, get it!
  63. X
  64. XIn the not-too-distant future I hope to be unleashing my hacked version
  65. Xof Mark Nudelman's less program.  It requires a termcap(3X) such as this.
  66. X
  67. XI welcome your problems, suggestions, and bug fixes.
  68. X
  69. XNorman Azadian, 80A;  Hasler AG;  Belpstrasse 23;  3000 Berne 14;  Switzerland
  70. XX.400:    azadian@hslrswi.hasler                   Telephone:   +41 31 63 2178
  71. XUucp:     ... {uunet,ukc,mcvax, ... }!cernvax!hslrswi!azadian
  72. XBitnet:   azadian%hslrswi.UUCP@cernvax.BITNET
  73. ________This_Is_The_END________
  74. if test `wc -c < README` -ne 1079; then
  75.     echo 'shar: README was damaged during transit (should have been 1079 bytes)'
  76. fi
  77. fi        ; : end of overwriting check
  78. echo 'x - termcap.pc'
  79. if test -f termcap.pc; then echo 'shar: not overwriting termcap.pc'; else
  80. sed 's/^X//' << '________This_Is_The_END________' > termcap.pc
  81. X#
  82. X#    /etc/termcap for IBM PC's and friends.
  83. X#    Gratiously supplied by Darren Friedlein.
  84. X#    Completed by Norman H. Azadian.
  85. X#
  86. X
  87. X#
  88. X# Monochrome IBMPC.
  89. X#    This is a termcap for the NANSI.SYS device driver.
  90. X#    It is the same as the ANSI termcap, except NANSI supports additionally
  91. X#    line & char insert & delete (AL,al, DL,dl, DC,dc, IC,ic).
  92. X#
  93. Xnansi-mono|mono:\
  94. X    :AL=\E[%dL:al=\E[1L:\
  95. X    :DC=\E[%dP:dc=\E[1P:DL=\E[%dM:dl=\E[1M:\
  96. X    :IC=\E[%d@:ic=\E[1@:\
  97. X    :tc=ansi-mono:
  98. X
  99. X
  100. X#
  101. X# monochrome ANSI
  102. X#
  103. Xansi-mono:\
  104. X    :am:\
  105. X    :bc=\E[1D:bl=^G:bs:\
  106. X    :cd=\E[2J:ce=\E[K:cl=\E[2J\E[H:cm=\E[%i%2;%i%2H:co#80:\
  107. X    :ho=\E[H:\
  108. X    :K1=\200G:K2=\200I:K4=\200O:K5=\200Q:\
  109. X    :k0=\200;:k1=\200<:k2=\200=:k3=\200>:k4=\200?:k5=\200@:\
  110. X    :k6=\200A:k7=\200B:k8=\200C:k9=\200D:\
  111. X    :kb=^H:kC=\200w:kD=\200S:kd=\200H:kE=\200u:kH=\200O:kh=\200G:\
  112. X    :kI=\200R:kl=\200K:kN=\200Q:kP=\200I:kr=\200M:kS=\200v:ku=\200P:\
  113. X    :LE=\E[%dD:le=\E[1D:li#25:\
  114. X    :mb=\E[5m:md=\E[1m:me=\E[0m:mk=\E[8m:mr=\E[7m:ms:\
  115. X    :nd=\E[C:\
  116. X    :RI=\E[%dC:rc=\E[u:\
  117. X    :sc=\E[s:se=\E[0m:so=\E[7m:\
  118. X    :te=\E[0m:ti=\E[0m:\
  119. X    :UP=\E[%dA:ue=\E[0m:up=\E[A:us=\E[4m:\
  120. X    :xd=\E[B:xs:
  121. X
  122. X
  123. X#
  124. X# Color IBMPC.
  125. X#    This is a termcap for the NANSI.SYS device driver.
  126. X#    It is the same as the ANSI termcap, except NANSI supports
  127. X#    character & line insert & delete, while ANSI does not.
  128. X#
  129. Xnansi-color|color:\
  130. X    :AL=\E[%dL:al=\E[1L:\
  131. X    :DC=\E[%dP:dc=\E[1P:DL=\E[%dM:dl=\E[1M:\
  132. X    :IC=\E[%d@:ic=\E[1@:\
  133. X    :tc=ansi-color:
  134. X
  135. X#
  136. X# ANSI Color
  137. X#
  138. Xansi-color:\
  139. X    :bc=\E[1D:bl=^G:bs:\
  140. X    :cd=\E[2J:ce=\E[K:cl=\E[2J\E[H:cm=\E[%i%2;%i%2H:co#80:\
  141. X    :ho=\E[H:\
  142. X    :K1=\200G:K2=\200I:K4=\200O:K5=\200Q:\
  143. X    :k0=\200;:k1=\200<:k2=\200=:k3=\200>:k4=\200?:k5=\200@:\
  144. X    :k6=\200A:k7=\200B:k8=\200C:k9=\200D:\
  145. X    :kb=^H:kC=\200w:kD=\200S:kd=\200H:kE=\200u:kH=\200O:kh=\200G:\
  146. X    :kI=\200R:kl=\200K:kN=\200Q:kP=\200I:kr=\200M:kS=\200v:ku=\200P:\
  147. X    :LE=\E[%dD:le=\E[1D:li#25:\
  148. X    :mb=\E[5m:md=\E[1m:me=\E[0m:mk=\E[8m:mr=\E[7m:ms:\
  149. X    :nd=\E[C:\
  150. X    :RI=\E[%dC:rc=\E[u:\
  151. X    :sc=\E[s:se=\E[44;37m:so=\E[31m:\
  152. X    :te=\E[0m:ti=\E[44;37m:\
  153. X    :UP=\E[%dA:ue=\E[0m:up=\E[A:us=\E[4m:\
  154. X    :xd=\E[B:xs:
  155. X
  156. X
  157. X
  158. X#
  159. X# alternative nansi color
  160. X#
  161. Xalt-nansi-color:\
  162. X    :co#80:\
  163. X    :li#25:\
  164. X    :cl=\E[2J:\
  165. X    :bs:\
  166. X    :ho=\E[H:\
  167. X    :cm=\E[%i%2;%2H:\
  168. X    :up=\E[A:\
  169. X    :xd=\E[B:\
  170. X    :nd=\E[C:\
  171. X    :bc=\E[D:\
  172. X    :ce=\E[K:\
  173. X    :ti=\E[44;37m:\
  174. X    :te=\E[0m:\
  175. X    :so=\E[31m:\
  176. X    :se=\E[44;37m:\
  177. X    :us=\E[1m:\
  178. X    :ue=\E[m:\
  179. X    :hi=\E[32m:\
  180. X    :he=\E[44;37m:\
  181. X    :al=\E[L:\
  182. X    :dl=\E[M:
  183. X
  184. X#
  185. X# Monochrome IBMPC, especially lobotomized for /usr/games/larn.
  186. X#    Each capability (that larn requires) must start on a new line.
  187. X#    Must not use 2nd %i in :cm capability, although it should be there.
  188. X#
  189. Xlarn-mono|hack-mono:\
  190. X    :al=\E[L:\
  191. X    :bc=\E[D:\
  192. X    :bs:\
  193. X    :ce=\E[K:\
  194. X    :cl=\E[2J:\
  195. X    :cm=\E[%i%2;%2H:\
  196. X    :co#80:\
  197. X    :dc=\E[P:\
  198. X    :dl=\E[M:\
  199. X    :ho=\E[H:\
  200. X    :ic=\E[@:\
  201. X    :li#25:\
  202. X    :mb=\E[5m:\
  203. X    :md=\E[7m:\
  204. X    :me=\E[0m:\
  205. X    :mk=\E[8m:\
  206. X    :mr=\E[7m:\
  207. X    :nd=\E[C:\
  208. X    :se=\E[0m:\
  209. X    :so=\E[1m:\
  210. X    :te=\E[0m:\
  211. X    :ti=\E[0m:\
  212. X    :ue=\E[0m:\
  213. X    :up=\E[A:\
  214. X    :us=\E[4m:\
  215. X    :xd=\E[B:\
  216. X    :xs:
  217. X    
  218. X#
  219. X# Color IBMPC, especially lobotomized for /usr/games/larn.
  220. X#    Each capability (that larn requires) must start on a new line.
  221. X#    Must not use 2nd %i in :cm capability, although it should be there.
  222. X#
  223. Xlarn-color|hack-color:\
  224. X    :bc=\E[D:\
  225. X    :bs:\
  226. X    :ce=\E[K:\
  227. X    :cl=\E[2J:\
  228. X    :cm=\E[%i%2;%2H:\
  229. X    :co#80:\
  230. X    :he=\E[44;37m:\
  231. X    :hi=\E[32m:\
  232. X    :ho=\E[H:\
  233. X    :li#25:\
  234. X    :nd=\E[C:\
  235. X    :se=\E[44;37m:\
  236. X    :so=\E[31m:\
  237. X    :te=\E[0m:\
  238. X    :ti=\E[44;37m:\
  239. X    :ue=\E[m:\
  240. X    :up=\E[A:\
  241. X    :us=\E[1m:\
  242. X    :xd=\E[B:\
  243. X    :xs:
  244. ________This_Is_The_END________
  245. if test `wc -c < termcap.pc` -ne 3370; then
  246.     echo 'shar: termcap.pc was damaged during transit (should have been 3370 bytes)'
  247. fi
  248. fi        ; : end of overwriting check
  249. echo 'x - termcap.c'
  250. if test -f termcap.c; then echo 'shar: not overwriting termcap.c'; else
  251. sed 's/^X//' << '________This_Is_The_END________' > termcap.c
  252. X/*    termcap.c    880204    NHA    */
  253. X/* My implementation of the termcap(3X) library routines.
  254. X * All specs lifted straight from 4.3bsd Programmers Reference Manual.
  255. X * These functions extract and use capabilities from the terminal
  256. X * capability database termcap(5).  These are low level routines;
  257. X * see curses(3X) for a higher level package.
  258. X ** You'll find it looks a lot nicer if you use a tab interval of 4.
  259. X */
  260. X
  261. X#define    DEBUG    0
  262. X
  263. X#if DEBUG
  264. X#define    MAJOR    'L'                            /* major module identifier */
  265. X#define    MINOR    'T'                            /* minor module identifier */
  266. X#include    <gen.h>                            /* my all-purpose include file */
  267. X#else DEBUG
  268. X#include    <stdio.h>
  269. X#include    <fcntl.h>
  270. X#define        export
  271. X#define        import        extern
  272. X#define        local        static
  273. X#define        bool        int
  274. X#define        abs(x)        ( (x < 0) ? (-(x)) : (x) )
  275. X#define        YES            1
  276. X#define        NO            0
  277. X#define        error(s)    {perror(s);  exit(99);}
  278. X#define        initdebug(pac, pav, confile, listfile, initstring)
  279. Xstatic        printd(lvl, fmt) {}
  280. X#endif DEBUG
  281. X
  282. X#define    BUFSIZE    1024
  283. X
  284. X/* external variables (supplied by user) required by this package */
  285. Ximport char        PC;                            /* pad char, default ^@ */
  286. Ximport char        BC;                            /* backspace char if not ^H */
  287. Ximport char        UP;                            /* char for Upline (cursor up) */
  288. Ximport char        ospeed;                        /* output speed, see stty(3) */
  289. X
  290. X#ifdef __STDC__
  291. Ximport char        *getenv(char *id);
  292. Ximport int        open(char *name, unsigned mode);
  293. Ximport unsigned    strlen(char *str);
  294. Ximport unsigned    strspn(char *str1, char *str2);
  295. Ximport int        strcmp(char *str1, char *str2);
  296. Ximport int        strncmp(char *str1, char *str2, unsigned n);
  297. Ximport char        *strncpy(char *buf, char *str, unsigned n);
  298. Ximport char        *strchr(char *string, char ch);
  299. Ximport char        *strpbrk(char *string, char *delimiters);
  300. X#else __STDC__
  301. Ximport char        *getenv();
  302. Ximport int        open();
  303. Ximport unsigned    strlen();
  304. Ximport unsigned    strspn();
  305. Ximport int        strcmp();
  306. Ximport int        strncmp();
  307. Ximport char        *strncpy();
  308. Ximport char        *strchr();
  309. Ximport char        *strpbrk();
  310. X#endif __STDC__
  311. X
  312. X/* milliseconds per character, for each of the possible baud rates of ospeed */
  313. X/* here multiplied by 10 for computational convenience */
  314. Xlocal unsigned    delayFactor[] = {
  315. X                                   0,        /* B0 */    /* hang up dataphone */
  316. X                                1920,        /* B50 */
  317. X                                1280,        /* B75 */
  318. X                                 872,        /* B110 */
  319. X                                 730,        /* B134 */
  320. X                                 640,        /* B150 */
  321. X                                 480,        /* B200 */
  322. X                                 320,        /* B300 */
  323. X                                 160,        /* B600 */
  324. X                                  80,        /* B1200 */
  325. X                                  50,        /* B1800 */
  326. X                                  40,        /* B2400 */
  327. X                                  20,        /* B4800 */
  328. X                                  10,        /* B9600 */
  329. X                                   5,        /* EXTA (19200 here) */
  330. X                                   2,        /* EXTB (34800 here) */
  331. X                                };
  332. X/* remember where user's terminal entry buffer is */
  333. Xlocal char        *ebuf = NULL;                /* pointer to entry buffer */
  334. X
  335. X
  336. X
  337. X/*+        f i n d C a p
  338. X * Returns pointing to the character immediately following the capability id.
  339. X * Returns NULL if tgetent() has not yet been called successfully.
  340. X * Returns NULL if capability not found.
  341. X */
  342. Xlocal char *findCap(id)
  343. Xchar    *id;                                /* name of the capability to find */
  344. X    {
  345. X    char    *p;                                /* pointer into the entry buffer */
  346. X
  347. X    printd(5, "findCap(\"%s\"), ebuf=%p\n", id, ebuf);
  348. X    if (ebuf == NULL)
  349. X        return NULL;
  350. X    for (p = ebuf   ;   *p   ;   ++p)
  351. X        {
  352. X        printd(9, " %02x", *p);
  353. X        if ( (p[0] == ':')  &&  (p[1] == id[0])  &&  (p[2] == id[1]) )
  354. X            {
  355. X            printd(7, "findCap(): SUCCESS, p=%.15s...\n", p);
  356. X            p = &p[3];
  357. X            break;
  358. X            }
  359. X        }
  360. X    if ( ! *p)
  361. X        p = NULL;
  362. X    printd(5, "findCap(): returning %p (%.11s...)\n", p, p);
  363. X    return p;
  364. X    }
  365. X
  366. X
  367. X
  368. X/*+        g e t E n t r y
  369. X * Gets the named entry from the already-opened termcap file into the buffer.
  370. X * The size of the buffer is BUFSIZE, and it is considered to be an
  371. X * error if the size of the entry equals or exceeds this.
  372. X * We place a terminating NULL character at the end of the entry.
  373. X * Call error() on any irregularities.
  374. X * Return 0 if the named entry not found, else 1.
  375. X * Removes terminal names and all newlines from the entry.
  376. X **If this is called for a 2nd time from tgetent(), then the length checking
  377. X **is useless.
  378. X */
  379. Xlocal int getEntry(fd, outbuf, name)
  380. Xint        fd;                                    /* FileDescriptor for termcap file*/
  381. Xchar    *outbuf;                            /* where we put the entry */
  382. Xchar    *name;                                /* terminal type name we seek */
  383. X    {
  384. X    unsigned    namlen;                        /* # chars in name */
  385. X    int            cnt;                        /* # unprocessed chars in inbuf[] */
  386. X    char        *ip;                        /* pointer into input buffer */
  387. X    char        *op;                        /* pointer into output buffer */
  388. X    char        *ptmp;                        /* temporary pointer */
  389. X    int            stat;                        /* status of read(), etc */
  390. X    char        inbuf[BUFSIZE];                /* termcap file is read into here */
  391. X
  392. X    printd(5, "getEntry(%d, %p, \"%s\")\n", fd, inbuf, name);
  393. X    op = outbuf;
  394. X    namlen = strlen(name);
  395. X    cnt = read(fd, inbuf, BUFSIZE-1);
  396. X    if (cnt == -1)
  397. X        error("getEntry(): file is empty\n");
  398. X    inbuf[cnt] = '\0';                        /* maintain inbuf[] as a string */
  399. X    for (ip = inbuf   ;   0 < cnt   ;   ++ip, --cnt)
  400. X        {
  401. X        printd(7, "cnt=%d, ip='%.55s...'\n", cnt, ip);
  402. X        stat = strspn(ip, "\r\n \t\b\f");
  403. X        if (0 < stat)
  404. X            {
  405. X            printd(8, "skipping %d whitespace characters\n", stat);
  406. X            ip = &ip[--stat];
  407. X            cnt -= stat;
  408. X            }
  409. X        else if (*ip == '#')
  410. X            {
  411. X            printd(6, "comment line '%.11s...'\n", ip);
  412. X            ptmp = ip;
  413. X            ip = strchr(ip, (char)'\n');
  414. X            cnt  -=  (ip == NULL) ? cnt : (int)(ip - ptmp);
  415. X            }
  416. X        else if (strncmp(name, ip, namlen) == 0)
  417. X            {
  418. X            printd(6, "getEntry(): SUCCESS, ip = '%.22s...', cnt=%u\n", ip,cnt);
  419. X            ip = strchr(ip, (char)':');        /* skip over namelist */
  420. X            printd(7, "getEntry(): raw entry is: '%s'\n", ip);
  421. X            /* copy entry into output buffer */
  422. X            /* eliminate non-space whitespace and continuation \ */
  423. X            for (op = outbuf   ;   ip != NULL  &&  *ip != '\0'   ;   ++ip)
  424. X                {
  425. X                printd(9, " %02x", *ip);
  426. X                if (ip[0] == '\\'   &&   ip[1] == '\r'   &&   ip[2] == '\n')
  427. X                    ip = &ip[2];
  428. X                else if (ip[0] == '\\'   &&   ip[1] == '\n')
  429. X                    ++ip;
  430. X                else if (strchr("\t\r\b\f", *ip) != NULL)
  431. X                    continue;
  432. X                else if (*ip == '\n')
  433. X                    break;
  434. X                else
  435. X                    *op++  =  *ip;
  436. X                }
  437. X            if (*ip != '\n')
  438. X                error("getEntry(): entry too long\n");
  439. X            *op = '\0';
  440. X            printd(6, "getEntry(): outbuf='%s'\n", outbuf);
  441. X            printd(5, "getEntry(): returning 1  [SUCCESS]\n");
  442. X            return 1;
  443. X            }
  444. X        else
  445. X            {                                /* advance to next name in list */
  446. X            ptmp = ip;
  447. X            ip = strpbrk(ip, "|:");            /* find name delimiter */
  448. X            if (ip == NULL)
  449. X                error("getEntry(): bad format\n");
  450. X            cnt -= ip - ptmp;
  451. X            if (*ip != '|')
  452. X                {                            /* at end of namelist for entry */
  453. X                /* dispose of entire entry */
  454. X                printd(8, "end of namelist, cnt=%d\n", cnt);
  455. X                for (++ip, --cnt   ;   0 < cnt   ;   ++ip, --cnt)
  456. X                    if ( ip[0] == '\n'   && 
  457. X                          ( (ip[-1] == '\r'  &&   ip[-2] != '\\')
  458. X                                              ||
  459. X                            (ip[-1] != '\r'  &&   ip[-1] != '\\') )
  460. X                       )
  461. X                        {                /* skip to next entry in file */
  462. X                        /* delete this entry from inbuf */
  463. X                        for (ptmp = inbuf   ;   *ip != '\0'   ;   ++ptmp, ++ip)
  464. X                            *ptmp = *ip;
  465. X                        *ptmp = *ip;        /* string stopper character */
  466. X                        ip = inbuf;
  467. X                        if (strlen(ip) != cnt)
  468. X                            error("getEntry(): bad strlen(ip)\n");
  469. X                        /* fill inbuf with more characters */
  470. X                        stat = read(fd, ptmp, BUFSIZE - cnt - 1);
  471. X                        if (0 < stat)
  472. X                            {
  473. X                            cnt += stat;
  474. X                            inbuf[cnt] = '\0';
  475. X                            }
  476. X                        break;
  477. X                        }
  478. X                if (cnt <= 0)
  479. X                    error("getEntry(): entry too long!\n");
  480. X                }
  481. X            }
  482. X        }
  483. X    outbuf[0] = '\0';                        /* not found */
  484. X    printd(6, "getEntry(): outbuf='%s'\n", outbuf);
  485. X    printd(5, "getEntry(): returning 0  [FAILURE]\n");
  486. X    return 0;
  487. X    }
  488. X
  489. X
  490. X    
  491. X/*+        t g e t e n t
  492. X * Extracts the entry for terminal name into the buffer at bp.
  493. X * Bp should be a character array of size 1024 and must be retained through
  494. X * all subsequent calls to tgetnum(), tgetflag(), and tgetstr().
  495. X * Returns -1 if it cannot open the termcap file, 0 if the terminal name
  496. X * given does not have an entry, and 1 if all goes well.
  497. X * Looks in the environment for a TERMCAP variable.  If found, and the value
  498. X * does not begin with a slash, and the terminal type name is the same as
  499. X * the environment string TERM, the TERMCAP string is used instead of reading
  500. X * the termcap file.  If it does begin with a slash, the string is used
  501. X * as a pathname rather than /etc/termcap.  This can speed up entry into
  502. X * programs that call tgetent(), as well as to help debug new terminal
  503. X * descriptions  or to make one for your terminal if you can't write the
  504. X * file /etc/termcap.
  505. X */
  506. Xexport int tgetent(bp, name)
  507. Xchar    *bp;                                /* pointer to user's buffer */
  508. Xchar    *name;                                /* terminal type name */
  509. X    {
  510. X    char    *termcap;                        /* pointer to $TERMCAP string */
  511. X    int        fd;                                /* File Descriptor, termcap file */
  512. X    int        retval;                            /* return value */
  513. X    
  514. X    printd(3, "tgetent(%p, \"%s\")\n", bp, name);
  515. X    termcap = getenv("TERMCAP");
  516. X    if (termcap != NULL   &&   termcap[0] != '/'   &&
  517. X        strcmp(name, getenv("TERM")) == 0)
  518. X        {                                    /* use $TERMCAP as the entry */
  519. X        printd(6, "tgetent(): using contents of $EXINIT\n");
  520. X        strncpy(bp, termcap, (BUFSIZE-1));
  521. X        bp[BUFSIZE] = '\0';
  522. X        termcap = "/etc/termcap";            /* in case :tc capability found */
  523. X        retval = 1;
  524. X        }
  525. X    else
  526. X        {                                    /* look for entry in termcap file */
  527. X        if (termcap[0] != '/')
  528. X            termcap = "/etc/termcap";        /* use default termcap file */
  529. X        printd(6, "tgetent(): opening file %s\n", termcap);
  530. X        fd = open(termcap, O_RDONLY);
  531. X        if (fd == -1)
  532. X            retval = -1;
  533. X        else
  534. X            {
  535. X            retval = getEntry(fd, bp, name);
  536. X            close(fd);
  537. X            }
  538. X        }
  539. X    if (retval == 1)
  540. X        ebuf = bp;                            /* for our use in future pkg calls*/
  541. X    
  542. X    /* deal with the :tc= capability */
  543. X    bp = findCap("tc");
  544. X    if (bp != NULL)
  545. X        {
  546. X        char    newname[88];
  547. X        
  548. X        printd(6, "tgetent(): :tc found at %p, is '%s'\n", &bp[-3], &bp[-3]);
  549. X        strncpy(newname, &bp[1], sizeof newname);
  550. X        if (strchr(newname, (char)':') != NULL)
  551. X            *(strchr(newname, (char)':'))  =  '\0';
  552. X        fd = open(termcap, O_RDONLY);
  553. X        if (fd == -1)
  554. X            {
  555. X            printd(2, "tgetent(%s): can't open :tc file '%s'\n", name, newname);
  556. X            retval = -1;
  557. X            }
  558. X        else
  559. X            {
  560. X            retval = getEntry(fd, &bp[-2], newname);
  561. X            close(fd);
  562. X            }
  563. X        }
  564. X        
  565. X    printd(3, "tgetent(): returning %d\n", retval);
  566. X    return retval;
  567. X    }
  568. X
  569. X
  570. X    
  571. X/*+        t g e t n u m
  572. X * Gets the numeric value of capability id, returning -1 if it is not given
  573. X * for the terminal.
  574. X */
  575. Xexport int tgetnum(id)
  576. Xchar    *id;                                /* capability name */
  577. X    {
  578. X    int        retval;
  579. X    char    *p;
  580. X
  581. X    printd(3, "tgetnum(\"%s\")\n", id);
  582. X    p = findCap(id);
  583. X    if (p == NULL   ||   *p != '#')
  584. X        retval = -1;                        /* not found, or not numeric */
  585. X    else
  586. X        {
  587. X        retval = 0;
  588. X        for (++p   ;   *p != ':'   ;   ++p)
  589. X            retval  =  (retval * 10) + (*p - '0');
  590. X        }
  591. X    printd(3, "tgetnum(): returning %d\n", retval);
  592. X    return retval;
  593. X    }
  594. X
  595. X
  596. X
  597. X/*+        t g e t f l a g
  598. X * Returns 1 if the specified capability is present in the terminal's entry,
  599. X * 0 if it is not.
  600. X **This implementation requires that the capability be a boolean one.
  601. X */
  602. Xexport int tgetflag(id)
  603. Xchar    *id;                                /* capability name */
  604. X    {
  605. X    int        retval;
  606. X    char    *p;
  607. X
  608. X    printd(3, "tgetflag(\"%s\")\n", id);
  609. X    p = findCap(id);
  610. X    retval  =  (p != NULL  &&  *p == ':');
  611. X    printd(3, "tgetflag(): returning %d\n", retval);
  612. X    return retval;
  613. X    }
  614. X
  615. X
  616. X
  617. X/*+        t g e t s t r
  618. X * Returns the string value of the capability id, places it in the buffer
  619. X * at area, and advances the area pointer [past the terminating '\0' char].
  620. X * It decodes the abbreviations for this field described in termcap(5),
  621. X * except for cursor addressing and padding information.
  622. X * Returns NULL if the capability was not found.
  623. X */
  624. Xexport char *tgetstr(id, area)
  625. Xchar    *id;                                /* capability name */
  626. Xchar    **area;                                /* pointer to output pointer */
  627. X    {
  628. X    char        *retval;                    /* return value */
  629. X    char        *p;                            /* pointer into capability string */
  630. X    unsigned    sum;                        /* for chars given in octal */
  631. X
  632. X    printd(3, "tgetstr(\"%s\", %p): *area=%p\n", id, area, *area);
  633. X    p = findCap(id);
  634. X    if (p == NULL   ||   *p != '=')
  635. X        retval = NULL;
  636. X    else
  637. X        {
  638. X        retval = *area;
  639. X        for (++p   ;   *p != ':'   ;   ++p)
  640. X            {
  641. X            printd(9, "p=%p,  *p=%02x\n", p, *p);
  642. X            if (*p == '\\')
  643. X                switch (*++p)
  644. X                    {                        /* special */
  645. X                case '0': case '1': case '2': case '3':
  646. X                case '4': case '5': case '6': case '7':
  647. X                    sum = (p[0] - '0') << 6  +
  648. X                          (p[1] - '0') << 3  +
  649. X                          (p[2] - '0');
  650. X                    ++p;
  651. X                    ++p;
  652. X                    *(*area)++  =  (char)(sum & 0377);
  653. X                    /** will \200 really end up as \000 like it should ? **/
  654. X                    /** see termcap(5), top of page 6 **/
  655. X                    break;
  656. X                case '^':    *(*area)++  =  '^';        break;
  657. X                case '\\':    *(*area)++  =  '\\';    break;
  658. X                case 'E':    *(*area)++  =  '\033';    break;        /* escape */
  659. X                case 'b':    *(*area)++  =  '\b';    break;
  660. X                case 'f':    *(*area)++  =  '\f';    break;
  661. X                case 'n':    *(*area)++  =  '\n';    break;
  662. X                case 'r':    *(*area)++  =  '\r';    break;
  663. X                case 't':    *(*area)++  =  '\t';    break;
  664. X                default:    *(*area)++  =  *p;        break;
  665. X                    }
  666. X            else if (*p == '^')
  667. X                *(*area)++  =  *++p - '@';    /* control */
  668. X            else
  669. X                *(*area)++  =  *p;            /* normal */
  670. X            }
  671. X        *(*area)++ = '\0';                    /* NULL-terminate the string */
  672. X        }
  673. X    printd(3, "tgetstr(): returning ");
  674. X    if (retval == NULL)
  675. X        {                                    /* these must be here for print() */
  676. X        printd(3, "NULL");
  677. X        }                                    /* these must be here for print() */
  678. X    else
  679. X        {
  680. X        printd(3, "%p  [", retval);
  681. X        for (p = retval   ;   p != *area   ;   ++p)
  682. X            printd(3, " %02x", (unsigned)*p);
  683. X        printd(3, "]");
  684. X        }
  685. X    printd(3, ",  *area=%p\n",  *area);
  686. X    return retval;
  687. X    }
  688. X
  689. X
  690. X    
  691. X/*+        t g o t o
  692. X * Returns a cursor addressing string decoded from cm to go to column destcol
  693. X * in line destline. It uses the external variables UP (from the up capability)
  694. X * and BC (if bc is given rather than bs) if necessary to avoid placing
  695. X * \n, ^D, or ^@ in the returned string.  (Programs which call tgoto() should
  696. X * be sure to turn off the XTABS bit(s), since tgoto() may not output a tab.
  697. X * Note that programs using termcap should in general turn off XTABS anyway
  698. X * since some terminals use control I for other functions, such as non-
  699. X * destructive space.)  If a % sequence is given which is not understood,
  700. X * then tgoto() returns "OOPS".
  701. X **Output buffer is local, so don't try any recursion.
  702. X **No error checking here.
  703. X */
  704. Xexport char *tgoto(cm, destcol, destline)
  705. Xchar    *cm;                                /* cm capability string */
  706. Xint        destcol;                            /* destination column (left is 0) */
  707. Xint        destline;                            /* destination line (top is 0) */
  708. X    {
  709. X    char        *outp;                        /* pointer into answer[] */
  710. X    local char    answer[88];                    /* result stashed here */
  711. X    bool        reversed;                    /* YES when should send col 1st */
  712. X    int            value;                        /* next value to output */
  713. X
  714. X    printd(3, "tgoto(\"%s\", %d, %d)\n", cm, destcol, destline);
  715. X    reversed = NO;
  716. X    value = destline;
  717. X    outp = answer;
  718. X    for (   ;   *cm   ;   ++cm)
  719. X        {
  720. X        printd(9, " %02x", *cm);
  721. X        if (*cm == '%')
  722. X            {
  723. X            switch (*++cm)
  724. X                {
  725. X            case '%':    *outp++ = '%';
  726. X                        break;
  727. X            case 'd':    sprintf(outp, "%d", value);
  728. X                        if (value < 0)
  729. X                            ++outp;
  730. X                        ++outp;
  731. X                        if (9 < abs(value))
  732. X                            ++outp;
  733. X                        if (99 < abs(value))
  734. X                            ++outp;
  735. X                        value = (reversed) ? destline : destcol;
  736. X                        break;
  737. X            case '2':    sprintf(outp, "%02d", value);
  738. X                        outp += 2;
  739. X                        value = (reversed) ? destline : destcol;
  740. X                        break;
  741. X            case '3':    sprintf(outp, "%03d", value);
  742. X                        outp += 3;
  743. X                        value = (reversed) ? destline : destcol;
  744. X                        break;
  745. X            case '.':    *outp++ = value;
  746. X                        value = (reversed) ? destline : destcol;
  747. X                        break;
  748. X            case '+':    *outp++ = value + *++cm;
  749. X                        value = (reversed) ? destline : destcol;
  750. X                        break;
  751. X            case '>':    if (value > *++cm)
  752. X                            value += *++cm;
  753. X                        else
  754. X                            ++cm;
  755. X                        break;
  756. X            case 'r':    value = (reversed) ? destline : destcol;
  757. X                        reversed ^= YES;
  758. X                        break;
  759. X            case 'i':    ++value;
  760. X                        break;
  761. X            case 'n':    destcol  ^= 0140;
  762. X                        destline ^= 0140;
  763. X                        break;
  764. X            case 'B':    value = (16 * (value / 10))  +  (value % 10);
  765. X                        break;
  766. X            case 'D':    value = (value - (2 * (value % 16)));
  767. X                        break;
  768. X            default:    sprintf(outp, "OOPS");
  769. X                        outp += 4;
  770. X                        break;
  771. X                }
  772. X            printd(8, "reversed=%b, value=%d\n", reversed, value);
  773. X            }
  774. X        else
  775. X            *outp++ = *cm;
  776. X        }
  777. X    *outp = '\0';
  778. X    printd(3, "tgoto(): returning '%s'\n", answer);
  779. X    return answer;
  780. X    }
  781. X
  782. X
  783. X
  784. X/*+        t p u t s
  785. X * Decodes the leading pad information of the string cp; affcnt gives the
  786. X * number of lines affected by the operation, or 1 if this is not applicable.
  787. X * Outc is a routine which is called with each character in turn.
  788. X * The external variable ospeed should contain the output speed of
  789. X * the terminal as encoded by stty(3).
  790. X * The external variable PC should contain a pad character to be used
  791. X * (from the pc capability) if a null (^@) is inappropriate.
  792. X */
  793. Xexport void tputs(cp, affcnt, outc)
  794. Xchar    *cp;                                /* leading pad information string */
  795. Xint        affcnt;                                /* number lines affected, or 1 */
  796. Xint        (*outc)();                            /*output function to call per char*/
  797. X    {
  798. X    char        *p;
  799. X    bool        decimalFlag;                /* delay had a decimal point */
  800. X    unsigned    delay;
  801. X    unsigned    cnt;
  802. X    
  803. X    printd(3, "tputs(\"%s\", %d, %p):  ospeed=%u\n", cp, affcnt, outc, ospeed);
  804. X
  805. X    /* calculate delay, if any */
  806. X    /* currently no guard against having more than 1 digit after decimal point*/
  807. X    decimalFlag = NO;
  808. X    delay = 0;
  809. X    for (p = cp   ;   strchr("0123456789.", *p)   ;   ++p)
  810. X        if (*p == '.')
  811. X            decimalFlag = YES;
  812. X        else
  813. X            delay  =  (delay * 10) + (*p - '0');
  814. X    if ( ! decimalFlag)
  815. X        delay *= 10;                        /* units are really 10ms */
  816. X    if (*p == '*')
  817. X        delay *= affcnt;
  818. X    printd(6, "tputs(): delay = %u.%u milliseconds\n", delay/10, delay%10);
  819. X    delay += (delayFactor[ospeed] + 1) / 2;    /* round up */
  820. X    delay /= delayFactor[ospeed];
  821. X    printd(5, "tputs(): delay = %u characters,  [delayFactor is %u]\n",
  822. X      delay, delayFactor[ospeed]);
  823. X
  824. X    for (   ;   *cp != '\0'   ;   ++cp)
  825. X        outc(*cp);                            /* output string */
  826. X    for (cnt = delay   ;   cnt   ;   --cnt)
  827. X        outc(PC);                            /* output delay characters */
  828. X    printd(3, "tputs(): returning\n");
  829. X    }
  830. X
  831. X
  832. X
  833. X#if        TEST
  834. X
  835. Xexport char        PC;                            /* pad char, default ^@ */
  836. Xexport char        BC;                            /* backspace char if not ^H */
  837. Xexport char        UP;                            /* char for Upline (cursor up) */
  838. Xexport char        ospeed = 13;                /* output speed, see stty(3) */
  839. X
  840. Xlocal char    buf[1024];                        /* holds termcap entry */
  841. Xlocal char    strbuf[512];                    /* for output of tgetstr() */
  842. Xlocal char    *strptr;                        /* ptr to strbuf[] */
  843. X
  844. X
  845. X/*+        o c
  846. X * Tiny test routine to simulate putting out a character.
  847. X */
  848. Xlocal void oc(c)
  849. Xchar    c;
  850. X    {
  851. X    putc(c, stdout);
  852. X    }
  853. X
  854. X
  855. X/*+        m a i n
  856. X * Test program for the termcap routines.
  857. X * Command line parameters:
  858. X *    1st is terminal name, defaulted to "mono".
  859. X *    2nd is name of numeric capability, default "co".
  860. X *    3rd is name of boolean capability, default "bs".
  861. X *    4th is name of string capability, default "so".
  862. X *    5th is test string for tgoto(), default is "6\\E&%r%2c%2Y".
  863. X *    6th is test string for tputs(), default is "3.5*123".
  864. X */
  865. Xexport int main(ac, av)
  866. Xint        ac;
  867. Xchar    **av;
  868. X    {
  869. X    int        stat;                            /* integer return value */
  870. X    char    *instr;                            /* input string value */
  871. X    char    *outstr;                        /* string return value */
  872. X    char    *ttype;                            /* terminal type string */
  873. X    char    *capability;                    /* capability name string */
  874. X    
  875. X    /* setup */
  876. X    initdebug(&ac, &av, "/dev/con", "debug.out", "LB3LT8");
  877. X    PC = '@';
  878. X    BC = 'H';
  879. X    UP = 'B';
  880. X    
  881. X    /* test tgetent() */
  882. X    ttype = (ac < 2) ? "mono" : av[1];
  883. X    stat = tgetent(buf, ttype);
  884. X    printf("main: tgetent(buf, \"%s\") returned %d\n", ttype, stat);
  885. X    if (stat != 1)
  886. X        exit (99);
  887. X        
  888. X    /* test tgetnum() */
  889. X    capability = (ac < 3) ? "co" : av[2];
  890. X    stat = tgetnum(capability);
  891. X    printf("main: tgetnum(%s) returned %d\n", capability, stat);
  892. X
  893. X    /* test tgetflag() */
  894. X    capability = (ac < 4) ? "bs" : av[3];
  895. X    stat = tgetflag(capability);
  896. X    printf("main: tgetflag(%s) returned %d\n", capability, stat);
  897. X
  898. X    /* test tgetstr() */
  899. X    capability = (ac < 5) ? "so" : av[4];
  900. X    strptr = strbuf;
  901. X    outstr = tgetstr(capability, &strptr);
  902. X    printf("main: tgetstr(%s, 0x%lx) returned '%s'  [strbuf=0x%lx, strptr=0x%lx]\n",
  903. X      capability, &strptr, outstr, strbuf, strptr);
  904. X    if (strcmp(capability, "so") == 0)
  905. X        {
  906. X        strptr = strbuf;
  907. X        tgetstr("se", &strptr);
  908. X        printf(strbuf);
  909. X        }
  910. X
  911. X    /* test tgoto() */
  912. X    instr = (ac < 6) ? "6\\E&%r%2c%2Y" : av[5];
  913. X    outstr = tgoto(instr, 12, 3);
  914. X    printf("main: tgoto(\"%s\", 12, 3) returned '%s'\n", instr, outstr);
  915. X    
  916. X    /* test tputs() */
  917. X    instr = (ac < 7) ? "3.5*123" : av[6];
  918. X    printf("main: tputs(\"%s\", 3, oc) returned '", instr);
  919. X    tputs(instr, 3, oc);
  920. X    printf("'\n");
  921. X    
  922. X    return 0;
  923. X    }
  924. X
  925. X#endif    TEST
  926. ________This_Is_The_END________
  927. if test `wc -c < termcap.c` -ne 20209; then
  928.     echo 'shar: termcap.c was damaged during transit (should have been 20209 bytes)'
  929. fi
  930. fi        ; : end of overwriting check
  931. exit 0
  932. --------------------------------------------------------------------------
  933. NHA
  934. ---
  935. Norman Azadian, 80A;  Hasler AG;  Belpstrasse 23;  3000 Berne 14;  Switzerland
  936. X.400:  azadian@hslrswi.hasler                     Telephone:   +41 31 63 2178
  937. Uucp:   ... {uunet,ukc,mcvax, ... }!cernvax!hslrswi!azadian
  938. Bitnet: azadian%hslrswi.UUCP@cernvax.BITNET
  939.  
  940.  
  941.