1 /* $MirOS: contrib/code/jupp/termcap.c,v 1.12 2017/01/11 22:41:19 tg Exp $ */
3 * TERMCAP/TERMINFO database interface
5 * (C) 1992 Joseph H. Allen
7 * This file is part of JOE (Joe's Own Editor)
13 #ifdef HAVE_SYS_TYPES_H
14 #include <sys/types.h>
16 #ifdef HAVE_SYS_STAT_H
35 unsigned char *joeterm = NULL;
37 /* Default termcap entry */
39 static const unsigned char defentry[] = "\
41 :ho=\\E[H:cm=\\E[%i%d;%dH:cV=\\E[%i%dH:\
42 :up=\\E[A:UP=\\E[%dA:DO=\\E[%dB:nd=\\E[C:RI=\\E[%dC:LE=\\E[%dD:\
43 :cd=\\E[J:ce=\\E[K:cl=\\E[H\\E[J:\
44 :so=\\E[7m:se=\\E[m:us=\\E[4m:ue=\\E[m:\
45 :mb=\\E[5m:md=\\E[1m:mh=\\E[2m:me=\\E[m:\
46 :ku=\\E[A:kd=\\E[B:kl=\\E[D:kr=\\E[C:\
47 :al=\\E[L:AL=\\E[%dL:dl=\\E[M:DL=\\E[%dM:\
48 :ic=\\E[@:IC=\\E[%d@:dc=\\E[P:DC=\\E[%dP:\
51 /* Return true if termcap line matches name */
53 static int match(unsigned char *s, unsigned char *name)
55 if (s[0] == 0 || s[0] == '#')
60 for (x = 0; s[x] == name[x] && name[x] && s[x]; ++x) ;
61 if (name[x] == 0 && (s[x] == ':' || s[x] == '|'))
63 while (s[x] != ':' && s[x] != '|' && s[x])
66 } while (s[-1] == '|');
70 /* Find termcap entry in a file */
72 static unsigned char *lfind(unsigned char *s, int pos, FILE *fd, unsigned char *name)
79 while (c = getc(fd), c == ' ' || c == '\t' || c == '#')
82 } while (!(c == -1 || c == '\n'));
84 return s = vstrunc(s, pos);
86 s = vstrunc(s, x = pos);
89 if (c == -1 || c == '\n')
90 if (x != pos && s[x - 1] == '\\') {
92 if (!match(s + pos, name))
96 } else if (!match(s + pos, name))
107 while (c = getc(fd), c != -1)
109 if (s[x - 1] == '\\')
123 /* Lookup termcap entry in index */
125 static off_t findidx(FILE *file, unsigned char *name)
127 unsigned char buf[80];
130 while (fgets((char *)buf, 80, file)) {
131 int x = 0, flg = 0, c, y, z;
134 for (y = x; buf[y] && buf[y] != ' ' && buf[y] != '\n'; ++y) ;
137 if (c == '\n' || !c) {
139 sscanf((char *)(buf + x), "%x", &z);
141 } else if (!strcmp(buf + x, name))
144 } while (c && c != '\n');
151 /* Load termcap entry */
153 CAP *getcap(unsigned char *name, unsigned int baud, void (*out) (unsigned char *, unsigned char), void *outptr)
159 unsigned char *tp, *pp, *qq, *namebuf, **npbuf, *idxname;
162 if (!name && !(name = joeterm) && !(name = (unsigned char *)getenv("TERM")))
164 cap = (CAP *) joe_malloc(sizeof(CAP));
165 cap->tbuf = vsmk(4096);
168 cap->paste_on = NULL;
169 cap->paste_off = NULL;
171 if (!strcmp(name, "xterm-xfree86")) {
172 cap->paste_on = "\033[?2004h";
173 cap->paste_off = "\033[?2004l";
177 cap->abuf = (unsigned char *) joe_malloc(4096);
178 cap->abufp = cap->abuf;
179 if (tgetent((char *)cap->tbuf, (char *)name) == 1)
180 return setcap(cap, baud, out, outptr);
187 name = vsncpy(NULL, 0, sz(name));
188 cap->sort = (struct sortentry *) joe_malloc(sizeof(struct sortentry) * (sortsiz = 64));
192 tp = (unsigned char *)getenv("TERMCAP");
194 if (tp && tp[0] == '/')
195 namebuf = vsncpy(NULL, 0, sz(tp));
198 cap->tbuf = vsncpy(sv(cap->tbuf), sz(tp));
199 if ((tp = (unsigned char *)getenv("TERMPATH")))
200 namebuf = vsncpy(NULL, 0, sz(tp));
202 if ((tp = (unsigned char *)getenv("HOME"))) {
203 namebuf = vsncpy(NULL, 0, sz(tp));
204 namebuf = vsadd(namebuf, '/');
207 namebuf = vsncpy(sv(namebuf), sc(".termcap "));
209 vsscan(sz(get_JOERC), sc("\t :")) == ~0) {
210 namebuf = vsncpy(sv(namebuf), sz(get_JOERC));
211 namebuf = vsncpy(sv(namebuf), sc("termcap "));
213 namebuf = vsncpy(sv(namebuf), sc("/etc/termcap"));
217 npbuf = vawords(NULL, sv(namebuf), sc("\t :"));
223 if (match(cap->tbuf, name))
226 cap->tbuf = vstrunc(cap->tbuf, 0);
238 fprintf(stderr, "Couldn't load termcap entry. Using ansi default\n");
240 cap->tbuf = vsncpy(cap->tbuf, 0, sc(defentry));
244 idxname = vsncpy(NULL, 0, sz(npbuf[y]));
245 idxname = vsncpy(idxname, sLEN(idxname), sc(".idx"));
246 f1 = fopen((char *)(npbuf[y]), "r");
250 f = fopen((char *)idxname, "r");
252 struct stat buf, buf1;
254 fstat(fileno(f), &buf);
255 fstat(fileno(f1), &buf1);
256 if (buf.st_mtime > buf1.st_mtime)
257 idx = findidx(f, name);
259 fprintf(stderr, "%s is out of date\n", idxname);
267 fseek(f1, (long)idx, 0);
269 cap->tbuf = lfind(cap->tbuf, ti, f1, name);
271 if (sLEN(cap->tbuf) == ti)
278 while (x && cap->tbuf[--x] != ':')
280 } while (x && (!cap->tbuf[x + 1] || cap->tbuf[x + 1] == ':'));
282 if (cap->tbuf[x + 1] == 't' && cap->tbuf[x + 2] == 'c' && cap->tbuf[x + 3] == '=') {
283 name = vsncpy(NULL, 0, sz(cap->tbuf + x + 4));
285 cap->tbuf[x + 1] = 0;
287 sLen(cap->tbuf) = x + 1;
296 /* Process line at pp */
299 while (*pp && *pp != ':')
306 if (pp[0] == ' ' || pp[0] == '\t')
308 for (q = 0; pp[q] && pp[q] != '#' && pp[q] != '=' && pp[q] != '@' && pp[q] != ':'; ++q) ;
321 /* dead store: z = 0; */
324 while (z != (x + y) / 2) {
328 found = strcmp(qq, cap->sort[z].name);
331 } else if(found < 0) {
335 mmove(cap->sort + z, cap->sort + z + 1, (cap->sortlen-- - (z + 1)) * sizeof(struct sortentry));
337 else if (c && c != ':')
338 cap->sort[z].value = qq + q + 1;
340 cap->sort[z].value = NULL;
348 if (cap->sortlen == sortsiz)
349 cap->sort = (struct sortentry *) joe_realloc(cap->sort, (sortsiz += 32) * sizeof(struct sortentry));
350 mmove(cap->sort + y + 1, cap->sort + y, (cap->sortlen++ - y) * sizeof(struct sortentry));
352 cap->sort[y].name = qq;
354 cap->sort[y].value = qq + q + 1;
356 cap->sort[y].value = NULL;
365 if (!cap->tbuf[ti - 1])
373 cap->pad = jgetstr(cap, US "pc");
379 /* show sorted entries
380 for(x=0;x!=cap->sortlen;++x)
381 printf("%s = %s\n",cap->sort[x].name,cap->sort[x].value);
383 return setcap(cap, baud, out, outptr);
386 static struct sortentry *findcap(CAP *cap, unsigned char *name)
394 while (z != (x + y) / 2) {
396 found = strcmp(name, cap->sort[z].name);
402 return cap->sort + z;
407 CAP *setcap(CAP *cap, unsigned int baud, void (*out) (unsigned char *, unsigned char), void *outptr)
410 cap->div = 100000 / baud;
412 cap->outptr = outptr;
416 int getflag(CAP *cap, unsigned char *name)
420 return tgetflag((char *)name);
422 return findcap(cap, name) != NULL;
425 unsigned char *jgetstr(CAP *cap, unsigned char *name)
431 return (unsigned char *)tgetstr((char *)name, (char **)&cap->abufp);
433 s = findcap(cap, name);
440 int getnum(CAP *cap, unsigned char *name)
446 return tgetnum((char *)name);
448 s = findcap(cap, name);
450 return atoi((char *)(s->value));
464 static unsigned char escape(unsigned char **s)
466 unsigned char c = *(*s)++;
470 return 037 & *(*s)++;
475 else if (c == '\\' && **s)
476 switch (c = *((*s)++)) {
486 if (**s >= '0' && **s <= '7')
487 c = (c << 3) + *((*s)++) - '0';
488 if (**s >= '0' && **s <= '7')
489 c = (c << 3) + *((*s)++) - '0';
515 static int outout(int c)
517 outcap->out(outcap->outptr, c);
518 return(c); /* act like putchar() - return written char */
522 void texec(CAP *cap, unsigned char *s, int l, int a0, int a1, int a2, int a3)
529 /* Do nothing if there is no string */
538 aa = (unsigned char *)tgoto((char *)s, a1, a0);
539 tputs((char *)aa, l, outout);
544 /* Copy args into array (yuk) */
550 /* Get tenths of MS of padding needed */
551 while (*s >= '0' && *s <= '9')
552 tenth = tenth * 10 + *s++ - '0';
559 /* Check if we have to multiply by number of lines */
566 while ((c = *s++) != '\0')
567 if (c == '%' && *s) {
568 switch (x = a[0], c = escape(&s)) {
571 cap->out(cap->outptr, x / 96);
580 cap->out(cap->outptr, x);
595 cap->out(cap->outptr, c);
602 cap->out(cap->outptr, c);
603 one:cap->out(cap->outptr, '0' + x);
660 a[0] = a[0] - 2 * (a[0] & 15);
663 a[0] = 16 * (a[0] / 10) + a[0] % 10;
666 if (a[0] > escape(&s))
672 cap->out(cap->outptr, '%');
673 cap->out(cap->outptr, c);
677 cap->out(cap->outptr, escape(&s));
680 /* Output padding characters */
681 if (cap->dopadding) {
683 while (tenth >= cap->div)
684 for (s = cap->pad; *s; ++s) {
685 cap->out(cap->outptr, *s);
689 while (tenth >= cap->div) {
690 cap->out(cap->outptr, 0);
698 static void cst(unsigned char *ptr, unsigned char c)
703 int tcost(CAP *cap, unsigned char *s, int l, int a0, int a1, int a2, int a3)
705 void (*out) (unsigned char *, unsigned char) = cap->out;
711 texec(cap, s, l, a0, a1, a2, a3);
716 static unsigned char *ssp;
717 static void cpl(unsigned char *ptr, unsigned char c)
722 unsigned char *tcompile(CAP *cap, unsigned char *s, int a0, int a1, int a2, int a3)
724 void (*out) (unsigned char *, unsigned char) = cap->out;
725 int divider = cap->div;
732 texec(cap, s, 0, a0, a1, a2, a3);