openenvutils/commandshell/shell/src/modules/termcap.c
changeset 0 2e3d3ce01487
child 1 0fdb7f6b0309
equal deleted inserted replaced
-1:000000000000 0:2e3d3ce01487
       
     1 // termcap.c - termcap manipulation through curses
       
     2 //
       
     3 // © Portions Copyright (c) Symbian Software Ltd 2007. All rights reserved.
       
     4 //
       
     5 /*
       
     6  * This file is part of zsh, the Z shell.
       
     7  *
       
     8  * Copyright (c) 1992-1997 Paul Falstad
       
     9  * All rights reserved.
       
    10  *
       
    11  * Permission is hereby granted, without written agreement and without
       
    12  * license or royalty fees, to use, copy, modify, and distribute this
       
    13  * software and to distribute modified versions of this software for any
       
    14  * purpose, provided that the above copyright notice and the following
       
    15  * two paragraphs appear in all copies of this software.
       
    16  *
       
    17  * In no event shall Paul Falstad or the Zsh Development Group be liable
       
    18  * to any party for direct, indirect, special, incidental, or consequential
       
    19  * damages arising out of the use of this software and its documentation,
       
    20  * even if Paul Falstad and the Zsh Development Group have been advised of
       
    21  * the possibility of such damage.
       
    22  *
       
    23  * Paul Falstad and the Zsh Development Group specifically disclaim any
       
    24  * warranties, including, but not limited to, the implied warranties of
       
    25  * merchantability and fitness for a particular purpose.  The software
       
    26  * provided hereunder is on an "as is" basis, and Paul Falstad and the
       
    27  * Zsh Development Group have no obligation to provide maintenance,
       
    28  * support, updates, enhancements, or modifications.
       
    29  *
       
    30  */
       
    31 
       
    32 /*
       
    33  * We need to include the zsh headers later to avoid clashes with
       
    34  * the definitions on some systems, however we need the configuration
       
    35  * file to decide whether we should avoid curses.h, which clashes
       
    36  * with several zsh constants on some systems (e.g. SunOS 4).
       
    37  */
       
    38 #include "config.h"
       
    39 
       
    40 #ifdef __SYMBIAN32__
       
    41 #include "dummy.h"
       
    42 #endif //__SYMBIAN32__
       
    43 
       
    44 #ifdef __SYMBIAN32__
       
    45 #ifdef __WINSCW__
       
    46 #pragma warn_unusedarg off
       
    47 #endif//__WINSCW__
       
    48 #endif//__SYMBIAN32__
       
    49 
       
    50 #ifdef HAVE_TGETENT
       
    51 # if defined(HAVE_CURSES_H) && defined(HAVE_TERM_H)
       
    52 #  define USES_TERM_H 1
       
    53 # else
       
    54 #  ifdef HAVE_TERMCAP_H
       
    55 #   define USES_TERMCAP_H 1
       
    56 #  endif
       
    57 # endif
       
    58 #endif
       
    59 
       
    60 #include "termcap.mdh"
       
    61 #include "termcap.pro"
       
    62 
       
    63 #ifdef __SYMBIAN32__
       
    64 #include "dummy.h"
       
    65 #endif //__SYMBIAN32__
       
    66 
       
    67 static char termcap_nam[] = "termcap";
       
    68 
       
    69 #ifdef HAVE_TGETENT
       
    70 # ifdef USES_TERM_H
       
    71 #  ifdef HAVE_TERMIO_H
       
    72 #ifndef __SYMBIAN32__
       
    73 #   include <termio.h>
       
    74 #endif//__SYMBIAN32__
       
    75 #  endif
       
    76 #  ifdef TERM_H_NEEDS_CURSES_H
       
    77 #   include <curses.h>
       
    78 #  endif
       
    79 #ifndef __SYMBIAN32__
       
    80 #  include <term.h> //is mandatory as it defines 'boolcodes', 'numcodes', 'strcodes'.
       
    81 #endif//__SYMBIAN32__
       
    82 # else
       
    83 #  ifdef USES_TERMCAP_H 
       
    84 #   include <termcap.h>
       
    85 #  endif
       
    86 # endif
       
    87 
       
    88 static Param termcap_pm;
       
    89 
       
    90 #ifndef HAVE_BOOLCODES
       
    91 static char *boolcodes[] = {
       
    92     "bw", "am", "ut", "cc", "xs", "YA", "YF", "YB", "xt", "xn", "eo",
       
    93     "gn", "hc", "HC", "km", "YC", "hs", "hl", "in", "YG", "da", "db",
       
    94     "mi", "ms", "nx", "xb", "NP", "ND", "NR", "os", "5i", "YD", "YE",
       
    95     "es", "hz", "ul", "xo", NULL};
       
    96 #endif
       
    97 
       
    98 /**/
       
    99 static int
       
   100 ztgetflag(char *s)
       
   101 {
       
   102     char **b;
       
   103 
       
   104     /* ncurses can tell if an existing boolean capability is *
       
   105      * off, but other curses variants can't, so we fudge it. *
       
   106      * This feature of ncurses appears to have gone away as  *
       
   107      * of NCURSES_MAJOR_VERSION == 5, so don't rely on it.   */
       
   108     switch (tgetflag(s)) {
       
   109     case -1:
       
   110 	break;
       
   111     case 0:
       
   112 	for (b = (char **)boolcodes; *b; ++b)
       
   113 	    if (s[0] == (*b)[0] && s[1] == (*b)[1])
       
   114 		return 0;
       
   115 	break;
       
   116     default:
       
   117 	return 1;
       
   118     }
       
   119     return -1;
       
   120 }
       
   121 
       
   122 /* echotc: output a termcap */
       
   123 
       
   124 /**/
       
   125 static int
       
   126 bin_echotc(char *name, char **argv, UNUSED(Options ops), UNUSED(int func))
       
   127 {
       
   128     char *s, buf[2048], *t, *u;
       
   129     int num, argct;
       
   130 
       
   131     s = *argv++;
       
   132     if (termflags & TERM_BAD)
       
   133 	return 1;
       
   134     if ((termflags & TERM_UNKNOWN) && (isset(INTERACTIVE) || !init_term()))
       
   135 	return 1;
       
   136     /* if the specified termcap has a numeric value, display it */
       
   137     if ((num = tgetnum(s)) != -1) {
       
   138 	printf("%d\n", num);
       
   139 	return 0;
       
   140     }
       
   141     /* if the specified termcap is boolean, and set, say so  */
       
   142     switch (ztgetflag(s)) {
       
   143     case -1:
       
   144 	break;
       
   145     case 0:
       
   146 	puts("no");
       
   147 	return 0;
       
   148     default:
       
   149 	puts("yes");
       
   150 	return 0;
       
   151     }
       
   152     /* get a string-type capability */
       
   153     u = buf;
       
   154     t = (char*)tgetstr(s, &u);
       
   155     if (t == (char *)-1 || !t || !*t) {
       
   156 	/* capability doesn't exist, or (if boolean) is off */
       
   157 	zwarnnam(name, "no such capability: %s", s, 0);
       
   158 	return 1;
       
   159     }
       
   160     /* count the number of arguments required */
       
   161     for (argct = 0, u = t; *u; u++)
       
   162 	if (*u == '%') {
       
   163 	    if (u++, (*u == 'd' || *u == '2' || *u == '3' || *u == '.' ||
       
   164 		      *u == '+'))
       
   165 		argct++;
       
   166 	}
       
   167     /* check that the number of arguments provided is correct */
       
   168     if (arrlen(argv) != argct) {
       
   169 	zwarnnam(name, (arrlen(argv) < argct) ? "not enough arguments" :
       
   170 		 "too many arguments", NULL, 0);
       
   171 	return 1;
       
   172     }
       
   173     /* output string, through the proper termcap functions */
       
   174     if (!argct)
       
   175 	tputs(t, 1, putraw);
       
   176     else {
       
   177 	num = (argv[1]) ? atoi(argv[1]) : atoi(*argv);
       
   178 	tputs(tgoto(t, atoi(*argv), num), num, putraw);
       
   179     }
       
   180     return 0;
       
   181 }
       
   182 
       
   183 #else /* ! HAVE_TGETENT */
       
   184 
       
   185 #define bin_echotc bin_notavail
       
   186 
       
   187 #endif /* HAVE_TGETENT */
       
   188 
       
   189 static struct builtin bintab[] = {
       
   190     BUILTIN("echotc", 0, bin_echotc, 1, -1, 0, NULL, NULL),
       
   191 };
       
   192 
       
   193 /**/
       
   194 #ifdef HAVE_TGETENT
       
   195 
       
   196 /* Empty dummy function for special hash parameters. */
       
   197 
       
   198 /**/
       
   199 static void
       
   200 shempty(void)
       
   201 {
       
   202 }
       
   203 
       
   204 /* Create a simple special hash parameter. */
       
   205 
       
   206 /**/
       
   207 static Param
       
   208 createtchash()
       
   209 {
       
   210     Param pm;
       
   211     HashTable ht;
       
   212 
       
   213     unsetparam(termcap_nam);
       
   214 
       
   215     if (!(pm = createparam(termcap_nam, PM_SPECIAL|PM_HIDE|PM_HIDEVAL|
       
   216 			   PM_REMOVABLE|PM_HASHED)))
       
   217 	return NULL;
       
   218 
       
   219     pm->level = pm->old ? locallevel : 0;
       
   220     pm->gsu.h = &stdhash_gsu;
       
   221     pm->u.hash = ht = newhashtable(7, termcap_nam, NULL);
       
   222 
       
   223     ht->hash        = hasher;
       
   224     ht->emptytable  = (TableFunc) shempty;
       
   225     ht->filltable   = NULL;
       
   226     ht->addnode     = (AddNodeFunc) shempty;
       
   227     ht->getnode     = ht->getnode2 = gettermcap;
       
   228     ht->removenode  = (RemoveNodeFunc) shempty;
       
   229     ht->disablenode = NULL;
       
   230     ht->enablenode  = NULL;
       
   231     ht->freenode    = (FreeNodeFunc) shempty;
       
   232     ht->printnode   = printparamnode;
       
   233     ht->scantab     = scantermcap;
       
   234 
       
   235     return (termcap_pm = pm);
       
   236 }
       
   237 
       
   238 /**/
       
   239 static HashNode
       
   240 gettermcap(UNUSED(HashTable ht), char *name)
       
   241 {
       
   242     int len, num;
       
   243     char *tcstr, buf[2048], *u;
       
   244     Param pm = NULL;
       
   245 
       
   246     /* This depends on the termcap stuff in init.c */
       
   247     if (termflags & TERM_BAD)
       
   248 	return NULL;
       
   249     if ((termflags & TERM_UNKNOWN) && (isset(INTERACTIVE) || !init_term()))
       
   250 	return NULL;
       
   251 
       
   252     unmetafy(name, &len);
       
   253 
       
   254     pm = (Param) hcalloc(sizeof(struct param));
       
   255     pm->nam = dupstring(name);
       
   256     pm->flags = PM_READONLY;
       
   257     u = buf;
       
   258 
       
   259     /* logic in the following cascade copied from echotc, above */
       
   260 
       
   261     if ((num = tgetnum(name)) != -1) {
       
   262 	pm->gsu.i = &nullsetinteger_gsu;
       
   263 	pm->u.val = num;
       
   264 	pm->flags |= PM_INTEGER;
       
   265 	return (HashNode) pm;
       
   266     }
       
   267 
       
   268     pm->gsu.s = &nullsetscalar_gsu;
       
   269     switch (ztgetflag(name)) {
       
   270     case -1:
       
   271 	break;
       
   272     case 0:
       
   273 	pm->u.str = dupstring("no");
       
   274 	pm->flags |= PM_SCALAR;
       
   275 	return (HashNode) pm;
       
   276     default:
       
   277 	pm->u.str = dupstring("yes");
       
   278 	pm->flags |= PM_SCALAR;
       
   279 	return (HashNode) pm;
       
   280     }
       
   281     if ((tcstr = (char*)tgetstr(name, &u)) != NULL && tcstr != (char *)-1)
       
   282     {
       
   283 	pm->u.str = dupstring(tcstr);
       
   284 	pm->flags |= PM_SCALAR;
       
   285     }
       
   286     else
       
   287     {
       
   288 	/* zwarn("no such capability: %s", name, 0); */
       
   289 	pm->u.str = dupstring("");
       
   290 	pm->flags |= PM_UNSET;
       
   291     }
       
   292     return (HashNode) pm;
       
   293 }
       
   294 
       
   295 /**/
       
   296 static void
       
   297 scantermcap(UNUSED(HashTable ht), ScanFunc func, int flags)
       
   298 {
       
   299     Param pm = NULL;
       
   300     int num;
       
   301     char **capcode, *tcstr, buf[2048], *u;
       
   302 
       
   303 #ifndef HAVE_NUMCODES
       
   304     static char *numcodes[] = {
       
   305 	"co", "it", "lh", "lw", "li", "lm", "sg", "ma", "Co", "pa", "MW",
       
   306 	"NC", "Nl", "pb", "vt", "ws", "Yo", "Yp", "Ya", "BT", "Yc", "Yb",
       
   307 	"Yd", "Ye", "Yf", "Yg", "Yh", "Yi", "Yk", "Yj", "Yl", "Ym", "Yn",
       
   308 	NULL};
       
   309 #endif
       
   310 
       
   311 #ifndef HAVE_STRCODES
       
   312     static char *strcodes[] = {
       
   313 	"ac", "bt", "bl", "cr", "ZA", "ZB", "ZC", "ZD", "cs", "rP", "ct",
       
   314 	"MC", "cl", "cb", "ce", "cd", "ch", "CC", "CW", "cm", "do", "ho",
       
   315 	"vi", "le", "CM", "ve", "nd", "ll", "up", "vs", "ZE", "dc", "dl",
       
   316 	"DI", "ds", "DK", "hd", "eA", "as", "SA", "mb", "md", "ti", "dm",
       
   317 	"mh", "ZF", "ZG", "im", "ZH", "ZI", "ZJ", "ZK", "ZL", "mp", "mr",
       
   318 	"mk", "ZM", "so", "ZN", "ZO", "us", "ZP", "SX", "ec", "ae", "RA",
       
   319 	"me", "te", "ed", "ZQ", "ei", "ZR", "ZS", "ZT", "ZU", "se", "ZV",
       
   320 	"ZW", "ue", "ZX", "RX", "PA", "fh", "vb", "ff", "fs", "WG", "HU",
       
   321 	"i1", "is", "i3", "if", "iP", "Ic", "Ip", "ic", "al", "ip", "K1",
       
   322 	"K3", "K2", "kb", "@1", "kB", "K4", "K5", "@2", "ka", "kC", "@3",
       
   323 	"@4", "@5", "@6", "kt", "kD", "kL", "kd", "kM", "@7", "@8", "kE",
       
   324 	"kS", "@9", "k0", "k1", "k;", "F1", "F2", "F3", "F4", "F5", "F6",
       
   325 	"F7", "F8", "F9", "k2", "FA", "FB", "FC", "FD", "FE", "FF", "FG",
       
   326 	"FH", "FI", "FJ", "k3", "FK", "FL", "FM", "FN", "FO", "FP", "FQ",
       
   327 	"FR", "FS", "FT", "k4", "FU", "FV", "FW", "FX", "FY", "FZ", "Fa",
       
   328 	"Fb", "Fc", "Fd", "k5", "Fe", "Ff", "Fg", "Fh", "Fi", "Fj", "Fk",
       
   329 	"Fl", "Fm", "Fn", "k6", "Fo", "Fp", "Fq", "Fr", "k7", "k8", "k9",
       
   330 	"@0", "%1", "kh", "kI", "kA", "kl", "kH", "%2", "%3", "%4", "%5",
       
   331 	"kN", "%6", "%7", "kP", "%8", "%9", "%0", "&1", "&2", "&3", "&4",
       
   332 	"&5", "kr", "&6", "&9", "&0", "*1", "*2", "*3", "*4", "*5", "*6",
       
   333 	"*7", "*8", "*9", "kF", "*0", "#1", "#2", "#3", "#4", "%a", "%b",
       
   334 	"%c", "%d", "%e", "%f", "kR", "%g", "%h", "%i", "%j", "!1", "!2",
       
   335 	"kT", "!3", "&7", "&8", "ku", "ke", "ks", "l0", "l1", "la", "l2",
       
   336 	"l3", "l4", "l5", "l6", "l7", "l8", "l9", "Lf", "LF", "LO", "mo",
       
   337 	"mm", "ZY", "ZZ", "Za", "Zb", "Zc", "Zd", "nw", "Ze", "oc", "op",
       
   338 	"pc", "DC", "DL", "DO", "Zf", "IC", "SF", "AL", "LE", "Zg", "RI",
       
   339 	"Zh", "SR", "UP", "Zi", "pk", "pl", "px", "pn", "ps", "pO", "pf",
       
   340 	"po", "PU", "QD", "RC", "rp", "RF", "r1", "r2", "r3", "rf", "rc",
       
   341 	"cv", "sc", "sf", "sr", "Zj", "sa", "Sb", "Zk", "Zl", "SC", "sp",
       
   342 	"Sf", "ML", "Zm", "MR", "Zn", "st", "Zo", "Zp", "wi", "Zq", "Zr",
       
   343 	"Zs", "Zt", "Zu", "Zv", "ta", "Zw", "ts", "TO", "uc", "hu", "u0",
       
   344 	"u1", "u2", "u3", "u4", "u5", "u6", "u7", "u8", "u9", "WA", "XF",
       
   345 	"XN", "Zx", "S8", "Yv", "Zz", "Xy", "Zy", "ci", "Yw", "Yx", "dv",
       
   346 	"S1", "Yy", "S2", "S4", "S3", "S5", "Gm", "Km", "Mi", "S6", "xl",
       
   347 	"RQ", "S7", "s0", "s1", "s2", "s3", "AB", "AF", "Yz", "ML", "YZ",
       
   348 	"MT", "Xh", "Xl", "Xo", "Xr", "Xt", "Xv", "sA", "sL", NULL};
       
   349 #endif
       
   350 
       
   351     pm = (Param) hcalloc(sizeof(struct param));
       
   352     u = buf;
       
   353 
       
   354     pm->flags = PM_READONLY | PM_SCALAR;
       
   355     pm->gsu.s = &nullsetscalar_gsu;
       
   356 
       
   357     for (capcode = (char **)boolcodes; *capcode; capcode++) {
       
   358 	if ((num = ztgetflag(*capcode)) != -1) {
       
   359 	    pm->u.str = num ? dupstring("yes") : dupstring("no");
       
   360 	    pm->nam = dupstring(*capcode);
       
   361 	    func((HashNode) pm, flags);
       
   362 	}
       
   363     }
       
   364 
       
   365     pm->flags = PM_READONLY | PM_INTEGER;
       
   366     pm->gsu.i = &nullsetinteger_gsu;
       
   367 
       
   368     for (capcode = (char **)numcodes; *capcode; capcode++) {
       
   369 	if ((num = tgetnum(*capcode)) != -1) {
       
   370 	    pm->u.val = num;
       
   371 	    pm->nam = dupstring(*capcode);
       
   372 	    func((HashNode) pm, flags);
       
   373 	}
       
   374     }
       
   375 
       
   376     pm->flags = PM_READONLY | PM_SCALAR;
       
   377     pm->gsu.s = &nullsetscalar_gsu;
       
   378 
       
   379     for (capcode = (char **)strcodes; *capcode; capcode++) {
       
   380 	if ((tcstr = (char *)tgetstr(*capcode,&u)) != NULL &&
       
   381 	    tcstr != (char *)-1) {
       
   382 	    pm->u.str = dupstring(tcstr);
       
   383 	    pm->nam = dupstring(*capcode);
       
   384 	    func((HashNode) pm, flags);
       
   385 	}
       
   386     }
       
   387 }
       
   388 
       
   389 /**/
       
   390 #endif /* HAVE_TGETENT */
       
   391 
       
   392 /**/
       
   393 int
       
   394 setup_(UNUSED(Module m))
       
   395 {
       
   396     return 0;
       
   397 }
       
   398 
       
   399 /**/
       
   400 int
       
   401 boot_(Module m)
       
   402 {
       
   403 #ifdef HAVE_TGETENT
       
   404 # ifdef HAVE_SETUPTERM
       
   405     setupterm((char *)0, 1, (int *)0);
       
   406 # endif
       
   407 
       
   408     if (!createtchash())
       
   409     	return 1;
       
   410 #else
       
   411     unsetparam(termcap_nam);
       
   412 #endif
       
   413     return  !addbuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
       
   414 }
       
   415 
       
   416 /**/
       
   417 int
       
   418 cleanup_(Module m)
       
   419 {
       
   420 #ifdef HAVE_TGETENT
       
   421     Param pm;
       
   422 
       
   423     if ((pm = (Param) paramtab->getnode(paramtab, termcap_nam)) &&
       
   424 	pm == termcap_pm) {
       
   425 	pm->flags &= ~PM_READONLY;
       
   426 	unsetparam_pm(pm, 0, 1);
       
   427     }
       
   428 #endif
       
   429     deletebuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab));
       
   430     return 0;
       
   431 }
       
   432 
       
   433 /**/
       
   434 int
       
   435 finish_(UNUSED(Module m))
       
   436 {
       
   437     return 0;
       
   438 }