/contrib/tcsh/vms.termcap.c

https://bitbucket.org/freebsd/freebsd-head/ · C · 354 lines · 262 code · 31 blank · 61 comment · 103 complexity · a84e45f6a0a6f65499b0c9860f669da9 MD5 · raw file

  1. /* $Header: /p/tcsh/cvsroot/tcsh/vms.termcap.c,v 1.12 2011/01/09 16:25:29 christos Exp $ */
  2. /*
  3. * termcap.c 1.1 20/7/87 agc Joypace Ltd
  4. *
  5. * Copyright Joypace Ltd, London, UK, 1987. All rights reserved.
  6. * This file may be freely distributed provided that this notice
  7. * remains attached.
  8. *
  9. * A public domain implementation of the termcap(3) routines.
  10. */
  11. #include "sh.h"
  12. RCSID("$tcsh: vms.termcap.c,v 1.12 2011/01/09 16:25:29 christos Exp $")
  13. #if defined(_VMS_POSIX) || defined(_OSD_POSIX) || defined(__ANDROID__)
  14. /* efth 1988-Apr-29
  15. - Correct when TERM != name and TERMCAP is defined [tgetent]
  16. - Correct the comparison for the terminal name [tgetent]
  17. - Correct the value of ^x escapes [tgetstr]
  18. - Added %r to reverse row/column [tgoto]
  19. Paul Gillingwater <paul@actrix.gen.nz> July 1992
  20. - Modified to allow terminal aliases in termcap file
  21. - Uses TERMCAP environment variable for file only
  22. */
  23. #include <stdio.h>
  24. #include <string.h>
  25. #define CAPABLEN 2
  26. #define ISSPACE(c) ((c) == ' ' || (c) == '\t' || (c) == '\r' || (c) == '\n')
  27. #define ISDIGIT(x) ((x) >= '0' && (x) <= '9')
  28. char *capab; /* the capability itself */
  29. extern char *getenv(); /* new, improved getenv */
  30. #ifndef fopen
  31. extern FILE *fopen(); /* old fopen */
  32. #endif
  33. /*
  34. * tgetent - get the termcap entry for terminal name, and put it
  35. * in bp (which must be an array of 1024 chars). Returns 1 if
  36. * termcap entry found, 0 if not found, and -1 if file not found.
  37. */
  38. int
  39. tgetent(char *bp, char *name)
  40. {
  41. #ifdef __ANDROID__
  42. /* Use static termcap entry since termcap file usually doesn't exist. */
  43. capab = bp;
  44. strcpy(bp,
  45. "linux|linux console:"
  46. ":am:eo:mi:ms:xn:xo:"
  47. ":it#8:"
  48. ":AL=\\E[%dL:DC=\\E[%dP:DL=\\E[%dM:IC=\\E[%d@:K2=\\E[G:al=\\E[L:"
  49. ":bl=^G:cd=\\E[J:ce=\\E[K:cl=\\E[H\\E[J:cm=\\E[%i%d;%dH:cr=^M:"
  50. ":cs=\\E[%i%d;%dr:ct=\\E[3g:dc=\\E[P:dl=\\E[M:do=^J:ec=\\E[%dX:"
  51. ":ei=\\E[4l:ho=\\E[H:ic=\\E[@:im=\\E[4h:k1=\\E[[A:k2=\\E[[B:"
  52. ":k3=\\E[[C:k4=\\E[[D:k5=\\E[[E:k6=\\E[17~:k7=\\E[18~:k8=\\E[19~:"
  53. ":k9=\\E[20~:kD=\\E[3~:kI=\\E[2~:kN=\\E[6~:kP=\\E[5~:kb=\\177:"
  54. ":kd=\\E[B:kh=\\E[1~:kl=\\E[D:kr=\\E[C:ku=\\E[A:le=^H:mb=\\E[5m:"
  55. ":md=\\E[1m:me=\\E[0m:mh=\\E[2m:mr=\\E[7m:nd=\\E[C:nw=^M^J:"
  56. ":rc=\\E8:sc=\\E7:se=\\E[27m:sf=^J:so=\\E[7m:sr=\\EM:st=\\EH:ta=^I:"
  57. ":ue=\\E[24m:up=\\E[A:us=\\E[4m:vb=200\\E[?5h\\E[?5l:"
  58. ":ve=\\E[?25h\\E[?0c:vi=\\E[?25l\\E[?1c:vs=\\E[?25h\\E[?0c:"
  59. );
  60. return(1);
  61. #else
  62. FILE *fp;
  63. char *termfile;
  64. char *cp,
  65. *ptr, /* temporary pointer */
  66. tmp[1024]; /* buffer for terminal name *//*FIXBUF*/
  67. size_t len = strlen(name);
  68. capab = bp;
  69. /* Use TERMCAP to override default. */
  70. termfile = getenv("TERMCAP");
  71. if (termfile == NULL ) termfile = "/etc/termcap";
  72. if ((fp = fopen(termfile, "r")) == (FILE *) NULL) {
  73. fprintf(stderr, CGETS(31, 1,
  74. "Can't open TERMCAP: [%s]\n"), termfile);
  75. fprintf(stderr, CGETS(31, 2, "Can't open %s.\n"), termfile);
  76. sleep(1);
  77. return(-1);
  78. }
  79. while (fgets(bp, 1024, fp) != NULL) {
  80. /* Any line starting with # or NL is skipped as a comment */
  81. if ((*bp == '#') || (*bp == '\n')) continue;
  82. /* Look for lines which end with two backslashes,
  83. and then append the next line. */
  84. while (*(cp = &bp[strlen(bp) - 2]) == '\\')
  85. fgets(cp, 1024, fp);
  86. /* Skip over any spaces or tabs */
  87. for (++cp ; ISSPACE(*cp) ; cp++);
  88. /* Make sure "name" matches exactly (efth) */
  89. /* Here we might want to look at any aliases as well. We'll use
  90. sscanf to look at aliases. These are delimited by '|'. */
  91. sscanf(bp,"%[^|]",tmp);
  92. if (strncmp(name, tmp, len) == 0) {
  93. fclose(fp);
  94. #ifdef DEBUG
  95. fprintf(stderr, CGETS(31, 3, "Found %s in %s.\n"), name, termfile);
  96. sleep(1);
  97. #endif /* DEBUG */
  98. return(1);
  99. }
  100. ptr = bp;
  101. while ((ptr = strchr(ptr,'|')) != NULL) {
  102. ptr++;
  103. if (strchr(ptr,'|') == NULL) break;
  104. sscanf(ptr,"%[^|]",tmp);
  105. if (strncmp(name, tmp, len) == 0) {
  106. fclose(fp);
  107. #ifdef DEBUG
  108. fprintf(stderr,CGETS(31, 3, "Found %s in %s.\n"), name, termfile);
  109. sleep(1);
  110. #endif /* DEBUG */
  111. return(1);
  112. }
  113. }
  114. }
  115. /* If we get here, then we haven't found a match. */
  116. fclose(fp);
  117. #ifdef DEBUG
  118. fprintf(stderr,CGETS(31, 4, "No match found for %s in file %s\n"),
  119. name, termfile);
  120. sleep(1);
  121. #endif /* DEBUG */
  122. return(0);
  123. #endif /* ANDROID */
  124. }
  125. /*
  126. * tgetnum - get the numeric terminal capability corresponding
  127. * to id. Returns the value, -1 if invalid.
  128. */
  129. int
  130. tgetnum(char *id)
  131. {
  132. char *cp;
  133. int ret;
  134. if ((cp = capab) == NULL || id == NULL)
  135. return(-1);
  136. while (*++cp != ':')
  137. ;
  138. for (++cp ; *cp ; cp++) {
  139. while (ISSPACE(*cp))
  140. cp++;
  141. if (strncmp(cp, id, CAPABLEN) == 0) {
  142. while (*cp && *cp != ':' && *cp != '#')
  143. cp++;
  144. if (*cp != '#')
  145. return(-1);
  146. for (ret = 0, cp++ ; *cp && ISDIGIT(*cp) ; cp++)
  147. ret = ret * 10 + *cp - '0';
  148. return(ret);
  149. }
  150. while (*cp && *cp != ':')
  151. cp++;
  152. }
  153. return(-1);
  154. }
  155. /*
  156. * tgetflag - get the boolean flag corresponding to id. Returns -1
  157. * if invalid, 0 if the flag is not in termcap entry, or 1 if it is
  158. * present.
  159. */
  160. int
  161. tgetflag(char *id)
  162. {
  163. char *cp;
  164. if ((cp = capab) == NULL || id == NULL)
  165. return(-1);
  166. while (*++cp != ':')
  167. ;
  168. for (++cp ; *cp ; cp++) {
  169. while (ISSPACE(*cp))
  170. cp++;
  171. if (strncmp(cp, id, CAPABLEN) == 0)
  172. return(1);
  173. while (*cp && *cp != ':')
  174. cp++;
  175. }
  176. return(0);
  177. }
  178. /*
  179. * tgetstr - get the string capability corresponding to id and place
  180. * it in area (advancing area at same time). Expand escape sequences
  181. * etc. Returns the string, or NULL if it can't do it.
  182. */
  183. char *
  184. tgetstr(char *id, char **area)
  185. {
  186. char *cp;
  187. char *ret;
  188. int i;
  189. if ((cp = capab) == NULL || id == NULL)
  190. return(NULL);
  191. while (*++cp != ':')
  192. ;
  193. for (++cp ; *cp ; cp++) {
  194. while (ISSPACE(*cp))
  195. cp++;
  196. if (strncmp(cp, id, CAPABLEN) == 0) {
  197. while (*cp && *cp != ':' && *cp != '=')
  198. cp++;
  199. if (*cp != '=')
  200. return(NULL);
  201. for (ret = *area, cp++; *cp && *cp != ':' ;
  202. (*area)++, cp++)
  203. switch(*cp) {
  204. case '^' :
  205. **area = *++cp - '@'; /* fix (efth)*/
  206. break;
  207. case '\\' :
  208. switch(*++cp) {
  209. case 'E' :
  210. **area = CTL_ESC('\033');
  211. break;
  212. case 'n' :
  213. **area = '\n';
  214. break;
  215. case 'r' :
  216. **area = '\r';
  217. break;
  218. case 't' :
  219. **area = '\t';
  220. break;
  221. case 'b' :
  222. **area = '\b';
  223. break;
  224. case 'f' :
  225. **area = '\f';
  226. break;
  227. case '0' :
  228. case '1' :
  229. case '2' :
  230. case '3' :
  231. for (i=0 ; *cp && ISDIGIT(*cp) ;
  232. cp++)
  233. i = i * 8 + *cp - '0';
  234. **area = i;
  235. cp--;
  236. break;
  237. case '^' :
  238. case '\\' :
  239. **area = *cp;
  240. break;
  241. }
  242. break;
  243. default :
  244. **area = *cp;
  245. }
  246. *(*area)++ = '\0';
  247. return(ret);
  248. }
  249. while (*cp && *cp != ':')
  250. cp++;
  251. }
  252. return(NULL);
  253. }
  254. /*
  255. * tgoto - given the cursor motion string cm, make up the string
  256. * for the cursor to go to (destcol, destline), and return the string.
  257. * Returns "OOPS" if something's gone wrong, or the string otherwise.
  258. */
  259. char *
  260. tgoto(char *cm, int destcol, int destline)
  261. {
  262. char *rp;
  263. static char ret[24];
  264. int incr = 0;
  265. int argno = 0, numval;
  266. for (rp = ret ; *cm ; cm++) {
  267. switch(*cm) {
  268. case '%' :
  269. switch(*++cm) {
  270. case '+' :
  271. numval = (argno == 0 ? destline : destcol);
  272. argno = 1 - argno;
  273. *rp++ = numval + incr + *++cm;
  274. break;
  275. case '%' :
  276. *rp++ = '%';
  277. break;
  278. case 'i' :
  279. incr = 1;
  280. break;
  281. case 'd' :
  282. numval = (argno == 0 ? destline : destcol);
  283. numval += incr;
  284. argno = 1 - argno;
  285. *rp++ = '0' + (numval/10);
  286. *rp++ = '0' + (numval%10);
  287. break;
  288. case 'r' :
  289. argno = 1;
  290. break;
  291. }
  292. break;
  293. default :
  294. *rp++ = *cm;
  295. }
  296. }
  297. *rp = '\0';
  298. return(ret);
  299. }
  300. /*
  301. * tputs - put the string cp out onto the terminal, using the function
  302. * outc. This should do padding for the terminal, but I can't find a
  303. * terminal that needs padding at the moment...
  304. */
  305. int
  306. tputs(char *cp, int affcnt, int (*outc)())
  307. {
  308. unsigned long delay = 0;
  309. if (cp == NULL)
  310. return(1);
  311. /* do any padding interpretation - left null for MINIX just now */
  312. for (delay = 0; *cp && ISDIGIT(*cp) ; cp++)
  313. delay = delay * 10 + *cp - '0';
  314. while (*cp)
  315. (*outc)(*cp++);
  316. #ifdef _OSD_POSIX
  317. usleep(delay*100); /* strictly spoken, it should be *1000 */
  318. #endif
  319. return(1);
  320. }
  321. #endif /* _VMS_POSIX || _OSD_POSIX */