tput.c revision 97049
150276Speter/****************************************************************************
297049Speter * Copyright (c) 1998,1999,2000,2001 Free Software Foundation, Inc.         *
350276Speter *                                                                          *
450276Speter * Permission is hereby granted, free of charge, to any person obtaining a  *
550276Speter * copy of this software and associated documentation files (the            *
650276Speter * "Software"), to deal in the Software without restriction, including      *
750276Speter * without limitation the rights to use, copy, modify, merge, publish,      *
850276Speter * distribute, distribute with modifications, sublicense, and/or sell       *
950276Speter * copies of the Software, and to permit persons to whom the Software is    *
1050276Speter * furnished to do so, subject to the following conditions:                 *
1150276Speter *                                                                          *
1250276Speter * The above copyright notice and this permission notice shall be included  *
1350276Speter * in all copies or substantial portions of the Software.                   *
1450276Speter *                                                                          *
1550276Speter * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
1650276Speter * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
1750276Speter * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
1850276Speter * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   *
1950276Speter * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    *
2050276Speter * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    *
2150276Speter * THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               *
2250276Speter *                                                                          *
2350276Speter * Except as contained in this notice, the name(s) of the above copyright   *
2450276Speter * holders shall not be used in advertising or otherwise to promote the     *
2550276Speter * sale, use or other dealings in this Software without prior written       *
2650276Speter * authorization.                                                           *
2750276Speter ****************************************************************************/
2850276Speter
2950276Speter/****************************************************************************
3050276Speter *  Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995               *
3150276Speter *     and: Eric S. Raymond <esr@snark.thyrsus.com>                         *
3250276Speter ****************************************************************************/
3350276Speter
3450276Speter/*
3550276Speter * tput.c -- shellscript access to terminal capabilities
3650276Speter *
3750276Speter * by Eric S. Raymond <esr@snark.thyrsus.com>, portions based on code from
3850276Speter * Ross Ridge's mytinfo package.
3950276Speter */
4050276Speter
4150276Speter#include <progs.priv.h>
4266963Speter
4366963Speter#if !PURE_TERMINFO
4450276Speter#include <termsort.c>
4550276Speter#endif
4666963Speter#include <transform.h>
4750276Speter
4897049SpeterMODULE_ID("$Id: tput.c,v 1.30 2001/07/22 00:16:33 tom Exp $")
4950276Speter
5050276Speter#define PUTS(s)		fputs(s, stdout)
5150276Speter#define PUTCHAR(c)	putchar(c)
5250276Speter#define FLUSH		fflush(stdout)
5350276Speter
5466963Spetertypedef enum {
5566963Speter    Numbers = 0
5666963Speter    ,Num_Str
5766963Speter    ,Num_Str_Str
5866963Speter} TParams;
5966963Speter
6050276Speterstatic char *prg_name;
6166963Speterstatic bool is_init = FALSE;
6266963Speterstatic bool is_reset = FALSE;
6350276Speter
6462449Speterstatic void
6562449Speterquit(int status, const char *fmt,...)
6650276Speter{
6762449Speter    va_list argp;
6850276Speter
6962449Speter    va_start(argp, fmt);
7062449Speter    vfprintf(stderr, fmt, argp);
7162449Speter    fprintf(stderr, "\n");
7262449Speter    va_end(argp);
7362449Speter    exit(status);
7450276Speter}
7550276Speter
7662449Speterstatic void
7762449Speterusage(void)
7850276Speter{
7966963Speter    fprintf(stderr, "usage: %s [-V] [-S] [-T term] capname\n", prg_name);
8062449Speter    exit(EXIT_FAILURE);
8150276Speter}
8250276Speter
8366963Speterstatic void
8466963Spetercheck_aliases(const char *name)
8566963Speter{
8666963Speter    is_init = (strcmp(name, PROG_INIT) == 0);
8766963Speter    is_reset = (strcmp(name, PROG_RESET) == 0);
8866963Speter}
8966963Speter
9066963Speter/*
9166963Speter * Lookup the type of call we should make to tparm().  This ignores the actual
9266963Speter * terminfo capability (bad, because it is not extensible), but makes this
9366963Speter * code portable to platforms where sizeof(int) != sizeof(char *).
9466963Speter *
9566963Speter * FIXME: If we want extensibility, analyze the capability string as we do
9666963Speter * in tparm() to decide how to parse the varargs list.
9766963Speter */
9866963Speterstatic TParams
9976726Spetertparm_type(const char *name)
10066963Speter{
10166963Speter#define TD(code, longname, ti, tc) {code,longname},{code,ti},{code,tc}
10266963Speter    TParams result = Numbers;
10366963Speter    /* *INDENT-OFF* */
10466963Speter    static const struct {
10566963Speter	TParams code;
10666963Speter	const char *name;
10766963Speter    } table[] = {
10866963Speter	TD(Num_Str,	"pkey_key",	"pfkey",	"pk"),
10966963Speter	TD(Num_Str,	"pkey_local",	"pfloc",	"pl"),
11066963Speter	TD(Num_Str,	"pkey_xmit",	"pfx",		"px"),
11166963Speter	TD(Num_Str,	"plab_norm",	"pln",		"pn"),
11266963Speter	TD(Num_Str_Str, "pkey_plab",	"pfxl",		"xl"),
11366963Speter    };
11466963Speter    /* *INDENT-ON* */
11566963Speter
11666963Speter    unsigned n;
11766963Speter    for (n = 0; n < SIZEOF(table); n++) {
11866963Speter	if (!strcmp(name, table[n].name)) {
11966963Speter	    result = table[n].code;
12066963Speter	    break;
12166963Speter	}
12266963Speter    }
12366963Speter    return result;
12466963Speter}
12566963Speter
12662449Speterstatic int
12762449Spetertput(int argc, char *argv[])
12850276Speter{
12962449Speter    NCURSES_CONST char *name;
13062449Speter    char *s;
13162449Speter    int i, j, c;
13266963Speter    int status;
13362449Speter    FILE *f;
13450276Speter
13597049Speter    if ((name = argv[0]) == 0)
13697049Speter	name = "";
13797049Speter    check_aliases(name);
13866963Speter    if (is_reset || is_init) {
13962449Speter	if (init_prog != 0) {
14062449Speter	    system(init_prog);
14150276Speter	}
14262449Speter	FLUSH;
14350276Speter
14466963Speter	if (is_reset && reset_1string != 0) {
14562449Speter	    PUTS(reset_1string);
14662449Speter	} else if (init_1string != 0) {
14762449Speter	    PUTS(init_1string);
14862449Speter	}
14962449Speter	FLUSH;
15050276Speter
15166963Speter	if (is_reset && reset_2string != 0) {
15262449Speter	    PUTS(reset_2string);
15362449Speter	} else if (init_2string != 0) {
15462449Speter	    PUTS(init_2string);
15562449Speter	}
15662449Speter	FLUSH;
15750276Speter
15897049Speter#ifdef set_lr_margin
15962449Speter	if (set_lr_margin != 0) {
16062449Speter	    PUTS(tparm(set_lr_margin, 0, columns - 1));
16197049Speter	} else
16297049Speter#endif
16397049Speter#ifdef set_left_margin_parm
16497049Speter	    if (set_left_margin_parm != 0
16597049Speter		&& set_right_margin_parm != 0) {
16662449Speter	    PUTS(tparm(set_left_margin_parm, 0));
16762449Speter	    PUTS(tparm(set_right_margin_parm, columns - 1));
16897049Speter	} else
16997049Speter#endif
17097049Speter	    if (clear_margins != 0
17197049Speter		&& set_left_margin != 0
17297049Speter		&& set_right_margin != 0) {
17362449Speter	    PUTS(clear_margins);
17462449Speter	    if (carriage_return != 0) {
17562449Speter		PUTS(carriage_return);
17662449Speter	    } else {
17762449Speter		PUTCHAR('\r');
17862449Speter	    }
17962449Speter	    PUTS(set_left_margin);
18062449Speter	    if (parm_right_cursor) {
18162449Speter		PUTS(tparm(parm_right_cursor, columns - 1));
18262449Speter	    } else {
18362449Speter		for (i = 0; i < columns - 1; i++) {
18462449Speter		    PUTCHAR(' ');
18550276Speter		}
18662449Speter	    }
18762449Speter	    PUTS(set_right_margin);
18862449Speter	    if (carriage_return != 0) {
18962449Speter		PUTS(carriage_return);
19062449Speter	    } else {
19162449Speter		PUTCHAR('\r');
19262449Speter	    }
19362449Speter	}
19462449Speter	FLUSH;
19550276Speter
19662449Speter	if (init_tabs != 8) {
19762449Speter	    if (clear_all_tabs != 0 && set_tab != 0) {
19862449Speter		for (i = 0; i < columns - 1; i += 8) {
19962449Speter		    if (parm_right_cursor) {
20062449Speter			PUTS(tparm(parm_right_cursor, 8));
20162449Speter		    } else {
20262449Speter			for (j = 0; j < 8; j++)
20362449Speter			    PUTCHAR(' ');
20462449Speter		    }
20562449Speter		    PUTS(set_tab);
20650276Speter		}
20750276Speter		FLUSH;
20862449Speter	    }
20962449Speter	}
21050276Speter
21166963Speter	if (is_reset && reset_file != 0) {
21262449Speter	    f = fopen(reset_file, "r");
21362449Speter	    if (f == 0) {
21462449Speter		quit(errno, "Can't open reset_file: '%s'", reset_file);
21562449Speter	    }
21662449Speter	    while ((c = fgetc(f)) != EOF) {
21762449Speter		PUTCHAR(c);
21862449Speter	    }
21962449Speter	    fclose(f);
22062449Speter	} else if (init_file != 0) {
22162449Speter	    f = fopen(init_file, "r");
22262449Speter	    if (f == 0) {
22362449Speter		quit(errno, "Can't open init_file: '%s'", init_file);
22462449Speter	    }
22562449Speter	    while ((c = fgetc(f)) != EOF) {
22662449Speter		PUTCHAR(c);
22762449Speter	    }
22862449Speter	    fclose(f);
22950276Speter	}
23062449Speter	FLUSH;
23150276Speter
23266963Speter	if (is_reset && reset_3string != 0) {
23362449Speter	    PUTS(reset_3string);
23462449Speter	} else if (init_2string != 0) {
23562449Speter	    PUTS(init_2string);
23650276Speter	}
23762449Speter	FLUSH;
23862449Speter	return 0;
23962449Speter    }
24050276Speter
24162449Speter    if (strcmp(name, "longname") == 0) {
24262449Speter	PUTS(longname());
24362449Speter	return 0;
24462449Speter    }
24566963Speter#if !PURE_TERMINFO
24662449Speter    {
24762449Speter	const struct name_table_entry *np;
24850276Speter
24962449Speter	if ((np = _nc_find_entry(name, _nc_get_hash_table(1))) != 0)
25062449Speter	    switch (np->nte_type) {
25162449Speter	    case BOOLEAN:
25262449Speter		if (bool_from_termcap[np->nte_index])
25362449Speter		    name = boolnames[np->nte_index];
25462449Speter		break;
25550276Speter
25662449Speter	    case NUMBER:
25762449Speter		if (num_from_termcap[np->nte_index])
25862449Speter		    name = numnames[np->nte_index];
25962449Speter		break;
26050276Speter
26162449Speter	    case STRING:
26262449Speter		if (str_from_termcap[np->nte_index])
26362449Speter		    name = strnames[np->nte_index];
26462449Speter		break;
26562449Speter	    }
26662449Speter    }
26750276Speter#endif
26850276Speter
26962449Speter    if ((status = tigetflag(name)) != -1) {
27062449Speter	return (status != 0);
27162449Speter    } else if ((status = tigetnum(name)) != CANCELLED_NUMERIC) {
27262449Speter	(void) printf("%d\n", status);
27362449Speter	return (0);
27462449Speter    } else if ((s = tigetstr(name)) == CANCELLED_STRING) {
27562449Speter	quit(4, "%s: unknown terminfo capability '%s'", prg_name, name);
27666963Speter    } else if (s != ABSENT_STRING) {
27762449Speter	if (argc > 1) {
27862449Speter	    int k;
27966963Speter	    int numbers[10];
28066963Speter	    char *strings[10];
28150276Speter
28262449Speter	    /* Nasty hack time. The tparm function needs to see numeric
28362449Speter	     * parameters as numbers, not as pointers to their string
28462449Speter	     * representations
28562449Speter	     */
28650276Speter
28762449Speter	    for (k = 1; k < argc; k++) {
28866963Speter		char *tmp = 0;
28966963Speter		strings[k] = argv[k];
29066963Speter		numbers[k] = strtol(argv[k], &tmp, 0);
29166963Speter		if (tmp == 0 || *tmp != 0)
29266963Speter		    numbers[k] = 0;
29362449Speter	    }
29466963Speter	    for (k = argc; k <= 9; k++) {
29566963Speter		numbers[k] = 0;
29666963Speter		strings[k] = 0;
29766963Speter	    }
29850276Speter
29966963Speter	    switch (tparm_type(name)) {
30066963Speter	    case Num_Str:
30166963Speter		s = tparm(s, numbers[1], strings[2]);
30266963Speter		break;
30366963Speter	    case Num_Str_Str:
30466963Speter		s = tparm(s, numbers[1], strings[2], strings[3]);
30566963Speter		break;
30666963Speter	    default:
30766963Speter		s = tparm(s,
30866963Speter			  numbers[1], numbers[2], numbers[3],
30966963Speter			  numbers[4], numbers[5], numbers[6],
31066963Speter			  numbers[7], numbers[8], numbers[9]);
31166963Speter		break;
31266963Speter	    }
31350276Speter	}
31462449Speter
31562449Speter	/* use putp() in order to perform padding */
31662449Speter	putp(s);
31762449Speter	return (0);
31862449Speter    }
31962449Speter    return (0);
32050276Speter}
32150276Speter
32262449Speterint
32362449Spetermain(int argc, char **argv)
32450276Speter{
32566963Speter    char *term;
32666963Speter    int errret;
32766963Speter    bool cmdline = TRUE;
32862449Speter    int c;
32962449Speter    char buf[BUFSIZ];
33062449Speter    int errors = 0;
33150276Speter
33297049Speter    check_aliases(prg_name = _nc_rootname(argv[0]));
33350276Speter
33462449Speter    term = getenv("TERM");
33550276Speter
33666963Speter    while ((c = getopt(argc, argv, "ST:V")) != EOF) {
33762449Speter	switch (c) {
33862449Speter	case 'S':
33966963Speter	    cmdline = FALSE;
34062449Speter	    break;
34162449Speter	case 'T':
34262449Speter	    use_env(FALSE);
34362449Speter	    term = optarg;
34462449Speter	    break;
34566963Speter	case 'V':
34666963Speter	    puts(curses_version());
34766963Speter	    return EXIT_SUCCESS;
34862449Speter	default:
34962449Speter	    usage();
35062449Speter	    /* NOTREACHED */
35150276Speter	}
35266963Speter    }
35350276Speter
35466963Speter    /*
35566963Speter     * Modify the argument list to omit the options we processed.
35666963Speter     */
35766963Speter    if (is_reset || is_init) {
35866963Speter	if (optind-- < argc) {
35966963Speter	    argc -= optind;
36066963Speter	    argv += optind;
36166963Speter	}
36266963Speter	argv[0] = prg_name;
36366963Speter    } else {
36466963Speter	argc -= optind;
36566963Speter	argv += optind;
36662449Speter    }
36750276Speter
36862449Speter    if (term == 0 || *term == '\0')
36962449Speter	quit(2, "No value for $TERM and no -T specified");
37050276Speter
37162449Speter    if (setupterm(term, STDOUT_FILENO, &errret) != OK && errret <= 0)
37262449Speter	quit(3, "unknown terminal \"%s\"", term);
37350276Speter
37466963Speter    if (cmdline) {
37566963Speter	if ((argc <= 0) && !is_reset && !is_init)
37666963Speter	    usage();
37762449Speter	return tput(argc, argv);
37866963Speter    }
37950276Speter
38062449Speter    while (fgets(buf, sizeof(buf), stdin) != 0) {
38162449Speter	char *argvec[16];	/* command, 9 parms, null, & slop */
38262449Speter	int argnum = 0;
38362449Speter	char *cp;
38450276Speter
38562449Speter	/* crack the argument list into a dope vector */
38662449Speter	for (cp = buf; *cp; cp++) {
38797049Speter	    if (isspace(UChar(*cp))) {
38862449Speter		*cp = '\0';
38997049Speter	    } else if (cp == buf || cp[-1] == 0) {
39062449Speter		argvec[argnum++] = cp;
39197049Speter		if (argnum >= (int) SIZEOF(argvec) - 1)
39297049Speter		    break;
39397049Speter	    }
39450276Speter	}
39562449Speter	argvec[argnum] = 0;
39650276Speter
39797049Speter	if (argnum != 0
39897049Speter	    && tput(argnum, argvec) != 0)
39962449Speter	    errors++;
40062449Speter    }
40162449Speter
40262449Speter    return errors > 0;
40350276Speter}
404