You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
342 lines
7.7 KiB
342 lines
7.7 KiB
/* 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);
|
|
}
|