version 1.14, 2005/04/11 19:59:07 |
version 1.15, 2011/09/16 18:12:09 |
|
|
/* |
/* |
* Copyright (C) 1984-2002 Mark Nudelman |
* Copyright (C) 1984-2011 Mark Nudelman |
* |
* |
* You may distribute under the terms of either the GNU General Public |
* You may distribute under the terms of either the GNU General Public |
* License or the Less License, as specified in the README file. |
* License or the Less License, as specified in the README file. |
|
|
|
|
#else |
#else |
|
|
#if HAVE_TERMIOS_H && HAVE_TERMIOS_FUNCS |
|
#include <termios.h> |
|
#if HAVE_SYS_IOCTL_H |
#if HAVE_SYS_IOCTL_H |
#include <sys/ioctl.h> |
#include <sys/ioctl.h> |
#endif |
#endif |
|
|
|
#if HAVE_TERMIOS_H && HAVE_TERMIOS_FUNCS |
|
#include <termios.h> |
#else |
#else |
#if HAVE_TERMIO_H |
#if HAVE_TERMIO_H |
#include <termio.h> |
#include <termio.h> |
|
|
#else |
#else |
#include <sgtty.h> |
#include <sgtty.h> |
#endif |
#endif |
#if HAVE_SYS_IOCTL_H && (defined(TIOCGWINSZ) || defined(TCGETA) || defined(TIOCGETP) || defined(WIOCGETD)) |
|
#include <sys/ioctl.h> |
|
#endif |
#endif |
#endif |
#endif |
#endif |
|
|
|
#if HAVE_TERMCAP_H |
#if HAVE_TERMCAP_H |
#include <termcap.h> |
#include <termcap.h> |
|
|
*sc_home, /* Cursor home */ |
*sc_home, /* Cursor home */ |
*sc_addline, /* Add line, scroll down following lines */ |
*sc_addline, /* Add line, scroll down following lines */ |
*sc_lower_left, /* Cursor to last line, first column */ |
*sc_lower_left, /* Cursor to last line, first column */ |
|
*sc_return, /* Cursor to beginning of current line */ |
*sc_move, /* General cursor positioning */ |
*sc_move, /* General cursor positioning */ |
*sc_clear, /* Clear screen */ |
*sc_clear, /* Clear screen */ |
*sc_eol_clear, /* Clear to end of line */ |
*sc_eol_clear, /* Clear to end of line */ |
|
|
|
|
public int auto_wrap; /* Terminal does \r\n when write past margin */ |
public int auto_wrap; /* Terminal does \r\n when write past margin */ |
public int ignaw; /* Terminal ignores \n immediately after wrap */ |
public int ignaw; /* Terminal ignores \n immediately after wrap */ |
public int erase_char, kill_char; /* The user's erase and line-kill chars */ |
public int erase_char; /* The user's erase char */ |
|
public int erase2_char; /* The user's other erase char */ |
|
public int kill_char; /* The user's line-kill char */ |
public int werase_char; /* The user's word-erase char */ |
public int werase_char; /* The user's word-erase char */ |
public int sc_width, sc_height; /* Height & width of screen */ |
public int sc_width, sc_height; /* Height & width of screen */ |
public int bo_s_width, bo_e_width; /* Printing width of boldface seq */ |
public int bo_s_width, bo_e_width; /* Printing width of boldface seq */ |
|
|
public int missing_cap = 0; /* Some capability is missing */ |
public int missing_cap = 0; /* Some capability is missing */ |
|
|
static int attrmode = AT_NORMAL; |
static int attrmode = AT_NORMAL; |
|
extern int binattr; |
|
|
#if !MSDOS_COMPILER |
#if !MSDOS_COMPILER |
static char *cheaper(); |
static char *cheaper(); |
|
|
extern int wscroll; |
extern int wscroll; |
extern int screen_trashed; |
extern int screen_trashed; |
extern int tty; |
extern int tty; |
extern int quit_at_eof; |
extern int top_scroll; |
extern int ismore; |
extern int oldbot; |
#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; |
|
erase2_char = '\b'; /* in case OS doesn't know about erase2 */ |
#if HAVE_TERMIOS_H && HAVE_TERMIOS_FUNCS |
#if HAVE_TERMIOS_H && HAVE_TERMIOS_FUNCS |
{ |
{ |
struct termios s; |
struct termios s; |
|
|
} |
} |
#endif |
#endif |
erase_char = s.c_cc[VERASE]; |
erase_char = s.c_cc[VERASE]; |
|
#ifdef VERASE2 |
|
erase2_char = s.c_cc[VERASE2]; |
|
#endif |
kill_char = s.c_cc[VKILL]; |
kill_char = s.c_cc[VKILL]; |
#ifdef VWERASE |
#ifdef VWERASE |
werase_char = s.c_cc[VWERASE]; |
werase_char = s.c_cc[VWERASE]; |
|
|
char *capname; |
char *capname; |
{ |
{ |
char name[16]; |
char name[16]; |
|
char *s; |
|
|
|
s = lgetenv("LESS_TERMCAP_DEBUG"); |
|
if (s != NULL && *s != '\0') |
|
{ |
|
struct env { struct env *next; char *name; char *value; }; |
|
static struct env *envs = NULL; |
|
struct env *p; |
|
size_t len; |
|
for (p = envs; p != NULL; p = p->next) |
|
if (strcmp(p->name, capname) == 0) |
|
return p->value; |
|
p = (struct env *) ecalloc(1, sizeof(struct env)); |
|
p->name = save(capname); |
|
len = strlen(capname) + 3; |
|
p->value = (char *) ecalloc(len, sizeof(char)); |
|
snprintf(p->value, len, "<%s>", capname); |
|
p->next = envs; |
|
envs = p; |
|
return p->value; |
|
} |
strlcpy(name, "LESS_TERMCAP_", sizeof(name)); |
strlcpy(name, "LESS_TERMCAP_", sizeof(name)); |
strlcat(name, capname, sizeof(name)); |
strlcat(name, capname, sizeof(name)); |
return (lgetenv(name)); |
return (lgetenv(name)); |
|
|
if ((term = lgetenv("TERM")) == NULL) |
if ((term = lgetenv("TERM")) == NULL) |
term = DEFAULT_TERM; |
term = DEFAULT_TERM; |
hardcopy = 0; |
hardcopy = 0; |
if (tgetent(termbuf, term) <= 0) |
if (tgetent(termbuf, term) != TGETENT_OK) |
hardcopy = 1; |
hardcopy = 1; |
if (ltgetflag("hc")) |
if (ltgetflag("hc")) |
hardcopy = 1; |
hardcopy = 1; |
|
|
if (sc_e_keypad == NULL) |
if (sc_e_keypad == NULL) |
sc_e_keypad = ""; |
sc_e_keypad = ""; |
|
|
/* |
sc_init = ltgetstr("ti", &sp); |
* This loses for terminals with termcap entries with ti/te strings |
|
* that switch to/from an alternate screen, and we're in quit_at_eof |
|
* (eg, more(1)). |
|
*/ |
|
if (!quit_at_eof && !ismore) { |
|
sc_init = ltgetstr("ti", &sp); |
|
sc_deinit= ltgetstr("te", &sp); |
|
} |
|
if (sc_init == NULL) |
if (sc_init == NULL) |
sc_init = ""; |
sc_init = ""; |
|
|
|
sc_deinit= ltgetstr("te", &sp); |
if (sc_deinit == NULL) |
if (sc_deinit == NULL) |
sc_deinit = ""; |
sc_deinit = ""; |
|
|
|
|
if (below_mem && (sc_eos_clear == NULL || *sc_eos_clear == '\0')) |
if (below_mem && (sc_eos_clear == NULL || *sc_eos_clear == '\0')) |
{ |
{ |
missing_cap = 1; |
missing_cap = 1; |
sc_eol_clear = ""; |
sc_eos_clear = ""; |
} |
} |
|
|
sc_clear = ltgetstr("cl", &sp); |
sc_clear = ltgetstr("cl", &sp); |
|
|
sc_lower_left = cheaper(t1, t2, "\r"); |
sc_lower_left = cheaper(t1, t2, "\r"); |
|
|
/* |
/* |
|
* Get carriage return string. |
|
*/ |
|
sc_return = ltgetstr("cr", &sp); |
|
if (sc_return == NULL) |
|
sc_return = "\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. |
*/ |
*/ |
|
|
tputs(sc_init, sc_height, putchr); |
tputs(sc_init, sc_height, putchr); |
if (!no_keypad) |
if (!no_keypad) |
tputs(sc_s_keypad, sc_height, putchr); |
tputs(sc_s_keypad, sc_height, putchr); |
|
if (top_scroll) |
|
{ |
|
int i; |
|
|
|
/* |
|
* This is nice to terminals with no alternate screen, |
|
* but with saved scrolled-off-the-top lines. This way, |
|
* no previous line is lost, but we start with a whole |
|
* screen to ourself. |
|
*/ |
|
for (i = 1; i < sc_height; i++) |
|
putchr('\n'); |
|
} else |
|
line_left(); |
#else |
#else |
#if MSDOS_COMPILER==WIN32C |
#if MSDOS_COMPILER==WIN32C |
if (!no_init) |
if (!no_init) |
|
|
|
|
/* Move the source text to the top of the screen. */ |
/* Move the source text to the top of the screen. */ |
new_org.X = rcSrc.Left; |
new_org.X = rcSrc.Left; |
new_org.Y = 0; |
new_org.Y = rcClip.Top; |
|
|
/* Fill the right character and attributes. */ |
/* Fill the right character and attributes. */ |
fillchar.Char.AsciiChar = ' '; |
fillchar.Char.AsciiChar = ' '; |
|
|
} |
} |
|
|
/* |
/* |
|
* Move cursor to left position of current line. |
|
*/ |
|
public void |
|
line_left() |
|
{ |
|
#if !MSDOS_COMPILER |
|
tputs(sc_return, 1, putchr); |
|
#else |
|
int row; |
|
flush(); |
|
#if MSDOS_COMPILER==WIN32C |
|
{ |
|
CONSOLE_SCREEN_BUFFER_INFO scr; |
|
GetConsoleScreenBufferInfo(con_out, &scr); |
|
row = scr.dwCursorPosition.Y - scr.srWindow.Top + 1; |
|
} |
|
#else |
|
#if MSDOS_COMPILER==BORLANDC || MSDOS_COMPILER==DJGPPC |
|
row = wherey(); |
|
#else |
|
{ |
|
struct rccoord tpos = _gettextposition(); |
|
row = tpos.row; |
|
} |
|
#endif |
|
#endif |
|
_settextposition(row, 1); |
|
#endif |
|
} |
|
|
|
/* |
* Check if the console size has changed and reset internals |
* Check if the console size has changed and reset internals |
* (in lieu of SIGWINCH for WIN32). |
* (in lieu of SIGWINCH for WIN32). |
*/ |
*/ |
|
|
videopages = w.numvideopages; |
videopages = w.numvideopages; |
if (videopages < 2) |
if (videopages < 2) |
{ |
{ |
so_enter(); |
at_enter(AT_STANDOUT); |
so_exit(); |
at_exit(); |
} else |
} else |
{ |
{ |
_setactivepage(1); |
_setactivepage(1); |
so_enter(); |
at_enter(AT_STANDOUT); |
blanks = (char *) ecalloc(w.numtextcols, sizeof(char)); |
blanks = (char *) ecalloc(w.numtextcols, sizeof(char)); |
for (col = 0; col < w.numtextcols; col++) |
for (col = 0; col < w.numtextcols; col++) |
blanks[col] = ' '; |
blanks[col] = ' '; |
|
|
_setactivepage(0); |
_setactivepage(0); |
_setvisualpage(0); |
_setvisualpage(0); |
free(blanks); |
free(blanks); |
so_exit(); |
at_exit(); |
} |
} |
#else |
#else |
#if MSDOS_COMPILER==BORLANDC |
#if MSDOS_COMPILER==BORLANDC |
|
|
* the mode while we do the clear. Some terminals fill the |
* the mode while we do the clear. Some terminals fill the |
* cleared area with the current attribute. |
* cleared area with the current attribute. |
*/ |
*/ |
lower_left(); |
if (oldbot) |
switch (attrmode) |
lower_left(); |
|
else |
|
line_left(); |
|
|
|
if (attrmode == AT_NORMAL) |
|
clear_eol_bot(); |
|
else |
{ |
{ |
case AT_STANDOUT: |
int saved_attrmode = attrmode; |
so_exit(); |
|
|
at_exit(); |
clear_eol_bot(); |
clear_eol_bot(); |
so_enter(); |
at_enter(saved_attrmode); |
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; |
|
} |
} |
} |
} |
|
|
/* |
|
* Begin "standout" (bold, underline, or whatever). |
|
*/ |
|
public void |
public void |
so_enter() |
at_enter(attr) |
|
int attr; |
{ |
{ |
#if !MSDOS_COMPILER |
attr = apply_at_specials(attr); |
tputs(sc_s_in, 1, putchr); |
|
#else |
|
flush(); |
|
SETCOLORS(so_fg_color, so_bg_color); |
|
#endif |
|
attrmode = AT_STANDOUT; |
|
} |
|
|
|
/* |
|
* End "standout". |
|
*/ |
|
public void |
|
so_exit() |
|
{ |
|
#if !MSDOS_COMPILER |
#if !MSDOS_COMPILER |
tputs(sc_s_out, 1, putchr); |
/* The one with the most priority is last. */ |
|
if (attr & AT_UNDERLINE) |
|
tputs(sc_u_in, 1, putchr); |
|
if (attr & AT_BOLD) |
|
tputs(sc_b_in, 1, putchr); |
|
if (attr & AT_BLINK) |
|
tputs(sc_bl_in, 1, putchr); |
|
if (attr & AT_STANDOUT) |
|
tputs(sc_s_in, 1, putchr); |
#else |
#else |
flush(); |
flush(); |
SETCOLORS(nm_fg_color, nm_bg_color); |
/* The one with the most priority is first. */ |
|
if (attr & AT_STANDOUT) |
|
{ |
|
SETCOLORS(so_fg_color, so_bg_color); |
|
} else if (attr & AT_BLINK) |
|
{ |
|
SETCOLORS(bl_fg_color, bl_bg_color); |
|
} |
|
else if (attr & AT_BOLD) |
|
{ |
|
SETCOLORS(bo_fg_color, bo_bg_color); |
|
} |
|
else if (attr & AT_UNDERLINE) |
|
{ |
|
SETCOLORS(ul_fg_color, ul_bg_color); |
|
} |
#endif |
#endif |
attrmode = AT_NORMAL; |
|
} |
|
|
|
/* |
attrmode = attr; |
* Begin "underline" (hopefully real underlining, |
|
* otherwise whatever the terminal provides). |
|
*/ |
|
public void |
|
ul_enter() |
|
{ |
|
#if !MSDOS_COMPILER |
|
tputs(sc_u_in, 1, putchr); |
|
#else |
|
flush(); |
|
SETCOLORS(ul_fg_color, ul_bg_color); |
|
#endif |
|
attrmode = AT_UNDERLINE; |
|
} |
} |
|
|
/* |
|
* End "underline". |
|
*/ |
|
public void |
public void |
ul_exit() |
at_exit() |
{ |
{ |
#if !MSDOS_COMPILER |
#if !MSDOS_COMPILER |
tputs(sc_u_out, 1, putchr); |
/* Undo things in the reverse order we did them. */ |
|
if (attrmode & AT_STANDOUT) |
|
tputs(sc_s_out, 1, putchr); |
|
if (attrmode & AT_BLINK) |
|
tputs(sc_bl_out, 1, putchr); |
|
if (attrmode & AT_BOLD) |
|
tputs(sc_b_out, 1, putchr); |
|
if (attrmode & AT_UNDERLINE) |
|
tputs(sc_u_out, 1, putchr); |
#else |
#else |
flush(); |
flush(); |
SETCOLORS(nm_fg_color, nm_bg_color); |
SETCOLORS(nm_fg_color, nm_bg_color); |
#endif |
#endif |
|
|
attrmode = AT_NORMAL; |
attrmode = AT_NORMAL; |
} |
} |
|
|
/* |
|
* Begin "bold" |
|
*/ |
|
public void |
public void |
bo_enter() |
at_switch(attr) |
|
int attr; |
{ |
{ |
#if !MSDOS_COMPILER |
int new_attrmode = apply_at_specials(attr); |
tputs(sc_b_in, 1, putchr); |
int ignore_modes = AT_ANSI; |
#else |
|
flush(); |
|
SETCOLORS(bo_fg_color, bo_bg_color); |
|
#endif |
|
attrmode = AT_BOLD; |
|
} |
|
|
|
/* |
if ((new_attrmode & ~ignore_modes) != (attrmode & ~ignore_modes)) |
* End "bold". |
{ |
*/ |
at_exit(); |
public void |
at_enter(attr); |
bo_exit() |
} |
{ |
|
#if !MSDOS_COMPILER |
|
tputs(sc_b_out, 1, putchr); |
|
#else |
|
flush(); |
|
SETCOLORS(nm_fg_color, nm_bg_color); |
|
#endif |
|
attrmode = AT_NORMAL; |
|
} |
} |
|
|
/* |
public int |
* Begin "blink" |
is_at_equiv(attr1, attr2) |
*/ |
int attr1; |
public void |
int attr2; |
bl_enter() |
|
{ |
{ |
#if !MSDOS_COMPILER |
attr1 = apply_at_specials(attr1); |
tputs(sc_bl_in, 1, putchr); |
attr2 = apply_at_specials(attr2); |
#else |
|
flush(); |
return (attr1 == attr2); |
SETCOLORS(bl_fg_color, bl_bg_color); |
|
#endif |
|
attrmode = AT_BLINK; |
|
} |
} |
|
|
/* |
public int |
* End "blink". |
apply_at_specials(attr) |
*/ |
int attr; |
public void |
|
bl_exit() |
|
{ |
{ |
#if !MSDOS_COMPILER |
if (attr & AT_BINARY) |
tputs(sc_bl_out, 1, putchr); |
attr |= binattr; |
#else |
if (attr & AT_HILITE) |
flush(); |
attr |= AT_STANDOUT; |
SETCOLORS(nm_fg_color, nm_bg_color); |
attr &= ~(AT_BINARY|AT_HILITE); |
#endif |
|
attrmode = AT_NORMAL; |
return attr; |
} |
} |
|
|
#if 0 /* No longer used */ |
#if 0 /* No longer used */ |
|
|
*/ |
*/ |
pending_scancode = (ascii == 0x00); |
pending_scancode = (ascii == 0x00); |
return ((char)ascii); |
return ((char)ascii); |
|
} |
|
#endif |
|
|
|
#if MSDOS_COMPILER |
|
/* |
|
*/ |
|
public void |
|
WIN32setcolors(fg, bg) |
|
int fg; |
|
int bg; |
|
{ |
|
SETCOLORS(fg, bg); |
|
} |
|
|
|
/* |
|
*/ |
|
public void |
|
WIN32textout(text, len) |
|
char *text; |
|
int len; |
|
{ |
|
#if MSDOS_COMPILER==WIN32C |
|
DWORD written; |
|
WriteConsole(con_out, text, len, &written, NULL); |
|
#else |
|
char c = text[len]; |
|
text[len] = '\0'; |
|
cputs(text); |
|
text[len] = c; |
|
#endif |
} |
} |
#endif |
#endif |