home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume2 / termcap < prev    next >
Encoding:
Internet Message Format  |  1991-08-07  |  27.9 KB

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