1997-08-22 00:57:35 +02:00
|
|
|
|
/* terminal.c -- How to handle the physical terminal for Info. */
|
|
|
|
|
|
|
|
|
|
/* This file is part of GNU Info, a program for reading online documentation
|
|
|
|
|
stored in Info format.
|
|
|
|
|
|
|
|
|
|
This file has appeared in prior works by the Free Software Foundation;
|
|
|
|
|
thus it carries copyright dates from 1988 through 1993.
|
|
|
|
|
|
|
|
|
|
Copyright (C) 1988, 89, 90, 91, 92, 93, 96 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
|
|
|
|
|
|
Written by Brian Fox (bfox@ai.mit.edu). */
|
|
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <sys/types.h>
|
|
|
|
|
#include "terminal.h"
|
|
|
|
|
#include "termdep.h"
|
|
|
|
|
|
|
|
|
|
extern void *xmalloc (), *xrealloc ();
|
|
|
|
|
|
|
|
|
|
/* The Unix termcap interface code. */
|
|
|
|
|
|
|
|
|
|
extern int tgetnum (), tgetflag (), tgetent ();
|
|
|
|
|
extern char *tgetstr (), *tgoto ();
|
|
|
|
|
extern char *getenv ();
|
|
|
|
|
extern void tputs ();
|
|
|
|
|
|
|
|
|
|
/* Function "hooks". If you make one of these point to a function, that
|
|
|
|
|
function is called when appropriate instead of its namesake. Your
|
|
|
|
|
function is called with exactly the same arguments that were passed
|
|
|
|
|
to the namesake function. */
|
|
|
|
|
VFunction *terminal_begin_inverse_hook = (VFunction *)NULL;
|
|
|
|
|
VFunction *terminal_end_inverse_hook = (VFunction *)NULL;
|
|
|
|
|
VFunction *terminal_prep_terminal_hook = (VFunction *)NULL;
|
|
|
|
|
VFunction *terminal_unprep_terminal_hook = (VFunction *)NULL;
|
|
|
|
|
VFunction *terminal_up_line_hook = (VFunction *)NULL;
|
|
|
|
|
VFunction *terminal_down_line_hook = (VFunction *)NULL;
|
|
|
|
|
VFunction *terminal_clear_screen_hook = (VFunction *)NULL;
|
|
|
|
|
VFunction *terminal_clear_to_eol_hook = (VFunction *)NULL;
|
|
|
|
|
VFunction *terminal_get_screen_size_hook = (VFunction *)NULL;
|
|
|
|
|
VFunction *terminal_goto_xy_hook = (VFunction *)NULL;
|
|
|
|
|
VFunction *terminal_initialize_terminal_hook = (VFunction *)NULL;
|
|
|
|
|
VFunction *terminal_new_terminal_hook = (VFunction *)NULL;
|
|
|
|
|
VFunction *terminal_put_text_hook = (VFunction *)NULL;
|
|
|
|
|
VFunction *terminal_ring_bell_hook = (VFunction *)NULL;
|
|
|
|
|
VFunction *terminal_write_chars_hook = (VFunction *)NULL;
|
|
|
|
|
VFunction *terminal_scroll_terminal_hook = (VFunction *)NULL;
|
|
|
|
|
|
|
|
|
|
/* **************************************************************** */
|
|
|
|
|
/* */
|
|
|
|
|
/* Terminal and Termcap */
|
|
|
|
|
/* */
|
|
|
|
|
/* **************************************************************** */
|
|
|
|
|
|
|
|
|
|
/* On Solaris2, sys/types.h #includes sys/reg.h, which #defines PC.
|
|
|
|
|
Unfortunately, PC is a global variable used by the termcap library. */
|
|
|
|
|
#undef PC
|
|
|
|
|
|
|
|
|
|
/* TERMCAP requires these variables, whether we access them or not. */
|
|
|
|
|
char PC;
|
|
|
|
|
char *BC, *UP;
|
|
|
|
|
short ospeed;
|
|
|
|
|
|
|
|
|
|
/* A buffer which holds onto the current terminal description, and a pointer
|
|
|
|
|
used to float within it. */
|
|
|
|
|
static char *term_buffer = (char *)NULL;
|
|
|
|
|
static char *term_string_buffer = (char *)NULL;
|
|
|
|
|
|
|
|
|
|
/* Some strings to control terminal actions. These are output by tputs (). */
|
|
|
|
|
static char *term_goto, *term_clreol, *term_cr, *term_clrpag;
|
|
|
|
|
static char *term_begin_use, *term_end_use;
|
|
|
|
|
static char *term_AL, *term_DL, *term_al, *term_dl;
|
|
|
|
|
|
|
|
|
|
/* How to go up a line. */
|
|
|
|
|
static char *term_up;
|
|
|
|
|
|
|
|
|
|
/* How to go down a line. */
|
|
|
|
|
static char *term_dn;
|
|
|
|
|
|
|
|
|
|
/* An audible bell, if the terminal can be made to make noise. */
|
|
|
|
|
static char *audible_bell;
|
|
|
|
|
|
|
|
|
|
/* A visible bell, if the terminal can be made to flash the screen. */
|
|
|
|
|
static char *visible_bell;
|
|
|
|
|
|
|
|
|
|
/* The string to write to turn on the meta key, if this term has one. */
|
|
|
|
|
static char *term_mm;
|
|
|
|
|
|
|
|
|
|
/* The string to write to turn off the meta key, if this term has one. */
|
|
|
|
|
static char *term_mo;
|
|
|
|
|
|
|
|
|
|
/* The string to turn on inverse mode, if this term has one. */
|
|
|
|
|
static char *term_invbeg;
|
|
|
|
|
|
|
|
|
|
/* The string to turn off inverse mode, if this term has one. */
|
|
|
|
|
static char *term_invend;
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
output_character_function (c)
|
|
|
|
|
int c;
|
|
|
|
|
{
|
|
|
|
|
putc (c, stdout);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Macro to send STRING to the terminal. */
|
|
|
|
|
#define send_to_terminal(string) \
|
|
|
|
|
do { \
|
|
|
|
|
if (string) \
|
|
|
|
|
tputs (string, 1, output_character_function); \
|
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
|
|
/* Tell the terminal that we will be doing cursor addressable motion. */
|
|
|
|
|
static void
|
|
|
|
|
terminal_begin_using_terminal ()
|
|
|
|
|
{
|
|
|
|
|
send_to_terminal (term_begin_use);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Tell the terminal that we will not be doing any more cursor addressable
|
|
|
|
|
motion. */
|
|
|
|
|
static void
|
|
|
|
|
terminal_end_using_terminal ()
|
|
|
|
|
{
|
|
|
|
|
send_to_terminal (term_end_use);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* **************************************************************** */
|
|
|
|
|
/* */
|
|
|
|
|
/* Necessary Terminal Functions */
|
|
|
|
|
/* */
|
|
|
|
|
/* **************************************************************** */
|
|
|
|
|
|
|
|
|
|
/* The functions and variables on this page implement the user visible
|
|
|
|
|
portion of the terminal interface. */
|
|
|
|
|
|
|
|
|
|
/* The width and height of the terminal. */
|
|
|
|
|
int screenwidth, screenheight;
|
|
|
|
|
|
|
|
|
|
/* Non-zero means this terminal can't really do anything. */
|
|
|
|
|
int terminal_is_dumb_p = 0;
|
|
|
|
|
|
|
|
|
|
/* Non-zero means that this terminal has a meta key. */
|
|
|
|
|
int terminal_has_meta_p = 0;
|
|
|
|
|
|
|
|
|
|
/* Non-zero means that this terminal can produce a visible bell. */
|
|
|
|
|
int terminal_has_visible_bell_p = 0;
|
|
|
|
|
|
|
|
|
|
/* Non-zero means to use that visible bell if at all possible. */
|
|
|
|
|
int terminal_use_visible_bell_p = 0;
|
|
|
|
|
|
|
|
|
|
/* Non-zero means that the terminal can do scrolling. */
|
|
|
|
|
int terminal_can_scroll = 0;
|
|
|
|
|
|
|
|
|
|
/* The key sequences output by the arrow keys, if this terminal has any. */
|
|
|
|
|
char *term_ku = (char *)NULL;
|
|
|
|
|
char *term_kd = (char *)NULL;
|
|
|
|
|
char *term_kr = (char *)NULL;
|
|
|
|
|
char *term_kl = (char *)NULL;
|
|
|
|
|
|
|
|
|
|
/* Move the cursor to the terminal location of X and Y. */
|
|
|
|
|
void
|
|
|
|
|
terminal_goto_xy (x, y)
|
|
|
|
|
int x, y;
|
|
|
|
|
{
|
|
|
|
|
if (terminal_goto_xy_hook)
|
|
|
|
|
(*terminal_goto_xy_hook) (x, y);
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (term_goto)
|
|
|
|
|
tputs (tgoto (term_goto, x, y), 1, output_character_function);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Print STRING to the terminal at the current position. */
|
|
|
|
|
void
|
|
|
|
|
terminal_put_text (string)
|
|
|
|
|
char *string;
|
|
|
|
|
{
|
|
|
|
|
if (terminal_put_text_hook)
|
|
|
|
|
(*terminal_put_text_hook) (string);
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
printf ("%s", string);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Print NCHARS from STRING to the terminal at the current position. */
|
|
|
|
|
void
|
|
|
|
|
terminal_write_chars (string, nchars)
|
|
|
|
|
char *string;
|
|
|
|
|
int nchars;
|
|
|
|
|
{
|
|
|
|
|
if (terminal_write_chars_hook)
|
|
|
|
|
(*terminal_write_chars_hook) (string, nchars);
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (nchars)
|
|
|
|
|
fwrite (string, 1, nchars, stdout);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Clear from the current position of the cursor to the end of the line. */
|
|
|
|
|
void
|
|
|
|
|
terminal_clear_to_eol ()
|
|
|
|
|
{
|
|
|
|
|
if (terminal_clear_to_eol_hook)
|
|
|
|
|
(*terminal_clear_to_eol_hook) ();
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
send_to_terminal (term_clreol);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Clear the entire terminal screen. */
|
|
|
|
|
void
|
|
|
|
|
terminal_clear_screen ()
|
|
|
|
|
{
|
|
|
|
|
if (terminal_clear_screen_hook)
|
|
|
|
|
(*terminal_clear_screen_hook) ();
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
send_to_terminal (term_clrpag);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Move the cursor up one line. */
|
|
|
|
|
void
|
|
|
|
|
terminal_up_line ()
|
|
|
|
|
{
|
|
|
|
|
if (terminal_up_line_hook)
|
|
|
|
|
(*terminal_up_line_hook) ();
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
send_to_terminal (term_up);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Move the cursor down one line. */
|
|
|
|
|
void
|
|
|
|
|
terminal_down_line ()
|
|
|
|
|
{
|
|
|
|
|
if (terminal_down_line_hook)
|
|
|
|
|
(*terminal_down_line_hook) ();
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
send_to_terminal (term_dn);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Turn on reverse video if possible. */
|
|
|
|
|
void
|
|
|
|
|
terminal_begin_inverse ()
|
|
|
|
|
{
|
|
|
|
|
if (terminal_begin_inverse_hook)
|
|
|
|
|
(*terminal_begin_inverse_hook) ();
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
send_to_terminal (term_invbeg);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Turn off reverse video if possible. */
|
|
|
|
|
void
|
|
|
|
|
terminal_end_inverse ()
|
|
|
|
|
{
|
|
|
|
|
if (terminal_end_inverse_hook)
|
|
|
|
|
(*terminal_end_inverse_hook) ();
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
send_to_terminal (term_invend);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Ring the terminal bell. The bell is run visibly if it both has one and
|
|
|
|
|
terminal_use_visible_bell_p is non-zero. */
|
|
|
|
|
void
|
|
|
|
|
terminal_ring_bell ()
|
|
|
|
|
{
|
|
|
|
|
if (terminal_ring_bell_hook)
|
|
|
|
|
(*terminal_ring_bell_hook) ();
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (terminal_has_visible_bell_p && terminal_use_visible_bell_p)
|
|
|
|
|
send_to_terminal (visible_bell);
|
|
|
|
|
else
|
|
|
|
|
send_to_terminal (audible_bell);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* At the line START, delete COUNT lines from the terminal display. */
|
|
|
|
|
static void
|
|
|
|
|
terminal_delete_lines (start, count)
|
|
|
|
|
int start, count;
|
|
|
|
|
{
|
|
|
|
|
int lines;
|
|
|
|
|
|
|
|
|
|
/* Normalize arguments. */
|
|
|
|
|
if (start < 0)
|
|
|
|
|
start = 0;
|
|
|
|
|
|
|
|
|
|
lines = screenheight - start;
|
|
|
|
|
terminal_goto_xy (0, start);
|
|
|
|
|
if (term_DL)
|
|
|
|
|
tputs (tgoto (term_DL, 0, count), lines, output_character_function);
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
while (count--)
|
|
|
|
|
tputs (term_dl, lines, output_character_function);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fflush (stdout);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* At the line START, insert COUNT lines in the terminal display. */
|
|
|
|
|
static void
|
|
|
|
|
terminal_insert_lines (start, count)
|
|
|
|
|
int start, count;
|
|
|
|
|
{
|
|
|
|
|
int lines;
|
|
|
|
|
|
|
|
|
|
/* Normalize arguments. */
|
|
|
|
|
if (start < 0)
|
|
|
|
|
start = 0;
|
|
|
|
|
|
|
|
|
|
lines = screenheight - start;
|
|
|
|
|
terminal_goto_xy (0, start);
|
|
|
|
|
|
|
|
|
|
if (term_AL)
|
|
|
|
|
tputs (tgoto (term_AL, 0, count), lines, output_character_function);
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
while (count--)
|
|
|
|
|
tputs (term_al, lines, output_character_function);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fflush (stdout);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Scroll an area of the terminal, starting with the region from START
|
|
|
|
|
to END, AMOUNT lines. If AMOUNT is negative, the lines are scrolled
|
|
|
|
|
towards the top of the screen, else they are scrolled towards the
|
|
|
|
|
bottom of the screen. */
|
|
|
|
|
void
|
|
|
|
|
terminal_scroll_terminal (start, end, amount)
|
|
|
|
|
int start, end, amount;
|
|
|
|
|
{
|
|
|
|
|
if (!terminal_can_scroll)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
/* Any scrolling at all? */
|
|
|
|
|
if (amount == 0)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (terminal_scroll_terminal_hook)
|
|
|
|
|
(*terminal_scroll_terminal_hook) (start, end, amount);
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/* If we are scrolling down, delete AMOUNT lines at END. Then insert
|
|
|
|
|
AMOUNT lines at START. */
|
|
|
|
|
if (amount > 0)
|
|
|
|
|
{
|
|
|
|
|
terminal_delete_lines (end, amount);
|
|
|
|
|
terminal_insert_lines (start, amount);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* If we are scrolling up, delete AMOUNT lines before START. This
|
|
|
|
|
actually does the upwards scroll. Then, insert AMOUNT lines
|
|
|
|
|
after the already scrolled region (i.e., END - AMOUNT). */
|
|
|
|
|
if (amount < 0)
|
|
|
|
|
{
|
|
|
|
|
int abs_amount = -amount;
|
|
|
|
|
terminal_delete_lines (start - abs_amount, abs_amount);
|
|
|
|
|
terminal_insert_lines (end - abs_amount, abs_amount);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Re-initialize the terminal considering that the TERM/TERMCAP variable
|
|
|
|
|
has changed. */
|
|
|
|
|
void
|
|
|
|
|
terminal_new_terminal (terminal_name)
|
|
|
|
|
char *terminal_name;
|
|
|
|
|
{
|
|
|
|
|
if (terminal_new_terminal_hook)
|
|
|
|
|
(*terminal_new_terminal_hook) (terminal_name);
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
terminal_initialize_terminal (terminal_name);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Set the global variables SCREENWIDTH and SCREENHEIGHT. */
|
|
|
|
|
void
|
|
|
|
|
terminal_get_screen_size ()
|
|
|
|
|
{
|
|
|
|
|
if (terminal_get_screen_size_hook)
|
|
|
|
|
(*terminal_get_screen_size_hook) ();
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
screenwidth = screenheight = 0;
|
|
|
|
|
|
|
|
|
|
#if defined (TIOCGWINSZ)
|
|
|
|
|
{
|
|
|
|
|
struct winsize window_size;
|
|
|
|
|
|
|
|
|
|
if (ioctl (fileno (stdout), TIOCGWINSZ, &window_size) == 0)
|
|
|
|
|
{
|
|
|
|
|
screenwidth = (int) window_size.ws_col;
|
|
|
|
|
screenheight = (int) window_size.ws_row;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif /* TIOCGWINSZ */
|
|
|
|
|
|
|
|
|
|
/* Environment variable COLUMNS overrides setting of "co". */
|
|
|
|
|
if (screenwidth <= 0)
|
|
|
|
|
{
|
|
|
|
|
char *sw = getenv ("COLUMNS");
|
|
|
|
|
|
|
|
|
|
if (sw)
|
|
|
|
|
screenwidth = atoi (sw);
|
|
|
|
|
|
|
|
|
|
if (screenwidth <= 0)
|
|
|
|
|
screenwidth = tgetnum ("co");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Environment variable LINES overrides setting of "li". */
|
|
|
|
|
if (screenheight <= 0)
|
|
|
|
|
{
|
|
|
|
|
char *sh = getenv ("LINES");
|
|
|
|
|
|
|
|
|
|
if (sh)
|
|
|
|
|
screenheight = atoi (sh);
|
|
|
|
|
|
|
|
|
|
if (screenheight <= 0)
|
|
|
|
|
screenheight = tgetnum ("li");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* If all else fails, default to 80x24 terminal. */
|
|
|
|
|
if (screenwidth <= 0)
|
|
|
|
|
screenwidth = 80;
|
|
|
|
|
|
|
|
|
|
if (screenheight <= 0)
|
|
|
|
|
screenheight = 24;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Initialize the terminal which is known as TERMINAL_NAME. If this terminal
|
|
|
|
|
doesn't have cursor addressability, TERMINAL_IS_DUMB_P becomes non-zero.
|
|
|
|
|
The variables SCREENHEIGHT and SCREENWIDTH are set to the dimensions that
|
|
|
|
|
this terminal actually has. The variable TERMINAL_HAS_META_P becomes non-
|
|
|
|
|
zero if this terminal supports a Meta key. Finally, the terminal screen is
|
|
|
|
|
cleared. */
|
|
|
|
|
void
|
|
|
|
|
terminal_initialize_terminal (terminal_name)
|
|
|
|
|
char *terminal_name;
|
|
|
|
|
{
|
|
|
|
|
char *term, *buffer;
|
|
|
|
|
|
|
|
|
|
terminal_is_dumb_p = 0;
|
|
|
|
|
|
|
|
|
|
if (terminal_initialize_terminal_hook)
|
|
|
|
|
{
|
|
|
|
|
(*terminal_initialize_terminal_hook) (terminal_name);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
term = terminal_name ? terminal_name : getenv ("TERM");
|
|
|
|
|
|
|
|
|
|
if (!term_string_buffer)
|
|
|
|
|
term_string_buffer = (char *)xmalloc (2048);
|
|
|
|
|
|
|
|
|
|
if (!term_buffer)
|
|
|
|
|
term_buffer = (char *)xmalloc (2048);
|
|
|
|
|
|
|
|
|
|
buffer = term_string_buffer;
|
|
|
|
|
|
|
|
|
|
term_clrpag = term_cr = term_clreol = (char *)NULL;
|
|
|
|
|
|
|
|
|
|
if (!term)
|
|
|
|
|
term = "dumb";
|
|
|
|
|
|
|
|
|
|
if (tgetent (term_buffer, term) <= 0)
|
|
|
|
|
{
|
|
|
|
|
terminal_is_dumb_p = 1;
|
|
|
|
|
screenwidth = 80;
|
|
|
|
|
screenheight = 24;
|
|
|
|
|
term_cr = "\r";
|
|
|
|
|
term_up = term_dn = audible_bell = visible_bell = (char *)NULL;
|
|
|
|
|
term_ku = term_kd = term_kl = term_kr = (char *)NULL;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BC = tgetstr ("pc", &buffer);
|
|
|
|
|
PC = BC ? *BC : 0;
|
|
|
|
|
|
|
|
|
|
#if defined (TIOCGETP)
|
|
|
|
|
{
|
|
|
|
|
struct sgttyb sg;
|
|
|
|
|
|
|
|
|
|
if (ioctl (fileno (stdout), TIOCGETP, &sg) != -1)
|
|
|
|
|
ospeed = sg.sg_ospeed;
|
|
|
|
|
else
|
|
|
|
|
ospeed = B9600;
|
|
|
|
|
}
|
|
|
|
|
#else
|
|
|
|
|
ospeed = B9600;
|
|
|
|
|
#endif /* !TIOCGETP */
|
|
|
|
|
|
|
|
|
|
term_cr = tgetstr ("cr", &buffer);
|
|
|
|
|
term_clreol = tgetstr ("ce", &buffer);
|
|
|
|
|
term_clrpag = tgetstr ("cl", &buffer);
|
|
|
|
|
term_goto = tgetstr ("cm", &buffer);
|
|
|
|
|
|
|
|
|
|
/* Find out about this terminals scrolling capability. */
|
|
|
|
|
term_AL = tgetstr ("AL", &buffer);
|
|
|
|
|
term_DL = tgetstr ("DL", &buffer);
|
|
|
|
|
term_al = tgetstr ("al", &buffer);
|
|
|
|
|
term_dl = tgetstr ("dl", &buffer);
|
|
|
|
|
|
|
|
|
|
terminal_can_scroll = ((term_AL || term_al) && (term_DL || term_dl));
|
|
|
|
|
|
|
|
|
|
term_invbeg = tgetstr ("mr", &buffer);
|
|
|
|
|
if (term_invbeg)
|
|
|
|
|
term_invend = tgetstr ("me", &buffer);
|
|
|
|
|
else
|
|
|
|
|
term_invend = (char *)NULL;
|
|
|
|
|
|
|
|
|
|
if (!term_cr)
|
|
|
|
|
term_cr = "\r";
|
|
|
|
|
|
|
|
|
|
terminal_get_screen_size ();
|
|
|
|
|
|
|
|
|
|
term_up = tgetstr ("up", &buffer);
|
|
|
|
|
term_dn = tgetstr ("dn", &buffer);
|
|
|
|
|
visible_bell = tgetstr ("vb", &buffer);
|
|
|
|
|
terminal_has_visible_bell_p = (visible_bell != (char *)NULL);
|
|
|
|
|
audible_bell = tgetstr ("bl", &buffer);
|
|
|
|
|
if (!audible_bell)
|
|
|
|
|
audible_bell = "\007";
|
|
|
|
|
term_begin_use = tgetstr ("ti", &buffer);
|
|
|
|
|
term_end_use = tgetstr ("te", &buffer);
|
|
|
|
|
|
|
|
|
|
/* Check to see if this terminal has a meta key. */
|
|
|
|
|
terminal_has_meta_p = (tgetflag ("km") || tgetflag ("MT"));
|
|
|
|
|
if (terminal_has_meta_p)
|
|
|
|
|
{
|
|
|
|
|
term_mm = tgetstr ("mm", &buffer);
|
|
|
|
|
term_mo = tgetstr ("mo", &buffer);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
term_mm = (char *)NULL;
|
|
|
|
|
term_mo = (char *)NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Attempt to find the arrow keys. */
|
|
|
|
|
term_ku = tgetstr ("ku", &buffer);
|
|
|
|
|
term_kd = tgetstr ("kd", &buffer);
|
|
|
|
|
term_kr = tgetstr ("kr", &buffer);
|
|
|
|
|
term_kl = tgetstr ("kl", &buffer);
|
|
|
|
|
|
|
|
|
|
/* If this terminal is not cursor addressable, then it is really dumb. */
|
|
|
|
|
if (!term_goto)
|
|
|
|
|
terminal_is_dumb_p = 1;
|
|
|
|
|
|
|
|
|
|
terminal_begin_using_terminal ();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* **************************************************************** */
|
|
|
|
|
/* */
|
|
|
|
|
/* How to Read Characters From the Terminal */
|
|
|
|
|
/* */
|
|
|
|
|
/* **************************************************************** */
|
|
|
|
|
|
|
|
|
|
#if defined (TIOCGETC)
|
|
|
|
|
/* A buffer containing the terminal interrupt characters upon entry
|
|
|
|
|
to Info. */
|
|
|
|
|
struct tchars original_tchars;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#if defined (TIOCGLTC)
|
|
|
|
|
/* A buffer containing the local terminal mode characters upon entry
|
|
|
|
|
to Info. */
|
|
|
|
|
struct ltchars original_ltchars;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#if defined (HAVE_TERMIOS_H)
|
|
|
|
|
struct termios original_termios, ttybuff;
|
|
|
|
|
#else
|
|
|
|
|
# if defined (HAVE_TERMIO_H)
|
|
|
|
|
/* A buffer containing the terminal mode flags upon entry to info. */
|
|
|
|
|
struct termio original_termio, ttybuff;
|
|
|
|
|
# else /* !HAVE_TERMIO_H */
|
|
|
|
|
/* Buffers containing the terminal mode flags upon entry to info. */
|
|
|
|
|
int original_tty_flags = 0;
|
|
|
|
|
int original_lmode;
|
|
|
|
|
struct sgttyb ttybuff;
|
|
|
|
|
# endif /* !HAVE_TERMIO_H */
|
|
|
|
|
#endif /* !HAVE_TERMIOS_H */
|
|
|
|
|
|
|
|
|
|
/* Prepare to start using the terminal to read characters singly. */
|
|
|
|
|
void
|
|
|
|
|
terminal_prep_terminal ()
|
|
|
|
|
{
|
|
|
|
|
int tty;
|
|
|
|
|
|
|
|
|
|
if (terminal_prep_terminal_hook)
|
|
|
|
|
{
|
|
|
|
|
(*terminal_prep_terminal_hook) ();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
tty = fileno (stdin);
|
|
|
|
|
|
|
|
|
|
#if defined (HAVE_TERMIOS_H)
|
|
|
|
|
tcgetattr (tty, &original_termios);
|
|
|
|
|
tcgetattr (tty, &ttybuff);
|
|
|
|
|
#else
|
|
|
|
|
# if defined (HAVE_TERMIO_H)
|
|
|
|
|
ioctl (tty, TCGETA, &original_termio);
|
|
|
|
|
ioctl (tty, TCGETA, &ttybuff);
|
|
|
|
|
# endif
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#if defined (HAVE_TERMIOS_H) || defined (HAVE_TERMIO_H)
|
|
|
|
|
ttybuff.c_iflag &= (~ISTRIP & ~INLCR & ~IGNCR & ~ICRNL & ~IXON);
|
1997-08-31 03:48:33 +02:00
|
|
|
|
/* These output flags are not part of POSIX, so only use them if they
|
|
|
|
|
are defined. */
|
|
|
|
|
#ifdef ONLCR
|
|
|
|
|
ttybuff.c_oflag &= ~ONLCR ;
|
|
|
|
|
#endif
|
|
|
|
|
#ifdef OCRNL
|
|
|
|
|
ttybuff.c_oflag &= ~OCRNL;
|
|
|
|
|
#endif
|
1997-08-22 00:57:35 +02:00
|
|
|
|
ttybuff.c_lflag &= (~ICANON & ~ECHO);
|
|
|
|
|
|
|
|
|
|
ttybuff.c_cc[VMIN] = 1;
|
|
|
|
|
ttybuff.c_cc[VTIME] = 0;
|
|
|
|
|
|
|
|
|
|
if (ttybuff.c_cc[VINTR] == '\177')
|
|
|
|
|
ttybuff.c_cc[VINTR] = -1;
|
|
|
|
|
|
|
|
|
|
if (ttybuff.c_cc[VQUIT] == '\177')
|
|
|
|
|
ttybuff.c_cc[VQUIT] = -1;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#if defined (HAVE_TERMIOS_H)
|
|
|
|
|
tcsetattr (tty, TCSANOW, &ttybuff);
|
|
|
|
|
#else
|
|
|
|
|
# if defined (HAVE_TERMIO_H)
|
|
|
|
|
ioctl (tty, TCSETA, &ttybuff);
|
|
|
|
|
# endif
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#if !defined (HAVE_TERMIOS_H) && !defined (HAVE_TERMIO_H)
|
|
|
|
|
ioctl (tty, TIOCGETP, &ttybuff);
|
|
|
|
|
|
|
|
|
|
if (!original_tty_flags)
|
|
|
|
|
original_tty_flags = ttybuff.sg_flags;
|
|
|
|
|
|
|
|
|
|
/* Make this terminal pass 8 bits around while we are using it. */
|
|
|
|
|
# if defined (PASS8)
|
|
|
|
|
ttybuff.sg_flags |= PASS8;
|
|
|
|
|
# endif /* PASS8 */
|
|
|
|
|
|
|
|
|
|
# if defined (TIOCLGET) && defined (LPASS8)
|
|
|
|
|
{
|
|
|
|
|
int flags;
|
|
|
|
|
ioctl (tty, TIOCLGET, &flags);
|
|
|
|
|
original_lmode = flags;
|
|
|
|
|
flags |= LPASS8;
|
|
|
|
|
ioctl (tty, TIOCLSET, &flags);
|
|
|
|
|
}
|
|
|
|
|
# endif /* TIOCLGET && LPASS8 */
|
|
|
|
|
|
|
|
|
|
# if defined (TIOCGETC)
|
|
|
|
|
{
|
|
|
|
|
struct tchars temp;
|
|
|
|
|
|
|
|
|
|
ioctl (tty, TIOCGETC, &original_tchars);
|
|
|
|
|
temp = original_tchars;
|
|
|
|
|
|
|
|
|
|
/* C-s and C-q. */
|
|
|
|
|
temp.t_startc = temp.t_stopc = -1;
|
|
|
|
|
|
|
|
|
|
/* Often set to C-d. */
|
|
|
|
|
temp.t_eofc = -1;
|
|
|
|
|
|
|
|
|
|
/* If the a quit or interrupt character conflicts with one of our
|
|
|
|
|
commands, then make it go away. */
|
|
|
|
|
if (temp.t_intrc == '\177')
|
|
|
|
|
temp.t_intrc = -1;
|
|
|
|
|
|
|
|
|
|
if (temp.t_quitc == '\177')
|
|
|
|
|
temp.t_quitc = -1;
|
|
|
|
|
|
|
|
|
|
ioctl (tty, TIOCSETC, &temp);
|
|
|
|
|
}
|
|
|
|
|
# endif /* TIOCGETC */
|
|
|
|
|
|
|
|
|
|
# if defined (TIOCGLTC)
|
|
|
|
|
{
|
|
|
|
|
struct ltchars temp;
|
|
|
|
|
|
|
|
|
|
ioctl (tty, TIOCGLTC, &original_ltchars);
|
|
|
|
|
temp = original_ltchars;
|
|
|
|
|
|
|
|
|
|
/* Make the interrupt keys go away. Just enough to make people happy. */
|
|
|
|
|
temp.t_lnextc = -1; /* C-v. */
|
|
|
|
|
temp.t_dsuspc = -1; /* C-y. */
|
|
|
|
|
temp.t_flushc = -1; /* C-o. */
|
|
|
|
|
ioctl (tty, TIOCSLTC, &temp);
|
|
|
|
|
}
|
|
|
|
|
# endif /* TIOCGLTC */
|
|
|
|
|
|
|
|
|
|
ttybuff.sg_flags &= ~ECHO;
|
|
|
|
|
ttybuff.sg_flags |= CBREAK;
|
|
|
|
|
ioctl (tty, TIOCSETN, &ttybuff);
|
|
|
|
|
#endif /* !HAVE_TERMIOS_H && !HAVE_TERMIO_H */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Restore the tty settings back to what they were before we started using
|
|
|
|
|
this terminal. */
|
|
|
|
|
void
|
|
|
|
|
terminal_unprep_terminal ()
|
|
|
|
|
{
|
|
|
|
|
int tty;
|
|
|
|
|
|
|
|
|
|
if (terminal_unprep_terminal_hook)
|
|
|
|
|
{
|
|
|
|
|
(*terminal_unprep_terminal_hook) ();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
tty = fileno (stdin);
|
|
|
|
|
|
|
|
|
|
#if defined (HAVE_TERMIOS_H)
|
|
|
|
|
tcsetattr (tty, TCSANOW, &original_termios);
|
|
|
|
|
#else
|
|
|
|
|
# if defined (HAVE_TERMIO_H)
|
|
|
|
|
ioctl (tty, TCSETA, &original_termio);
|
|
|
|
|
# else /* !HAVE_TERMIO_H */
|
|
|
|
|
ioctl (tty, TIOCGETP, &ttybuff);
|
|
|
|
|
ttybuff.sg_flags = original_tty_flags;
|
|
|
|
|
ioctl (tty, TIOCSETN, &ttybuff);
|
|
|
|
|
|
|
|
|
|
# if defined (TIOCGETC)
|
|
|
|
|
ioctl (tty, TIOCSETC, &original_tchars);
|
|
|
|
|
# endif /* TIOCGETC */
|
|
|
|
|
|
|
|
|
|
# if defined (TIOCGLTC)
|
|
|
|
|
ioctl (tty, TIOCSLTC, &original_ltchars);
|
|
|
|
|
# endif /* TIOCGLTC */
|
|
|
|
|
|
|
|
|
|
# if defined (TIOCLGET) && defined (LPASS8)
|
|
|
|
|
ioctl (tty, TIOCLSET, &original_lmode);
|
|
|
|
|
# endif /* TIOCLGET && LPASS8 */
|
|
|
|
|
|
|
|
|
|
# endif /* !HAVE_TERMIO_H */
|
|
|
|
|
#endif /* !HAVE_TERMIOS_H */
|
|
|
|
|
terminal_end_using_terminal ();
|
|
|
|
|
}
|
|
|
|
|
|