15589c42fa
Mostly this is intended to resolve the trace() badness once and for all. Obtained from: ftp://dickey.his.com/ncurses/
819 lines
15 KiB
C
819 lines
15 KiB
C
/*
|
|
** Copyright (C) 1991, 1997 Free Software Foundation, Inc.
|
|
**
|
|
** This file is part of TACK.
|
|
**
|
|
** TACK 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.
|
|
**
|
|
** TACK 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 TACK; see the file COPYING. If not, write to
|
|
** the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
** Boston, MA 02111-1307, USA.
|
|
*/
|
|
/* screen formatting and I/O utility functions */
|
|
|
|
#include <tack.h>
|
|
#include <time.h>
|
|
|
|
MODULE_ID("$Id: output.c,v 1.5 2000/03/04 21:06:57 tom Exp $")
|
|
|
|
/* globals */
|
|
long char_sent; /* number of characters sent */
|
|
int char_count; /* counts characters */
|
|
int line_count; /* counts line feeds */
|
|
int expand_chars; /* length of expand() string */
|
|
int replace_mode; /* used to output replace mode padding */
|
|
int can_go_home; /* TRUE if we can fashion a home command */
|
|
int can_clear_screen; /* TRUE if we can somehow clear the screen */
|
|
int raw_characters_sent; /* Total output characters */
|
|
int log_count; /* Number of characters on a log line */
|
|
|
|
/* translate mode default strings */
|
|
#define TM_carriage_return TM_string[0].value
|
|
#define TM_cursor_down TM_string[1].value
|
|
#define TM_scroll_forward TM_string[2].value
|
|
#define TM_newline TM_string[3].value
|
|
#define TM_cursor_left TM_string[4].value
|
|
#define TM_bell TM_string[5].value
|
|
#define TM_form_feed TM_string[6].value
|
|
#define TM_tab TM_string[7].value
|
|
|
|
struct default_string_list TM_string[TM_last] = {
|
|
{"cr", "\r", 0},
|
|
{"cud1", "\n", 0},
|
|
{"ind", "\n", 0},
|
|
{"nel", "\r\n", 0},
|
|
{"cub1", "\b", 0},
|
|
{"bel", "\007", 0},
|
|
{"ff", "\f", 0},
|
|
{"ht", "\t", 0}
|
|
};
|
|
|
|
static const char *c0[32] = {
|
|
"NUL", "SOH", "STX", "ETX", "EOT", "ENQ", "ACK",
|
|
"BEL", "BS", "HT", "LF", "VT", "FF", "CR", "SO", "SI",
|
|
"DLE", "DC1", "DC2", "DC3", "DC4", "NAK", "SYN", "ETB",
|
|
"CAN", "EM", "SUB", "ESC", "FS", "GS", "RS", "US"
|
|
};
|
|
|
|
static const char *c1[32] = {
|
|
"", "", "", "", "IND", "NEL", "SSA", "ESA",
|
|
"HTS", "HTJ", "VTS", "PLD", "PLU", "RI", "SS2", "SS3",
|
|
"DCS", "PU1", "PU2", "STS", "CCH", "MW", "SPA", "EPA",
|
|
"", "", "", "CSI", "ST", "OSC", "PM", "APC"
|
|
};
|
|
|
|
int
|
|
getnext(int mask)
|
|
{ /* get the next character without scan mode
|
|
conversion */
|
|
int ch;
|
|
unsigned char buf;
|
|
|
|
tc_putp(req_for_input);
|
|
fflush(stdout);
|
|
if (nodelay_read)
|
|
while (1) {
|
|
ch = read(fileno(stdin), &buf, 1);
|
|
if (ch == -1)
|
|
return EOF;
|
|
if (ch == 1)
|
|
return buf;
|
|
}
|
|
ch = getchar();
|
|
if (ch == EOF)
|
|
return EOF;
|
|
return ch & mask;
|
|
}
|
|
|
|
|
|
int
|
|
getchp(int mask)
|
|
{ /* read a character with scan mode conversion */
|
|
if (scan_mode) {
|
|
tc_putp(req_for_input);
|
|
fflush(stdout);
|
|
return scan_key();
|
|
} else
|
|
return getnext(mask);
|
|
}
|
|
|
|
/*
|
|
** tc_putch(c)
|
|
**
|
|
** Output one character
|
|
*/
|
|
int
|
|
tc_putch(int c)
|
|
{
|
|
char_sent++;
|
|
raw_characters_sent++;
|
|
putchar(c);
|
|
if ((raw_characters_sent & 31) == 31) {
|
|
fflush(stdout);
|
|
}
|
|
if (log_fp) {
|
|
/* terminal output logging */
|
|
c &= 0xff;
|
|
if (c < 32) {
|
|
fprintf(log_fp, "<%s>", c0[c]);
|
|
log_count += 5;
|
|
} else
|
|
if (c < 127) {
|
|
fprintf(log_fp, "%c", c);
|
|
log_count += 1;
|
|
} else {
|
|
fprintf(log_fp, "<%02x>", c);
|
|
log_count += 4;
|
|
}
|
|
if (c == '\n' || log_count >= 80) {
|
|
fprintf(log_fp, "\n");
|
|
log_count = 0;
|
|
}
|
|
}
|
|
return (c);
|
|
}
|
|
|
|
/*
|
|
** tt_tputs(string, reps)
|
|
**
|
|
** Output a string with tputs() translation.
|
|
** Use this function inside timing tests.
|
|
*/
|
|
void
|
|
tt_tputs(const char *string, int reps)
|
|
{
|
|
int i;
|
|
|
|
if (string) {
|
|
for (i = 0; i < TT_MAX; i++) {
|
|
if (i >= ttp) {
|
|
tt_cap[i] = string;
|
|
tt_affected[i] = reps;
|
|
tt_count[i] = 1;
|
|
tt_delay[i] = msec_cost(string, reps);
|
|
ttp++;
|
|
break;
|
|
}
|
|
if (string == tt_cap[i] && reps == tt_affected[i]) {
|
|
tt_count[i]++;
|
|
tt_delay_used += tt_delay[i];
|
|
break;
|
|
}
|
|
}
|
|
(void) tputs(string, reps, tc_putch);
|
|
}
|
|
}
|
|
|
|
/*
|
|
** tt_putp(string)
|
|
**
|
|
** Output a string with tputs() translation.
|
|
** Use this function inside timing tests.
|
|
*/
|
|
void
|
|
tt_putp(const char *string)
|
|
{
|
|
tt_tputs(string, 1);
|
|
}
|
|
|
|
/*
|
|
** tt_putparm(string, reps, arg1, arg2, ...)
|
|
**
|
|
** Send tt_tputs(tparm(string, args...), reps)
|
|
** Use this function inside timing tests.
|
|
*/
|
|
void
|
|
tt_putparm(
|
|
NCURSES_CONST char *string,
|
|
int reps,
|
|
int arg1,
|
|
int arg2)
|
|
{
|
|
int i;
|
|
|
|
if (string) {
|
|
for (i = 0; i < TT_MAX; i++) {
|
|
if (i >= ttp) {
|
|
tt_cap[i] = string;
|
|
tt_affected[i] = reps;
|
|
tt_count[i] = 1;
|
|
tt_delay[i] = msec_cost(string, reps);
|
|
ttp++;
|
|
break;
|
|
}
|
|
if (string == tt_cap[i] && reps == tt_affected[i]) {
|
|
tt_count[i]++;
|
|
tt_delay_used += tt_delay[i];
|
|
break;
|
|
}
|
|
}
|
|
(void) tputs(tparm((NCURSES_CONST char *)string, arg1, arg2), reps, tc_putch);
|
|
}
|
|
}
|
|
|
|
/*
|
|
** tc_putp(string)
|
|
**
|
|
** Output a string with tputs() translation.
|
|
** Use this function instead of putp() so we can track
|
|
** the actual number of characters sent.
|
|
*/
|
|
int
|
|
tc_putp(const char *string)
|
|
{
|
|
return tputs(string, 1, tc_putch);
|
|
}
|
|
|
|
|
|
void
|
|
put_this(int c)
|
|
{ /* output one character (with padding) */
|
|
tc_putch(c);
|
|
if (char_padding && replace_mode)
|
|
tt_putp(char_padding);
|
|
}
|
|
|
|
|
|
void
|
|
put_cr(void)
|
|
{
|
|
if (translate_mode && carriage_return) {
|
|
tt_putp(carriage_return);
|
|
} else {
|
|
tt_putp(TM_carriage_return);
|
|
}
|
|
char_count = 0;
|
|
}
|
|
|
|
|
|
void
|
|
put_lf(void)
|
|
{ /* send a linefeed (only works in RAW or
|
|
CBREAK mode) */
|
|
if (translate_mode && cursor_down) {
|
|
tt_putp(cursor_down);
|
|
} else {
|
|
tt_putp(TM_cursor_down);
|
|
}
|
|
line_count++;
|
|
}
|
|
|
|
|
|
void
|
|
put_ind(void)
|
|
{ /* scroll forward (only works in RAW or
|
|
CBREAK mode) */
|
|
if (translate_mode && scroll_forward) {
|
|
tt_putp(scroll_forward);
|
|
} else {
|
|
tt_putp(TM_scroll_forward);
|
|
}
|
|
line_count++;
|
|
}
|
|
|
|
/*
|
|
** put_crlf()
|
|
**
|
|
** Send (nel) or <cr> <lf>
|
|
*/
|
|
void
|
|
put_crlf(void)
|
|
{
|
|
if (translate_mode && newline) {
|
|
tt_putp(newline);
|
|
} else {
|
|
tt_putp(TM_newline);
|
|
}
|
|
char_count = 0;
|
|
line_count++;
|
|
}
|
|
|
|
/*
|
|
** put_new_lines(count)
|
|
**
|
|
** Send a number of newlines. (nel)
|
|
*/
|
|
void
|
|
put_newlines(int n)
|
|
{
|
|
while (n-- > 0) {
|
|
put_crlf();
|
|
}
|
|
}
|
|
|
|
/*
|
|
** putchp(character)
|
|
**
|
|
** Send one character to the terminal.
|
|
** This function does translation of control characters.
|
|
*/
|
|
void
|
|
putchp(int c)
|
|
{
|
|
switch (c) {
|
|
case '\b':
|
|
if (translate_mode && cursor_left) {
|
|
tt_putp(cursor_left);
|
|
} else {
|
|
tt_putp(TM_cursor_left);
|
|
}
|
|
char_count--;
|
|
break;
|
|
case 7:
|
|
if (translate_mode && bell) {
|
|
tt_putp(bell);
|
|
} else {
|
|
tt_putp(TM_bell);
|
|
}
|
|
break;
|
|
case '\f':
|
|
if (translate_mode && form_feed) {
|
|
tt_putp(form_feed);
|
|
} else {
|
|
tt_putp(TM_form_feed);
|
|
}
|
|
char_count = 0;
|
|
line_count++;
|
|
break;
|
|
case '\n':
|
|
put_crlf();
|
|
break;
|
|
case '\r':
|
|
put_cr();
|
|
break;
|
|
case '\t':
|
|
if (translate_mode && tab) {
|
|
tt_putp(tab);
|
|
} else {
|
|
tt_putp(TM_tab);
|
|
}
|
|
char_count = ((char_count / 8) + 1) * 8;
|
|
break;
|
|
default:
|
|
put_this(c);
|
|
char_count++;
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
put_str(const char *s)
|
|
{ /* send the string to the terminal */
|
|
for (; *s; putchp(*s++));
|
|
}
|
|
|
|
|
|
void
|
|
putln(const char *s)
|
|
{ /* output a string followed by a CR LF */
|
|
for (; *s; putchp(*s++));
|
|
put_crlf();
|
|
}
|
|
|
|
|
|
void
|
|
put_columns(const char *s, int len, int w)
|
|
{ /* put out s in column format */
|
|
int l;
|
|
|
|
if (char_count + w > columns) {
|
|
put_crlf();
|
|
}
|
|
l = char_count % w;
|
|
if (l) {
|
|
while (l < w) {
|
|
putchp(' ');
|
|
l++;
|
|
}
|
|
}
|
|
if (char_count && char_count + len >= columns) {
|
|
put_crlf();
|
|
}
|
|
l = char_count;
|
|
put_str(s);
|
|
char_count = l + len;
|
|
}
|
|
|
|
|
|
/*
|
|
** ptext(string)
|
|
**
|
|
** Output a string but do not assume the terminal will wrap to a
|
|
** new line. Break the line at a word boundary then send a CR LF.
|
|
** This is more esthetic on 40 column terminals.
|
|
*/
|
|
void
|
|
ptext(const char *s)
|
|
{
|
|
const char *t;
|
|
|
|
while (*s) {
|
|
for (t = s + 1; *t > ' '; t++);
|
|
if ((char_count != 0) && ((t - s) + char_count >= columns)) {
|
|
put_crlf();
|
|
while (*s == ' ')
|
|
s++;
|
|
}
|
|
while (s < t) {
|
|
putchp(*s++);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
put_dec(char *f, int i)
|
|
{ /* print a line with a decimal number in it */
|
|
char tm[128];
|
|
|
|
sprintf(tm, f, i / 10, i % 10);
|
|
ptext(tm);
|
|
}
|
|
|
|
|
|
void
|
|
three_digit(char *tx, int i)
|
|
{ /* convert the decimal number to a string of
|
|
at least 3 digits */
|
|
if (i < 1000)
|
|
sprintf(tx, "%d.%d", i / 10, i % 10);
|
|
else
|
|
sprintf(tx, "%d", i / 10);
|
|
}
|
|
|
|
|
|
void
|
|
ptextln(const char *s)
|
|
{ /* print the text using ptext() then add a CR
|
|
LF */
|
|
ptext(s);
|
|
put_crlf();
|
|
}
|
|
|
|
|
|
static void
|
|
expand_one(int ch, char **v)
|
|
{ /* expand one character */
|
|
char *t = *v;
|
|
|
|
if (ch & 0x80) { /* dump it in octal (yuck) */
|
|
*t++ = '\\';
|
|
*t++ = '0' + ((ch >> 6) & 3);
|
|
*t++ = '0' + ((ch >> 3) & 7);
|
|
*t++ = '0' + (ch & 7);
|
|
expand_chars += 4;
|
|
} else if (ch == 127) { /* DEL */
|
|
*t++ = '^';
|
|
*t++ = '?';
|
|
expand_chars += 2;
|
|
} else if (ch >= ' ') {
|
|
*t++ = ch;
|
|
expand_chars++;
|
|
} else { /* control characters */
|
|
*t++ = '^';
|
|
*t++ = ch + '@';
|
|
expand_chars += 2;
|
|
}
|
|
*v = t;
|
|
}
|
|
|
|
|
|
char *
|
|
expand(const char *s)
|
|
{ /* convert the string to printable form */
|
|
static char buf[4096];
|
|
char *t, *v;
|
|
int ch;
|
|
|
|
if (magic_cookie_glitch <= 0 && exit_attribute_mode) {
|
|
v = enter_reverse_mode;
|
|
} else {
|
|
v = NULL;
|
|
}
|
|
expand_chars = 0;
|
|
t = buf;
|
|
if (s) {
|
|
for (; (ch = *s); s++) {
|
|
if ((ch & 0x80) && v) { /* print it in reverse video
|
|
mode */
|
|
strcpy(t, liberated(tparm(v)));
|
|
for (; *t; t++);
|
|
expand_one(ch & 0x7f, &t);
|
|
strcpy(t, liberated(tparm(exit_attribute_mode)));
|
|
for (; *t; t++);
|
|
} else {
|
|
expand_one(ch, &t);
|
|
}
|
|
}
|
|
}
|
|
*t = '\0';
|
|
return buf;
|
|
}
|
|
|
|
|
|
char *
|
|
print_expand(char *s)
|
|
{ /* convert the string to 7-bit printable form */
|
|
static char buf[4096];
|
|
char *t;
|
|
int ch;
|
|
|
|
expand_chars = 0;
|
|
t = buf;
|
|
if (s) {
|
|
for (; (ch = *s); s++) {
|
|
expand_one(ch, &t);
|
|
}
|
|
}
|
|
*t = '\0';
|
|
return buf;
|
|
}
|
|
|
|
|
|
char *
|
|
expand_to(char *s, int l)
|
|
{ /* expand s to length l */
|
|
char *t;
|
|
|
|
for (s = t = expand(s); *t; t++);
|
|
for (; expand_chars < l; expand_chars++) {
|
|
*t++ = ' ';
|
|
}
|
|
*t = '\0';
|
|
return s;
|
|
}
|
|
|
|
|
|
char *
|
|
hex_expand_to(char *s, int l)
|
|
{ /* expand s to length l in hex */
|
|
static char buf[4096];
|
|
char *t;
|
|
|
|
for (t = buf; *s; s++) {
|
|
sprintf(t, "%02X ", *s & 0xff);
|
|
t += 3;
|
|
if (t - buf > (int) sizeof(buf) - 4) {
|
|
break;
|
|
}
|
|
}
|
|
for (; t - buf < l;) {
|
|
*t++ = ' ';
|
|
}
|
|
*t = '\0';
|
|
expand_chars = t - buf;
|
|
return buf;
|
|
}
|
|
|
|
|
|
char *
|
|
expand_command(const char *c)
|
|
{ /* expand an ANSI escape sequence */
|
|
static char buf[256];
|
|
int i, j, ch;
|
|
char *s;
|
|
|
|
s = buf;
|
|
for (i = FALSE; (ch = (*c & 0xff)); c++) {
|
|
if (i) {
|
|
*s++ = ' ';
|
|
}
|
|
i = TRUE;
|
|
if (ch < 32) {
|
|
j = c[1] & 0xff;
|
|
if (ch == '\033' && j >= '@' && j <= '_') {
|
|
ch = j - '@';
|
|
c++;
|
|
for (j = 0; (*s = c1[ch][j++]); s++);
|
|
} else
|
|
for (j = 0; (*s = c0[ch][j++]); s++);
|
|
} else {
|
|
*s++ = ch;
|
|
j = c[1] & 0xff;
|
|
if (ch >= '0' && ch <= '9' &&
|
|
j >= '0' && j <= '9') {
|
|
i = FALSE;
|
|
}
|
|
}
|
|
}
|
|
*s = '\0';
|
|
return buf;
|
|
}
|
|
|
|
/*
|
|
** go_home()
|
|
**
|
|
** Move the cursor to the home position
|
|
*/
|
|
void
|
|
go_home(void)
|
|
{
|
|
int i;
|
|
|
|
if (cursor_home)
|
|
tt_putp(cursor_home);
|
|
else if (cursor_address)
|
|
tt_putparm(cursor_address, lines, 0, 0);
|
|
else if (row_address) { /* use (vpa) */
|
|
put_cr();
|
|
tt_putparm(row_address, 1, 0, 0);
|
|
} else if (cursor_up && cursor_to_ll) {
|
|
tt_putp(cursor_to_ll);
|
|
for (i = 1; i < lines; i++) {
|
|
tt_putp(cursor_up);
|
|
}
|
|
} else {
|
|
can_go_home = FALSE;
|
|
return;
|
|
}
|
|
char_count = line_count = 0;
|
|
can_go_home = TRUE;
|
|
}
|
|
|
|
|
|
void
|
|
home_down(void)
|
|
{ /* move the cursor to the lower left hand
|
|
corner */
|
|
int i;
|
|
|
|
if (cursor_to_ll)
|
|
tt_putp(cursor_to_ll);
|
|
else if (cursor_address)
|
|
tt_putparm(cursor_address, lines, lines - 1, 0);
|
|
else if (row_address) { /* use (vpa) */
|
|
put_cr();
|
|
tt_putparm(row_address, 1, lines - 1, 0);
|
|
} else if (cursor_down && cursor_home) {
|
|
tt_putp(cursor_home);
|
|
for (i = 1; i < lines; i++)
|
|
tt_putp(cursor_down);
|
|
} else
|
|
return;
|
|
char_count = 0;
|
|
line_count = lines - 1;
|
|
}
|
|
|
|
|
|
void
|
|
put_clear(void)
|
|
{ /* clear the screen */
|
|
int i;
|
|
|
|
if (clear_screen)
|
|
tt_tputs(clear_screen, lines);
|
|
else if (clr_eos && can_go_home) {
|
|
go_home();
|
|
tt_tputs(clr_eos, lines);
|
|
} else if (scroll_forward && !over_strike && (can_go_home || cursor_up)) {
|
|
/* clear the screen by scrolling */
|
|
put_cr();
|
|
if (cursor_to_ll) {
|
|
tt_putp(cursor_to_ll);
|
|
} else if (cursor_address) {
|
|
tt_putparm(cursor_address, lines, lines - 1, 0);
|
|
} else if (row_address) {
|
|
tt_putparm(row_address, 1, lines - 1, 0);
|
|
} else {
|
|
for (i = 1; i < lines; i++) {
|
|
tt_putp(scroll_forward);
|
|
}
|
|
}
|
|
for (i = 1; i < lines; i++) {
|
|
tt_putp(scroll_forward);
|
|
}
|
|
if (can_go_home) {
|
|
go_home();
|
|
} else {
|
|
for (i = 1; i < lines; i++) {
|
|
tt_putp(cursor_up);
|
|
}
|
|
}
|
|
} else {
|
|
can_clear_screen = FALSE;
|
|
return;
|
|
}
|
|
char_count = line_count = 0;
|
|
can_clear_screen = TRUE;
|
|
}
|
|
|
|
/*
|
|
** wait_here()
|
|
**
|
|
** read one character from the input stream
|
|
** If the terminal is not in RAW mode then this function will
|
|
** wait for a <cr> or <lf>.
|
|
*/
|
|
int
|
|
wait_here(void)
|
|
{
|
|
char ch, cc[64];
|
|
char message[16];
|
|
int i, j;
|
|
|
|
for (i = 0; i < (int) sizeof(cc); i++) {
|
|
cc[i] = ch = getchp(STRIP_PARITY);
|
|
if (ch == '\r' || ch == '\n') {
|
|
put_crlf();
|
|
char_sent = 0;
|
|
return cc[i ? i - 1 : 0];
|
|
}
|
|
if (ch >= ' ') {
|
|
if (stty_query(TTY_CHAR_MODE)) {
|
|
put_crlf();
|
|
char_sent = 0;
|
|
return ch;
|
|
}
|
|
continue;
|
|
}
|
|
if (ch == 023) { /* Control S */
|
|
/* ignore control S, but tell me about it */
|
|
while (ch == 023 || ch == 021) {
|
|
ch = getchp(STRIP_PARITY);
|
|
if (i < (int) sizeof(cc))
|
|
cc[++i] = ch;
|
|
}
|
|
put_str("\nThe terminal sent a ^S -");
|
|
for (j = 0; j <= i; j++) {
|
|
sprintf(message, " %02X", cc[j] & 0xFF);
|
|
put_str(message);
|
|
}
|
|
put_crlf();
|
|
i = -1;
|
|
} else if (ch != 021) { /* Not Control Q */
|
|
/* could be abort character */
|
|
spin_flush();
|
|
if (tty_can_sync == SYNC_TESTED) {
|
|
(void) tty_sync_error();
|
|
} else {
|
|
put_str("\n? ");
|
|
}
|
|
}
|
|
}
|
|
return '?';
|
|
}
|
|
|
|
|
|
/*
|
|
** read_string(buffer, length)
|
|
**
|
|
** Read a string of characters from the input stream.
|
|
*/
|
|
void
|
|
read_string(
|
|
char *buf,
|
|
int length)
|
|
{
|
|
int ch, i;
|
|
|
|
for (i = 0; i < length - 1; ) {
|
|
ch = getchp(STRIP_PARITY);
|
|
if (ch == '\r' || ch == '\n') {
|
|
break;
|
|
}
|
|
if (ch == '\b' || ch == 127) {
|
|
if (i) {
|
|
putchp('\b');
|
|
putchp(' ');
|
|
putchp('\b');
|
|
i--;
|
|
}
|
|
} else {
|
|
buf[i++] = ch;
|
|
putchp(ch);
|
|
}
|
|
}
|
|
buf[i] = '\0';
|
|
put_crlf();
|
|
char_sent = 0;
|
|
}
|
|
|
|
/*
|
|
** maybe_wait(lines)
|
|
**
|
|
** wait if near the end of the screen, then clear screen
|
|
*/
|
|
void
|
|
maybe_wait(int n)
|
|
{
|
|
if (line_count + n >= lines) {
|
|
if (char_sent != 0) {
|
|
ptext("Go? ");
|
|
(void) wait_here();
|
|
}
|
|
put_clear();
|
|
} else {
|
|
put_crlf();
|
|
}
|
|
}
|