home *** CD-ROM | disk | FTP | other *** search
- /* tput -- shell-level interface to terminfo, emulated by termcap.
- Copyright (C) 1989 Free Software Foundation, Inc.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
-
- /* Usage: tput [-T termtype] [+terminal=termtype] capability [parameter...]
-
- Options:
- -T termtype
- +terminal=termtype Override $TERM.
-
- Link with -ltermcap.
- Requires the GNU termcap library.
- Also requires the bsearch library function.
-
- David MacKenzie <djm@ai.mit.edu> */
-
- #include <stdio.h>
- #include <signal.h>
- #include <sgtty.h>
- #include <termcap.h>
- #include <getopt.h>
- #include "tput.h"
-
- #ifndef SIGTYPE
- #define SIGTYPE void
- #endif
-
- /* Exit codes. */
- #define CAP_PRESENT 0 /* Normal operation. */
- #define BOOLEAN_FALSE 1 /* Boolean capability not present. */
- #define USAGE_ERROR 2 /* Invalid arguments given. */
- #define UNKNOWN_TERM 3 /* $TERM not found in termcap file. */
- #define MISSING_CAP 4 /* Termcap entry lacks this capability. */
- #define ERROR_EXIT 5 /* Real error or signal. */
-
- char *bsearch ();
- char *getenv ();
-
- int info_compare ();
- SIGTYPE signal_handler ();
- int tcputchar ();
- struct conversion *find_info ();
- void put_bool ();
- void put_num ();
- void put_str ();
- void restore_translations ();
- void translations_off ();
- void setup_termcap ();
- void usage ();
-
- /* The name this program was run with, for error messages. */
- char *program_name;
-
- struct option long_options[] =
- {
- {"terminal", 1, NULL, 0},
- {NULL, 0, NULL, 0}
- };
-
- void
- main (argc, argv)
- int argc;
- char **argv;
- {
- struct conversion *conv; /* Conversion table entry. */
- char *term; /* Terminal type. */
- int c; /* Option character. */
-
- program_name = argv[0];
- term = getenv ("TERM");
-
- while ((c = getopt_long (argc, argv, "T:", long_options, (int *) 0)) != EOF)
- {
- switch (c)
- {
- case 0:
- break;
-
- case 'T':
- term = optarg;
- break;
-
- default:
- usage ();
- }
- }
-
- if (optind == argc)
- usage ();
-
- setup_termcap (term);
-
- conv = find_info (argv[optind]);
- if (conv == NULL)
- {
- fprintf (stderr, "%s: Unknown terminfo capability `%s'\n",
- program_name, argv[optind]);
- exit (MISSING_CAP);
- }
-
- ++optind;
-
- if (conv->type & NUM)
- put_num (conv);
- else if (conv->type & BOOL)
- put_bool (conv);
- else
- put_str (conv, argv, argc);
-
- exit (CAP_PRESENT);
- }
-
- /* Return a pointer to the conversion table entry for terminfo
- capability INFONAME.
- Return NULL if INFONAME is not a valid terminfo capability. */
-
- struct conversion *
- find_info (infoname)
- char *infoname;
- {
- struct conversion conv;
-
- conv.info = infoname;
- return (struct conversion *)
- bsearch ((char *) &conv, (char *) conversions, CAPABILITIES,
- sizeof (struct conversion), info_compare);
- }
-
- /* Terminfo capability name comparison function for bsearch. */
-
- int
- info_compare (conv1, conv2)
- struct conversion *conv1, *conv2;
- {
- return strcmp (conv1->info, conv2->info);
- }
-
- void
- put_num (conv)
- struct conversion *conv;
- {
- printf ("%d\n", tgetnum (conv->cap));
- }
-
- void
- put_bool (conv)
- struct conversion *conv;
- {
- if (!tgetflag (conv->cap))
- exit (BOOLEAN_FALSE);
- }
-
- void
- put_str (conv, argv, argc)
- struct conversion *conv;
- char **argv;
- int argc;
- {
- char *string_value; /* String capability. */
- int lines_affected; /* Number of lines affected by capability. */
-
- string_value = tgetstr (conv->cap, (char **) NULL);
- if (string_value == NULL)
- exit (MISSING_CAP);
-
- if (!strcmp (conv->cap, "cm"))
- {
- BC = tgetstr ("le", (char **) NULL);
- UP = tgetstr ("up", (char **) NULL);
-
- /* The order of command-line arguments is `vertical horizontal'.
- If horizontal is not given, it defaults to 0. */
- switch (argc - optind)
- {
- case 0:
- break;
- case 1:
- string_value = tgoto (string_value, 0, atoi (argv[optind]));
- break;
- default:
- string_value = tgoto (string_value,
- atoi (argv[optind + 1]), atoi (argv[optind]));
- break;
- }
- }
- else
- /* Although the terminfo `sgr' capability can take 9 parameters,
- the GNU tparam function only accepts up to 4.
- I don't know whether tparam could interpret an `sgr'
- capability reasonably even if it could accept that many
- parameters. For now, we'll live with the 4-parameter limit. */
- switch (argc - optind)
- {
- case 0:
- break;
- case 1:
- string_value = tparam (string_value, (char *) NULL, 0,
- atoi (argv[optind]));
- break;
- case 2:
- string_value = tparam (string_value, (char *) NULL, 0,
- atoi (argv[optind]),
- atoi (argv[optind + 1]));
- break;
- case 3:
- string_value = tparam (string_value, (char *) NULL, 0,
- atoi (argv[optind]),
- atoi (argv[optind + 1]),
- atoi (argv[optind + 2]));
- break;
- default:
- string_value = tparam (string_value, (char *) NULL, 0,
- atoi (argv[optind]),
- atoi (argv[optind + 1]),
- atoi (argv[optind + 2]),
- atoi (argv[optind + 3]));
- break;
- }
-
- /* Since we don't know where the cursor is, we have to be
- pessimistic for capabilities that need padding proportional to
- the number of lines affected, and tell them that the whole
- screen is affected. */
- if (conv->type & PAD)
- lines_affected = tgetnum ("li");
- else
- lines_affected = 1;
-
- if (lines_affected < 1)
- lines_affected = 1;
-
- translations_off ();
- tputs (string_value, lines_affected, tcputchar);
- fflush (stdout);
- restore_translations ();
- }
-
- /* Output function for tputs. */
-
- int
- tcputchar (c)
- char c;
- {
- putchar (c & 0x7f);
- return c;
- }
-
- /* Read in the needed termcap strings for terminal type TERM. */
-
- void
- setup_termcap (term)
- char *term;
- {
- char *tc_pc; /* "pc" termcap string. */
-
- if (term == NULL)
- {
- fprintf (stderr, "%s: No value for $TERM and no -T specified\n",
- program_name);
- exit (UNKNOWN_TERM);
- }
- switch (tgetent ((char *) NULL, term))
- {
- case 0:
- fprintf (stderr, "%s: Unknown terminal type `%s'\n", program_name, term);
- exit (UNKNOWN_TERM);
- case -1:
- fprintf (stderr, "%s: No termcap database\n", program_name);
- exit (UNKNOWN_TERM);
- }
-
- tc_pc = tgetstr ("pc", (char **) NULL);
- PC = tc_pc ? *tc_pc : 0;
- }
-
- struct sgttyb old_modes, new_modes;
-
- /* Turn off expansion of tabs into spaces, saving the old
- terminal settings first.
- Also set OSPEED. */
-
- void
- translations_off ()
- {
- if (isatty (1))
- {
- gtty (1, &old_modes);
-
- if (signal (SIGINT, SIG_IGN) != SIG_IGN)
- signal (SIGINT, signal_handler);
- if (signal (SIGHUP, SIG_IGN) != SIG_IGN)
- signal (SIGHUP, signal_handler);
- if (signal (SIGQUIT, SIG_IGN) != SIG_IGN)
- signal (SIGQUIT, signal_handler);
- signal (SIGTERM, signal_handler);
-
- new_modes = old_modes;
- new_modes.sg_flags &= ~XTABS;
- stty (1, &new_modes);
- ospeed = old_modes.sg_ospeed;
- }
- else
- ospeed = 0;
- }
-
- /* Restore the old terminal settings. */
-
- void
- restore_translations ()
- {
- stty (1, &old_modes);
- }
-
- SIGTYPE
- signal_handler ()
- {
- restore_translations ();
- exit (ERROR_EXIT);
- }
-
- void
- usage ()
- {
- fprintf (stderr, "\
- Usage: %s [-T termtype] [+terminal=termtype] capability [parameter...]\n",
- program_name);
- exit (USAGE_ERROR);
- }
-