2 * TERMCAP/TERMINFO database interface
4 * (C) 1992 Joseph H. Allen
6 * This file is part of JOE (Joe's Own Editor)
11 __RCSID("$MirOS: contrib/code/jupp/termcap.c,v 1.23 2017/12/08 02:57:18 tg Exp $");
24 unsigned char *joeterm = NULL;
26 /* Default termcap entry */
28 static const unsigned char defentry[] = "\
30 :ho=\\E[H:cm=\\E[%i%d;%dH:cV=\\E[%i%dH:\
31 :up=\\E[A:UP=\\E[%dA:DO=\\E[%dB:nd=\\E[C:RI=\\E[%dC:LE=\\E[%dD:\
32 :cd=\\E[J:ce=\\E[K:cl=\\E[H\\E[J:\
33 :so=\\E[7m:se=\\E[m:us=\\E[4m:ue=\\E[m:\
34 :mb=\\E[5m:md=\\E[1m:mh=\\E[2m:me=\\E[m:\
35 :ku=\\E[A:kd=\\E[B:kl=\\E[D:kr=\\E[C:\
36 :al=\\E[L:AL=\\E[%dL:dl=\\E[M:DL=\\E[%dM:\
37 :ic=\\E[@:IC=\\E[%d@:dc=\\E[P:DC=\\E[%dP:\
40 /* Return true if termcap line matches name */
43 match(const unsigned char *s, const unsigned char *name)
45 if (s[0] == 0 || s[0] == '#')
50 for (x = 0; s[x] == name[x] && name[x] && s[x]; ++x) ;
51 if (name[x] == 0 && (s[x] == ':' || s[x] == '|'))
53 while (s[x] != ':' && s[x] != '|' && s[x])
56 } while (s[-1] == '|');
60 /* Find termcap entry in a file */
62 static unsigned char *
63 lfind(unsigned char *s, int pos, FILE *fd, const unsigned char *name)
70 while (c = getc(fd), c == ' ' || c == '\t' || c == '#')
73 } while (c != -1 && c != '\n');
75 return s = vstrunc(s, pos);
77 s = vstrunc(s, x = pos);
80 if (c == -1 || c == '\n')
81 if (x != pos && s[x - 1] == '\\') {
83 if (!match(s + pos, name))
87 } else if (!match(s + pos, name))
98 while (c = getc(fd), c != -1)
100 if (s[x - 1] == '\\')
114 /* Lookup termcap entry in index */
117 findidx(FILE *file, const unsigned char *name)
119 unsigned char buf[80];
122 while (fgets((char *)buf, 80, file)) {
123 int x = 0, flg = 0, c, y;
126 for (y = x; buf[y] && buf[y] != ' ' && buf[y] != '\n'; ++y) ;
130 addr += ustol(buf + x, NULL, USTOL_HEX);
131 else if (!strcmp(buf + x, name))
134 } while (c && c != '\n');
141 /* Load termcap entry */
143 CAP *getcap(unsigned char *name, unsigned int baud, void (*out) (unsigned char *, unsigned char), void *outptr)
149 unsigned char *tp, *pp, *qq, *namebuf, **npbuf, *idxname;
152 if (!name && !(name = joeterm) && !(name = (unsigned char *)getenv("TERM")))
154 cap = malloc(sizeof(CAP));
155 cap->tbuf = vsmk(4096);
158 cap->paste_on = NULL;
159 cap->paste_off = NULL;
161 if (!strcmp(name, "xterm-xfree86")) {
162 cap->paste_on = "\033[?2004h";
163 cap->paste_off = "\033[?2004l";
167 cap->abuf = malloc(4096);
168 cap->abufp = cap->abuf;
169 if (tgetent((char *)cap->tbuf, (char *)name) == 1)
170 return setcap(cap, baud, out, outptr);
177 name = vsncpy(NULL, 0, sz(name));
178 cap->sort = malloc(sizeof(struct sortentry) * (sortsiz = 64));
182 tp = (unsigned char *)getenv("TERMCAP");
184 if (tp && tp[0] == '/')
185 namebuf = vsncpy(NULL, 0, sz(tp));
188 cap->tbuf = vsncpy(sv(cap->tbuf), sz(tp));
189 if ((tp = (unsigned char *)getenv("TERMPATH")))
190 namebuf = vsncpy(NULL, 0, sz(tp));
192 if ((tp = (unsigned char *)getenv("HOME"))) {
193 namebuf = vsncpy(NULL, 0, sz(tp));
194 namebuf = vsadd(namebuf, '/');
197 namebuf = vsncpy(sv(namebuf), sc(".termcap "));
199 vsscan(sz(get_JOERC), sc("\t :")) == ~0) {
200 namebuf = vsncpy(sv(namebuf), sz(get_JOERC));
201 namebuf = vsncpy(sv(namebuf), sc("termcap "));
203 namebuf = vsncpy(sv(namebuf), sc("/etc/termcap"));
207 npbuf = vawords(NULL, sv(namebuf), sc("\t :"));
213 if (match(cap->tbuf, name))
216 cap->tbuf = vstrunc(cap->tbuf, 0);
220 fprintf(stderr, "Couldn't load termcap entry. Using ansi default\n");
222 cap->tbuf = vsncpy(cap->tbuf, 0, sc(defentry));
226 idxname = vsncpy(NULL, 0, sz(npbuf[y]));
227 idxname = vsncpy(idxname, sLEN(idxname), sc(".idx"));
228 f1 = fopen((char *)(npbuf[y]), "r");
232 f = fopen((char *)idxname, "r");
234 struct stat buf, buf1;
236 fstat(fileno(f), &buf);
237 fstat(fileno(f1), &buf1);
238 if (buf.st_mtime > buf1.st_mtime)
239 idx = findidx(f, name);
241 fprintf(stderr, "%s is out of date\n", idxname);
249 fseek(f1, (long)idx, 0);
251 cap->tbuf = lfind(cap->tbuf, ti, f1, name);
253 if (sLEN(cap->tbuf) == ti)
260 while (x && cap->tbuf[--x] != ':')
262 } while (x && (!cap->tbuf[x + 1] || cap->tbuf[x + 1] == ':'));
264 if (cap->tbuf[x + 1] == 't' && cap->tbuf[x + 2] == 'c' && cap->tbuf[x + 3] == '=') {
265 name = vsncpy(NULL, 0, sz(cap->tbuf + x + 4));
267 cap->tbuf[x + 1] = 0;
269 sLen(cap->tbuf) = x + 1;
278 /* Process line at pp */
281 while (*pp && *pp != ':')
288 if (pp[0] == ' ' || pp[0] == '\t')
290 for (q = 0; pp[q] && pp[q] != '#' && pp[q] != '=' && pp[q] != '@' && pp[q] != ':'; ++q) ;
304 while (z != (x + y) / 2) {
308 found = strcmp(qq, cap->sort[z].name);
311 } else if(found < 0) {
315 mmove(cap->sort + z, cap->sort + z + 1, (cap->sortlen-- - (z + 1)) * sizeof(struct sortentry));
317 else if (c && c != ':')
318 cap->sort[z].value = qq + q + 1;
320 cap->sort[z].value = NULL;
328 if (cap->sortlen == sortsiz)
329 cap->sort = realloc(cap->sort, (sortsiz += 32) * sizeof(struct sortentry));
330 mmove(cap->sort + y + 1, cap->sort + y, (cap->sortlen++ - y) * sizeof(struct sortentry));
332 cap->sort[y].name = qq;
334 cap->sort[y].value = qq + q + 1;
336 cap->sort[y].value = NULL;
345 if (!cap->tbuf[ti - 1])
353 cap->pad = jgetstr(cap, UC "pc");
359 /* show sorted entries
360 for(x=0;x!=cap->sortlen;++x)
361 printf("%s = %s\n",cap->sort[x].name,cap->sort[x].value);
363 return setcap(cap, baud, out, outptr);
366 static struct sortentry *
367 findcap(CAP *cap, const unsigned char *name)
375 while (z != (x + y) / 2) {
377 found = strcmp(name, cap->sort[z].name);
383 return cap->sort + z;
388 CAP *setcap(CAP *cap, unsigned int baud, void (*out) (unsigned char *, unsigned char), void *outptr)
391 cap->div = 100000 / baud;
393 cap->outptr = outptr;
398 getflag(CAP *cap, const unsigned char *name)
402 return tgetflag((char *)name);
404 return findcap(cap, name) != NULL;
407 const unsigned char *
408 jgetstr(CAP *cap, const unsigned char *name)
414 return (const unsigned char *)tgetstr((char *)name,
415 (char **)&cap->abufp);
417 s = findcap(cap, name);
425 getnum(CAP *cap, const unsigned char *name)
431 return tgetnum((char *)name);
433 s = findcap(cap, name);
435 return atoi((const char *)(s->value));
450 escape(const unsigned char **s)
452 unsigned char c = *(*s)++;
457 return 037 & *(*s)++;
462 else if (c == '\\' && **s)
463 switch (c = *((*s)++)) {
473 *s += ustoc_oct(*s, &i, USTOC_MAX);
499 static int outout(int c)
501 outcap->out(outcap->outptr, c);
502 return(c); /* act like putchar() - return written char */
507 texec(CAP *cap, const unsigned char *s, int l, int a0, int a1, int a2, int a3)
514 /* Do nothing if there is no string */
523 aa = (unsigned char *)tgoto((const char *)s, a1, a0);
524 tputs((char *)aa, l, outout);
529 /* Copy args into array (yuk) */
535 /* Get tenths of MS of padding needed */
536 while (*s >= '0' && *s <= '9')
537 tenth = tenth * 10 + *s++ - '0';
544 /* Check if we have to multiply by number of lines */
551 while ((c = *s++) != '\0')
552 if (c == '%' && *s) {
553 switch (x = a[0], c = escape(&s)) {
556 cap->out(cap->outptr, x / 96);
565 cap->out(cap->outptr, x);
582 cap->out(cap->outptr, c);
589 cap->out(cap->outptr, c);
590 one:cap->out(cap->outptr, '0' + x);
647 a[0] = a[0] - 2 * (a[0] & 15);
650 a[0] = 16 * (a[0] / 10) + a[0] % 10;
653 if (a[0] > escape(&s))
659 cap->out(cap->outptr, '%');
660 cap->out(cap->outptr, c);
664 cap->out(cap->outptr, escape(&s));
667 /* Output padding characters */
668 if (cap->dopadding) {
670 while (tenth >= cap->div)
671 for (s = cap->pad; *s; ++s) {
672 cap->out(cap->outptr, *s);
676 while (tenth >= cap->div) {
677 cap->out(cap->outptr, 0);
685 static void cst(unsigned char *ptr, unsigned char c)
690 int tcost(CAP *cap, const unsigned char *s, int l, int a0, int a1, int a2, int a3)
692 void (*out)(unsigned char *, unsigned char) = cap->out;
698 texec(cap, s, l, a0, a1, a2, a3);
703 static unsigned char *ssp;
704 static void cpl(unsigned char *ptr, unsigned char c)
710 tcompile(CAP *cap, const unsigned char *s, int a0, int a1, int a2, int a3)
712 void (*out) (unsigned char *, unsigned char) = cap->out;
713 int divider = cap->div;
720 texec(cap, s, 0, a0, a1, a2, a3);