#include <HTUtils.h>
#include <HTAlert.h>
#ifdef __MINGW32__
#ifdef UNIX
#undef UNIX
#endif /* UNIX */
#endif /* __MINGW32__ */
#include <LYCurses.h>
#include <LYStyle.h>
#include <LYUtils.h>
#include <LYGlobalDefs.h>
#include <LYSignal.h>
#include <LYClean.h>
#include <LYReadCFG.h>
#include <LYStrings.h>
#include <LYCharSets.h>
#include <UCAux.h>
#include <HTFont.h>
#include <LYexit.h>
#include <LYLeaks.h>
#ifdef VMS
#include <LYMainLoop.h>
#endif
#if defined(VMS) && defined(__GNUC__)
#include <gnu_hacks.h>
#undef LINES
#undef COLS
#define LINES lines
#define COLS cols
extern int _NOSHARE(LINES);
extern int _NOSHARE(COLS);
#endif /* VMS && __GNUC__ */
#ifdef USE_COLOR_STYLE
#include <AttrList.h>
#include <LYHash.h>
#endif
#ifdef NEED_WCHAR_H
#include <wchar.h>
#endif
#if defined(COLOR_CURSES)
int lynx_has_color = FALSE;
#endif
#ifdef HAVE_XCURSES
char *XCursesProgramName = "Lynx";
#endif
#if defined(USE_COLOR_STYLE) && !defined(USE_COLOR_TABLE)
#define COLOR_BKGD ((s_normal != NOSTYLE) ? hashStyles[s_normal].color : A_NORMAL)
#else
#define COLOR_BKGD ((COLOR_PAIRS >= 9) ? get_color_pair(9) : A_NORMAL)
#endif
#ifdef USE_CURSES_PADS
WINDOW *LYwin = 0;
int LYshiftWin = 0;
int LYwideLines = FALSE;
int LYtableCols = 0; /* in 1/12 of screen width */
BOOL LYuseCursesPads = TRUE; /* use pads for left/right shifting */
#endif
/*
* These are routines to start and stop curses and to cleanup the screen at the
* end.
*/
static int dumbterm(char *terminal);
BOOLEAN LYCursesON = FALSE;
#if defined(USE_BLINK) && defined(__EMX__)
static void make_blink_boldbg(void);
#endif
#if defined(USE_COLOR_TABLE) || defined(USE_SLANG)
int Current_Attr, Masked_Attr;
#endif
#ifdef USE_SLANG
unsigned int Lynx_Color_Flags = 0;
BOOLEAN FullRefresh = FALSE;
int curscr = 0;
#ifdef SLANG_MBCS_HACK
/*
* Will be set by size_change. - KW
*/
int PHYSICAL_SLtt_Screen_Cols = 10;
#endif /* SLANG_MBCS_HACK */
void LY_SLrefresh(void)
{
if (FullRefresh) {
SLsmg_suspend_smg();
SLsmg_resume_smg();
FullRefresh = FALSE;
} else {
SLsmg_refresh();
}
return;
}
/* the following renamed from LY_SLclear since it is more like erase()
described in curses man pages than like clear(); but for USE_SLANG
clear() is still a macro calling this, and will do the same thing as
erase(). - kw */
void LY_SLerase(void)
{
SLsmg_gotorc(0, 0);
SLsmg_erase_eos();
}
#ifdef VMS
void VTHome(void)
{
printf("\033[;H");
return;
}
#endif /* VMS */
void LYaddAttr(int a)
{
Current_Attr |= a;
SLsmg_set_color(Current_Attr & ~Masked_Attr);
}
void LYsubAttr(int a)
{
Current_Attr &= ~a;
SLsmg_set_color(Current_Attr & ~Masked_Attr);
}
static void lynx_setup_attrs(void)
{
static int monoattr[] =
{
0,
SLTT_BOLD_MASK,
SLTT_REV_MASK,
SLTT_REV_MASK | SLTT_BOLD_MASK,
SLTT_ULINE_MASK,
SLTT_ULINE_MASK | SLTT_BOLD_MASK,
SLTT_ULINE_MASK | SLTT_REV_MASK,
SLTT_ULINE_MASK | SLTT_BOLD_MASK | SLTT_REV_MASK
};
int n;
for (n = 1; n <= 7; n++)
SLtt_set_mono(n, NULL, (monoattr[n] & ~Masked_Attr));
}
void lynx_setup_colors(void)
{
CTRACE((tfp, "lynx_setup_colors\n"));
SLtt_set_color(0, NULL, DEFAULT_FG, DEFAULT_BG);
SLtt_set_color(1, NULL, "blue", DEFAULT_BG); /* bold */
SLtt_set_color(2, NULL, "yellow", "blue"); /* reverse */
SLtt_set_color(4, NULL, "magenta", DEFAULT_BG); /* underline */
/*
* The other objects are '|'ed together to get rest.
*/
SLtt_set_color(3, NULL, "green", DEFAULT_BG); /* bold-reverse */
SLtt_set_color(5, NULL, "blue", DEFAULT_BG); /* bold-underline */
SLtt_set_color(6, NULL, "red", DEFAULT_BG); /* reverse-underline */
SLtt_set_color(7, NULL, "magenta", "cyan"); /* reverse-underline-bold */
/*
* Now set monochrome attributes.
*/
lynx_setup_attrs();
}
static void sl_suspend(int sig)
{
#ifdef SIGSTOP
#ifndef VMS
int r, c;
lynx_enable_mouse(0);
if (sig == SIGTSTP)
SLsmg_suspend_smg();
SLang_reset_tty();
kill(getpid(), SIGSTOP);
#if SLANG_VERSION > 9929
SLang_init_tty(-1, 0, 1);
#else
SLang_init_tty(3, 0, 1);
#endif /* SLANG_VERSION > 9929 */
signal(SIGTSTP, sl_suspend);
#if defined(REAL_UNIX_SYSTEM) && !defined(__CYGWIN__)
SLtty_set_suspend_state(1);
#endif
if (sig == SIGTSTP)
SLsmg_resume_smg();
/*
* Get new window size in case it changed.
*/
r = SLtt_Screen_Rows;
c = SLtt_Screen_Cols;
size_change(0);
if ((r != SLtt_Screen_Rows) || (c != SLtt_Screen_Cols)) {
recent_sizechange = TRUE;
}
lynx_enable_mouse(1);
#endif /* !VMS */
#endif /* SIGSTOP */
return;
}
#else
#ifdef FANCY_CURSES
#ifndef VMS
/* *INDENT-OFF* */
/* definitions for the mono attributes we can use */
static struct {
char *name;
int code;
} Mono_Attrs[7] =
{
{ "normal", A_NORMAL },
{ "bold", A_BOLD },
{ "reverse", A_REVERSE },
{ "underline", A_UNDERLINE },
{ "standout", A_STANDOUT },
{ "blink", A_BLINK },
{ "dim", A_DIM },
};
/* *INDENT-ON* */
int string_to_attr(char *name)
{
unsigned i;
for (i = 0; i < TABLESIZE(Mono_Attrs); i++) {
if (!strcasecomp(Mono_Attrs[i].name, name)) {
return Mono_Attrs[i].code;
}
}
return 0;
}
#endif /* VMS */
#ifdef USE_COLOR_STYLE
static char *attr_to_string(int code)
{
static char result[sizeof(Mono_Attrs) + 80];
unsigned i;
int pair = PAIR_NUMBER(code);
int bold = (pair != 0 && (code & A_BOLD) != 0);
if (bold)
code &= ~A_BOLD;
*result = 0;
for (i = 0; i < TABLESIZE(Mono_Attrs); i++) {
if (Mono_Attrs[i].code & code) {
if (*result)
strcat(result, "+");
strcat(result, Mono_Attrs[i].name);
}
}
if (pair != 0) {
short f, b;
if (pair_content(pair, &f, &b) != ERR) {
const char *fg = lookup_color(bold ? f + COLORS : f);
const char *bg = lookup_color(b);
if (*result)
strcat(result, "+");
sprintf(result + strlen(result), "%s/%s", fg, bg);
}
}
return result;
}
#endif /* USE_COLOR_STYLE */
#endif /* FANCY_CURSES */
#endif /* USE_SLANG */
/*
* This function boxes windows for (n)curses.
*/
void LYbox(WINDOW * win, BOOLEAN formfield GCC_UNUSED)
{
#ifdef USE_SLANG
SLsmg_draw_box(win->top_y, win->left_x, win->height, win->width + 4);
#else
#ifdef VMS
/*
* This should work for VAX-C and DEC-C, since they both have the same
* win._max_y and win._max_x members -TD
*
* (originally VMSbox by FM)
*/
int i;
wmove(win, 0, 0);
waddstr(win, "\033)0\016l");
for (i = 1; i < win->_max_x; i++)
waddch(win, 'q');
waddch(win, 'k');
for (i = 1; i < win->_max_y - 1; i++) {
wmove(win, i, 0);
waddch(win, 'x');
wmove(win, i, win->_max_x - 1);
waddch(win, 'x');
}
wmove(win, i, 0);
waddch(win, 'm');
for (i = 1; i < win->_max_x; i++)
waddch(win, 'q');
waddstr(win, "j\017");
#else /* !VMS */
/*
* If the terminal is in UTF-8 mode, it probably cannot understand box
* drawing characters as (n)curses handles them. (This may also be true
* for other display character sets, but isn't currently checked.) In that
* case, substitute ASCII characters for BOXVERT and BOXHORI if they were
* defined to 0 for automatic use of box drawing characters. They'll stay
* as they are otherwise. - KW & FM
*/
int boxvert, boxhori;
UCSetBoxChars(current_char_set, &boxvert, &boxhori, BOXVERT, BOXHORI);
#ifdef CSS
if (formfield)
wcurses_css(win, "frame", ABS_ON);
#endif
/*
* If we don't have explicitly specified characters for either vertical or
* horizontal lines, the characters that box() would use for the corners
* probably also won't work well. So we specify our own ASCII characters
* for the corners and call wborder() instead of box(). - kw
*/
LynxWChangeStyle(win, s_menu_frame, STACK_ON);
#ifdef HAVE_WBORDER
if (!boxvert || !boxhori)
box(win, boxvert, boxhori);
else if (boxvert == '*' || boxhori == '*')
wborder(win, boxvert, boxvert, boxhori, boxhori, '*', '*', '*', '*');
else
wborder(win, boxvert, boxvert, boxhori, boxhori, '/', '\\', '\\', '/');
#else
box(win, boxvert, boxhori);
#endif
LynxWChangeStyle(win, s_menu_frame, STACK_OFF);
#ifdef CSS
if (formfield)
wcurses_css(win, "frame", ABS_OFF);
#endif
#endif /* VMS */
wrefresh(win);
#endif /* USE_SLANG */
}
#if defined(USE_COLOR_STYLE)
/* Ok, explanation of the USE_COLOR_STYLE styles. The basic styles (ie non
* HTML) are set the same as the SLANG version for ease of programming. The
* other styles are simply the HTML enum from HTMLDTD.h + 16.
*/
HTCharStyle displayStyles[DSTYLE_ELEMENTS];
/*
* set a style's attributes - RP
*/
void setStyle(int style,
int color,
int cattr,
int mono)
{
displayStyles[style].color = color;
displayStyles[style].cattr = cattr;
displayStyles[style].mono = mono;
}
void setHashStyle(int style,
int color,
int cattr,
int mono,
char *element)
{
bucket *ds = &hashStyles[style];
CTRACE2(TRACE_STYLE,
(tfp, "CSS(SET): <%s> hash=%d, ca=%#x, ma=%#x\n",
element, style, color, mono));
ds->color = color;
ds->cattr = cattr;
ds->mono = mono;
ds->code = style;
FREE(ds->name);
StrAllocCopy(ds->name, element);
}
/*
* set the curses attributes to be color or mono - RP
*/
static void LYAttrset(WINDOW * win, int color,
int mono)
{
if (lynx_has_color
&& LYShowColor >= SHOW_COLOR_ON
&& color >= 0) {
CTRACE2(TRACE_STYLE, (tfp, "CSS:LYAttrset color (%s)\n",
attr_to_string(color)));
wattrset(win, color);
} else if (mono >= 0) {
CTRACE2(TRACE_STYLE, (tfp, "CSS:LYAttrset mono (%s)\n",
attr_to_string(mono)));
wattrset(win, mono);
} else {
CTRACE2(TRACE_STYLE, (tfp, "CSS:LYAttrset (A_NORMAL)\n"));
wattrset(win, A_NORMAL);
}
}
void curses_w_style(WINDOW * win, int style,
int dir)
{
#if OMIT_SCN_KEEPING
# define SPECIAL_STYLE /*(CSHASHSIZE+1) */ 88888
/* if TRACEs are not compiled in, this macro is redundant - we needn't valid
'ds' to stack off. */
#endif
int YP, XP;
#if !OMIT_SCN_KEEPING
bucket *ds = (style == NOSTYLE ? &nostyle_bucket : &hashStyles[style]);
#else
bucket *ds = (style == NOSTYLE ? &nostyle_bucket :
(style == SPECIAL_STYLE ? &special_bucket : &hashStyles[style]));
#endif
if (!ds->name) {
CTRACE2(TRACE_STYLE, (tfp, "CSS.CS:Style %d not configured\n", style));
#if !OMIT_SCN_KEEPING
return;
#endif
}
CTRACE2(TRACE_STYLE, (tfp, "CSS.CS:<%s%s> (%d)\n",
(dir ? "" : "/"),
ds->name, ds->code));
getyx(win, YP, XP);
if (style == s_normal && dir) {
wattrset(win, A_NORMAL);
if (win == LYwin)
cached_styles[YP][XP] = s_normal;
return;
}
switch (dir) {
/* ABS_OFF is the same as STACK_OFF for the moment */
case STACK_OFF:
if (last_colorattr_ptr) {
int last_attr = last_styles[--last_colorattr_ptr];
LYAttrset(win, last_attr, last_attr);
} else
LYAttrset(win, A_NORMAL, -1);
break;
case STACK_ON: /* remember the current attributes */
if (last_colorattr_ptr >= MAX_LAST_STYLES) {
CTRACE2(TRACE_STYLE, (tfp, "........... %s (0x%x) %s\r\n",
"attribute cache FULL, dropping last",
last_styles[last_colorattr_ptr],
"in LynxChangeStyle(curses_w_style)"));
last_colorattr_ptr = MAX_LAST_STYLES - 1;
}
last_styles[last_colorattr_ptr++] = LYgetattrs(win);
/* don't cache style changes for active links */
#if OMIT_SCN_KEEPING
/* since we don't compute the hcode to stack off in HTML.c, we
* don't know whether this style is configured. So, we
* shouldn't simply return on stacking on unconfigured
* styles, we should push curr attrs on stack. -HV
*/
if (!ds->name)
break;
#endif
/* FALL THROUGH */
case ABS_ON: /* change without remembering the previous style */
/* don't cache style changes for active links and edits */
if (style != s_alink
&& style != s_curedit
&& style != s_aedit
&& style != s_aedit_sel
&& style != s_aedit_pad
&& style != s_aedit_arr) {
CTRACE2(TRACE_STYLE, (tfp, "CACHED: <%s> @(%d,%d)\n",
ds->name, YP, XP));
if (win == LYwin)
cached_styles[YP][XP] = style;
}
LYAttrset(win, ds->color, ds->mono);
break;
}
}
/*
* wrapper function to set on-screen styles - RP
*/
void wcurses_css(WINDOW * win, char *name,
int dir)
{
int try_again = 1;
while (try_again) {
int tmpHash = hash_code(name);
CTRACE2(TRACE_STYLE, (tfp, "CSSTRIM:trying to set [%s] style - ", name));
if (tmpHash == NOSTYLE) {
char *class = strrchr(name, '.');
CTRACE2(TRACE_STYLE, (tfp, "undefined, trimming at %p\n", class));
if (class)
*class = '\0';
else
try_again = 0;
} else {
CTRACE2(TRACE_STYLE, (tfp, "ok (%d)\n", hash_code(name)));
curses_w_style(win, hash_code(name), dir);
try_again = 0;
}
}
}
void curses_css(char *name,
int dir)
{
wcurses_css(LYwin, name, dir);
}
void curses_style(int style,
int dir)
{
curses_w_style(LYwin, style, dir);
}
#endif /* USE_COLOR_STYLE */
static BOOL lynx_called_initscr = FALSE;
#if defined(HAVE_USE_DEFAULT_COLORS) && defined(USE_DEFAULT_COLORS)
/*
* If we find a "default" color while reading the config-file, set default
* colors on the screen.
*/
int lynx_default_colors(void)
{
int code = 0;
if (lynx_called_initscr) {
code = -1;
if (!default_color_reset && use_default_colors() == OK) {
default_fg = DEFAULT_COLOR;
default_bg = DEFAULT_COLOR;
code = 1;
}
}
return code;
}
#endif /* HAVE_USE_DEFAULT_COLORS && USE_DEFAULT_COLORS */
#if defined(USE_COLOR_TABLE) && defined(COLOR_CURSES)
/*
* This block of code is designed to produce the same color effects using SVr4
* curses as the slang library's implementation in this module. That maps the
* SGR codes into a 0-7 index into the color table, with special treatment for
* backgrounds. There's a bit of convoluted (but necessary) code handling the
* special case of initialization before 'initscr()' is called.
* 1997/1/19 - T.E.Dickey <dickey@clark.net>
*/
/* *INDENT-OFF* */
static struct {
int fg, bg;
} lynx_color_cfg[] = {
/*0*/ { DEFAULT_FG, DEFAULT_BG},
/*1*/ { COLOR_BLUE, DEFAULT_BG},
/*2*/ { COLOR_YELLOW+8,COLOR_BLUE},
/*3*/ { COLOR_GREEN, DEFAULT_BG},
/*4*/ { COLOR_MAGENTA, DEFAULT_BG},
/*5*/ { COLOR_BLUE, DEFAULT_BG},
/*6*/ { COLOR_RED, DEFAULT_BG},
/*7*/ { COLOR_MAGENTA, COLOR_CYAN}
};
/* *INDENT-ON* */
/*
* Hold the codes for color-pairs here until 'initscr()' is called.
*/
static struct {
int fg;
int bg;
} lynx_color_pairs[25];
/*
* If we find an exact match for the given default colors, force curses to use
* color pair 0, which corresponds to the terminal's default colors. Normally
* curses assumes white-on-black, but we can override the assumption with this
* function.
*/
static int get_color_pair(int n)
{
#ifdef USE_CURSES_PAIR_0
if (lynx_color_pairs[n].fg == default_fg
&& lynx_color_pairs[n].bg == default_bg)
return 0;
#endif
return COLOR_PAIR(n);
}
/*
* Lynx "knows" about 16 colors. ANSI colors (and most color terminal
* emulators) only go to 8, though some curses implementations (ncurses and
* PDCurses) handle 16. If lynx's configuration calls for a color past the
* number of colors that the terminal handles (COLORS), map the extra value
* to bold.
*/
#define is_boldc(c) ((c) > (COLORS-1))
#define map2bold(c) (is_boldc(c) ? ((c) & (COLORS-1)) : (c))
/*
* Return the extra color as A_BOLD.
* If there is no extra color, return A_NORMAL.
*/
static int lynx_color_cfg_attr(int code)
{
int result = A_NORMAL;
if (code >= 0 && code < 8) {
int fg = lynx_color_cfg[code].fg;
if (is_boldc(fg) && (fg & COLORS))
result = A_BOLD;
}
return result;
}
/*
* Map the SGR attributes (0-7) into ANSI colors, modified with the actual BOLD
* attribute we'll get 16 colors.
*/
static void LYsetWAttr(WINDOW * win)
{
if (lynx_has_color && LYShowColor >= SHOW_COLOR_ON) {
int code = 0;
int attr = A_NORMAL;
int offs = 1;
if (Current_Attr & A_BOLD)
code |= 1;
if (Current_Attr & A_REVERSE)
code |= 2;
if (Current_Attr & A_UNDERLINE)
code |= 4;
attr = lynx_color_cfg_attr(code);
if (code + offs < COLOR_PAIRS) {
attr |= get_color_pair(code + offs);
}
wattrset(win, attr & ~Masked_Attr);
} else {
wattrset(win, Current_Attr & ~Masked_Attr);
}
}
/*
* Initialize a curses color-pair based on our configured color values.
*/
static void lynx_init_color_pair(int n)
{
int m;
if (lynx_called_initscr) {
for (m = 0; m <= 16; m += 8) {
int pair = n + m + 1;
if (pair < COLOR_PAIRS)
init_pair((short) pair,
(short) map2bold(lynx_color_pairs[pair].fg),
(short) map2bold(lynx_color_pairs[pair].bg));
}
if (n == 0 && LYShowColor >= SHOW_COLOR_ON)
wbkgd(LYwin, COLOR_BKGD | ' ');
}
}
static void lynx_map_color(int n)
{
CTRACE((tfp, "lynx_map_color(%d)\n", n));
lynx_color_pairs[n + 1].fg = lynx_color_cfg[n].fg;
lynx_color_pairs[n + 1].bg = lynx_color_cfg[n].bg;
lynx_color_pairs[n + 9].fg = lynx_color_cfg[n].fg;
lynx_color_pairs[n + 9].bg = lynx_color_cfg[0].bg;
lynx_color_pairs[n + 17].fg = lynx_color_cfg[n].bg;
lynx_color_pairs[n + 17].bg = lynx_color_cfg[n].bg;
lynx_init_color_pair(n);
}
/*
* Change a configured color value. This may be called before initscr(), so
* we may not be able to call init_pair() to finish the change.
*/
int lynx_chg_color(int color,
int fg,
int bg
)
{
if (fg == ERR_COLOR || bg == ERR_COLOR)
return -1;
if (color >= 0 && color < 8) {
lynx_color_cfg[color].fg = fg;
lynx_color_cfg[color].bg = bg;
lynx_map_color(color);
} else {
return -1;
}
return 0;
}
void lynx_set_color(int a)
{
if (lynx_has_color && LYShowColor >= SHOW_COLOR_ON) {
wattrset(LYwin, lynx_color_cfg_attr(a)
| (((a + 1) < COLOR_PAIRS)
? get_color_pair(a + 1)
: A_NORMAL));
}
}
void lynx_standout(int flag)
{
if (flag)
LYaddAttr(A_REVERSE);
else
LYsubAttr(A_REVERSE);
}
static void lynx_init_colors(void)
{
if (lynx_has_color) {
size_t n;
CTRACE((tfp, "lynx_init_colors (default %d/%d)\n",
default_fg, default_bg));
lynx_color_cfg[0].fg = default_fg;
lynx_color_cfg[0].bg = default_bg;
for (n = 0; n < TABLESIZE(lynx_color_cfg); n++) {
lynx_init_color_pair(n);
}
} else if (LYShowColor != SHOW_COLOR_NEVER) {
LYShowColor = SHOW_COLOR_OFF;
}
}
void lynx_setup_colors(void)
{
int n;
CTRACE((tfp, "lynx_setup_colors\n"));
for (n = 0; n < 8; n++)
lynx_map_color(n);
}
#endif /* USE_COLOR_TABLE */
void LYnoVideo(int a)
{
CTRACE((tfp, "LYnoVideo(%d)\n", a));
#ifdef USE_SLANG
if (a & 1)
Masked_Attr |= SLTT_BOLD_MASK;
if (a & 2)
Masked_Attr |= SLTT_REV_MASK;
if (a & 4)
Masked_Attr |= SLTT_ULINE_MASK;
lynx_setup_attrs();
#else
#ifdef USE_COLOR_TABLE
if (a & 1)
Masked_Attr |= A_BOLD;
if (a & 2)
Masked_Attr |= A_REVERSE;
if (a & 4)
Masked_Attr |= A_UNDERLINE;
#endif
#endif
}
#define NEWTERM_NAME "newterm"
#if !defined(VMS) && !defined(USE_SLANG)
/*
* If newterm is not defined, assume a curses subset which
* supports only initscr. --gil
*/
#if defined(HAVE_NEWTERM) && defined(HAVE_DELSCREEN) && !(defined(NCURSES) && defined(HAVE_RESIZETERM))
static SCREEN *LYscreen = NULL;
#define LYDELSCR() { \
if (recent_sizechange) { \
CTRACE((tfp, "Screen size: delscreen()\n")); \
delscreen(LYscreen); \
LYscreen = NULL; } }
/*
* Surrogates for newterm annd delscreen
*/
#else /* HAVE_NEWTERM */
static WINDOW *LYscreen = NULL;
#undef NEWTERM_NAME
#define NEWTERM_NAME "initscr"
#undef newterm
#define newterm(type, out, in) (initscr())
#define LYDELSCR() /* nothing */
#endif /* HAVE_NEWTERM */
#else /* !defined(VMS) && !defined(USE_SLANG) */
/*
* Provide last recourse definitions of LYscreen and LYDELSCR for
* stop_curses, which only tests LYscreen for zero/nonzero but
* never uses it as a pointer or L-value.
*/
#define LYscreen TRUE
#define LYDELSCR() /* nothing */
#endif /* !defined(VMS) && !defined(USE_SLANG) */
#if defined(PDCURSES) && defined(PDC_BUILD) && PDC_BUILD >= 2401
int saved_scrsize_x = 0;
int saved_scrsize_y = 0;
#endif
void start_curses(void)
{
#ifdef USE_SLANG
static int slinit;
if (LYCursesON) {
CTRACE((tfp, "start_curses: Hmm, already ON.\n"));
return;
}
if (slinit == 0) {
#if defined(USE_KEYMAPS)
if (-1 == lynx_initialize_keymaps())
exit(EXIT_FAILURE);
#else
SLtt_get_terminfo();
#endif
#if (defined(__DJGPP__) && !defined(DJGPP_KEYHANDLER)) || defined(__CYGWIN__)
SLkp_init();
#endif /* __DJGPP__ && !DJGPP_KEYHANDLER */
#if defined(REAL_UNIX_SYSTEM) && !defined(__CYGWIN__)
#if SLANG_VERSION >= 9935
SLang_TT_Read_FD = fileno(stdin);
#endif /* SLANG_VERSION >= 9935 */
#endif /* REAL_UNIX_SYSTEM && !__CYGWIN__ */
#if !defined(USE_KEYMAPS) && defined(ENHANCED_LINEEDIT) && defined(ESCDELAY)
/* way to get ESC that's not part of a recognized sequence through */
ESCDELAY = 2000;
#endif
/*
* Check whether a saved show_color:off override is in effect. - kw
*/
if (LYrcShowColor == SHOW_COLOR_NEVER) {
SLtt_Use_Ansi_Colors = 0;
}
/*
* Check whether we're forcing color on. - FM
*/
if ((LYShowColor > 1) && (Lynx_Color_Flags & SL_LYNX_USE_COLOR))
SLtt_Use_Ansi_Colors = 1;
/*
* Check whether a -nocolor override is in effect. - kw
*/
if (Lynx_Color_Flags & SL_LYNX_OVERRIDE_COLOR)
SLtt_Use_Ansi_Colors = 0;
/*
* Make sure our flags are in register. - FM
*/
if (SLtt_Use_Ansi_Colors == 1) {
if (LYShowColor != SHOW_COLOR_ALWAYS) {
LYShowColor = SHOW_COLOR_ON;
}
} else {
if (LYShowColor != SHOW_COLOR_NEVER) {
LYShowColor = SHOW_COLOR_OFF;
}
}
size_change(0);
#if (defined(VMS) || defined(REAL_UNIX_SYSTEM)) && !defined(__CYGWIN__)
if ((Masked_Attr & SLTT_ULINE_MASK) == 0) {
SLtt_add_color_attribute(4, SLTT_ULINE_MASK);
SLtt_add_color_attribute(5, SLTT_ULINE_MASK);
}
/*
* If set, the blink escape sequence will turn on high intensity
* background (rxvt and maybe Linux console).
*/
SLtt_Blink_Mode = term_blink_is_boldbg;
#endif /* (VMS || REAL_UNIX_SYSTEM) && !__CYGWIN__ */
}
#ifdef __DJGPP__
_eth_init();
#endif /* __DJGPP__ */
slinit = 1;
Current_Attr = 0;
#ifndef VMS
#if SLANG_VERSION > 9929
SLang_init_tty(-1, 0, 1);
#else
SLang_init_tty(3, 0, 1);
#endif /* SLANG_VERSION > 9929 */
#endif /* !VMS */
SLsmg_init_smg();
SLsmg_Display_Eight_Bit = LYlowest_eightbit[current_char_set];
if (SLsmg_Display_Eight_Bit > 191)
SLsmg_Display_Eight_Bit = 191; /* may print ctrl chars otherwise - kw */
scrollok(0, 0);
SLsmg_Backspace_Moves = 1;
#if SLANG_VERSION > 10306
SLsmg_touch_screen();
#endif
#ifndef VMS
#if defined(REAL_UNIX_SYSTEM) && !defined(__CYGWIN__)
SLtty_set_suspend_state(1);
#endif /* REAL_UNIX_SYSTEM && !__CYGWIN__ */
#ifdef SIGTSTP
if (!no_suspend)
signal(SIGTSTP, sl_suspend);
#endif /* SIGTSTP */
signal(SIGINT, cleanup_sig);
#endif /* !VMS */
lynx_enable_mouse(1);
#else /* USE_SLANG; Now using curses: */
int keypad_on = 0;
#ifdef VMS
/*
* If we are VMS then do initscr() everytime start_curses() is called!
*/
CTRACE((tfp, "Screen size: initscr()\n"));
initscr(); /* start curses */
#else /* Unix: */
#ifdef __CYGWIN__
/*
* Workaround for buggy Cygwin, which breaks subprocesses of a
* full-screen application (tested with cygwin dll, dated
* 2002/6/23 -TD)
*/
if (!lynx_called_initscr) {
FILE *fp = fopen("/dev/tty", "w");
if (fp != 0)
stdout = fp;
}
#endif
if (!LYscreen) {
/*
* If we're not VMS then only do initscr() one time, and one time only!
*/
#if defined(HAVE_NEWTERM)
#if !(defined(NCURSES) && !defined(HAVE_RESIZETERM))
BOOLEAN savesize;
savesize = recent_sizechange;
size_change(0);
recent_sizechange = savesize; /* avoid extra redraw */
#if defined(__MVS__)
{
/*
* The requirement to do this may be a bug in OS/390.
*
* Put screen geometry in environment variables used by
* XOpen curses before calling newterm(). I believe this
* completes work left unfinished by AJL & FM -- gil
*/
static char lines_putenv[] = "LINES=abcde", cols_putenv[] = "COLUMNS=abcde";
sprintf(lines_putenv + 6, "%d", LYlines & 0xfff);
sprintf(cols_putenv + 8, "%d", LYcols & 0xfff);
putenv(lines_putenv);
putenv(cols_putenv);
CTRACE((tfp, "start_curses putenv %s, %s\n", lines_putenv, cols_putenv));
}
#endif /* defined(__MVS__) */
#endif /* !(defined(NCURSES) && defined(HAVE_RESIZETERM)) */
CTRACE((tfp, "Screen size: %s()\n", NEWTERM_NAME));
if (!(LYscreen = newterm(NULL, stdout, stdin))) { /* start curses */
fprintf(tfp, "%s\n",
gettext("Terminal initialisation failed - unknown terminal type?"));
exit_immediately(EXIT_FAILURE);
}
#else
CTRACE((tfp, "Screen size: initscr()\n"));
initscr();
#endif /* HAVE_NEWTERM */
lynx_called_initscr = TRUE;
LYlines = LYscreenHeight();
LYcols = LYscreenWidth();
#if defined(SIGWINCH) && defined(NCURSES_VERSION)
size_change(0);
recent_sizechange = FALSE; /* prevent mainloop drawing 1st doc twice */
#endif /* SIGWINCH */
CTRACE((tfp, "Screen size is now %d x %d\n", LYlines, LYcols));
#ifdef USE_CURSES_PADS
if (LYuseCursesPads) {
LYwin = newpad(LYlines, MAX_COLS);
LYshiftWin = 0;
LYwideLines = FALSE;
} else {
LYwin = stdscr;
}
#endif
#if defined(USE_KEYMAPS) && defined(NCURSES_VERSION)
# if HAVE_KEYPAD
/* Need to switch keypad on before initializing keymaps, otherwise
when the keypad is switched on, some keybindings may be overriden. */
keypad(LYwin, TRUE);
keypad_on = 1;
# endif /* HAVE_KEYPAD */
if (-1 == lynx_initialize_keymaps()) {
endwin();
exit(EXIT_FAILURE);
}
#endif
/*
* This is a workaround for a bug in SVr4 curses, observed on Solaris
* 2.4: if your terminal's alternate-character set contains codes in
* the range 128-255, they'll be sign-extended in the acs_map[] table,
* which in turn causes their values to be emitted as 255 (0xff).
* "Fix" this by forcing the table to 8-bit codes (it has to be
* anyway).
*/
#if defined(ALT_CHAR_SET) && !defined(NCURSES_VERSION)
{
int n;
for (n = 0; n < 128; n++)
if (ALT_CHAR_SET[n] & 0x80) {
ALT_CHAR_SET[n] &= 0xff;
ALT_CHAR_SET[n] |= A_ALTCHARSET;
}
}
#endif
#if defined(USE_COLOR_STYLE) || defined(USE_COLOR_TABLE)
if (has_colors()) {
lynx_has_color = TRUE;
start_color();
#ifndef COLORS
/* map2boldc() relies on COLORS being a power of 2 */
if (COLORS > 16)
COLORS = 16;
if (COLORS < 8)
COLORS = 2;
if (COLORS > 8 && COLORS != 16)
COLORS = 8;
#endif
#ifdef USE_DEFAULT_COLORS
#if defined(EXP_ASSUMED_COLOR) && defined(USE_COLOR_TABLE)
/*
* Adjust the color mapping table to match the ASSUMED_COLOR
* setting in lynx.cfg
*/
if (assume_default_colors(default_fg, default_bg) != OK) {
default_fg = COLOR_WHITE;
default_bg = COLOR_BLACK;
}
CTRACE((tfp, "initializing default colors %d/%d\n",
default_fg, default_bg));
if (default_fg >= 0 || default_bg >= 0) {
unsigned n;
for (n = 0; n < TABLESIZE(lynx_color_cfg); n++) {
if (default_fg >= 0 && lynx_color_cfg[n].fg < 0)
lynx_color_cfg[n].fg = default_fg;
if (default_bg >= 0 && lynx_color_cfg[n].bg < 0)
lynx_color_cfg[n].bg = default_bg;
CTRACE((tfp, "color_cfg[%d] = %d/%d\n", n,
lynx_color_cfg[n].fg,
lynx_color_cfg[n].bg));
}
lynx_setup_colors();
}
#else
#if defined(HAVE_USE_DEFAULT_COLORS)
lynx_default_colors();
#endif /* HAVE_USE_DEFAULT_COLORS */
#endif /* EXP_ASSUMED_COLOR */
#endif /* USE_DEFAULT_COLORS */
}
#endif /* USE_COLOR_STYLE || USE_COLOR_TABLE */
#ifdef USE_COLOR_STYLE
parse_userstyles();
#endif
#ifdef USE_COLOR_TABLE
lynx_init_colors();
#endif /* USE_COLOR_TABLE */
}
#ifdef __DJGPP__
_eth_init();
#endif /* __DJGPP__ */
#endif /* not VMS */
/* nonl(); *//* seems to slow things down */
#ifdef VMS
crmode();
raw();
#else
#ifdef HAVE_CBREAK
cbreak();
#else
crmode();
#endif /* HAVE_CBREAK */
signal(SIGINT, cleanup_sig);
#endif /* VMS */
noecho();
#ifdef HAVE_KEYPAD
if (!keypad_on)
keypad(LYwin, TRUE);
#endif /* HAVE_KEYPAD */
lynx_enable_mouse(1);
fflush(stdin);
fflush(stdout);
fflush(stderr);
#endif /* USE_SLANG */
#if defined(WIN_EX)
LYclear();
#endif
#if defined(USE_BLINK) && defined(__EMX__)
if (term_blink_is_boldbg) /* Now actually make it so! */
make_blink_boldbg();
#endif
LYCursesON = TRUE;
#if defined(PDCURSES) && defined(PDC_BUILD) && PDC_BUILD >= 2401
if ((scrsize_x != 0) && (scrsize_y != 0)) {
if (saved_scrsize_x == 0) {
saved_scrsize_x = COLS;
saved_scrsize_y = LINES;
}
CTRACE((tfp, "resize_term: x=%d, y=%d\n", scrsize_x, scrsize_y));
CTRACE((tfp, "saved terminal size: x=%d, y=%d\n", saved_scrsize_x, saved_scrsize_y));
resize_term(scrsize_y, scrsize_x);
LYclear();
}
#endif
CTRACE((tfp, "start_curses: done.\n"));
} /* end of start_curses() */
void lynx_enable_mouse(int state)
{
#ifdef USE_MOUSE
/***********************************************************************/
#if defined(WIN_EX)
/* modify lynx_enable_mouse() for pdcurses configuration so that mouse support
is disabled unless -use_mouse is specified
*/
HANDLE hConIn = INVALID_HANDLE_VALUE;
hConIn = GetStdHandle(STD_INPUT_HANDLE);
if (LYUseMouse == 0) {
SetConsoleMode(hConIn, ENABLE_WINDOW_INPUT);
FlushConsoleInputBuffer(hConIn);
return;
}
#endif
if (LYUseMouse == 0)
return;
#if defined(USE_SLANG)
SLtt_set_mouse_mode(state, 0);
SLtt_flush_output();
#else
#if defined(WIN_EX) && defined(PDCURSES)
if (state) {
SetConsoleMode(hConIn, ENABLE_MOUSE_INPUT | ENABLE_WINDOW_INPUT);
FlushConsoleInputBuffer(hConIn);
}
#else
#if defined(NCURSES)
if (state) {
/* Compensate for small value of maxclick in ncurses. */
static int was = 0;
if (!was) {
int old = mouseinterval(-1);
was++;
if (old < 200) /* Default 166 */
mouseinterval(300);
}
/* Inform ncurses which mouse events we're interested in.
* We shouldn't need to include BUTTONn_PRESSED and BUTTONn_RELEASED
* events, since ncurses should translate them to click events. - kw
* However, if we do not include them, then ncurses effectively
* ignores mouseinterval(), thus translates *any* sequence of
* press/release to a click, which leads to inconveniences.
* We special-case these events in LYStrings.c.
*/
mousemask(BUTTON_CTRL | BUTTON_ALT
| BUTTON1_PRESSED | BUTTON1_RELEASED
| BUTTON1_CLICKED
| BUTTON1_DOUBLE_CLICKED | BUTTON1_TRIPLE_CLICKED
| BUTTON2_PRESSED | BUTTON2_RELEASED
| BUTTON2_CLICKED
| BUTTON3_PRESSED | BUTTON3_RELEASED
| BUTTON3_CLICKED
| BUTTON3_DOUBLE_CLICKED | BUTTON3_TRIPLE_CLICKED,
NULL);
} else
mousemask(0, NULL);
#endif /* NCURSES */
#endif /* WIN_EX and PDCURSES */
#if defined(PDCURSES)
if (state)
mouse_set(
BUTTON1_CLICKED | BUTTON1_PRESSED | BUTTON1_RELEASED |
BUTTON2_CLICKED | BUTTON2_PRESSED | BUTTON2_RELEASED |
BUTTON3_CLICKED | BUTTON3_PRESSED | BUTTON3_RELEASED);
#endif
#endif /* NOT USE_SLANG */
/***********************************************************************/
#endif /* USE_MOUSE */
}
/*
* SVr4 curses (and ncurses) initialize the terminal I/O to raw mode, and
* simulate other modes in the library. This means that when running, it
* simulates the OCRNL setting. Normally that is not a problem. However, when
* spawning a subprocess (e.g., xli), the subprocess may write to the screen.
* Fine so far - curses resets the terminal I/O to the normal state on exit.
* But the subprocess's messages can still be coming to the screen when lynx
* returns to the screen mode. This function delays restoring OCRNL until
* after the first getch() call.
*
* The OCRNL setting is controlled by nl()/nonl() of course - but we do not
* want to give up that optimization since it would be a bit slower. (Note -
* slang does not use this optimization; if it did, the same screen glitch
* would occur).
*
* FIXME: for simplicity, only ncurses is implemented here - the TTY and
* SET_TTY definitions are ncurses-specific. The same effect could be done for
* other curses implementations, since the "cur_term->Nttyb" part is common to
* SVr4 curses.
*/
void lynx_nl2crlf(int normal GCC_UNUSED)
{
#if defined(NCURSES_VERSION_PATCH) && defined(SET_TTY) && defined(TERMIOS) && defined(ONLCR)
static TTY saved_tty;
static int did_save = FALSE;
static int waiting = FALSE;
static int can_fix = TRUE;
if (!did_save) {
saved_tty = cur_term->Nttyb;
did_save = TRUE;
#if NCURSES_VERSION_PATCH < 20010529
/* workaround for optimizer bug with nonl() */
if ((tigetstr("cud1") != 0 && *tigetstr("cud1") == '\n')
|| (tigetstr("ind") != 0 && *tigetstr("ind") == '\n'))
can_fix = FALSE;
#endif
}
if (can_fix) {
if (normal) {
if (!waiting) {
cur_term->Nttyb.c_oflag |= ONLCR;
waiting = TRUE;
nonl();
}
} else {
if (waiting) {
cur_term->Nttyb = saved_tty;
SET_TTY(fileno(stdout), &saved_tty);
waiting = FALSE;
nl();
LYrefresh();
}
}
}
#endif
}
void stop_curses(void)
{
if (LYCursesON) {
echo();
}
#if defined(PDCURSES) && defined(PDC_BUILD) && PDC_BUILD >= 2401
resetty();
#endif
#ifdef __DJGPP__
_eth_release();
#endif /* __DJGPP__ */
#if defined(DOSPATH) && !(defined(USE_SLANG) || defined(_WIN_CC))
#ifdef __DJGPP__
ScreenClear();
#else
#ifdef __MINGW32__
clear();
#else
clrscr();
#endif
#endif
#else
if (LYCursesON == TRUE) {
lynx_nl2crlf(TRUE);
lynx_enable_mouse(0);
#if 1 /* (!defined(WIN_EX) || defined(__CYGWIN__)) */ /* @@@ */
#ifdef WIN_EX
if (system_is_NT)
#endif
if (LYscreen || lynx_called_initscr) {
endwin(); /* stop curses */
LYDELSCR();
}
#endif
}
#ifdef SH_EX
{
int i;
for (i = 0; i <= 3; i++) {
fprintf(stdout, "\r\n");
}
}
#endif
fflush(stdout);
#endif /* defined(DOSPATH) && !(defined(USE_SLANG) || defined(_WIN_CC)) */
fflush(stderr);
LYCursesON = FALSE;
CTRACE((tfp, "stop_curses: done.\n"));
#if defined(SIGTSTP) && defined(USE_SLANG)
#ifndef VMS
if (!no_suspend)
signal(SIGTSTP, SIG_DFL);
#endif /* !VMS */
#endif /* SIGTSTP && USE_SLANG */
#ifndef VMS
signal(SIGINT, SIG_DFL);
#endif /* !VMS */
}
#ifdef VMS
/*
* Check terminal type, start curses & setup terminal.
*/
BOOLEAN setup(char *terminal)
{
int c;
int status;
char *dummy = 0, *cp, term[81];
#ifdef USE_SLANG
extern void longname();
#endif /* USE_SLANG */
/*
* If the display was not set by a command line option then see if it is
* available from the environment.
*/
if ((cp = LYgetXDisplay()) != 0) {
StrAllocCopy(x_display, cp);
} else {
FREE(x_display);
}
/*
* Get terminal type, and convert to lower case.
*/
term[0] = '\0';
longname(dummy, term);
if (term[0] == '\0' && (form_get_data || form_post_data)) {
/*
* Some yoyo used these under conditions which require -dump, so force
* that mode here. - FM
*/
dump_output_immediately = TRUE;
LYcols = DFT_COLS;
if (keypad_mode == NUMBERS_AS_ARROWS)
keypad_mode = LINKS_ARE_NUMBERED;
status = mainloop();
(void) signal(SIGHUP, SIG_DFL);
(void) signal(SIGTERM, SIG_DFL);
#ifdef SIGTSTP
if (no_suspend)
(void) signal(SIGTSTP, SIG_DFL);
#endif /* SIGTSTP */
exit(status);
}
LYLowerCase(term);
printf("%s%s\n", gettext("Terminal ="), term);
if ((strlen(term) < 5) ||
strncmp(term, "vt", 2) || !isdigit(term[2])) {
printf("%s\n",
gettext("You must use a vt100, 200, etc. terminal with this program."));
printf(CONFIRM_PROCEED, "n/y");
c = getchar();
if (c != 'y' && c != 'Y') {
printf("\n");
return (FALSE);
}
strcpy(term, "vt100");
}
ttopen();
start_curses();
LYlines = LYscreenHeight();
LYcols = LYscreenWidth();
return (TRUE);
}
#else /* Not VMS: */
/*
* Check terminal type, start curses & setup terminal.
*/
BOOLEAN setup(char *terminal)
{
char *term_putenv = NULL;
char *buffer = NULL;
char *cp;
/*
* If the display was not set by a command line option then see if it is
* available from the environment .
*/
if ((cp = LYgetXDisplay()) != NULL) {
StrAllocCopy(x_display, cp);
} else {
FREE(x_display);
}
if (terminal != NULL) {
HTSprintf0(&term_putenv, "TERM=%.106s", terminal);
(void) putenv(term_putenv);
}
/*
* Query the terminal type.
*/
if (dumbterm(LYGetEnv("TERM"))) {
printf("\n\n %s\n\n", gettext("Your Terminal type is unknown!"));
printf(" %s [vt100] ", gettext("Enter a terminal type:"));
if (LYSafeGets(&buffer, stdin) != 0) {
LYTrimLeading(buffer);
LYTrimTrailing(buffer);
}
if (isEmpty(buffer))
StrAllocCopy(buffer, "vt100");
HTSprintf0(&term_putenv, "TERM=%.106s", buffer);
FREE(buffer);
(void) putenv(term_putenv);
printf("\n%s %s\n", gettext("TERMINAL TYPE IS SET TO"),
LYGetEnv("TERM"));
LYSleepMsg();
}
start_curses();
#ifdef HAVE_TTYTYPE
/*
* Account for lossage on the 'sun' terminal type (80x24) Sun text console
* driver. It only supports reverse video, but all SGR sequences produce
* that same reverse video, and the terminfo entry lists different SGRs for
* 'bold' and 'rev'. As a result, the current link is indistinguishable
* from all other links. The workaround here is to disable the 'rev'
* capability.
*/
if ((strncmp((const char *) ttytype, "sun", 3) == 0)) {
LYnoVideo(2);
}
#endif /* HAVE_TTYTYPE */
LYlines = LYscreenHeight();
LYcols = LYscreenWidth();
return (1);
}
static int dumbterm(char *terminal)
{
int dumb = FALSE;
/*
* Began checking for terminal == NULL in case that TERM environment
* variable is not set. Thanks to Dick Wesseling (ftu@fi.ruu.nl).
*/
if (terminal == NULL ||
!strcasecomp(terminal, "network") ||
!strcasecomp(terminal, "unknown") ||
!strcasecomp(terminal, "dialup") ||
!strcasecomp(terminal, "dumb") ||
!strcasecomp(terminal, "switch") ||
!strcasecomp(terminal, "ethernet"))
dumb = TRUE;
return (dumb);
}
#ifdef FANCY_CURSES
#ifndef USE_COLOR_STYLE
#ifdef USE_COLOR_TABLE
void LYaddWAttr(WINDOW * win, int a)
{
Current_Attr |= a;
LYsetWAttr(win);
}
void LYaddAttr(int a)
{
LYaddWAttr(LYwin, a);
}
void LYsubWAttr(WINDOW * win, int a)
{
Current_Attr &= ~a;
LYsetWAttr(win);
}
void LYsubAttr(int a)
{
LYsubWAttr(LYwin, a);
}
#endif /* USE_COLOR_TABLE */
#endif /* !USE_COLOR_STYLE */
#endif /* FANCY_CURSES */
#endif /* VMS */
/* Use this rather than the 'wprintw()' function to write a blank-padded
* string to the given window, since someone's asserted that printw doesn't
* handle 8-bit characters unlike addstr (though more info would be useful).
*
* We're blank-filling so that with SVr4 curses, it'll show the background
* color to a uniform width in the popup-menu.
*/
#ifndef USE_SLANG
void LYpaddstr(WINDOW * the_window, int width,
const char *the_string)
{
int y, x;
int actual = strlen(the_string);
getyx(the_window, y, x);
if (width + x > LYcolLimit)
width = LYcolLimit - x;
if (actual > width)
actual = width;
LYwaddnstr(the_window, the_string, actual);
width -= actual;
while (width-- > 0)
waddstr(the_window, " ");
}
/*
* Workaround a bug in ncurses order-of-refresh by setting a pointer to
* the topmost window that should be displayed.
*
* FIXME: the associated call on 'keypad()' is not needed for Unix, but
* something in the OS/2 EMX port requires it.
*/
static WINDOW *my_subwindow;
void LYsubwindow(WINDOW * param)
{
if (param != 0) {
my_subwindow = param;
#if defined(NCURSES) || defined(PDCURSES)
keypad(my_subwindow, TRUE);
#if defined(HAVE_GETBKGD) /* not defined in ncurses 1.8.7 */
wbkgd(my_subwindow, getbkgd(LYwin));
wbkgdset(my_subwindow, getbkgd(LYwin));
#endif
#endif
scrollok(my_subwindow, TRUE);
} else {
touchwin(LYwin);
delwin(my_subwindow);
my_subwindow = 0;
}
}
WINDOW *LYtopwindow(void)
{
return (my_subwindow ? my_subwindow : LYwin);
}
#endif
WINDOW *LYstartPopup(int *top_y,
int *left_x,
int *height,
int *width)
{
WINDOW *form_window = 0;
#ifdef USE_SLANG
static WINDOW fake_window;
if (*left_x < 1 || (*left_x + *width + 4) >= LYcolLimit) {
*left_x = 1;
*width = LYcolLimit - 5;
}
SLsmg_fill_region(*top_y, *left_x - 1, *height, *width + 4, ' ');
form_window = &fake_window;
form_window->top_y = *top_y;
form_window->left_x = *left_x;
form_window->height = *height;
form_window->width = *width;
#else
if (*left_x > 0 && (*left_x + *width + 4) < LYcolLimit)
form_window = newwin(*height, *width + 4, *top_y, *left_x - 1);
if (form_window == 0) {
*width = LYcolLimit - 4;
form_window = newwin(*height, LYcolLimit, *top_y, 0);
}
if (form_window == 0) {
HTAlert(POPUP_FAILED);
} else {
LYsubwindow(form_window);
# ifdef USE_COLOR_STYLE
{
long b;
/* Get a proper value for the attribute */
LynxWChangeStyle(form_window, s_menu_bg, STACK_ON);
b = LYgetattrs(form_window);
LynxWChangeStyle(form_window, s_menu_bg, STACK_OFF);
wbkgd(form_window, b | ' ');
/* wbkgdset does not make a lot of sense with USE_COLOR_STYLE
since it *forces* attributes on all the cells in the window.
Undo the change done in LYsubwindow, since we set our styles.
*/
wbkgdset(form_window, (b & ~(A_BOLD | A_BLINK)) | ' ');
}
# endif
}
#endif /* USE_SLANG */
return form_window;
}
void LYstartTargetEmphasis(void)
{
#ifdef USE_COLOR_STYLE
if (s_whereis != NOSTYLE) {
curses_style(s_whereis, STACK_ON);
return;
}
#endif
#if defined(FANCY_CURSES) || defined(USE_SLANG)
lynx_start_bold();
lynx_start_reverse();
#endif /* FANCY_CURSES || USE_SLANG */
lynx_start_underline();
}
void LYstopTargetEmphasis(void)
{
#ifdef USE_COLOR_STYLE
if (s_whereis != NOSTYLE) {
curses_style(s_whereis, STACK_OFF);
return;
}
#endif
lynx_stop_underline();
#if defined(FANCY_CURSES) || defined(USE_SLANG)
lynx_stop_reverse();
lynx_stop_bold();
#endif /* FANCY_CURSES || USE_SLANG */
}
/*
* Accommodate the different flavors of touchline
*/
void LYtouchline(int row)
{
#if defined(HAVE_WREDRAWLN) && !defined(NCURSES_VERSION)
wredrawln(LYwin, row, 1);
#else
#if defined(HAVE_TOUCHLINE)
/* touchline() is not available on VMS before version 7.0, and then only on
* Alpha, since prior ports of curses were broken. BSD touchline() has a
* 4th parameter since it is used internally by touchwin().
*/
#if defined(HAVE_BSD_TOUCHLINE)
touchline(LYwin, row, 0, COLS);
#else
touchline(LYwin, row, 1);
#endif
#else
#if !defined(USE_SLANG)
touchwin(LYwin);
#else
SLsmg_touch_lines(row, 1);
#endif
#endif
#endif
}
/*
* Wrapper for waddnstr().
*/
void LYwaddnstr(WINDOW * w GCC_UNUSED,
const char *src,
size_t len)
{
/*
* We only want to trace this function for the color-style code. It would
* be too much logging if not needed.
*/
#ifdef USE_COLOR_STYLE
if (TRACE) {
int y, x;
LYGetYX(y, x);
CTRACE2(TRACE_STYLE, (tfp, "[%2d,%2d] LYwaddnstr(%.*s)\n",
y, x, (int) len, src));
}
#endif
/*
* Wide (multibyte) characters are always written as part of a string. So
* we can handle the conversion in one place.
*
* X/Open curses documents addstr() as able to handle multibyte sequences
* directly, but that is not (2001/11/5) yet implemented in ncurses. Two
* alternatives are possible: translating the string to an array of
* wchar_t's or to an array of cchar_t's. The former is more direct. Both
* have problems with combining-characters in this version of ncurses
* (successive calls are not merged), so I'm using them for testing -TD
*/
#if 0 /* defined(WIDEC_CURSES) && defined(HAVE_MBSTATE_T) */
#if 1 /* array of wchar_t's */
{
static wchar_t *temp = 0;
static size_t used = 0;
wchar_t wch;
int l = 0;
mbstate_t state;
size_t rc;
int width;
unsigned j;
size_t need;
memset(&state, 0, sizeof(state));
need = 1 + len;
if (need > used) {
used = 2 * need;
CTRACE((tfp, "allocated %d (%d)\n", used, len));
FREE(temp);
temp = typecallocn(wchar_t, used);
}
for (j = 0; j < len; j++) {
rc = mbrtowc(&wch, src + j, len - j, &state);
if (rc == 0 || rc == (size_t) (-1) || rc == (size_t) (-2))
break;
j += rc - 1;
if ((width = wcwidth(wch)) < 0)
break;
temp[l++] = wch;
}
temp[l] = L'\0';
waddnwstr(w, temp, l);
#ifdef LY_FIND_LEAKS
FREE(temp);
used = 0;
#endif
}
#else /* array of cchar_t's */
{
static cchar_t *temp = 0;
static size_t used = 0;
wchar_t wch;
wchar_t wstr[CCHARW_MAX + 1];
int l = 0;
mbstate_t state;
size_t rc;
int width;
int y, x;
unsigned j, k;
size_t need;
attr_t attr;
short pair;
wattr_get(w, &attr, &pair, (void *) 0);
memset(&state, 0, sizeof(state));
need = 1 + len;
if (need > used) {
used = 2 * need;
CTRACE((tfp, "allocated %d (%d)\n", used, len));
FREE(temp);
temp = typecallocn(cchar_t, used);
}
for (j = k = 0; j < len; j++) {
rc = mbrtowc(&wch, src + j, len - j, &state);
if (rc == 0 || rc == (size_t) (-1) || rc == (size_t) (-2))
break;
j += rc - 1;
if ((width = wcwidth(wch)) < 0)
break;
if ((width > 0 && l > 0) || l == CCHARW_MAX) {
wstr[l] = L'\0';
l = 0;
if (setcchar(temp + k, wstr, attr, 0, NULL) != OK)
break;
++k;
}
if (width == 0 && l == 0)
wstr[l++] = L' ';
wstr[l++] = wch;
}
if (l > 0) {
wstr[l] = L'\0';
if (setcchar(temp + k, wstr, attr, 0, NULL) == OK)
++k;
}
setcchar(temp + k, L"", 0, 0, NULL);
wadd_wchnstr(w, temp, k);
getyx(w, y, x); /* we didn't move - do it now */
wmove(w, y, x + k);
#ifdef LY_FIND_LEAKS
FREE(temp);
used = 0;
#endif
}
#endif
#else
/*
* There's no guarantee that a library won't temporarily write on its input.
* Be safe and copy it when we have const-data.
*/
while (len > 0) {
char temp[MAX_LINE];
size_t use = (len >= MAX_LINE) ? MAX_LINE - 1 : len;
memcpy(temp, src, use);
temp[use] = 0;
waddstr(w, temp);
len -= use;
}
#endif
}
/*
* Determine the number of cells the given string would take up on the screen,
* limited by the maxCells parameter. This is used for constructing aligned
* text in the options and similar forms.
*
* FIXME: make this account for wrapping, too.
* FIXME: make this useful for "lynx -dump", which hasn't initialized curses.
*/
int LYstrExtent(const char *string, int len, int maxCells)
{
int result = 0;
int used;
if (len < 0)
used = strlen(string);
else
used = len;
result = used;
#ifdef WIDEC_CURSES
if (used > 0 && lynx_called_initscr) {
static WINDOW *fake_win;
static int fake_max;
int n;
if (fake_max < maxCells) {
fake_max = (maxCells + 1) * 2;
if (fake_win != 0) {
delwin(fake_win);
fake_win = 0;
}
}
if (fake_win == 0) {
fake_win = newwin(2, fake_max, 0, 0);
}
if (fake_win != 0) {
int new_x = 0;
int new_y = 0;
result = 0;
wmove(fake_win, 0, 0);
for (n = 0; n < used; ++n) {
if (IsNormalChar(string[n])) {
waddch(fake_win, UCH(string[n]));
getyx(fake_win, new_y, new_x);
if (new_y > 0 || new_x > maxCells)
break;
result = new_x;
}
}
}
}
#endif
if (result > maxCells)
result = maxCells;
return result;
}
/*
* A simple call that relies upon the coincidence that multicell characters
* use at least as many bytes as cells.
*/
int LYstrExtent2(const char *string, int len)
{
return LYstrExtent(string, len, len);
}
/*
* Returns the total number of cells that the string would use.
*/
int LYstrCells(const char *string)
{
return LYstrExtent2(string, strlen(string));
}
#ifdef VMS
/*
* Cut-down termio --
* Do character-oriented stream input for Jeff.
* Code ripped off from Micro-Emacs 3.7 by Daniel Lawrence.
*
* Ever-so-slightly modified by Kathryn Huxtable. 29-Jan-1991.
* Cut down for Lou. 8 Sep 1992.
* Cut down farther for Lou. 19 Apr 1993.
* We don't set PASSALL or PASTHRU since we don't
* want to block CTRL/C, CTRL/Y, CTRL/S or CTRL/Q.
* Simply setting NOECHO and doing timed reads
* is sufficient.
* Further mods by Fote. 29-June-1993
* ttopen() and ttclose() are now terminal initialization
* and restoration procedures, called once at startup
* and at exit, respectively, of the LYNX image.
* ttclose() should be called before an exit from LYNX
* no matter how the exit is invoked.
* setup(terminal) does the ttopen().
* cleanup() calls cleanup_files() and ttclose().
* ttgetc() now handles NOECHO and NOFLITR (instead of
* setting the terminal itself to NOECHO in ttopen()).
* VMSsignal() added for handling both Ctrl-C *and* Ctrl-Y
* interrupts, and disabling system response to Ctrl-T.
* Further mods by Fote. 15-Dec-1993
* Added edit handler in ttopen() which will invoke
* VMSexit() and behave intelligently on ACCVIO's.
* Further mods by Fote. 29-Dec-1993
* Simplified ttgetc().
* Further mods by Fote. 16-Jan-1994
* Added code in ttopen() which will invoke VMSVersion()
* to get the version of VMS as VersionVMS for use by
* by new or modified interrupt or spawning routines.
* Further mods by Fote. 27-Jan-1994
* Added back a typeahead() which supports 'z' or 'Z' as
* an "Zap transfer" command via HTCheckForInterrupt()
* in LYUtils.c.
*/
#include <descrip.h>
#include <iodef.h>
#include <ssdef.h>
#include <msgdef.h>
#include <ttdef.h>
#include <tt2def.h>
#include <libclidef.h>
#include <lib$routines.h>
#include <starlet.h>
#include <clidef.h>
#include <syidef.h>
#ifdef signal
#undef signal
#endif /* signal */
#include <signal.h>
#ifdef system
#undef system
#endif /* system */
#include <processes.h>
#include <LYVMSdef.h>
#define EFN 0 /* Event flag */
static unsigned char buffer[20]; /* Input buffer */
static int in_pos, in_len; /* For escape sequences */
static int oldmode[3]; /* Old TTY mode bits */
static int newmode[3]; /* New TTY mode bits */
static short iochan; /* TTY I/O channel */
static $DESCRIPTOR(term_nam_dsc, "TT"); /* Descriptor for iochan */
static unsigned long mask = LIB$M_CLI_CTRLY | LIB$M_CLI_CTRLT; /* ^Y and ^T */
static unsigned long old_msk; /* Saved control mask */
static short trap_flag = FALSE; /* TRUE if AST is set */
BOOLEAN DidCleanup = FALSE; /* Exit handler flag */
static char VersionVMS[20]; /* Version of VMS */
int VMSVersion(char *VerString,
int VerLen)
{
unsigned long status, itm_cod = SYI$_VERSION;
int i, verlen = 0;
struct dsc$descriptor version;
char *m;
version.dsc$a_pointer = VerString;
version.dsc$w_length = VerLen - 1;
version.dsc$b_dtype = DSC$K_DTYPE_B;
version.dsc$b_class = DSC$K_CLASS_S;
status = lib$getsyi(&itm_cod, 0, &version, &verlen, 0, 0);
if (!(status & 1) || verlen == 0)
return 0;
/*
* Cut out trailing spaces
*/
for (m = VerString + verlen, i = verlen - 1; i > 0 && VerString[i] == ' '; --i)
*(--m) = '\0';
return strlen(VerString) + 1; /* Transmit ending 0 too */
}
void VMSexit(void)
{
/*
* If we get here and DidCleanup is not set, it was via an ACCVIO, or
* outofmemory forced exit, so make *sure* we attempt a cleanup and reset
* the terminal.
*/
if (!DidCleanup) {
if (LYOutOfMemory == FALSE) {
fprintf(stderr,
gettext("\nA Fatal error has occurred in %s Ver. %s\n"),
LYNX_NAME, LYNX_VERSION);
fprintf(stderr,
gettext("\nPlease notify your system administrator to confirm a bug, and if\n\
confirmed, to notify the lynx-dev list. Bug reports should have concise\n\
descriptions of the command and/or URL which causes the problem, the\n\
operating system name with version number, the TCPIP implementation, the\n\
TRACEBACK if it can be captured, and any other relevant information.\n"));
if (LYTraceLogFP == NULL) {
fprintf(stderr, RETURN_TO_CLEANUP);
(void) getchar();
}
} else if (LYCursesON) {
HTAlert(MEMORY_EXHAUSTED_ABORT);
}
cleanup();
}
if (LYOutOfMemory == TRUE) {
printf("\r\n%s\r\n\r\n", MEMORY_EXHAUSTED_ABORT);
fflush(stdout);
fflush(stderr);
}
}
/*
* TTOPEN --
* This function is called once to set up the terminal
* device streams. It translates TT until it finds
* the terminal, then assigns a channel to it, sets it
* to EDIT, and sets up the Ctrl-C and Ctrl-Y interrupt
* handling.
*/
int ttopen(void)
{
int iosb[2];
int status;
static unsigned long condition;
static struct _exit_block {
unsigned long forward;
unsigned long address;
unsigned long zero;
unsigned long condition;
} exit_handler_block;
status = sys$assign(&term_nam_dsc, &iochan, 0, 0);
if (status != SS$_NORMAL)
exit(status);
status = sys$qiow(EFN, iochan, IO$_SENSEMODE, &iosb, 0, 0,
&oldmode, sizeof(oldmode), 0, 0, 0, 0);
if (status != SS$_NORMAL)
exit(status);
status = iosb[0] & 0xFFFF;
if (status != SS$_NORMAL)
exit(status);
newmode[0] = oldmode[0];
newmode[1] = oldmode[1];
newmode[2] = oldmode[2] | TT2$M_EDIT;
status = sys$qiow(EFN, iochan, IO$_SETMODE, &iosb, 0, 0,
&newmode, sizeof(newmode), 0, 0, 0, 0);
if (status != SS$_NORMAL)
exit(status);
status = iosb[0] & 0xFFFF;
if (status != SS$_NORMAL)
exit(status);
/*
* Declare the exit handler block.
*/
exit_handler_block.forward = 0;
exit_handler_block.address = (unsigned long) &VMSexit;
exit_handler_block.zero = 0;
exit_handler_block.condition = (unsigned long) &condition;
status = sys$dclexh(&exit_handler_block);
if (status != SS$_NORMAL)
exit(status);
/*
* Set the AST.
*/
lib$disable_ctrl(&mask, &old_msk);
trap_flag = TRUE;
status = sys$qiow(EFN, iochan,
IO$_SETMODE | IO$M_CTRLCAST | IO$M_CTRLYAST,
&iosb, 0, 0,
&cleanup_sig, SIGINT, 0, 0, 0, 0);
if (status != SS$_NORMAL) {
lib$enable_ctrl(&old_msk);
exit(status);
}
/*
* Get the version of VMS.
*/
if (VMSVersion(VersionVMS, 20) < 3)
/*
* Load zeros on error.
*/
strcpy(VersionVMS, "V0.0-0");
return (0);
} /* ttopen */
/*
* TTCLOSE --
* This function gets called just before we go back home
* to the command interpreter. It puts the terminal back
* in a reasonable state.
*/
int ttclose(void)
{
int status;
int iosb[1];
status = sys$qiow(EFN, iochan, IO$_SETMODE, &iosb, 0, 0,
&oldmode, sizeof(oldmode), 0, 0, 0, 0);
if (status != SS$_NORMAL || (iosb[0] & 0xFFFF) != SS$_NORMAL)
exit(status);
if (trap_flag) {
status = sys$dassgn(iochan);
status = lib$enable_ctrl(&old_msk);
trap_flag = FALSE;
}
return (0);
} /* ttclose */
/*
* TTGETC --
* Read a character from the terminal, with NOECHO and NOFILTR.
*/
int ttgetc(void)
{
int status;
unsigned short iosb[4];
if (in_pos < in_len)
return (buffer[in_pos++]);
status = sys$qiow(EFN, iochan,
IO$_READVBLK | IO$M_NOECHO | IO$M_NOFILTR,
&iosb, 0, 0,
&buffer, 1, 0, 0, 0, 0);
if ((status & 1) == 1)
status = iosb[0];
if (status == SS$_PARTESCAPE) {
/*
* Escape sequence in progress. Fake a successful read.
*/
status = 1;
}
if ((status & 1) != 1 && status != SS$_DATAOVERUN)
exit(status);
in_pos = 1;
in_len = iosb[1] + iosb[3];
return (buffer[0]);
}
/*
* TYPEAHEAD -- Fote Macrides 27-Jan-1994
* Check whether a keystroke has been entered, and return
* it, or -1 if none was entered.
*/
int typeahead(void)
{
int status;
unsigned short iosb[4];
if (dump_output_immediately)
return -1;
if (in_pos < in_len)
return (buffer[in_pos++]);
again:
status = sys$qiow(EFN, iochan,
IO$_READVBLK | IO$M_TIMED | IO$M_NOECHO | IO$M_NOFILTR,
&iosb, 0, 0,
&buffer, 1, 0, 0, 0, 0);
if ((status & 1) == 1)
status = iosb[0];
if (status == SS$_PARTESCAPE) {
/*
* Escape sequence in progress, finish reading it.
*/
goto again;
}
in_pos = 1;
in_len = iosb[1] + iosb[3];
if (status == SS$_TIMEOUT || status == SS$_DATAOVERUN)
return (-1);
return (buffer[0]);
}
/*
* VMSSIGNAL -- Fote Macrides 29-Jun-1993
* Sets up AST for both Ctrl-C and Ctrl-Y, with system response
* to Ctrl-T disabled. If called with a sig other than SIGINT,
* it will use the C library's system(sig, func).
* The equivalent of VMSsignal(SIGINT, cleanup_sig) is done on
* intialization by ttopen(), so don't do it again.
* VMSsignal(SIGINT, SIG_DFL) is treated as a call to ttclose().
* Call VMSsignal(SIGINT, SIG_IGN) before system() calls to
* enable Ctrl-C and Ctrl-Y in the subprocess, and then call
* VMSsignal(SIG_INT, cleanup_sig) on return from the subprocess.
* For func's which set flags and do not invoke an exit from
* LYNX, the func should reassert itself.
* The VMS signal() calls do not fully emulate the Unix calls,
* and VMSsignal() is just a "helper", also not a full emulation.
*/
void VMSsignal(int sig,
void (*func) ())
{
int status;
short iosb[4];
static int SIG_IGN_flag;
/*
* Pass all signals other than SIGINT to signal().
* Also pass SIGINT to signal() if we're dumping.
*/
if (sig != SIGINT || dump_output_immediately) {
signal(sig, func);
return;
}
/*
* If func is SIG_DFL, treat it as ttclose().
*/
if (func == SIG_DFL) {
ttclose();
return;
}
/*
* Clear any previous AST.
*/
if (trap_flag) {
status = sys$dassgn(iochan);
status = lib$enable_ctrl(&old_msk);
trap_flag = FALSE;
}
/*
* If func is SIG_IGN, leave the TT channel closed and the system response
* to interrupts enabled for system() calls.
*/
if (func == SIG_IGN)
return;
/*
* If we get to here, we have a LYNX func, so set the AST.
*/
lib$disable_ctrl(&mask, &old_msk);
trap_flag = TRUE;
status = sys$assign(&term_nam_dsc, &iochan, 0, 0);
status = sys$qiow(EFN, iochan,
IO$_SETMODE | IO$M_CTRLCAST | IO$M_CTRLYAST,
&iosb, 0, 0,
func, SIGINT, 0, 0, 0, 0);
} /* VMSsignal */
/*
* DCLspawn_exception, spawn_DCLprocess, DCLsystem -- F.Macrides 16-Jan-1994
* Exception-handler routines for regulating interrupts and enabling
* Control-T during spawns. Includes TRUSTED flag for versions of VMS
* which require it in captive accounts. This code should be used
* instead of the VAXC or DECC system(), by including LYUtils.h in
* modules which have system() calls. It helps ensure that we return
* to Lynx instead of breaking out to DCL if a user issues interrupts
* or generates an ACCVIO during spawns.
*/
#ifdef __DECC
static unsigned int DCLspawn_exception(void *sigarr,
void *mecharr)
#else
static int DCLspawn_exception(void *sigarr,
void *mecharr)
#endif /* __DECC */
{
int status;
status = lib$sig_to_ret(sigarr, mecharr);
return (SS$_UNWIND);
}
static int spawn_DCLprocess(char *command)
{
int status;
unsigned long Status = 0;
/*
* Keep DECC from complaining.
*/
struct dsc$descriptor_s command_desc;
command_desc.dsc$w_length = strlen(command);
command_desc.dsc$b_class = DSC$K_CLASS_S;
command_desc.dsc$b_dtype = DSC$K_DTYPE_T;
command_desc.dsc$a_pointer = command;
VAXC$ESTABLISH(DCLspawn_exception);
#ifdef __ALPHA /** OpenVMS/AXP lacked the TRUSTED flag before v6.1 **/
if (VersionVMS[1] > '6' ||
(VersionVMS[1] == '6' && VersionVMS[2] == '.' &&
VersionVMS[3] >= '1'))
#else
if (VersionVMS[1] >= '6')
#endif /* __ALPHA */
{
/*
* Include TRUSTED flag.
*/
unsigned long trusted = CLI$M_TRUSTED;
status = lib$spawn(&command_desc, 0, 0, &trusted,
0, 0, &Status);
/*
* If it was invalid, try again without the flag.
*/
if (status == LIB$_INVARG)
status = lib$spawn(&command_desc, 0, 0, 0,
0, 0, &Status);
} else
status = lib$spawn(&command_desc, 0, 0, 0,
0, 0, &Status);
/*
* Return -1 on error.
*/
if ((status & 1) != 1 || (Status & 1) != 1)
return (-1);
/*
* Return 0 on success.
*/
return (0);
}
int DCLsystem(char *command)
{
int status;
VMSsignal(SIGINT, SIG_IGN);
status = spawn_DCLprocess(command);
VMSsignal(SIGINT, cleanup_sig);
/*
* Returns 0 on success, -1 any error.
*/
return (status);
}
#endif /* VMS */
/*
* Return the physical screen dimensions that we're allowed to use.
*/
int LYscreenHeight(void)
{
int result = LINES;
if (result <= 0)
result = DFT_ROWS;
return result;
}
int LYscreenWidth(void)
{
int result = COLS;
#if defined(PDCURSES_EXP) && defined(WIN_EX) && defined(CJK_EX) /* 1999/08/26 (Thu) 17:53:38 */
{
extern int current_codepage; /* PDCurses lib. */
if (current_codepage == 932)
result--;
}
#endif
if (result <= 0)
result = DFT_COLS;
return result;
}
/*
* The functions ifdef'd with USE_CURSES_PADS are implemented that way so we
* don't break the slang configuration.
*/
void LYclear(void)
{
#ifdef USE_CURSES_PADS
wclear(LYwin);
#else
clear();
#endif
}
void LYclrtoeol(void)
{
#ifdef USE_CURSES_PADS
wclrtoeol(LYwin);
#else
clrtoeol();
#endif
}
void LYerase(void)
{
#ifdef USE_CURSES_PADS
werase(LYwin);
#else
erase();
#endif
}
void LYmove(int y, int x)
{
#ifdef USE_CURSES_PADS
wmove(LYwin, y, x);
#else
move(y, x);
#endif
}
void LYrefresh(void)
{
#ifdef USE_CURSES_PADS
if (LYwin != stdscr) {
/*
* Workaround for special case where lynx is prompting for a mailto,
* and has a subject line that is wider than the screen. The
* wnoutrefresh() call resets newscr's position to match stdscr's,
* which happens to be the window's origin because we were not updating
* that, and other stray wmove's in lynx fail because the coordinate
* is on/after the right margin. Force things to look ok here.
*/
int y, x;
getyx(LYwin, y, x);
if (x > LYcolLimit)
x = LYcolLimit;
wmove(stdscr, y, x);
wnoutrefresh(stdscr);
pnoutrefresh(LYwin, 0, LYshiftWin, 0, 0, LYlines, LYscreenWidth() - 1);
/*
* Keep a popup window visible. This can happen if the user presses
* '/' to do a search within a popup.
*/
if (my_subwindow != 0) {
touchwin(my_subwindow);
wnoutrefresh(my_subwindow);
}
doupdate();
} else {
refresh();
}
#else
refresh();
#endif
}
void lynx_force_repaint(void)
{
clearok(curscr, TRUE);
}
void lynx_start_title_color(void)
{
#ifdef SH_EX
lynx_start_reverse();
#endif
}
void lynx_stop_title_color(void)
{
#ifdef SH_EX
lynx_stop_reverse();
#endif
}
void lynx_start_link_color(int flag,
int pending)
{
if (flag) {
/* makes some terminals work wrong because
* they can't handle two attributes at the
* same time
*/
/* lynx_start_bold(); */
lynx_start_reverse();
#if defined(USE_SLANG)
#ifndef __DJGPP__
if (SLtt_Use_Ansi_Colors)
#endif /* !__DJGPP__ */
lynx_start_underline();
#endif /* USE_SLANG */
#if defined(FANCY_CURSES) && defined(COLOR_CURSES)
if (lynx_has_color && LYShowColor >= SHOW_COLOR_ON)
lynx_start_underline();
#endif /* USE_SLANG */
} else {
lynx_start_bold();
/*
* Make sure when flag is OFF that "unhighlighted" links will be
* underlined if appropriate. - LE & FM
*/
if (pending)
lynx_start_underline();
}
}
void lynx_stop_link_color(int flag,
int pending GCC_UNUSED)
{
#ifdef USE_COLOR_STYLE
LynxChangeStyle(flag == ON ? s_alink : s_a, ABS_OFF);
#else
if (flag) {
lynx_stop_reverse();
#if defined(USE_SLANG)
#ifndef __DJGPP__
if (SLtt_Use_Ansi_Colors)
#endif /* !__DJGPP__ */
lynx_stop_underline();
#endif /* USE_SLANG */
#if defined(FANCY_CURSES) && defined(COLOR_CURSES)
if (lynx_has_color && LYShowColor >= SHOW_COLOR_ON)
lynx_stop_underline();
#endif /* FANCY_CURSES && COLOR_CURSES */
} else {
lynx_stop_bold();
/*
* If underlining was turned on above, turn it off. - LE & FM
*/
if (pending)
lynx_stop_underline();
}
#endif
}
/* FIXME: consider inlining these */
void lynx_stop_target_color(void)
{
lynx_stop_underline();
lynx_stop_reverse();
lynx_stop_bold();
}
void lynx_start_target_color(void)
{
lynx_start_bold();
lynx_start_reverse();
lynx_start_underline();
}
void lynx_start_status_color(void)
{
#if defined(USE_COLOR_TABLE) && defined(COLOR_CURSES)
if (lynx_has_color && LYShowColor >= SHOW_COLOR_ON)
lynx_set_color(2);
else
#endif
lynx_start_reverse();
}
void lynx_stop_status_color(void)
{
#if defined(USE_COLOR_TABLE) && defined(COLOR_CURSES)
if (lynx_has_color && LYShowColor >= SHOW_COLOR_ON)
lynx_set_color(0);
else
#endif
lynx_stop_reverse();
}
void lynx_start_h1_color(void)
{
if (bold_H1 || bold_headers)
lynx_start_bold();
}
void lynx_stop_h1_color(void)
{
if (bold_H1 || bold_headers)
lynx_stop_bold();
}
void lynx_start_prompt_color(void)
{
lynx_start_reverse();
}
void lynx_stop_prompt_color(void)
{
lynx_stop_reverse();
}
void lynx_start_radio_color(void)
{
lynx_start_bold();
}
void lynx_stop_radio_color(void)
{
lynx_stop_bold();
}
void lynx_stop_all_colors(void)
{
lynx_stop_underline();
lynx_stop_reverse();
lynx_stop_bold();
}
/*
* Wrappers for LYUnderlineLinks flag.
*/
void lynx_start_bold(void)
{
start_bold();
}
void lynx_start_reverse(void)
{
start_reverse();
}
void lynx_start_underline(void)
{
start_underline();
}
void lynx_stop_bold(void)
{
stop_bold();
}
void lynx_stop_reverse(void)
{
stop_reverse();
}
void lynx_stop_underline(void)
{
stop_underline();
}
/*
* If LYShowCursor is ON, move the cursor to the left of the current option, so
* that blind users, who are most likely to have LYShowCursor ON, will have
* it's string spoken or passed to the braille interface as each option is made
* current. Otherwise, move it to the bottom, right column of the screen, to
* "hide" the cursor as for the main document, and let sighted users rely on
* the current option's highlighting or color without the distraction of a
* blinking cursor in the window. - FM
*/
void LYstowCursor(WINDOW * win, int row,
int col)
{
if (LYShowCursor)
wmove(win, row, col);
else
LYHideCursor();
#ifdef USE_SLANG
SLsmg_refresh();
#else
wrefresh(win);
#endif /* USE_SLANG */
}
#if defined(USE_BLINK) && defined(__EMX__) /* Can't put it earler due to BOOLEAN conflict */
# define BOOLEAN os2BOOLEAN
# define INCL_VIO
# include "os2.h"
static void make_blink_boldbg(void)
{
VIOINTENSITY buf; /* VIO windows have it anyway, */
/* but FS session need a switch */
buf.cb = sizeof(buf);
buf.type = 2; /* VIOINTENSITY request */
buf.fs = 1; /* Intensity == boldbg */
VioSetState(&buf, 0);
}
#endif
#if defined(HAVE_WATTR_GET)
/*
* getattrs() is not in X/Open curses, but it is more convenient than this.
*/
long LYgetattrs(WINDOW * win)
{
#if ( defined(HAVE_GETATTRS) && ( !defined(NCURSES_MAJOR_VERSION) || NCURSES_VERSION_MAJOR < 5 ) )
long result = 0;
result = getattrs(win);
#else
attr_t result = 0;
short pair = 0;
wattr_get(win, &result, &pair, NULL);
#endif
return result;
}
#endif /* HAVE_WATTR_GET */