version 1.1.1.1, 1996/09/21 05:39:41 |
version 1.1.1.2, 2003/04/13 18:21:21 |
|
|
/* |
/* |
* Copyright (c) 1984,1985,1989,1994,1995 Mark Nudelman |
* Copyright (C) 1984-2002 Mark Nudelman |
* All rights reserved. |
|
* |
* |
* Redistribution and use in source and binary forms, with or without |
* You may distribute under the terms of either the GNU General Public |
* modification, are permitted provided that the following conditions |
* License or the Less License, as specified in the README file. |
* are met: |
|
* 1. Redistributions of source code must retain the above copyright |
|
* notice, this list of conditions and the following disclaimer. |
|
* 2. Redistributions in binary form must reproduce the above copyright |
|
* notice in the documentation and/or other materials provided with |
|
* the distribution. |
|
* |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY |
* For more information about less, or for information on how to |
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
* contact the author, see the README file. |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE |
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT |
|
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR |
|
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
|
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE |
|
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN |
|
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|
*/ |
*/ |
|
|
|
|
/* |
/* |
* Routines which deal with the characteristics of the terminal. |
* Routines which deal with the characteristics of the terminal. |
* Uses termcap to be as terminal-independent as possible. |
* Uses termcap to be as terminal-independent as possible. |
* |
|
* {{ Maybe someday this should be rewritten to use curses or terminfo. }} |
|
*/ |
*/ |
|
|
#include "less.h" |
#include "less.h" |
#include "cmd.h" |
#include "cmd.h" |
|
|
|
#if MSDOS_COMPILER |
|
#include "pckeys.h" |
|
#if MSDOS_COMPILER==MSOFTC |
|
#include <graph.h> |
|
#else |
|
#if MSDOS_COMPILER==BORLANDC || MSDOS_COMPILER==DJGPPC |
|
#include <conio.h> |
|
#if MSDOS_COMPILER==DJGPPC |
|
#include <pc.h> |
|
extern int fd0; |
|
#endif |
|
#else |
|
#if MSDOS_COMPILER==WIN32C |
|
#include <windows.h> |
|
#endif |
|
#endif |
|
#endif |
|
#include <time.h> |
|
|
|
#else |
|
|
#if HAVE_TERMIOS_H && HAVE_TERMIOS_FUNCS |
#if HAVE_TERMIOS_H && HAVE_TERMIOS_FUNCS |
#include <termios.h> |
#include <termios.h> |
#if HAVE_SYS_IOCTL_H && !defined(TIOCGWINSZ) |
#if HAVE_SYS_IOCTL_H && !defined(TIOCGWINSZ) |
|
|
#if HAVE_TERMIO_H |
#if HAVE_TERMIO_H |
#include <termio.h> |
#include <termio.h> |
#else |
#else |
|
#if HAVE_SGSTAT_H |
|
#include <sgstat.h> |
|
#else |
#include <sgtty.h> |
#include <sgtty.h> |
|
#endif |
#if HAVE_SYS_IOCTL_H && (defined(TIOCGWINSZ) || defined(TCGETA) || defined(TIOCGETP) || defined(WIOCGETD)) |
#if HAVE_SYS_IOCTL_H && (defined(TIOCGWINSZ) || defined(TCGETA) || defined(TIOCGETP) || defined(WIOCGETD)) |
#include <sys/ioctl.h> |
#include <sys/ioctl.h> |
#endif |
#endif |
#endif |
#endif |
#endif |
#endif |
|
|
#if HAVE_TERMCAP_H |
#if HAVE_TERMCAP_H |
#include <termcap.h> |
#include <termcap.h> |
#endif |
#endif |
|
#ifdef _OSK |
#ifndef TIOCGWINSZ |
#include <signal.h> |
/* |
#endif |
* For the Unix PC (ATT 7300 & 3B1): |
#if OS2 |
* Since WIOCGETD is defined in sys/window.h, we can't use that to decide |
|
* whether to include sys/window.h. Use SIGPHONE from sys/signal.h instead. |
|
*/ |
|
#include <sys/signal.h> |
#include <sys/signal.h> |
#ifdef SIGPHONE |
#include "pckeys.h" |
#include <sys/window.h> |
|
#endif |
#endif |
#endif |
|
|
|
#if HAVE_SYS_STREAM_H |
#if HAVE_SYS_STREAM_H |
#include <sys/stream.h> |
#include <sys/stream.h> |
#endif |
#endif |
|
|
#include <sys/ptem.h> |
#include <sys/ptem.h> |
#endif |
#endif |
|
|
|
#endif /* MSDOS_COMPILER */ |
|
|
|
/* |
|
* Check for broken termios package that forces you to manually |
|
* set the line discipline. |
|
*/ |
|
#ifdef __ultrix__ |
|
#define MUST_SET_LINE_DISCIPLINE 1 |
|
#else |
|
#define MUST_SET_LINE_DISCIPLINE 0 |
|
#endif |
|
|
#if OS2 |
#if OS2 |
#define DEFAULT_TERM "ansi" |
#define DEFAULT_TERM "ansi" |
|
static char *windowid; |
#else |
#else |
#define DEFAULT_TERM "unknown" |
#define DEFAULT_TERM "unknown" |
#endif |
#endif |
|
|
|
#if MSDOS_COMPILER==MSOFTC |
|
static int videopages; |
|
static long msec_loops; |
|
static int flash_created = 0; |
|
#define SETCOLORS(fg,bg) { _settextcolor(fg); _setbkcolor(bg); } |
|
#endif |
|
|
|
#if MSDOS_COMPILER==BORLANDC |
|
static unsigned short *whitescreen; |
|
static int flash_created = 0; |
|
#endif |
|
#if MSDOS_COMPILER==BORLANDC || MSDOS_COMPILER==DJGPPC |
|
#define _settextposition(y,x) gotoxy(x,y) |
|
#define _clearscreen(m) clrscr() |
|
#define _outtext(s) cputs(s) |
|
#define SETCOLORS(fg,bg) { textcolor(fg); textbackground(bg); } |
|
extern int sc_height; |
|
#endif |
|
|
|
#if MSDOS_COMPILER==WIN32C |
|
struct keyRecord |
|
{ |
|
int ascii; |
|
int scan; |
|
} currentKey; |
|
|
|
static int keyCount = 0; |
|
static WORD curr_attr; |
|
static int pending_scancode = 0; |
|
static WORD *whitescreen; |
|
|
|
static HANDLE con_out_save = INVALID_HANDLE_VALUE; /* previous console */ |
|
static HANDLE con_out_ours = INVALID_HANDLE_VALUE; /* our own */ |
|
HANDLE con_out = INVALID_HANDLE_VALUE; /* current console */ |
|
|
|
extern int quitting; |
|
static void win32_init_term(); |
|
static void win32_deinit_term(); |
|
|
|
#define FG_COLORS (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY) |
|
#define BG_COLORS (BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_INTENSITY) |
|
#define MAKEATTR(fg,bg) ((WORD)((fg)|((bg)<<4))) |
|
#define SETCOLORS(fg,bg) { curr_attr = MAKEATTR(fg,bg); \ |
|
if (SetConsoleTextAttribute(con_out, curr_attr) == 0) \ |
|
error("SETCOLORS failed"); } |
|
#endif |
|
|
|
#if MSDOS_COMPILER |
|
public int nm_fg_color; /* Color of normal text */ |
|
public int nm_bg_color; |
|
public int bo_fg_color; /* Color of bold text */ |
|
public int bo_bg_color; |
|
public int ul_fg_color; /* Color of underlined text */ |
|
public int ul_bg_color; |
|
public int so_fg_color; /* Color of standout text */ |
|
public int so_bg_color; |
|
public int bl_fg_color; /* Color of blinking text */ |
|
public int bl_bg_color; |
|
static int sy_fg_color; /* Color of system text (before less) */ |
|
static int sy_bg_color; |
|
|
|
#else |
|
|
/* |
/* |
* Strings passed to tputs() to do various terminal functions. |
* Strings passed to tputs() to do various terminal functions. |
*/ |
*/ |
|
|
*sc_e_keypad, /* End keypad mode */ |
*sc_e_keypad, /* End keypad mode */ |
*sc_init, /* Startup terminal initialization */ |
*sc_init, /* Startup terminal initialization */ |
*sc_deinit; /* Exit terminal de-initialization */ |
*sc_deinit; /* Exit terminal de-initialization */ |
|
#endif |
|
|
static int init_done = 0; |
static int init_done = 0; |
|
|
|
|
public int bl_s_width, bl_e_width; /* Printing width of blink seq */ |
public int bl_s_width, bl_e_width; /* Printing width of blink seq */ |
public int above_mem, below_mem; /* Memory retained above/below screen */ |
public int above_mem, below_mem; /* Memory retained above/below screen */ |
public int can_goto_line; /* Can move cursor to any line */ |
public int can_goto_line; /* Can move cursor to any line */ |
|
public int clear_bg; /* Clear fills with background color */ |
|
public int missing_cap = 0; /* Some capability is missing */ |
|
|
|
static int attrmode = AT_NORMAL; |
|
|
|
#if !MSDOS_COMPILER |
static char *cheaper(); |
static char *cheaper(); |
|
static void tmodes(); |
|
#endif |
|
|
/* |
/* |
* These two variables are sometimes defined in, |
* These two variables are sometimes defined in, |
|
|
extern short ospeed; /* Terminal output baud rate */ |
extern short ospeed; /* Terminal output baud rate */ |
extern char PC; /* Pad character */ |
extern char PC; /* Pad character */ |
#endif |
#endif |
|
#ifdef _OSK |
|
short ospeed; |
|
char PC_, *UP, *BC; |
|
#endif |
|
|
extern int quiet; /* If VERY_QUIET, use visual bell for bell */ |
extern int quiet; /* If VERY_QUIET, use visual bell for bell */ |
extern int know_dumb; /* Don't complain about a dumb terminal */ |
extern int no_back_scroll; |
extern int back_scroll; |
|
extern int swindow; |
extern int swindow; |
extern int no_init; |
extern int no_init; |
|
extern int no_keypad; |
|
extern int sigs; |
|
extern int wscroll; |
|
extern int screen_trashed; |
|
extern int tty; |
#if HILITE_SEARCH |
#if HILITE_SEARCH |
extern int hilite_search; |
extern int hilite_search; |
#endif |
#endif |
|
|
|
|
if (on == curr_on) |
if (on == curr_on) |
return; |
return; |
#if OS2 |
|
signal(SIGINT, SIG_IGN); |
|
erase_char = '\b'; |
|
kill_char = '\033'; |
|
#else |
|
#if HAVE_TERMIOS_H && HAVE_TERMIOS_FUNCS |
#if HAVE_TERMIOS_H && HAVE_TERMIOS_FUNCS |
{ |
{ |
struct termios s; |
struct termios s; |
static struct termios save_term; |
static struct termios save_term; |
|
static int saved_term = 0; |
|
|
if (on) |
if (on) |
{ |
{ |
/* |
/* |
* Get terminal modes. |
* Get terminal modes. |
*/ |
*/ |
tcgetattr(2, &s); |
tcgetattr(tty, &s); |
|
|
/* |
/* |
* Save modes and set certain variables dependent on modes. |
* Save modes and set certain variables dependent on modes. |
*/ |
*/ |
save_term = s; |
if (!saved_term) |
|
{ |
|
save_term = s; |
|
saved_term = 1; |
|
} |
#if HAVE_OSPEED |
#if HAVE_OSPEED |
switch (cfgetospeed(&s)) |
switch (cfgetospeed(&s)) |
{ |
{ |
|
|
#ifdef VWERASE |
#ifdef VWERASE |
werase_char = s.c_cc[VWERASE]; |
werase_char = s.c_cc[VWERASE]; |
#else |
#else |
werase_char = 0; |
werase_char = CONTROL('W'); |
#endif |
#endif |
|
|
/* |
/* |
|
|
); |
); |
|
|
s.c_oflag |= (0 |
s.c_oflag |= (0 |
#ifdef XTABS |
#ifdef OXTABS |
| XTABS |
| OXTABS |
#else |
#else |
#ifdef TAB3 |
#ifdef TAB3 |
| TAB3 |
| TAB3 |
#else |
#else |
#ifdef OXTABS |
#ifdef XTABS |
| OXTABS |
| XTABS |
#endif |
#endif |
#endif |
#endif |
#endif |
#endif |
|
|
); |
); |
s.c_cc[VMIN] = 1; |
s.c_cc[VMIN] = 1; |
s.c_cc[VTIME] = 0; |
s.c_cc[VTIME] = 0; |
|
#ifdef VLNEXT |
|
s.c_cc[VLNEXT] = 0; |
|
#endif |
|
#ifdef VDSUSP |
|
s.c_cc[VDSUSP] = 0; |
|
#endif |
|
#if MUST_SET_LINE_DISCIPLINE |
|
/* |
|
* System's termios is broken; need to explicitly |
|
* request TERMIODISC line discipline. |
|
*/ |
|
s.c_line = TERMIODISC; |
|
#endif |
} else |
} else |
{ |
{ |
/* |
/* |
|
|
*/ |
*/ |
s = save_term; |
s = save_term; |
} |
} |
tcsetattr(2, TCSADRAIN, &s); |
#if HAVE_FSYNC |
|
fsync(tty); |
|
#endif |
|
tcsetattr(tty, TCSADRAIN, &s); |
|
#if MUST_SET_LINE_DISCIPLINE |
|
if (!on) |
|
{ |
|
/* |
|
* Broken termios *ignores* any line discipline |
|
* except TERMIODISC. A different old line discipline |
|
* is therefore not restored, yet. Restore the old |
|
* line discipline by hand. |
|
*/ |
|
ioctl(tty, TIOCSETD, &save_term.c_line); |
|
} |
|
#endif |
} |
} |
#else |
#else |
#ifdef TCGETA |
#ifdef TCGETA |
{ |
{ |
struct termio s; |
struct termio s; |
static struct termio save_term; |
static struct termio save_term; |
|
static int saved_term = 0; |
|
|
if (on) |
if (on) |
{ |
{ |
/* |
/* |
* Get terminal modes. |
* Get terminal modes. |
*/ |
*/ |
ioctl(2, TCGETA, &s); |
ioctl(tty, TCGETA, &s); |
|
|
/* |
/* |
* Save modes and set certain variables dependent on modes. |
* Save modes and set certain variables dependent on modes. |
*/ |
*/ |
save_term = s; |
if (!saved_term) |
|
{ |
|
save_term = s; |
|
saved_term = 1; |
|
} |
#if HAVE_OSPEED |
#if HAVE_OSPEED |
ospeed = s.c_cflag & CBAUD; |
ospeed = s.c_cflag & CBAUD; |
#endif |
#endif |
|
|
#ifdef VWERASE |
#ifdef VWERASE |
werase_char = s.c_cc[VWERASE]; |
werase_char = s.c_cc[VWERASE]; |
#else |
#else |
werase_char = 0; |
werase_char = CONTROL('W'); |
#endif |
#endif |
|
|
/* |
/* |
|
|
*/ |
*/ |
s = save_term; |
s = save_term; |
} |
} |
ioctl(2, TCSETAW, &s); |
ioctl(tty, TCSETAW, &s); |
} |
} |
#else |
#else |
|
#ifdef TIOCGETP |
{ |
{ |
struct sgttyb s; |
struct sgttyb s; |
static struct sgttyb save_term; |
static struct sgttyb save_term; |
|
static int saved_term = 0; |
|
|
if (on) |
if (on) |
{ |
{ |
/* |
/* |
* Get terminal modes. |
* Get terminal modes. |
*/ |
*/ |
ioctl(2, TIOCGETP, &s); |
ioctl(tty, TIOCGETP, &s); |
|
|
/* |
/* |
* Save modes and set certain variables dependent on modes. |
* Save modes and set certain variables dependent on modes. |
*/ |
*/ |
save_term = s; |
if (!saved_term) |
|
{ |
|
save_term = s; |
|
saved_term = 1; |
|
} |
#if HAVE_OSPEED |
#if HAVE_OSPEED |
ospeed = s.sg_ospeed; |
ospeed = s.sg_ospeed; |
#endif |
#endif |
erase_char = s.sg_erase; |
erase_char = s.sg_erase; |
kill_char = s.sg_kill; |
kill_char = s.sg_kill; |
werase_char = 0; |
werase_char = CONTROL('W'); |
|
|
/* |
/* |
* Set the modes to the way we want them. |
* Set the modes to the way we want them. |
|
|
*/ |
*/ |
s = save_term; |
s = save_term; |
} |
} |
ioctl(2, TIOCSETN, &s); |
ioctl(tty, TIOCSETN, &s); |
} |
} |
|
#else |
|
#ifdef _OSK |
|
{ |
|
struct sgbuf s; |
|
static struct sgbuf save_term; |
|
static int saved_term = 0; |
|
|
|
if (on) |
|
{ |
|
/* |
|
* Get terminal modes. |
|
*/ |
|
_gs_opt(tty, &s); |
|
|
|
/* |
|
* Save modes and set certain variables dependent on modes. |
|
*/ |
|
if (!saved_term) |
|
{ |
|
save_term = s; |
|
saved_term = 1; |
|
} |
|
erase_char = s.sg_bspch; |
|
kill_char = s.sg_dlnch; |
|
werase_char = CONTROL('W'); |
|
|
|
/* |
|
* Set the modes to the way we want them. |
|
*/ |
|
s.sg_echo = 0; |
|
s.sg_eofch = 0; |
|
s.sg_pause = 0; |
|
s.sg_psch = 0; |
|
} else |
|
{ |
|
/* |
|
* Restore saved modes. |
|
*/ |
|
s = save_term; |
|
} |
|
_ss_opt(tty, &s); |
|
} |
|
#else |
|
/* MS-DOS, Windows, or OS2 */ |
|
#if OS2 |
|
/* OS2 */ |
|
LSIGNAL(SIGINT, SIG_IGN); |
#endif |
#endif |
|
erase_char = '\b'; |
|
#if MSDOS_COMPILER==DJGPPC |
|
kill_char = CONTROL('U'); |
|
/* |
|
* So that when we shell out or run another program, its |
|
* stdin is in cooked mode. We do not switch stdin to binary |
|
* mode if fd0 is zero, since that means we were called before |
|
* tty was reopened in open_getchr, in which case we would be |
|
* changing the original stdin device outside less. |
|
*/ |
|
if (fd0 != 0) |
|
setmode(0, on ? O_BINARY : O_TEXT); |
|
#else |
|
kill_char = ESC; |
#endif |
#endif |
|
werase_char = CONTROL('W'); |
#endif |
#endif |
|
#endif |
|
#endif |
|
#endif |
curr_on = on; |
curr_on = on; |
} |
} |
|
|
static void |
#if !MSDOS_COMPILER |
cannot(s) |
/* |
char *s; |
* Some glue to prevent calling termcap functions if tgetent() failed. |
|
*/ |
|
static int hardcopy; |
|
|
|
static char * |
|
ltget_env(capname) |
|
char *capname; |
{ |
{ |
PARG parg; |
char name[16]; |
|
|
if (know_dumb) |
strcpy(name, "LESS_TERMCAP_"); |
/* |
strcat(name, capname); |
* User knows this is a dumb terminal, so don't tell him. |
return (lgetenv(name)); |
*/ |
|
return; |
|
|
|
parg.p_string = s; |
|
error("WARNING: terminal cannot %s", &parg); |
|
} |
} |
|
|
/* |
static int |
* Get size of the output screen. |
ltgetflag(capname) |
*/ |
char *capname; |
#if OS2 |
|
public void |
|
scrsize() |
|
{ |
{ |
int s[2]; |
char *s; |
|
|
_scrsize(s); |
if ((s = ltget_env(capname)) != NULL) |
sc_width = s[0]; |
return (*s != '\0' && *s != '0'); |
sc_height = s[1]; |
if (hardcopy) |
|
return (0); |
|
return (tgetflag(capname)); |
} |
} |
|
|
#else |
static int |
|
ltgetnum(capname) |
public void |
char *capname; |
scrsize() |
|
{ |
{ |
register char *s; |
char *s; |
#ifdef TIOCGWINSZ |
|
struct winsize w; |
|
#else |
|
#ifdef WIOCGETD |
|
struct uwdata w; |
|
#endif |
|
#endif |
|
|
|
#ifdef TIOCGWINSZ |
if ((s = ltget_env(capname)) != NULL) |
if (ioctl(2, TIOCGWINSZ, &w) == 0 && w.ws_row > 0) |
return (atoi(s)); |
sc_height = w.ws_row; |
if (hardcopy) |
else |
return (-1); |
#else |
return (tgetnum(capname)); |
#ifdef WIOCGETD |
} |
if (ioctl(2, WIOCGETD, &w) == 0 && w.uw_height > 0) |
|
sc_height = w.uw_height/w.uw_vs; |
|
else |
|
#endif |
|
#endif |
|
if ((s = getenv("LINES")) != NULL) |
|
sc_height = atoi(s); |
|
else |
|
sc_height = tgetnum("li"); |
|
|
|
if (sc_height <= 0) |
static char * |
sc_height = 24; |
ltgetstr(capname, pp) |
|
char *capname; |
|
char **pp; |
|
{ |
|
char *s; |
|
|
#ifdef TIOCGWINSZ |
if ((s = ltget_env(capname)) != NULL) |
if (ioctl(2, TIOCGWINSZ, &w) == 0 && w.ws_col > 0) |
return (s); |
sc_width = w.ws_col; |
if (hardcopy) |
else |
return (NULL); |
#ifdef WIOCGETD |
return (tgetstr(capname, pp)); |
if (ioctl(2, WIOCGETD, &w) == 0 && w.uw_width > 0) |
|
sc_width = w.uw_width/w.uw_hs; |
|
else |
|
#endif |
|
#endif |
|
if ((s = getenv("COLUMNS")) != NULL) |
|
sc_width = atoi(s); |
|
else |
|
sc_width = tgetnum("co"); |
|
|
|
if (sc_width <= 0) |
|
sc_width = 80; |
|
} |
} |
#endif /* OS2 */ |
#endif /* MSDOS_COMPILER */ |
|
|
/* |
/* |
* Take care of the "variable" keys. |
* Get size of the output screen. |
* Certain keys send escape sequences which differ on different terminals |
|
* (such as the arrow keys, INSERT, DELETE, etc.) |
|
* Construct the commands based on these keys. |
|
*/ |
*/ |
public void |
public void |
get_editkeys() |
scrsize() |
{ |
{ |
char *sp; |
register char *s; |
char *s; |
int sys_height; |
char tbuf[40]; |
int sys_width; |
|
#if !MSDOS_COMPILER |
|
int n; |
|
#endif |
|
|
static char kfcmdtable[400]; |
#define DEF_SC_WIDTH 80 |
int sz_kfcmdtable = 0; |
#if MSDOS_COMPILER |
static char kecmdtable[400]; |
#define DEF_SC_HEIGHT 25 |
int sz_kecmdtable = 0; |
#else |
|
#define DEF_SC_HEIGHT 24 |
|
#endif |
|
|
#define put_cmd(str,action,tbl,sz) { \ |
|
strcpy(tbl+sz, str); \ |
|
sz += strlen(str) + 1; \ |
|
tbl[sz++] = action; } |
|
#define put_esc_cmd(str,action,tbl,sz) { \ |
|
tbl[sz++] = ESC; \ |
|
put_cmd(str,action,tbl,sz); } |
|
|
|
#define put_fcmd(str,action) put_cmd(str,action,kfcmdtable,sz_kfcmdtable) |
sys_width = sys_height = 0; |
#define put_ecmd(str,action) put_cmd(str,action,kecmdtable,sz_kecmdtable) |
|
#define put_esc_fcmd(str,action) put_esc_cmd(str,action,kfcmdtable,sz_kfcmdtable) |
|
#define put_esc_ecmd(str,action) put_esc_cmd(str,action,kecmdtable,sz_kecmdtable) |
|
|
|
/* |
#if MSDOS_COMPILER==MSOFTC |
* Look at some interesting keys and see what strings they send. |
|
* Create commands (both command keys and line-edit keys). |
|
*/ |
|
|
|
/* RIGHT ARROW */ |
|
sp = tbuf; |
|
if ((s = tgetstr("kr", &sp)) != NULL) |
|
{ |
{ |
put_ecmd(s, EC_RIGHT); |
struct videoconfig w; |
put_esc_ecmd(s, EC_W_RIGHT); |
_getvideoconfig(&w); |
|
sys_height = w.numtextrows; |
|
sys_width = w.numtextcols; |
} |
} |
|
#else |
/* LEFT ARROW */ |
#if MSDOS_COMPILER==BORLANDC || MSDOS_COMPILER==DJGPPC |
sp = tbuf; |
|
if ((s = tgetstr("kl", &sp)) != NULL) |
|
{ |
{ |
put_ecmd(s, EC_LEFT); |
struct text_info w; |
put_esc_ecmd(s, EC_W_LEFT); |
gettextinfo(&w); |
|
sys_height = w.screenheight; |
|
sys_width = w.screenwidth; |
} |
} |
|
#else |
/* UP ARROW */ |
#if MSDOS_COMPILER==WIN32C |
sp = tbuf; |
|
if ((s = tgetstr("ku", &sp)) != NULL) |
|
{ |
{ |
put_ecmd(s, EC_UP); |
CONSOLE_SCREEN_BUFFER_INFO scr; |
put_fcmd(s, A_B_LINE); |
GetConsoleScreenBufferInfo(con_out, &scr); |
|
sys_height = scr.srWindow.Bottom - scr.srWindow.Top + 1; |
|
sys_width = scr.srWindow.Right - scr.srWindow.Left + 1; |
} |
} |
|
#else |
/* DOWN ARROW */ |
#if OS2 |
sp = tbuf; |
|
if ((s = tgetstr("kd", &sp)) != NULL) |
|
{ |
{ |
put_ecmd(s, EC_DOWN); |
int s[2]; |
put_fcmd(s, A_F_LINE); |
_scrsize(s); |
|
sys_width = s[0]; |
|
sys_height = s[1]; |
|
/* |
|
* When using terminal emulators for XFree86/OS2, the |
|
* _scrsize function does not work well. |
|
* Call the scrsize.exe program to get the window size. |
|
*/ |
|
windowid = getenv("WINDOWID"); |
|
if (windowid != NULL) |
|
{ |
|
FILE *fd = popen("scrsize", "rt"); |
|
if (fd != NULL) |
|
{ |
|
int w, h; |
|
fscanf(fd, "%i %i", &w, &h); |
|
if (w > 0 && h > 0) |
|
{ |
|
sys_width = w; |
|
sys_height = h; |
|
} |
|
pclose(fd); |
|
} |
|
} |
} |
} |
|
#else |
/* PAGE UP */ |
#ifdef TIOCGWINSZ |
sp = tbuf; |
|
if ((s = tgetstr("kP", &sp)) != NULL) |
|
{ |
{ |
put_fcmd(s, A_B_SCREEN); |
struct winsize w; |
|
if (ioctl(2, TIOCGWINSZ, &w) == 0) |
|
{ |
|
if (w.ws_row > 0) |
|
sys_height = w.ws_row; |
|
if (w.ws_col > 0) |
|
sys_width = w.ws_col; |
|
} |
} |
} |
|
#else |
/* PAGE DOWN */ |
#ifdef WIOCGETD |
sp = tbuf; |
|
if ((s = tgetstr("kN", &sp)) != NULL) |
|
{ |
{ |
put_fcmd(s, A_F_SCREEN); |
struct uwdata w; |
|
if (ioctl(2, WIOCGETD, &w) == 0) |
|
{ |
|
if (w.uw_height > 0) |
|
sys_height = w.uw_height / w.uw_vs; |
|
if (w.uw_width > 0) |
|
sys_width = w.uw_width / w.uw_hs; |
|
} |
} |
} |
|
#endif |
/* HOME */ |
#endif |
sp = tbuf; |
#endif |
if ((s = tgetstr("kh", &sp)) != NULL) |
#endif |
{ |
#endif |
put_ecmd(s, EC_HOME); |
#endif |
} |
|
|
|
/* END */ |
if (sys_height > 0) |
sp = tbuf; |
sc_height = sys_height; |
if ((s = tgetstr("@7", &sp)) != NULL) |
else if ((s = lgetenv("LINES")) != NULL) |
{ |
sc_height = atoi(s); |
put_ecmd(s, EC_END); |
#if !MSDOS_COMPILER |
} |
else if ((n = ltgetnum("li")) > 0) |
|
sc_height = n; |
|
#endif |
|
else |
|
sc_height = DEF_SC_HEIGHT; |
|
|
/* DELETE */ |
if (sys_width > 0) |
sp = tbuf; |
sc_width = sys_width; |
if ((s = tgetstr("kD", &sp)) == NULL) |
else if ((s = lgetenv("COLUMNS")) != NULL) |
{ |
sc_width = atoi(s); |
/* Use DEL (\177) if no "kD" termcap. */ |
#if !MSDOS_COMPILER |
tbuf[1] = '\177'; |
else if ((n = ltgetnum("co")) > 0) |
tbuf[2] = '\0'; |
sc_width = n; |
s = tbuf+1; |
#endif |
} |
else |
put_ecmd(s, EC_DELETE); |
sc_width = DEF_SC_WIDTH; |
put_esc_ecmd(s, EC_W_DELETE); |
} |
|
|
/* BACKSPACE */ |
|
tbuf[0] = ESC; |
|
tbuf[1] = erase_char; |
|
tbuf[2] = '\0'; |
|
put_ecmd(tbuf, EC_W_BACKSPACE); |
|
|
|
if (werase_char != 0) |
#if MSDOS_COMPILER==MSOFTC |
{ |
/* |
tbuf[0] = werase_char; |
* Figure out how many empty loops it takes to delay a millisecond. |
tbuf[1] = '\0'; |
*/ |
put_ecmd(tbuf, EC_W_BACKSPACE); |
static void |
} |
get_clock() |
|
{ |
|
clock_t start; |
|
|
/* |
/* |
* Register the two tables. |
* Get synchronized at the start of a tick. |
*/ |
*/ |
add_fcmd_table(kfcmdtable, sz_kfcmdtable); |
start = clock(); |
add_ecmd_table(kecmdtable, sz_kecmdtable); |
while (clock() == start) |
|
; |
|
/* |
|
* Now count loops till the next tick. |
|
*/ |
|
start = clock(); |
|
msec_loops = 0; |
|
while (clock() == start) |
|
msec_loops++; |
|
/* |
|
* Convert from (loops per clock) to (loops per millisecond). |
|
*/ |
|
msec_loops *= CLOCKS_PER_SEC; |
|
msec_loops /= 1000; |
} |
} |
|
|
#if DEBUG |
/* |
|
* Delay for a specified number of milliseconds. |
|
*/ |
static void |
static void |
get_debug_term() |
dummy_func() |
{ |
{ |
auto_wrap = 1; |
static long delay_dummy = 0; |
ignaw = 1; |
delay_dummy++; |
so_s_width = so_e_width = 0; |
|
bo_s_width = bo_e_width = 0; |
|
ul_s_width = ul_e_width = 0; |
|
bl_s_width = bl_e_width = 0; |
|
sc_s_keypad = "(InitKey)"; |
|
sc_e_keypad = "(DeinitKey)"; |
|
sc_init = "(InitTerm)"; |
|
sc_deinit = "(DeinitTerm)"; |
|
sc_eol_clear = "(ClearEOL)"; |
|
sc_eos_clear = "(ClearEOS)"; |
|
sc_clear = "(ClearScreen)"; |
|
sc_move = "(Move<%d,%d>)"; |
|
sc_s_in = "(SO+)"; |
|
sc_s_out = "(SO-)"; |
|
sc_u_in = "(UL+)"; |
|
sc_u_out = "(UL-)"; |
|
sc_b_in = "(BO+)"; |
|
sc_b_out = "(BO-)"; |
|
sc_bl_in = "(BL+)"; |
|
sc_bl_out = "(BL-)"; |
|
sc_visual_bell ="(VBell)"; |
|
sc_backspace = "(BS)"; |
|
sc_home = "(Home)"; |
|
sc_lower_left = "(LL)"; |
|
sc_addline = "(AddLine)"; |
|
} |
} |
|
|
|
static void |
|
delay(msec) |
|
int msec; |
|
{ |
|
long i; |
|
|
|
while (msec-- > 0) |
|
{ |
|
for (i = 0; i < msec_loops; i++) |
|
{ |
|
/* |
|
* Make it look like we're doing something here, |
|
* so the optimizer doesn't remove the whole loop. |
|
*/ |
|
dummy_func(); |
|
} |
|
} |
|
} |
#endif |
#endif |
|
|
/* |
/* |
|
* Return the characters actually input by a "special" key. |
|
*/ |
|
public char * |
|
special_key_str(key) |
|
int key; |
|
{ |
|
static char tbuf[40]; |
|
char *s; |
|
#if MSDOS_COMPILER || OS2 |
|
static char k_right[] = { '\340', PCK_RIGHT, 0 }; |
|
static char k_left[] = { '\340', PCK_LEFT, 0 }; |
|
static char k_ctl_right[] = { '\340', PCK_CTL_RIGHT, 0 }; |
|
static char k_ctl_left[] = { '\340', PCK_CTL_LEFT, 0 }; |
|
static char k_insert[] = { '\340', PCK_INSERT, 0 }; |
|
static char k_delete[] = { '\340', PCK_DELETE, 0 }; |
|
static char k_ctl_delete[] = { '\340', PCK_CTL_DELETE, 0 }; |
|
static char k_ctl_backspace[] = { '\177', 0 }; |
|
static char k_home[] = { '\340', PCK_HOME, 0 }; |
|
static char k_end[] = { '\340', PCK_END, 0 }; |
|
static char k_up[] = { '\340', PCK_UP, 0 }; |
|
static char k_down[] = { '\340', PCK_DOWN, 0 }; |
|
static char k_backtab[] = { '\340', PCK_SHIFT_TAB, 0 }; |
|
static char k_pagedown[] = { '\340', PCK_PAGEDOWN, 0 }; |
|
static char k_pageup[] = { '\340', PCK_PAGEUP, 0 }; |
|
static char k_f1[] = { '\340', PCK_F1, 0 }; |
|
#endif |
|
#if !MSDOS_COMPILER |
|
char *sp = tbuf; |
|
#endif |
|
|
|
switch (key) |
|
{ |
|
#if OS2 |
|
/* |
|
* If windowid is not NULL, assume less is executed in |
|
* the XFree86 environment. |
|
*/ |
|
case SK_RIGHT_ARROW: |
|
s = windowid ? ltgetstr("kr", &sp) : k_right; |
|
break; |
|
case SK_LEFT_ARROW: |
|
s = windowid ? ltgetstr("kl", &sp) : k_left; |
|
break; |
|
case SK_UP_ARROW: |
|
s = windowid ? ltgetstr("ku", &sp) : k_up; |
|
break; |
|
case SK_DOWN_ARROW: |
|
s = windowid ? ltgetstr("kd", &sp) : k_down; |
|
break; |
|
case SK_PAGE_UP: |
|
s = windowid ? ltgetstr("kP", &sp) : k_pageup; |
|
break; |
|
case SK_PAGE_DOWN: |
|
s = windowid ? ltgetstr("kN", &sp) : k_pagedown; |
|
break; |
|
case SK_HOME: |
|
s = windowid ? ltgetstr("kh", &sp) : k_home; |
|
break; |
|
case SK_END: |
|
s = windowid ? ltgetstr("@7", &sp) : k_end; |
|
break; |
|
case SK_DELETE: |
|
if (windowid) |
|
{ |
|
s = ltgetstr("kD", &sp); |
|
if (s == NULL) |
|
{ |
|
tbuf[0] = '\177'; |
|
tbuf[1] = '\0'; |
|
s = tbuf; |
|
} |
|
} else |
|
s = k_delete; |
|
break; |
|
#endif |
|
#if MSDOS_COMPILER |
|
case SK_RIGHT_ARROW: |
|
s = k_right; |
|
break; |
|
case SK_LEFT_ARROW: |
|
s = k_left; |
|
break; |
|
case SK_UP_ARROW: |
|
s = k_up; |
|
break; |
|
case SK_DOWN_ARROW: |
|
s = k_down; |
|
break; |
|
case SK_PAGE_UP: |
|
s = k_pageup; |
|
break; |
|
case SK_PAGE_DOWN: |
|
s = k_pagedown; |
|
break; |
|
case SK_HOME: |
|
s = k_home; |
|
break; |
|
case SK_END: |
|
s = k_end; |
|
break; |
|
case SK_DELETE: |
|
s = k_delete; |
|
break; |
|
#endif |
|
#if MSDOS_COMPILER || OS2 |
|
case SK_INSERT: |
|
s = k_insert; |
|
break; |
|
case SK_CTL_LEFT_ARROW: |
|
s = k_ctl_left; |
|
break; |
|
case SK_CTL_RIGHT_ARROW: |
|
s = k_ctl_right; |
|
break; |
|
case SK_CTL_BACKSPACE: |
|
s = k_ctl_backspace; |
|
break; |
|
case SK_CTL_DELETE: |
|
s = k_ctl_delete; |
|
break; |
|
case SK_F1: |
|
s = k_f1; |
|
break; |
|
case SK_BACKTAB: |
|
s = k_backtab; |
|
break; |
|
#else |
|
case SK_RIGHT_ARROW: |
|
s = ltgetstr("kr", &sp); |
|
break; |
|
case SK_LEFT_ARROW: |
|
s = ltgetstr("kl", &sp); |
|
break; |
|
case SK_UP_ARROW: |
|
s = ltgetstr("ku", &sp); |
|
break; |
|
case SK_DOWN_ARROW: |
|
s = ltgetstr("kd", &sp); |
|
break; |
|
case SK_PAGE_UP: |
|
s = ltgetstr("kP", &sp); |
|
break; |
|
case SK_PAGE_DOWN: |
|
s = ltgetstr("kN", &sp); |
|
break; |
|
case SK_HOME: |
|
s = ltgetstr("kh", &sp); |
|
break; |
|
case SK_END: |
|
s = ltgetstr("@7", &sp); |
|
break; |
|
case SK_DELETE: |
|
s = ltgetstr("kD", &sp); |
|
if (s == NULL) |
|
{ |
|
tbuf[0] = '\177'; |
|
tbuf[1] = '\0'; |
|
s = tbuf; |
|
} |
|
break; |
|
#endif |
|
case SK_CONTROL_K: |
|
tbuf[0] = CONTROL('K'); |
|
tbuf[1] = '\0'; |
|
s = tbuf; |
|
break; |
|
default: |
|
return (NULL); |
|
} |
|
return (s); |
|
} |
|
|
|
/* |
* Get terminal capabilities via termcap. |
* Get terminal capabilities via termcap. |
*/ |
*/ |
public void |
public void |
get_term() |
get_term() |
{ |
{ |
|
#if MSDOS_COMPILER |
|
auto_wrap = 1; |
|
ignaw = 0; |
|
can_goto_line = 1; |
|
clear_bg = 1; |
|
/* |
|
* Set up default colors. |
|
* The xx_s_width and xx_e_width vars are already initialized to 0. |
|
*/ |
|
#if MSDOS_COMPILER==MSOFTC |
|
sy_bg_color = _getbkcolor(); |
|
sy_fg_color = _gettextcolor(); |
|
get_clock(); |
|
#else |
|
#if MSDOS_COMPILER==BORLANDC || MSDOS_COMPILER==DJGPPC |
|
{ |
|
struct text_info w; |
|
gettextinfo(&w); |
|
sy_bg_color = (w.attribute >> 4) & 0x0F; |
|
sy_fg_color = (w.attribute >> 0) & 0x0F; |
|
} |
|
#else |
|
#if MSDOS_COMPILER==WIN32C |
|
{ |
|
DWORD nread; |
|
CONSOLE_SCREEN_BUFFER_INFO scr; |
|
|
|
con_out_save = con_out = GetStdHandle(STD_OUTPUT_HANDLE); |
|
/* |
|
* Always open stdin in binary. Note this *must* be done |
|
* before any file operations have been done on fd0. |
|
*/ |
|
SET_BINARY(0); |
|
GetConsoleScreenBufferInfo(con_out, &scr); |
|
ReadConsoleOutputAttribute(con_out, &curr_attr, |
|
1, scr.dwCursorPosition, &nread); |
|
sy_bg_color = (curr_attr & BG_COLORS) >> 4; /* normalize */ |
|
sy_fg_color = curr_attr & FG_COLORS; |
|
} |
|
#endif |
|
#endif |
|
#endif |
|
nm_fg_color = sy_fg_color; |
|
nm_bg_color = sy_bg_color; |
|
bo_fg_color = 11; |
|
bo_bg_color = 0; |
|
ul_fg_color = 9; |
|
ul_bg_color = 0; |
|
so_fg_color = 15; |
|
so_bg_color = 9; |
|
bl_fg_color = 15; |
|
bl_bg_color = 0; |
|
|
|
/* |
|
* Get size of the screen. |
|
*/ |
|
scrsize(); |
|
pos_init(); |
|
|
|
|
|
#else /* !MSDOS_COMPILER */ |
|
|
char *sp; |
char *sp; |
register char *t1, *t2; |
register char *t1, *t2; |
register int hard; |
|
char *term; |
char *term; |
char termbuf[2048]; |
char termbuf[TERMBUF_SIZE]; |
|
|
static char sbuf[1024]; |
static char sbuf[TERMSBUF_SIZE]; |
|
|
#ifdef OS2 |
#if OS2 |
/* |
/* |
* Make sure the termcap database is available. |
* Make sure the termcap database is available. |
*/ |
*/ |
sp = getenv("TERMCAP"); |
sp = lgetenv("TERMCAP"); |
if (sp == NULL || *sp == '\0') |
if (sp == NULL || *sp == '\0') |
{ |
{ |
char *termcap; |
char *termcap; |
|
|
/* |
/* |
* Find out what kind of terminal this is. |
* Find out what kind of terminal this is. |
*/ |
*/ |
if ((term = getenv("TERM")) == NULL) |
if ((term = lgetenv("TERM")) == NULL) |
term = DEFAULT_TERM; |
term = DEFAULT_TERM; |
|
hardcopy = 0; |
if (tgetent(termbuf, term) <= 0) |
if (tgetent(termbuf, term) <= 0) |
strcpy(termbuf, "dumb:hc:"); |
hardcopy = 1; |
|
if (ltgetflag("hc")) |
|
hardcopy = 1; |
|
|
hard = tgetflag("hc"); |
|
|
|
/* |
/* |
* Get size of the screen. |
* Get size of the screen. |
*/ |
*/ |
scrsize(); |
scrsize(); |
pos_init(); |
pos_init(); |
|
|
#if DEBUG |
auto_wrap = ltgetflag("am"); |
if (strncmp(term,"LESSDEBUG",9) == 0) |
ignaw = ltgetflag("xn"); |
{ |
above_mem = ltgetflag("da"); |
get_debug_term(); |
below_mem = ltgetflag("db"); |
return; |
clear_bg = ltgetflag("ut"); |
} |
|
#endif /* DEBUG */ |
|
|
|
auto_wrap = tgetflag("am"); |
|
ignaw = tgetflag("xn"); |
|
above_mem = tgetflag("da"); |
|
below_mem = tgetflag("db"); |
|
|
|
/* |
/* |
* Assumes termcap variable "sg" is the printing width of: |
* Assumes termcap variable "sg" is the printing width of: |
* the standout sequence, the end standout sequence, |
* the standout sequence, the end standout sequence, |
* the underline sequence, the end underline sequence, |
* the underline sequence, the end underline sequence, |
* the boldface sequence, and the end boldface sequence. |
* the boldface sequence, and the end boldface sequence. |
*/ |
*/ |
if ((so_s_width = tgetnum("sg")) < 0) |
if ((so_s_width = ltgetnum("sg")) < 0) |
so_s_width = 0; |
so_s_width = 0; |
so_e_width = so_s_width; |
so_e_width = so_s_width; |
|
|
|
|
sp = sbuf; |
sp = sbuf; |
|
|
#if HAVE_OSPEED |
#if HAVE_OSPEED |
sc_pad = tgetstr("pc", &sp); |
sc_pad = ltgetstr("pc", &sp); |
if (sc_pad != NULL) |
if (sc_pad != NULL) |
PC = *sc_pad; |
PC = *sc_pad; |
#endif |
#endif |
|
|
sc_s_keypad = tgetstr("ks", &sp); |
sc_s_keypad = ltgetstr("ks", &sp); |
if (sc_s_keypad == NULL) |
if (sc_s_keypad == NULL) |
sc_s_keypad = ""; |
sc_s_keypad = ""; |
sc_e_keypad = tgetstr("ke", &sp); |
sc_e_keypad = ltgetstr("ke", &sp); |
if (sc_e_keypad == NULL) |
if (sc_e_keypad == NULL) |
sc_e_keypad = ""; |
sc_e_keypad = ""; |
|
|
sc_init = tgetstr("ti", &sp); |
sc_init = ltgetstr("ti", &sp); |
if (sc_init == NULL) |
if (sc_init == NULL) |
sc_init = ""; |
sc_init = ""; |
|
|
sc_deinit= tgetstr("te", &sp); |
sc_deinit= ltgetstr("te", &sp); |
if (sc_deinit == NULL) |
if (sc_deinit == NULL) |
sc_deinit = ""; |
sc_deinit = ""; |
|
|
sc_eol_clear = tgetstr("ce", &sp); |
sc_eol_clear = ltgetstr("ce", &sp); |
if (hard || sc_eol_clear == NULL || *sc_eol_clear == '\0') |
if (sc_eol_clear == NULL || *sc_eol_clear == '\0') |
{ |
{ |
cannot("clear to end of line"); |
missing_cap = 1; |
sc_eol_clear = ""; |
sc_eol_clear = ""; |
} |
} |
|
|
sc_eos_clear = tgetstr("cd", &sp); |
sc_eos_clear = ltgetstr("cd", &sp); |
if (below_mem && |
if (below_mem && (sc_eos_clear == NULL || *sc_eos_clear == '\0')) |
(hard || sc_eos_clear == NULL || *sc_eos_clear == '\0')) |
|
{ |
{ |
cannot("clear to end of screen"); |
missing_cap = 1; |
sc_eol_clear = ""; |
sc_eol_clear = ""; |
} |
} |
|
|
sc_clear = tgetstr("cl", &sp); |
sc_clear = ltgetstr("cl", &sp); |
if (hard || sc_clear == NULL || *sc_clear == '\0') |
if (sc_clear == NULL || *sc_clear == '\0') |
{ |
{ |
cannot("clear screen"); |
missing_cap = 1; |
sc_clear = "\n\n"; |
sc_clear = "\n\n"; |
} |
} |
|
|
sc_move = tgetstr("cm", &sp); |
sc_move = ltgetstr("cm", &sp); |
if (hard || sc_move == NULL || *sc_move == '\0') |
if (sc_move == NULL || *sc_move == '\0') |
{ |
{ |
/* |
/* |
* This is not an error here, because we don't |
* This is not an error here, because we don't |
|
|
} else |
} else |
can_goto_line = 1; |
can_goto_line = 1; |
|
|
sc_s_in = tgetstr("so", &sp); |
tmodes("so", "se", &sc_s_in, &sc_s_out, "", "", &sp); |
if (hard || sc_s_in == NULL) |
tmodes("us", "ue", &sc_u_in, &sc_u_out, sc_s_in, sc_s_out, &sp); |
sc_s_in = ""; |
tmodes("md", "me", &sc_b_in, &sc_b_out, sc_s_in, sc_s_out, &sp); |
|
tmodes("mb", "me", &sc_bl_in, &sc_bl_out, sc_s_in, sc_s_out, &sp); |
|
|
sc_s_out = tgetstr("se", &sp); |
sc_visual_bell = ltgetstr("vb", &sp); |
if (hard || sc_s_out == NULL) |
if (sc_visual_bell == NULL) |
sc_s_out = ""; |
|
|
|
sc_u_in = tgetstr("us", &sp); |
|
if (hard || sc_u_in == NULL) |
|
sc_u_in = sc_s_in; |
|
|
|
sc_u_out = tgetstr("ue", &sp); |
|
if (hard || sc_u_out == NULL) |
|
sc_u_out = sc_s_out; |
|
|
|
sc_b_in = tgetstr("md", &sp); |
|
if (hard || sc_b_in == NULL) |
|
{ |
|
sc_b_in = sc_s_in; |
|
sc_b_out = sc_s_out; |
|
} else |
|
{ |
|
sc_b_out = tgetstr("me", &sp); |
|
if (hard || sc_b_out == NULL) |
|
sc_b_out = ""; |
|
} |
|
|
|
sc_bl_in = tgetstr("mb", &sp); |
|
if (hard || sc_bl_in == NULL) |
|
{ |
|
sc_bl_in = sc_s_in; |
|
sc_bl_out = sc_s_out; |
|
} else |
|
{ |
|
sc_bl_out = tgetstr("me", &sp); |
|
if (hard || sc_bl_out == NULL) |
|
sc_bl_out = ""; |
|
} |
|
|
|
sc_visual_bell = tgetstr("vb", &sp); |
|
if (hard || sc_visual_bell == NULL) |
|
sc_visual_bell = ""; |
sc_visual_bell = ""; |
|
|
if (tgetflag("bs")) |
if (ltgetflag("bs")) |
sc_backspace = "\b"; |
sc_backspace = "\b"; |
else |
else |
{ |
{ |
sc_backspace = tgetstr("bc", &sp); |
sc_backspace = ltgetstr("bc", &sp); |
if (sc_backspace == NULL || *sc_backspace == '\0') |
if (sc_backspace == NULL || *sc_backspace == '\0') |
sc_backspace = "\b"; |
sc_backspace = "\b"; |
} |
} |
|
|
* Choose between using "ho" and "cm" ("home" and "cursor move") |
* Choose between using "ho" and "cm" ("home" and "cursor move") |
* to move the cursor to the upper left corner of the screen. |
* to move the cursor to the upper left corner of the screen. |
*/ |
*/ |
t1 = tgetstr("ho", &sp); |
t1 = ltgetstr("ho", &sp); |
if (hard || t1 == NULL) |
if (t1 == NULL) |
t1 = ""; |
t1 = ""; |
if (*sc_move == '\0') |
if (*sc_move == '\0') |
t2 = ""; |
t2 = ""; |
|
|
t2 = sp; |
t2 = sp; |
sp += strlen(sp) + 1; |
sp += strlen(sp) + 1; |
} |
} |
sc_home = cheaper(t1, t2, "home cursor", "|\b^"); |
sc_home = cheaper(t1, t2, "|\b^"); |
|
|
/* |
/* |
* Choose between using "ll" and "cm" ("lower left" and "cursor move") |
* Choose between using "ll" and "cm" ("lower left" and "cursor move") |
* to move the cursor to the lower left corner of the screen. |
* to move the cursor to the lower left corner of the screen. |
*/ |
*/ |
t1 = tgetstr("ll", &sp); |
t1 = ltgetstr("ll", &sp); |
if (hard || t1 == NULL) |
if (t1 == NULL) |
t1 = ""; |
t1 = ""; |
if (*sc_move == '\0') |
if (*sc_move == '\0') |
t2 = ""; |
t2 = ""; |
|
|
t2 = sp; |
t2 = sp; |
sp += strlen(sp) + 1; |
sp += strlen(sp) + 1; |
} |
} |
sc_lower_left = cheaper(t1, t2, |
sc_lower_left = cheaper(t1, t2, "\r"); |
"move cursor to lower left of screen", "\r"); |
|
|
|
/* |
/* |
* Choose between using "al" or "sr" ("add line" or "scroll reverse") |
* Choose between using "al" or "sr" ("add line" or "scroll reverse") |
* to add a line at the top of the screen. |
* to add a line at the top of the screen. |
*/ |
*/ |
t1 = tgetstr("al", &sp); |
t1 = ltgetstr("al", &sp); |
if (hard || t1 == NULL) |
if (t1 == NULL) |
t1 = ""; |
t1 = ""; |
t2 = tgetstr("sr", &sp); |
t2 = ltgetstr("sr", &sp); |
if (hard || t2 == NULL) |
if (t2 == NULL) |
t2 = ""; |
t2 = ""; |
#if OS2 |
#if OS2 |
if (*t1 == '\0' && *t2 == '\0') |
if (*t1 == '\0' && *t2 == '\0') |
|
|
if (above_mem) |
if (above_mem) |
sc_addline = t1; |
sc_addline = t1; |
else |
else |
sc_addline = cheaper(t1, t2, "scroll backwards", ""); |
sc_addline = cheaper(t1, t2, ""); |
if (*sc_addline == '\0') |
if (*sc_addline == '\0') |
{ |
{ |
/* |
/* |
* Force repaint on any backward movement. |
* Force repaint on any backward movement. |
*/ |
*/ |
back_scroll = 0; |
no_back_scroll = 1; |
} |
} |
|
#endif /* MSDOS_COMPILER */ |
} |
} |
|
|
|
#if !MSDOS_COMPILER |
/* |
/* |
* Return the cost of displaying a termcap string. |
* Return the cost of displaying a termcap string. |
* We use the trick of calling tputs, but as a char printing function |
* We use the trick of calling tputs, but as a char printing function |
|
|
* cost (see cost() function). |
* cost (see cost() function). |
*/ |
*/ |
static char * |
static char * |
cheaper(t1, t2, doit, def) |
cheaper(t1, t2, def) |
char *t1, *t2; |
char *t1, *t2; |
char *doit; |
|
char *def; |
char *def; |
{ |
{ |
if (*t1 == '\0' && *t2 == '\0') |
if (*t1 == '\0' && *t2 == '\0') |
{ |
{ |
cannot(doit); |
missing_cap = 1; |
return (def); |
return (def); |
} |
} |
if (*t1 == '\0') |
if (*t1 == '\0') |
|
|
return (t2); |
return (t2); |
} |
} |
|
|
|
static void |
|
tmodes(incap, outcap, instr, outstr, def_instr, def_outstr, spp) |
|
char *incap; |
|
char *outcap; |
|
char **instr; |
|
char **outstr; |
|
char *def_instr; |
|
char *def_outstr; |
|
char **spp; |
|
{ |
|
*instr = ltgetstr(incap, spp); |
|
if (*instr == NULL) |
|
{ |
|
/* Use defaults. */ |
|
*instr = def_instr; |
|
*outstr = def_outstr; |
|
return; |
|
} |
|
|
|
*outstr = ltgetstr(outcap, spp); |
|
if (*outstr == NULL) |
|
/* No specific out capability; use "me". */ |
|
*outstr = ltgetstr("me", spp); |
|
if (*outstr == NULL) |
|
/* Don't even have "me"; use a null string. */ |
|
*outstr = ""; |
|
} |
|
|
|
#endif /* MSDOS_COMPILER */ |
|
|
|
|
/* |
/* |
* Below are the functions which perform all the |
* Below are the functions which perform all the |
* terminal-specific screen manipulation. |
* terminal-specific screen manipulation. |
*/ |
*/ |
|
|
|
|
|
#if MSDOS_COMPILER |
|
|
|
#if MSDOS_COMPILER==WIN32C |
|
static void |
|
_settextposition(int row, int col) |
|
{ |
|
COORD cpos; |
|
CONSOLE_SCREEN_BUFFER_INFO csbi; |
|
|
|
GetConsoleScreenBufferInfo(con_out, &csbi); |
|
cpos.X = csbi.srWindow.Left + (col - 1); |
|
cpos.Y = csbi.srWindow.Top + (row - 1); |
|
SetConsoleCursorPosition(con_out, cpos); |
|
} |
|
#endif |
|
|
/* |
/* |
|
* Initialize the screen to the correct color at startup. |
|
*/ |
|
static void |
|
initcolor() |
|
{ |
|
SETCOLORS(nm_fg_color, nm_bg_color); |
|
#if 0 |
|
/* |
|
* This clears the screen at startup. This is different from |
|
* the behavior of other versions of less. Disable it for now. |
|
*/ |
|
char *blanks; |
|
int row; |
|
int col; |
|
|
|
/* |
|
* Create a complete, blank screen using "normal" colors. |
|
*/ |
|
SETCOLORS(nm_fg_color, nm_bg_color); |
|
blanks = (char *) ecalloc(width+1, sizeof(char)); |
|
for (col = 0; col < sc_width; col++) |
|
blanks[col] = ' '; |
|
blanks[sc_width] = '\0'; |
|
for (row = 0; row < sc_height; row++) |
|
_outtext(blanks); |
|
free(blanks); |
|
#endif |
|
} |
|
#endif |
|
|
|
#if MSDOS_COMPILER==WIN32C |
|
|
|
/* |
|
* Termcap-like init with a private win32 console. |
|
*/ |
|
static void |
|
win32_init_term() |
|
{ |
|
CONSOLE_SCREEN_BUFFER_INFO scr; |
|
COORD size; |
|
|
|
if (con_out_save == INVALID_HANDLE_VALUE) |
|
return; |
|
|
|
GetConsoleScreenBufferInfo(con_out_save, &scr); |
|
|
|
if (con_out_ours == INVALID_HANDLE_VALUE) |
|
{ |
|
/* |
|
* Create our own screen buffer, so that we |
|
* may restore the original when done. |
|
*/ |
|
con_out_ours = CreateConsoleScreenBuffer( |
|
GENERIC_WRITE | GENERIC_READ, |
|
FILE_SHARE_WRITE | FILE_SHARE_READ, |
|
(LPSECURITY_ATTRIBUTES) NULL, |
|
CONSOLE_TEXTMODE_BUFFER, |
|
(LPVOID) NULL); |
|
} |
|
|
|
size.X = scr.srWindow.Right - scr.srWindow.Left + 1; |
|
size.Y = scr.srWindow.Bottom - scr.srWindow.Top + 1; |
|
SetConsoleScreenBufferSize(con_out_ours, size); |
|
SetConsoleActiveScreenBuffer(con_out_ours); |
|
con_out = con_out_ours; |
|
} |
|
|
|
/* |
|
* Restore the startup console. |
|
*/ |
|
static void |
|
win32_deinit_term() |
|
{ |
|
if (con_out_save == INVALID_HANDLE_VALUE) |
|
return; |
|
if (quitting) |
|
(void) CloseHandle(con_out_ours); |
|
SetConsoleActiveScreenBuffer(con_out_save); |
|
con_out = con_out_save; |
|
} |
|
|
|
#endif |
|
|
|
/* |
* Initialize terminal |
* Initialize terminal |
*/ |
*/ |
public void |
public void |
init() |
init() |
{ |
{ |
if (no_init) |
#if !MSDOS_COMPILER |
return; |
if (!no_init) |
tputs(sc_init, sc_height, putchr); |
tputs(sc_init, sc_height, putchr); |
tputs(sc_s_keypad, sc_height, putchr); |
if (!no_keypad) |
|
tputs(sc_s_keypad, sc_height, putchr); |
|
#else |
|
#if MSDOS_COMPILER==WIN32C |
|
if (!no_init) |
|
win32_init_term(); |
|
#endif |
|
initcolor(); |
|
flush(); |
|
#endif |
init_done = 1; |
init_done = 1; |
} |
} |
|
|
|
|
public void |
public void |
deinit() |
deinit() |
{ |
{ |
if (no_init) |
|
return; |
|
if (!init_done) |
if (!init_done) |
return; |
return; |
tputs(sc_e_keypad, sc_height, putchr); |
#if !MSDOS_COMPILER |
tputs(sc_deinit, sc_height, putchr); |
if (!no_keypad) |
|
tputs(sc_e_keypad, sc_height, putchr); |
|
if (!no_init) |
|
tputs(sc_deinit, sc_height, putchr); |
|
#else |
|
/* Restore system colors. */ |
|
SETCOLORS(sy_fg_color, sy_bg_color); |
|
#if MSDOS_COMPILER==WIN32C |
|
if (!no_init) |
|
win32_deinit_term(); |
|
#else |
|
/* Need clreol to make SETCOLORS take effect. */ |
|
clreol(); |
|
#endif |
|
#endif |
init_done = 0; |
init_done = 0; |
} |
} |
|
|
|
|
public void |
public void |
home() |
home() |
{ |
{ |
|
#if !MSDOS_COMPILER |
tputs(sc_home, 1, putchr); |
tputs(sc_home, 1, putchr); |
|
#else |
|
flush(); |
|
_settextposition(1,1); |
|
#endif |
} |
} |
|
|
/* |
/* |
|
|
public void |
public void |
add_line() |
add_line() |
{ |
{ |
|
#if !MSDOS_COMPILER |
tputs(sc_addline, sc_height, putchr); |
tputs(sc_addline, sc_height, putchr); |
|
#else |
|
flush(); |
|
#if MSDOS_COMPILER==MSOFTC |
|
_scrolltextwindow(_GSCROLLDOWN); |
|
_settextposition(1,1); |
|
#else |
|
#if MSDOS_COMPILER==BORLANDC || MSDOS_COMPILER==DJGPPC |
|
movetext(1,1, sc_width,sc_height-1, 1,2); |
|
gotoxy(1,1); |
|
clreol(); |
|
#else |
|
#if MSDOS_COMPILER==WIN32C |
|
{ |
|
CHAR_INFO fillchar; |
|
SMALL_RECT rcSrc, rcClip; |
|
COORD new_org; |
|
CONSOLE_SCREEN_BUFFER_INFO csbi; |
|
|
|
GetConsoleScreenBufferInfo(con_out,&csbi); |
|
|
|
/* The clip rectangle is the entire visible screen. */ |
|
rcClip.Left = csbi.srWindow.Left; |
|
rcClip.Top = csbi.srWindow.Top; |
|
rcClip.Right = csbi.srWindow.Right; |
|
rcClip.Bottom = csbi.srWindow.Bottom; |
|
|
|
/* The source rectangle is the visible screen minus the last line. */ |
|
rcSrc = rcClip; |
|
rcSrc.Bottom--; |
|
|
|
/* Move the top left corner of the source window down one row. */ |
|
new_org.X = rcSrc.Left; |
|
new_org.Y = rcSrc.Top + 1; |
|
|
|
/* Fill the right character and attributes. */ |
|
fillchar.Char.AsciiChar = ' '; |
|
curr_attr = MAKEATTR(nm_fg_color, nm_bg_color); |
|
fillchar.Attributes = curr_attr; |
|
ScrollConsoleScreenBuffer(con_out, &rcSrc, &rcClip, new_org, &fillchar); |
|
_settextposition(1,1); |
|
} |
|
#endif |
|
#endif |
|
#endif |
|
#endif |
} |
} |
|
|
|
#if 0 |
/* |
/* |
|
* Remove the n topmost lines and scroll everything below it in the |
|
* window upward. This is needed to stop leaking the topmost line |
|
* into the scrollback buffer when we go down-one-line (in WIN32). |
|
*/ |
|
public void |
|
remove_top(n) |
|
int n; |
|
{ |
|
#if MSDOS_COMPILER==WIN32C |
|
SMALL_RECT rcSrc, rcClip; |
|
CHAR_INFO fillchar; |
|
COORD new_org; |
|
CONSOLE_SCREEN_BUFFER_INFO csbi; /* to get buffer info */ |
|
|
|
if (n >= sc_height - 1) |
|
{ |
|
clear(); |
|
home(); |
|
return; |
|
} |
|
|
|
flush(); |
|
|
|
GetConsoleScreenBufferInfo(con_out, &csbi); |
|
|
|
/* Get the extent of all-visible-rows-but-the-last. */ |
|
rcSrc.Left = csbi.srWindow.Left; |
|
rcSrc.Top = csbi.srWindow.Top + n; |
|
rcSrc.Right = csbi.srWindow.Right; |
|
rcSrc.Bottom = csbi.srWindow.Bottom; |
|
|
|
/* Get the clip rectangle. */ |
|
rcClip.Left = rcSrc.Left; |
|
rcClip.Top = csbi.srWindow.Top; |
|
rcClip.Right = rcSrc.Right; |
|
rcClip.Bottom = rcSrc.Bottom ; |
|
|
|
/* Move the source window up n rows. */ |
|
new_org.X = rcSrc.Left; |
|
new_org.Y = rcSrc.Top - n; |
|
|
|
/* Fill the right character and attributes. */ |
|
fillchar.Char.AsciiChar = ' '; |
|
curr_attr = MAKEATTR(nm_fg_color, nm_bg_color); |
|
fillchar.Attributes = curr_attr; |
|
|
|
ScrollConsoleScreenBuffer(con_out, &rcSrc, &rcClip, new_org, &fillchar); |
|
|
|
/* Position cursor on first blank line. */ |
|
goto_line(sc_height - n - 1); |
|
#endif |
|
} |
|
#endif |
|
|
|
#if MSDOS_COMPILER==WIN32C |
|
/* |
|
* Clear the screen. |
|
*/ |
|
static void |
|
win32_clear() |
|
{ |
|
/* |
|
* This will clear only the currently visible rows of the NT |
|
* console buffer, which means none of the precious scrollback |
|
* rows are touched making for faster scrolling. Note that, if |
|
* the window has fewer columns than the console buffer (i.e. |
|
* there is a horizontal scrollbar as well), the entire width |
|
* of the visible rows will be cleared. |
|
*/ |
|
COORD topleft; |
|
DWORD nchars; |
|
DWORD winsz; |
|
CONSOLE_SCREEN_BUFFER_INFO csbi; |
|
|
|
/* get the number of cells in the current buffer */ |
|
GetConsoleScreenBufferInfo(con_out, &csbi); |
|
winsz = csbi.dwSize.X * (csbi.srWindow.Bottom - csbi.srWindow.Top + 1); |
|
topleft.X = 0; |
|
topleft.Y = csbi.srWindow.Top; |
|
|
|
curr_attr = MAKEATTR(nm_fg_color, nm_bg_color); |
|
FillConsoleOutputCharacter(con_out, ' ', winsz, topleft, &nchars); |
|
FillConsoleOutputAttribute(con_out, curr_attr, winsz, topleft, &nchars); |
|
} |
|
|
|
/* |
|
* Remove the n topmost lines and scroll everything below it in the |
|
* window upward. |
|
*/ |
|
public void |
|
win32_scroll_up(n) |
|
int n; |
|
{ |
|
SMALL_RECT rcSrc, rcClip; |
|
CHAR_INFO fillchar; |
|
COORD topleft; |
|
COORD new_org; |
|
DWORD nchars; |
|
DWORD size; |
|
CONSOLE_SCREEN_BUFFER_INFO csbi; |
|
|
|
if (n <= 0) |
|
return; |
|
|
|
if (n >= sc_height - 1) |
|
{ |
|
win32_clear(); |
|
_settextposition(1,1); |
|
return; |
|
} |
|
|
|
/* Get the extent of what will remain visible after scrolling. */ |
|
GetConsoleScreenBufferInfo(con_out, &csbi); |
|
rcSrc.Left = csbi.srWindow.Left; |
|
rcSrc.Top = csbi.srWindow.Top + n; |
|
rcSrc.Right = csbi.srWindow.Right; |
|
rcSrc.Bottom = csbi.srWindow.Bottom; |
|
|
|
/* Get the clip rectangle. */ |
|
rcClip.Left = rcSrc.Left; |
|
rcClip.Top = csbi.srWindow.Top; |
|
rcClip.Right = rcSrc.Right; |
|
rcClip.Bottom = rcSrc.Bottom ; |
|
|
|
/* Move the source text to the top of the screen. */ |
|
new_org.X = rcSrc.Left; |
|
new_org.Y = 0; |
|
|
|
/* Fill the right character and attributes. */ |
|
fillchar.Char.AsciiChar = ' '; |
|
fillchar.Attributes = MAKEATTR(nm_fg_color, nm_bg_color); |
|
|
|
/* Scroll the window. */ |
|
SetConsoleTextAttribute(con_out, fillchar.Attributes); |
|
ScrollConsoleScreenBuffer(con_out, &rcSrc, &rcClip, new_org, &fillchar); |
|
|
|
/* Clear remaining lines at bottom. */ |
|
topleft.X = csbi.dwCursorPosition.X; |
|
topleft.Y = rcSrc.Bottom - n; |
|
size = (n * csbi.dwSize.X) + (rcSrc.Right - topleft.X); |
|
FillConsoleOutputCharacter(con_out, ' ', size, topleft, |
|
&nchars); |
|
FillConsoleOutputAttribute(con_out, fillchar.Attributes, size, topleft, |
|
&nchars); |
|
SetConsoleTextAttribute(con_out, curr_attr); |
|
|
|
/* Move cursor n lines up from where it was. */ |
|
csbi.dwCursorPosition.Y -= n; |
|
SetConsoleCursorPosition(con_out, csbi.dwCursorPosition); |
|
} |
|
#endif |
|
|
|
/* |
* Move cursor to lower left corner of screen. |
* Move cursor to lower left corner of screen. |
*/ |
*/ |
public void |
public void |
lower_left() |
lower_left() |
{ |
{ |
|
#if !MSDOS_COMPILER |
tputs(sc_lower_left, 1, putchr); |
tputs(sc_lower_left, 1, putchr); |
|
#else |
|
flush(); |
|
_settextposition(sc_height, 1); |
|
#endif |
} |
} |
|
|
/* |
/* |
|
* Check if the console size has changed and reset internals |
|
* (in lieu of SIGWINCH for WIN32). |
|
*/ |
|
public void |
|
check_winch() |
|
{ |
|
#if MSDOS_COMPILER==WIN32C |
|
CONSOLE_SCREEN_BUFFER_INFO scr; |
|
COORD size; |
|
|
|
if (con_out == INVALID_HANDLE_VALUE) |
|
return; |
|
|
|
flush(); |
|
GetConsoleScreenBufferInfo(con_out, &scr); |
|
size.Y = scr.srWindow.Bottom - scr.srWindow.Top + 1; |
|
size.X = scr.srWindow.Right - scr.srWindow.Left + 1; |
|
if (size.Y != sc_height || size.X != sc_width) |
|
{ |
|
sc_height = size.Y; |
|
sc_width = size.X; |
|
if (!no_init && con_out_ours == con_out) |
|
SetConsoleScreenBufferSize(con_out, size); |
|
pos_init(); |
|
wscroll = (sc_height + 1) / 2; |
|
screen_trashed = 1; |
|
} |
|
#endif |
|
} |
|
|
|
/* |
* Goto a specific line on the screen. |
* Goto a specific line on the screen. |
*/ |
*/ |
public void |
public void |
goto_line(slinenum) |
goto_line(slinenum) |
int slinenum; |
int slinenum; |
{ |
{ |
char *sc_goto; |
#if !MSDOS_COMPILER |
|
tputs(tgoto(sc_move, 0, slinenum), 1, putchr); |
sc_goto = tgoto(sc_move, 0, slinenum); |
#else |
tputs(sc_goto, 1, putchr); |
flush(); |
|
_settextposition(slinenum+1, 1); |
|
#endif |
} |
} |
|
|
|
#if MSDOS_COMPILER==MSOFTC || MSDOS_COMPILER==BORLANDC |
/* |
/* |
* Ring the terminal bell. |
* Create an alternate screen which is all white. |
|
* This screen is used to create a "flash" effect, by displaying it |
|
* briefly and then switching back to the normal screen. |
|
* {{ Yuck! There must be a better way to get a visual bell. }} |
*/ |
*/ |
public void |
static void |
bell() |
create_flash() |
{ |
{ |
if (quiet == VERY_QUIET) |
#if MSDOS_COMPILER==MSOFTC |
vbell(); |
struct videoconfig w; |
else |
char *blanks; |
putchr('\7'); |
int row, col; |
|
|
|
_getvideoconfig(&w); |
|
videopages = w.numvideopages; |
|
if (videopages < 2) |
|
{ |
|
so_enter(); |
|
so_exit(); |
|
} else |
|
{ |
|
_setactivepage(1); |
|
so_enter(); |
|
blanks = (char *) ecalloc(w.numtextcols, sizeof(char)); |
|
for (col = 0; col < w.numtextcols; col++) |
|
blanks[col] = ' '; |
|
for (row = w.numtextrows; row > 0; row--) |
|
_outmem(blanks, w.numtextcols); |
|
_setactivepage(0); |
|
_setvisualpage(0); |
|
free(blanks); |
|
so_exit(); |
|
} |
|
#else |
|
#if MSDOS_COMPILER==BORLANDC |
|
register int n; |
|
|
|
whitescreen = (unsigned short *) |
|
malloc(sc_width * sc_height * sizeof(short)); |
|
if (whitescreen == NULL) |
|
return; |
|
for (n = 0; n < sc_width * sc_height; n++) |
|
whitescreen[n] = 0x7020; |
|
#else |
|
#if MSDOS_COMPILER==WIN32C |
|
register int n; |
|
|
|
whitescreen = (WORD *) |
|
malloc(sc_height * sc_width * sizeof(WORD)); |
|
if (whitescreen == NULL) |
|
return; |
|
/* Invert the standard colors. */ |
|
for (n = 0; n < sc_width * sc_height; n++) |
|
whitescreen[n] = (WORD)((nm_fg_color << 4) | nm_bg_color); |
|
#endif |
|
#endif |
|
#endif |
|
flash_created = 1; |
} |
} |
|
#endif /* MSDOS_COMPILER */ |
|
|
/* |
/* |
* Output the "visual bell", if there is one. |
* Output the "visual bell", if there is one. |
|
|
public void |
public void |
vbell() |
vbell() |
{ |
{ |
|
#if !MSDOS_COMPILER |
if (*sc_visual_bell == '\0') |
if (*sc_visual_bell == '\0') |
return; |
return; |
tputs(sc_visual_bell, sc_height, putchr); |
tputs(sc_visual_bell, sc_height, putchr); |
|
#else |
|
#if MSDOS_COMPILER==DJGPPC |
|
ScreenVisualBell(); |
|
#else |
|
#if MSDOS_COMPILER==MSOFTC |
|
/* |
|
* Create a flash screen on the second video page. |
|
* Switch to that page, then switch back. |
|
*/ |
|
if (!flash_created) |
|
create_flash(); |
|
if (videopages < 2) |
|
return; |
|
_setvisualpage(1); |
|
delay(100); |
|
_setvisualpage(0); |
|
#else |
|
#if MSDOS_COMPILER==BORLANDC |
|
unsigned short *currscreen; |
|
|
|
/* |
|
* Get a copy of the current screen. |
|
* Display the flash screen. |
|
* Then restore the old screen. |
|
*/ |
|
if (!flash_created) |
|
create_flash(); |
|
if (whitescreen == NULL) |
|
return; |
|
currscreen = (unsigned short *) |
|
malloc(sc_width * sc_height * sizeof(short)); |
|
if (currscreen == NULL) return; |
|
gettext(1, 1, sc_width, sc_height, currscreen); |
|
puttext(1, 1, sc_width, sc_height, whitescreen); |
|
delay(100); |
|
puttext(1, 1, sc_width, sc_height, currscreen); |
|
free(currscreen); |
|
#else |
|
#if MSDOS_COMPILER==WIN32C |
|
/* paint screen with an inverse color */ |
|
clear(); |
|
|
|
/* leave it displayed for 100 msec. */ |
|
Sleep(100); |
|
|
|
/* restore with a redraw */ |
|
repaint(); |
|
#endif |
|
#endif |
|
#endif |
|
#endif |
|
#endif |
} |
} |
|
|
/* |
/* |
|
* Make a noise. |
|
*/ |
|
static void |
|
beep() |
|
{ |
|
#if !MSDOS_COMPILER |
|
putchr(CONTROL('G')); |
|
#else |
|
#if MSDOS_COMPILER==WIN32C |
|
MessageBeep(0); |
|
#else |
|
write(1, "\7", 1); |
|
#endif |
|
#endif |
|
} |
|
|
|
/* |
|
* Ring the terminal bell. |
|
*/ |
|
public void |
|
bell() |
|
{ |
|
if (quiet == VERY_QUIET) |
|
vbell(); |
|
else |
|
beep(); |
|
} |
|
|
|
/* |
* Clear the screen. |
* Clear the screen. |
*/ |
*/ |
public void |
public void |
clear() |
clear() |
{ |
{ |
|
#if !MSDOS_COMPILER |
tputs(sc_clear, sc_height, putchr); |
tputs(sc_clear, sc_height, putchr); |
|
#else |
|
flush(); |
|
#if MSDOS_COMPILER==WIN32C |
|
win32_clear(); |
|
#else |
|
_clearscreen(_GCLEARSCREEN); |
|
#endif |
|
#endif |
} |
} |
|
|
/* |
/* |
|
|
public void |
public void |
clear_eol() |
clear_eol() |
{ |
{ |
|
#if !MSDOS_COMPILER |
tputs(sc_eol_clear, 1, putchr); |
tputs(sc_eol_clear, 1, putchr); |
|
#else |
|
#if MSDOS_COMPILER==MSOFTC |
|
short top, left; |
|
short bot, right; |
|
struct rccoord tpos; |
|
|
|
flush(); |
|
/* |
|
* Save current state. |
|
*/ |
|
tpos = _gettextposition(); |
|
_gettextwindow(&top, &left, &bot, &right); |
|
/* |
|
* Set a temporary window to the current line, |
|
* from the cursor's position to the right edge of the screen. |
|
* Then clear that window. |
|
*/ |
|
_settextwindow(tpos.row, tpos.col, tpos.row, sc_width); |
|
_clearscreen(_GWINDOW); |
|
/* |
|
* Restore state. |
|
*/ |
|
_settextwindow(top, left, bot, right); |
|
_settextposition(tpos.row, tpos.col); |
|
#else |
|
#if MSDOS_COMPILER==BORLANDC || MSDOS_COMPILER==DJGPPC |
|
flush(); |
|
clreol(); |
|
#else |
|
#if MSDOS_COMPILER==WIN32C |
|
DWORD nchars; |
|
COORD cpos; |
|
CONSOLE_SCREEN_BUFFER_INFO scr; |
|
|
|
flush(); |
|
memset(&scr, 0, sizeof(scr)); |
|
GetConsoleScreenBufferInfo(con_out, &scr); |
|
cpos.X = scr.dwCursorPosition.X; |
|
cpos.Y = scr.dwCursorPosition.Y; |
|
curr_attr = MAKEATTR(nm_fg_color, nm_bg_color); |
|
FillConsoleOutputAttribute(con_out, curr_attr, |
|
scr.dwSize.X - cpos.X, cpos, &nchars); |
|
FillConsoleOutputCharacter(con_out, ' ', |
|
scr.dwSize.X - cpos.X, cpos, &nchars); |
|
#endif |
|
#endif |
|
#endif |
|
#endif |
} |
} |
|
|
/* |
/* |
|
* Clear the current line. |
|
* Clear the screen if there's off-screen memory below the display. |
|
*/ |
|
static void |
|
clear_eol_bot() |
|
{ |
|
#if MSDOS_COMPILER |
|
clear_eol(); |
|
#else |
|
if (below_mem) |
|
tputs(sc_eos_clear, 1, putchr); |
|
else |
|
tputs(sc_eol_clear, 1, putchr); |
|
#endif |
|
} |
|
|
|
/* |
* Clear the bottom line of the display. |
* Clear the bottom line of the display. |
* Leave the cursor at the beginning of the bottom line. |
* Leave the cursor at the beginning of the bottom line. |
*/ |
*/ |
public void |
public void |
clear_bot() |
clear_bot() |
{ |
{ |
|
/* |
|
* If we're in a non-normal attribute mode, temporarily exit |
|
* the mode while we do the clear. Some terminals fill the |
|
* cleared area with the current attribute. |
|
*/ |
lower_left(); |
lower_left(); |
if (below_mem) |
switch (attrmode) |
tputs(sc_eos_clear, 1, putchr); |
{ |
else |
case AT_STANDOUT: |
tputs(sc_eol_clear, 1, putchr); |
so_exit(); |
|
clear_eol_bot(); |
|
so_enter(); |
|
break; |
|
case AT_UNDERLINE: |
|
ul_exit(); |
|
clear_eol_bot(); |
|
ul_enter(); |
|
break; |
|
case AT_BOLD: |
|
bo_exit(); |
|
clear_eol_bot(); |
|
bo_enter(); |
|
break; |
|
case AT_BLINK: |
|
bl_exit(); |
|
clear_eol_bot(); |
|
bl_enter(); |
|
break; |
|
default: |
|
clear_eol_bot(); |
|
break; |
|
} |
} |
} |
|
|
/* |
/* |
|
|
public void |
public void |
so_enter() |
so_enter() |
{ |
{ |
|
#if !MSDOS_COMPILER |
tputs(sc_s_in, 1, putchr); |
tputs(sc_s_in, 1, putchr); |
|
#else |
|
flush(); |
|
SETCOLORS(so_fg_color, so_bg_color); |
|
#endif |
|
attrmode = AT_STANDOUT; |
} |
} |
|
|
/* |
/* |
|
|
public void |
public void |
so_exit() |
so_exit() |
{ |
{ |
|
#if !MSDOS_COMPILER |
tputs(sc_s_out, 1, putchr); |
tputs(sc_s_out, 1, putchr); |
|
#else |
|
flush(); |
|
SETCOLORS(nm_fg_color, nm_bg_color); |
|
#endif |
|
attrmode = AT_NORMAL; |
} |
} |
|
|
/* |
/* |
|
|
public void |
public void |
ul_enter() |
ul_enter() |
{ |
{ |
|
#if !MSDOS_COMPILER |
tputs(sc_u_in, 1, putchr); |
tputs(sc_u_in, 1, putchr); |
|
#else |
|
flush(); |
|
SETCOLORS(ul_fg_color, ul_bg_color); |
|
#endif |
|
attrmode = AT_UNDERLINE; |
} |
} |
|
|
/* |
/* |
|
|
public void |
public void |
ul_exit() |
ul_exit() |
{ |
{ |
|
#if !MSDOS_COMPILER |
tputs(sc_u_out, 1, putchr); |
tputs(sc_u_out, 1, putchr); |
|
#else |
|
flush(); |
|
SETCOLORS(nm_fg_color, nm_bg_color); |
|
#endif |
|
attrmode = AT_NORMAL; |
} |
} |
|
|
/* |
/* |
|
|
public void |
public void |
bo_enter() |
bo_enter() |
{ |
{ |
|
#if !MSDOS_COMPILER |
tputs(sc_b_in, 1, putchr); |
tputs(sc_b_in, 1, putchr); |
|
#else |
|
flush(); |
|
SETCOLORS(bo_fg_color, bo_bg_color); |
|
#endif |
|
attrmode = AT_BOLD; |
} |
} |
|
|
/* |
/* |
|
|
public void |
public void |
bo_exit() |
bo_exit() |
{ |
{ |
|
#if !MSDOS_COMPILER |
tputs(sc_b_out, 1, putchr); |
tputs(sc_b_out, 1, putchr); |
|
#else |
|
flush(); |
|
SETCOLORS(nm_fg_color, nm_bg_color); |
|
#endif |
|
attrmode = AT_NORMAL; |
} |
} |
|
|
/* |
/* |
|
|
public void |
public void |
bl_enter() |
bl_enter() |
{ |
{ |
|
#if !MSDOS_COMPILER |
tputs(sc_bl_in, 1, putchr); |
tputs(sc_bl_in, 1, putchr); |
|
#else |
|
flush(); |
|
SETCOLORS(bl_fg_color, bl_bg_color); |
|
#endif |
|
attrmode = AT_BLINK; |
} |
} |
|
|
/* |
/* |
|
|
public void |
public void |
bl_exit() |
bl_exit() |
{ |
{ |
|
#if !MSDOS_COMPILER |
tputs(sc_bl_out, 1, putchr); |
tputs(sc_bl_out, 1, putchr); |
|
#else |
|
flush(); |
|
SETCOLORS(nm_fg_color, nm_bg_color); |
|
#endif |
|
attrmode = AT_NORMAL; |
} |
} |
|
|
|
#if 0 /* No longer used */ |
/* |
/* |
* Erase the character to the left of the cursor |
* Erase the character to the left of the cursor |
* and move the cursor left. |
* and move the cursor left. |
|
|
public void |
public void |
backspace() |
backspace() |
{ |
{ |
|
#if !MSDOS_COMPILER |
/* |
/* |
* Try to erase the previous character by overstriking with a space. |
* Erase the previous character by overstriking with a space. |
*/ |
*/ |
tputs(sc_backspace, 1, putchr); |
tputs(sc_backspace, 1, putchr); |
putchr(' '); |
putchr(' '); |
tputs(sc_backspace, 1, putchr); |
tputs(sc_backspace, 1, putchr); |
|
#else |
|
#if MSDOS_COMPILER==MSOFTC |
|
struct rccoord tpos; |
|
|
|
flush(); |
|
tpos = _gettextposition(); |
|
if (tpos.col <= 1) |
|
return; |
|
_settextposition(tpos.row, tpos.col-1); |
|
_outtext(" "); |
|
_settextposition(tpos.row, tpos.col-1); |
|
#else |
|
#if MSDOS_COMPILER==BORLANDC || MSDOS_COMPILER==DJGPPC |
|
cputs("\b"); |
|
#else |
|
#if MSDOS_COMPILER==WIN32C |
|
COORD cpos; |
|
DWORD cChars; |
|
CONSOLE_SCREEN_BUFFER_INFO scr; |
|
|
|
flush(); |
|
GetConsoleScreenBufferInfo(con_out, &scr); |
|
cpos = scr.dwCursorPosition; |
|
if (cpos.X <= 0) |
|
return; |
|
cpos.X--; |
|
SetConsoleCursorPosition(con_out, cpos); |
|
FillConsoleOutputCharacter(con_out, (TCHAR)' ', 1, cpos, &cChars); |
|
SetConsoleCursorPosition(con_out, cpos); |
|
#endif |
|
#endif |
|
#endif |
|
#endif |
} |
} |
|
#endif /* 0 */ |
|
|
/* |
/* |
* Output a plain backspace, without erasing the previous char. |
* Output a plain backspace, without erasing the previous char. |
|
|
public void |
public void |
putbs() |
putbs() |
{ |
{ |
|
#if !MSDOS_COMPILER |
tputs(sc_backspace, 1, putchr); |
tputs(sc_backspace, 1, putchr); |
|
#else |
|
int row, col; |
|
|
|
flush(); |
|
{ |
|
#if MSDOS_COMPILER==MSOFTC |
|
struct rccoord tpos; |
|
tpos = _gettextposition(); |
|
row = tpos.row; |
|
col = tpos.col; |
|
#else |
|
#if MSDOS_COMPILER==BORLANDC || MSDOS_COMPILER==DJGPPC |
|
row = wherey(); |
|
col = wherex(); |
|
#else |
|
#if MSDOS_COMPILER==WIN32C |
|
CONSOLE_SCREEN_BUFFER_INFO scr; |
|
GetConsoleScreenBufferInfo(con_out, &scr); |
|
row = scr.dwCursorPosition.Y - scr.srWindow.Top + 1; |
|
col = scr.dwCursorPosition.X - scr.srWindow.Left + 1; |
|
#endif |
|
#endif |
|
#endif |
|
} |
|
if (col <= 1) |
|
return; |
|
_settextposition(row, col-1); |
|
#endif /* MSDOS_COMPILER */ |
} |
} |
|
|
|
#if MSDOS_COMPILER==WIN32C |
|
/* |
|
* Determine whether an input character is waiting to be read. |
|
*/ |
|
static int |
|
win32_kbhit(tty) |
|
HANDLE tty; |
|
{ |
|
INPUT_RECORD ip; |
|
DWORD read; |
|
|
|
if (keyCount > 0) |
|
return (TRUE); |
|
|
|
currentKey.ascii = 0; |
|
currentKey.scan = 0; |
|
|
|
/* |
|
* Wait for a real key-down event, but |
|
* ignore SHIFT and CONTROL key events. |
|
*/ |
|
do |
|
{ |
|
PeekConsoleInput(tty, &ip, 1, &read); |
|
if (read == 0) |
|
return (FALSE); |
|
ReadConsoleInput(tty, &ip, 1, &read); |
|
} while (ip.EventType != KEY_EVENT || |
|
ip.Event.KeyEvent.bKeyDown != TRUE || |
|
ip.Event.KeyEvent.wVirtualScanCode == 0 || |
|
ip.Event.KeyEvent.wVirtualKeyCode == VK_SHIFT || |
|
ip.Event.KeyEvent.wVirtualKeyCode == VK_CONTROL || |
|
ip.Event.KeyEvent.wVirtualKeyCode == VK_MENU); |
|
|
|
currentKey.ascii = ip.Event.KeyEvent.uChar.AsciiChar; |
|
currentKey.scan = ip.Event.KeyEvent.wVirtualScanCode; |
|
keyCount = ip.Event.KeyEvent.wRepeatCount; |
|
|
|
if (ip.Event.KeyEvent.dwControlKeyState & |
|
(LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED)) |
|
{ |
|
switch (currentKey.scan) |
|
{ |
|
case PCK_ALT_E: /* letter 'E' */ |
|
currentKey.ascii = 0; |
|
break; |
|
} |
|
} else if (ip.Event.KeyEvent.dwControlKeyState & |
|
(LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) |
|
{ |
|
switch (currentKey.scan) |
|
{ |
|
case PCK_RIGHT: /* right arrow */ |
|
currentKey.scan = PCK_CTL_RIGHT; |
|
break; |
|
case PCK_LEFT: /* left arrow */ |
|
currentKey.scan = PCK_CTL_LEFT; |
|
break; |
|
case PCK_DELETE: /* delete */ |
|
currentKey.scan = PCK_CTL_DELETE; |
|
break; |
|
} |
|
} |
|
return (TRUE); |
|
} |
|
|
|
/* |
|
* Read a character from the keyboard. |
|
*/ |
|
public char |
|
WIN32getch(tty) |
|
int tty; |
|
{ |
|
int ascii; |
|
|
|
if (pending_scancode) |
|
{ |
|
pending_scancode = 0; |
|
return ((char)(currentKey.scan & 0x00FF)); |
|
} |
|
|
|
while (win32_kbhit((HANDLE)tty) == FALSE) |
|
{ |
|
Sleep(20); |
|
if (ABORT_SIGS()) |
|
return ('\003'); |
|
continue; |
|
} |
|
keyCount --; |
|
ascii = currentKey.ascii; |
|
/* |
|
* On PC's, the extended keys return a 2 byte sequence beginning |
|
* with '00', so if the ascii code is 00, the next byte will be |
|
* the lsb of the scan code. |
|
*/ |
|
pending_scancode = (ascii == 0x00); |
|
return ((char)ascii); |
|
} |
|
#endif |