1 /* $LynxId: LYCurses.c,v 1.174 2013/07/21 00:40:06 tom Exp $ */
2 #include <HTUtils.h>
3 #include <HTAlert.h>
4
5 #ifdef __MINGW32__
6 #ifdef UNIX
7 #undef UNIX
8 #endif /* UNIX */
9 #endif /* __MINGW32__ */
10
11 #ifdef __DJGPP__
12 #include <pc.h>
13 #endif /* __DJGPP__ */
14
15 #include <LYCurses.h>
16 #include <LYStyle.h>
17 #include <LYUtils.h>
18 #include <LYGlobalDefs.h>
19 #include <LYSignal.h>
20 #include <LYClean.h>
21 #include <LYReadCFG.h>
22 #include <LYStrings.h>
23 #include <LYCharSets.h>
24 #include <UCAux.h>
25 #include <HTFont.h>
26
27 #include <LYexit.h>
28 #include <LYLeaks.h>
29
30 #ifdef VMS
31 #include <LYMainLoop.h>
32 #endif
33
34 #if defined(VMS) && defined(__GNUC__)
35 #include <gnu_hacks.h>
36 #undef LINES
37 #undef COLS
38 #define LINES lines
39 #define COLS cols
40 extern int _NOSHARE(LINES);
41 extern int _NOSHARE(COLS);
42 #endif /* VMS && __GNUC__ */
43
44 #ifdef USE_COLOR_STYLE
45 #include <AttrList.h>
46 #include <LYHash.h>
47 #endif
48
49 #ifdef NEED_WCHAR_H
50 #include <wchar.h>
51 #endif
52
53 #if defined(COLOR_CURSES)
54 int lynx_has_color = FALSE;
55 #endif
56
57 #ifdef HAVE_XCURSES
58 char *XCursesProgramName = "Lynx";
59 #endif
60
61 #if defined(USE_COLOR_STYLE) && !defined(USE_COLOR_TABLE)
62 #define COLOR_BKGD ((s_normal != NOSTYLE) ? hashStyles[s_normal].color : A_NORMAL)
63 #else
64 #define COLOR_BKGD ((COLOR_PAIRS >= 9) ? (chtype) get_color_pair(9) : A_NORMAL)
65 #endif
66
67 #ifdef USE_CURSES_PADS
68 WINDOW *LYwin = 0;
69 int LYshiftWin = 0;
70 int LYwideLines = FALSE;
71 int LYtableCols = 0; /* in 1/12 of screen width */
72 BOOLEAN LYuseCursesPads = TRUE; /* use pads for left/right shifting */
73 #endif
74
75 /*
76 * These are routines to start and stop curses and to cleanup the screen at the
77 * end.
78 */
79
80 static int dumbterm(char *terminal);
81 BOOLEAN LYCursesON = FALSE;
82
83 #if defined(USE_BLINK) && defined(__EMX__)
84 static void make_blink_boldbg(void);
85 #endif
86
87 #if defined(USE_COLOR_TABLE) || defined(USE_SLANG)
88 int Current_Attr;
89 static int Masked_Attr;
90 #endif
91
92 #ifdef USE_SLANG
93 unsigned Lynx_Color_Flags = 0;
94 BOOLEAN FullRefresh = FALSE;
95 int curscr = 0;
96
97 #ifdef SLANG_MBCS_HACK
98 /*
99 * Will be set by size_change. - KW
100 */
101 int PHYSICAL_SLtt_Screen_Cols = 10;
102 #endif /* SLANG_MBCS_HACK */
103
LY_SLrefresh(void)104 void LY_SLrefresh(void)
105 {
106 if (FullRefresh) {
107 SLsmg_suspend_smg();
108 SLsmg_resume_smg();
109 FullRefresh = FALSE;
110 } else {
111 SLsmg_refresh();
112 }
113
114 return;
115 }
116
117 /* the following renamed from LY_SLclear since it is more like erase()
118 described in curses man pages than like clear(); but for USE_SLANG
119 clear() is still a macro calling this, and will do the same thing as
120 erase(). - kw */
LY_SLerase(void)121 void LY_SLerase(void)
122 {
123 SLsmg_gotorc(0, 0);
124 SLsmg_erase_eos();
125 }
126
127 #ifdef VMS
VTHome(void)128 void VTHome(void)
129 {
130 printf("\033[;H");
131
132 return;
133 }
134 #endif /* VMS */
135
LYaddAttr(int a)136 void LYaddAttr(int a)
137 {
138 Current_Attr |= a;
139 SLsmg_set_color((SLsmg_Color_Type) (Current_Attr & ~Masked_Attr));
140 }
141
LYsubAttr(int a)142 void LYsubAttr(int a)
143 {
144 Current_Attr &= ~a;
145 SLsmg_set_color((SLsmg_Color_Type) (Current_Attr & ~Masked_Attr));
146 }
147
lynx_setup_attrs(void)148 static void lynx_setup_attrs(void)
149 {
150 static int monoattr[] =
151 {
152 0,
153 SLTT_BOLD_MASK,
154 SLTT_REV_MASK,
155 SLTT_REV_MASK | SLTT_BOLD_MASK,
156 SLTT_ULINE_MASK,
157 SLTT_ULINE_MASK | SLTT_BOLD_MASK,
158 SLTT_ULINE_MASK | SLTT_REV_MASK,
159 SLTT_ULINE_MASK | SLTT_BOLD_MASK | SLTT_REV_MASK
160 };
161 int n;
162
163 for (n = 1; n <= 7; n++)
164 SLtt_set_mono(n, NULL, (SLtt_Char_Type) (monoattr[n] & ~Masked_Attr));
165 }
166
lynx_setup_colors(void)167 void lynx_setup_colors(void)
168 {
169 CTRACE((tfp, "lynx_setup_colors\n"));
170 SLtt_set_color(0, NULL, DEFAULT_FG, DEFAULT_BG);
171 SLtt_set_color(1, NULL, "blue", DEFAULT_BG); /* bold */
172 SLtt_set_color(2, NULL, "yellow", "blue"); /* reverse */
173 SLtt_set_color(4, NULL, "magenta", DEFAULT_BG); /* underline */
174 /*
175 * The other objects are '|'ed together to get rest.
176 */
177 SLtt_set_color(3, NULL, "green", DEFAULT_BG); /* bold-reverse */
178 SLtt_set_color(5, NULL, "blue", DEFAULT_BG); /* bold-underline */
179 SLtt_set_color(6, NULL, "red", DEFAULT_BG); /* reverse-underline */
180 SLtt_set_color(7, NULL, "magenta", "cyan"); /* reverse-underline-bold */
181 /*
182 * Now set monochrome attributes.
183 */
184 lynx_setup_attrs();
185 }
186
sl_suspend(int sig)187 static void sl_suspend(int sig)
188 {
189 #ifdef SIGSTOP
190 #ifndef VMS
191 int r, c;
192
193 lynx_enable_mouse(0);
194 if (sig == SIGTSTP)
195 SLsmg_suspend_smg();
196 SLang_reset_tty();
197 kill(getpid(), SIGSTOP);
198 #if SLANG_VERSION > 9929
199 SLang_init_tty(-1, 0, 1);
200 #else
201 SLang_init_tty(3, 0, 1);
202 #endif /* SLANG_VERSION > 9929 */
203 signal(SIGTSTP, sl_suspend);
204 #if defined(REAL_UNIX_SYSTEM) && !defined(__CYGWIN__)
205 SLtty_set_suspend_state(1);
206 #endif
207 if (sig == SIGTSTP)
208 SLsmg_resume_smg();
209 /*
210 * Get new window size in case it changed.
211 */
212 r = SLtt_Screen_Rows;
213 c = SLtt_Screen_Cols;
214 size_change(0);
215 if ((r != SLtt_Screen_Rows) || (c != SLtt_Screen_Cols)) {
216 recent_sizechange = TRUE;
217 }
218 lynx_enable_mouse(1);
219 #endif /* !VMS */
220 #endif /* SIGSTOP */
221 return;
222 }
223 #else
224
225 #ifdef FANCY_CURSES
226
227 #ifndef VMS
228 /* *INDENT-OFF* */
229 /* definitions for the mono attributes we can use */
230 static struct {
231 const char *name;
232 int code;
233 } Mono_Attrs[7] =
234 {
235 { "normal", A_NORMAL },
236 { "bold", A_BOLD },
237 { "reverse", A_REVERSE },
238 { "underline", A_UNDERLINE },
239 { "standout", A_STANDOUT },
240 { "blink", A_BLINK },
241 { "dim", A_DIM },
242 };
243 /* *INDENT-ON* */
244
string_to_attr(const char * name)245 int string_to_attr(const char *name)
246 {
247 unsigned i;
248
249 for (i = 0; i < TABLESIZE(Mono_Attrs); i++) {
250 if (!strcasecomp(Mono_Attrs[i].name, name)) {
251 return Mono_Attrs[i].code;
252 }
253 }
254 return 0;
255 }
256 #endif /* VMS */
257
258 #ifdef USE_COLOR_STYLE
attr_to_string(int code)259 static char *attr_to_string(int code)
260 {
261 static char *result;
262
263 if (code >= 0) {
264 unsigned i;
265 int pair = PAIR_NUMBER((unsigned) code);
266 int bold = (pair != 0 && ((unsigned) code & A_BOLD) != 0);
267
268 StrAllocCopy(result, "");
269
270 if (bold)
271 code &= (int) ~A_BOLD;
272
273 for (i = 0; i < TABLESIZE(Mono_Attrs); i++) {
274 if (Mono_Attrs[i].code & code) {
275 if (non_empty(result))
276 StrAllocCat(result, "+");
277 StrAllocCat(result, Mono_Attrs[i].name);
278 }
279 }
280 if (pair != 0) {
281 short f, b;
282
283 if (pair_content((short) pair, &f, &b) != ERR) {
284 if (non_empty(result))
285 StrAllocCat(result, "+");
286 StrAllocCat(result, lookup_color(bold ? f + COLORS : f));
287 StrAllocCat(result, "/");
288 StrAllocCat(result, lookup_color(b));
289 }
290 }
291 } else {
292 FREE(result);
293 }
294 return result;
295 }
296 #endif /* USE_COLOR_STYLE */
297 #endif /* FANCY_CURSES */
298 #endif /* USE_SLANG */
299
300 /*
301 * This function boxes windows for (n)curses.
302 */
LYbox(WINDOW * win,int formfield GCC_UNUSED)303 void LYbox(WINDOW * win, int formfield GCC_UNUSED)
304 {
305 #ifdef USE_SLANG
306 SLsmg_draw_box(win->top_y,
307 win->left_x,
308 (unsigned) win->height,
309 (unsigned) win->width + 4);
310 #else
311 #ifdef VMS
312 /*
313 * This should work for VAX-C and DEC-C, since they both have the same
314 * win._max_y and win._max_x members -TD
315 *
316 * (originally VMSbox by FM)
317 */
318 int i;
319
320 wmove(win, 0, 0);
321 waddstr(win, "\033)0\016l");
322 for (i = 1; i < win->_max_x; i++)
323 waddch(win, 'q');
324 waddch(win, 'k');
325 for (i = 1; i < win->_max_y - 1; i++) {
326 wmove(win, i, 0);
327 waddch(win, 'x');
328 wmove(win, i, win->_max_x - 1);
329 waddch(win, 'x');
330 }
331 wmove(win, i, 0);
332 waddch(win, 'm');
333 for (i = 1; i < win->_max_x; i++)
334 waddch(win, 'q');
335 waddstr(win, "j\017");
336 #else /* !VMS */
337 int boxvert, boxhori;
338
339 UCSetBoxChars(current_char_set, &boxvert, &boxhori, BOXVERT, BOXHORI);
340 #ifdef CSS
341 if (formfield)
342 wcurses_css(win, "frame", ABS_ON);
343 #endif
344 /*
345 * If we don't have explicitly specified characters for either vertical or
346 * horizontal lines, the characters that box() would use for the corners
347 * probably also won't work well. So we specify our own ASCII characters
348 * for the corners and call wborder() instead of box(). - kw
349 */
350 LynxWChangeStyle(win, s_menu_frame, STACK_ON);
351 #ifdef HAVE_WBORDER
352 if (!boxvert || !boxhori) {
353 box(win,
354 (chtype) boxvert,
355 (chtype) boxhori);
356 } else if (boxvert == '*' || boxhori == '*') {
357 wborder(win,
358 (chtype) boxvert,
359 (chtype) boxvert,
360 (chtype) boxhori,
361 (chtype) boxhori,
362 '*', '*', '*', '*');
363 } else {
364 wborder(win,
365 (chtype) boxvert,
366 (chtype) boxvert,
367 (chtype) boxhori,
368 (chtype) boxhori,
369 '/', '\\', '\\', '/');
370 }
371 #else
372 box(win, boxvert, boxhori);
373 #endif
374 LynxWChangeStyle(win, s_menu_frame, STACK_OFF);
375 #ifdef CSS
376 if (formfield)
377 wcurses_css(win, "frame", ABS_OFF);
378 #endif
379 #endif /* VMS */
380 wrefresh(win);
381 #endif /* USE_SLANG */
382 }
383
384 #if defined(USE_COLOR_STYLE)
385 /* Ok, explanation of the USE_COLOR_STYLE styles. The basic styles (ie non
386 * HTML) are set the same as the SLANG version for ease of programming. The
387 * other styles are simply the HTML enum from HTMLDTD.h + 16.
388 */
389 HTCharStyle displayStyles[DSTYLE_ELEMENTS];
390
391 /*
392 * set a style's attributes - RP
393 */
setStyle(int style,int color,int cattr,int mono)394 void setStyle(int style,
395 int color,
396 int cattr,
397 int mono)
398 {
399 displayStyles[style].color = color;
400 displayStyles[style].cattr = cattr;
401 displayStyles[style].mono = mono;
402 }
403
setHashStyle(int style,int color,int cattr,int mono,const char * element)404 void setHashStyle(int style,
405 int color,
406 int cattr,
407 int mono,
408 const char *element)
409 {
410 bucket *ds = &hashStyles[style];
411
412 CTRACE2(TRACE_STYLE,
413 (tfp, "CSS(SET): <%s> hash=%d, ca=%#x, ma=%#x\n",
414 element, style, color, mono));
415
416 ds->color = color;
417 ds->cattr = cattr;
418 ds->mono = mono;
419 ds->code = style;
420 FREE(ds->name);
421 StrAllocCopy(ds->name, element);
422 }
423
424 /*
425 * set the curses attributes to be color or mono - RP
426 */
LYAttrset(WINDOW * win,int color,int mono)427 static void LYAttrset(WINDOW * win, int color,
428 int mono)
429 {
430 char *shown = NULL;
431
432 if (lynx_has_color
433 && LYShowColor >= SHOW_COLOR_ON
434 && color >= 0) {
435 CTRACE2(TRACE_STYLE, (tfp, "CSS:LYAttrset color %#x -> (%s)\n",
436 color, shown = attr_to_string(color)));
437 (void) wattrset(win, (unsigned) color);
438 } else if (mono >= 0) {
439 CTRACE2(TRACE_STYLE, (tfp, "CSS:LYAttrset mono %#x -> (%s)\n",
440 mono, shown = attr_to_string(mono)));
441 (void) wattrset(win, (unsigned) mono);
442 } else {
443 CTRACE2(TRACE_STYLE, (tfp, "CSS:LYAttrset (A_NORMAL)\n"));
444 (void) wattrset(win, A_NORMAL);
445 }
446 if (shown != NULL)
447 (void) attr_to_string(-1);
448 }
449
curses_w_style(WINDOW * win,int style,int dir)450 void curses_w_style(WINDOW * win, int style,
451 int dir)
452 {
453 #if OMIT_SCN_KEEPING
454 # define SPECIAL_STYLE /*(CSHASHSIZE+1) */ 88888
455 /* if TRACEs are not compiled in, this macro is redundant - we needn't valid
456 'ds' to stack off. */
457 #endif
458
459 int YP, XP;
460 bucket *ds;
461 BOOL free_ds = TRUE;
462
463 switch (style) {
464 #if OMIT_SCN_KEEPING
465 case SPECIAL_STYLE:
466 ds = special_bucket();
467 break;
468 #endif
469 case NOSTYLE:
470 ds = nostyle_bucket();
471 break;
472 default:
473 ds = &hashStyles[style];
474 free_ds = FALSE;
475 break;
476 }
477
478 if (!ds->name) {
479 CTRACE2(TRACE_STYLE, (tfp, "CSS.CS:Style %d not configured\n", style));
480 #if !OMIT_SCN_KEEPING
481 if (free_ds)
482 free(ds);
483 return;
484 #endif
485 }
486
487 CTRACE2(TRACE_STYLE, (tfp, "CSS.CS:<%s%s> style %d code %#x, color %#x\n",
488 (dir ? "" : "/"),
489 ds->name, style, ds->code, ds->color));
490
491 getyx(win, YP, XP);
492
493 if (style == s_normal && dir) {
494 LYAttrset(win, ds->color, ds->mono);
495 if (win == LYwin)
496 SetCachedStyle(YP, XP, (unsigned) s_normal);
497 if (free_ds)
498 free(ds);
499 return;
500 }
501
502 switch (dir) {
503 /* ABS_OFF is the same as STACK_OFF for the moment */
504 case STACK_OFF:
505 if (last_colorattr_ptr) {
506 int last_attr = last_styles[--last_colorattr_ptr];
507
508 LYAttrset(win, last_attr, last_attr);
509 } else
510 LYAttrset(win, A_NORMAL, -1);
511 break;
512
513 case STACK_ON: /* remember the current attributes */
514 if (last_colorattr_ptr >= MAX_LAST_STYLES) {
515 CTRACE2(TRACE_STYLE, (tfp, "........... %s (0x%x) %s\r\n",
516 "attribute cache FULL, dropping last",
517 last_styles[last_colorattr_ptr],
518 "in LynxChangeStyle(curses_w_style)"));
519 last_colorattr_ptr = MAX_LAST_STYLES - 1;
520 }
521 last_styles[last_colorattr_ptr++] = (int) LYgetattrs(win);
522 /* don't cache style changes for active links */
523 #if OMIT_SCN_KEEPING
524 /* since we don't compute the hcode to stack off in HTML.c, we
525 * don't know whether this style is configured. So, we
526 * shouldn't simply return on stacking on unconfigured
527 * styles, we should push curr attrs on stack. -HV
528 */
529 if (!ds->name)
530 break;
531 #endif
532 /* FALL THROUGH */
533 case ABS_ON: /* change without remembering the previous style */
534 /* don't cache style changes for active links and edits */
535 if (style != s_alink
536 && style != s_curedit
537 && style != s_aedit
538 && style != s_aedit_sel
539 && style != s_aedit_pad
540 && style != s_aedit_arr) {
541 CTRACE2(TRACE_STYLE, (tfp, "CACHED: <%s> @(%d,%d)\n",
542 ds->name, YP, XP));
543 if (win == LYwin)
544 SetCachedStyle(YP, XP, (unsigned) style);
545 }
546 LYAttrset(win, ds->color, ds->mono);
547 break;
548 }
549
550 if (free_ds)
551 free(ds);
552
553 return;
554 }
555
556 /*
557 * wrapper function to set on-screen styles - RP
558 */
wcurses_css(WINDOW * win,char * name,int dir)559 void wcurses_css(WINDOW * win, char *name,
560 int dir)
561 {
562 int try_again = 1;
563
564 while (try_again) {
565 int tmpHash = hash_code(name);
566
567 CTRACE2(TRACE_STYLE, (tfp, "CSSTRIM:trying to set [%s] style - ", name));
568 if (tmpHash == NOSTYLE) {
569 char *pclass = strrchr(name, '.');
570
571 CTRACE2(TRACE_STYLE, (tfp, "undefined, trimming at %p\n", pclass));
572 if (pclass)
573 *pclass = '\0';
574 else
575 try_again = 0;
576 } else {
577 CTRACE2(TRACE_STYLE, (tfp, "ok (%d)\n", hash_code(name)));
578 curses_w_style(win, hash_code(name), dir);
579 try_again = 0;
580 }
581 }
582 }
583
curses_css(char * name,int dir)584 void curses_css(char *name,
585 int dir)
586 {
587 wcurses_css(LYwin, name, dir);
588 }
589
curses_style(int style,int dir)590 void curses_style(int style,
591 int dir)
592 {
593 curses_w_style(LYwin, style, dir);
594 }
595 #endif /* USE_COLOR_STYLE */
596
597 static BOOL lynx_called_initscr = FALSE;
598
599 #if defined(USE_COLOR_TABLE) && defined(COLOR_CURSES)
600 #define COLOR_CFG_MAX 8
601
602 /*
603 * This block of code is designed to produce the same color effects using SVr4
604 * curses as the slang library's implementation in this module. That maps the
605 * SGR codes into a 0-7 index into the color table, with special treatment for
606 * backgrounds. There's a bit of convoluted (but necessary) code handling the
607 * special case of initialization before 'initscr()' is called.
608 * 1997/1/19 - T.E.Dickey <dickey@clark.net>
609 */
610 /* *INDENT-OFF* */
611 #define COLOR_CFG(c) c, (c) == DEFAULT_COLOR
612 static struct {
613 int fg, dft_fg, bg, dft_bg;
614 } lynx_color_cfg[] = {
615 /*0*/ { COLOR_CFG(DEFAULT_FG), COLOR_CFG(DEFAULT_BG)},
616 /*1*/ { COLOR_CFG(COLOR_BLUE), COLOR_CFG(DEFAULT_BG)},
617 /*2*/ { COLOR_CFG((COLOR_YELLOW)+8), COLOR_CFG(COLOR_BLUE)},
618 /*3*/ { COLOR_CFG(COLOR_GREEN), COLOR_CFG(DEFAULT_BG)},
619 /*4*/ { COLOR_CFG(COLOR_MAGENTA), COLOR_CFG(DEFAULT_BG)},
620 /*5*/ { COLOR_CFG(COLOR_BLUE), COLOR_CFG(DEFAULT_BG)},
621 /*6*/ { COLOR_CFG(COLOR_RED), COLOR_CFG(DEFAULT_BG)},
622 /*7*/ { COLOR_CFG(COLOR_MAGENTA), COLOR_CFG(COLOR_CYAN)}
623 };
624 /* *INDENT-ON* */
625
626 #define COLOR_PAIRS_MAX (COLOR_CFG_MAX * 3 + 1)
627
628 /*
629 * Hold the codes for color-pairs here until 'initscr()' is called.
630 */
631 static struct {
632 int fg;
633 int bg;
634 } lynx_color_pairs[COLOR_PAIRS_MAX];
635
636 /*
637 * If we find an exact match for the given default colors, force curses to use
638 * color pair 0, which corresponds to the terminal's default colors. Normally
639 * curses assumes white-on-black, but we can override the assumption with this
640 * function.
641 */
get_color_pair(int n)642 static int get_color_pair(int n)
643 {
644 #ifdef USE_CURSES_PAIR_0
645 if ((n < (int) TABLESIZE(lynx_color_pairs))
646 && lynx_color_pairs[n].fg == default_fg
647 && lynx_color_pairs[n].bg == default_bg)
648 return 0;
649 #endif
650 return COLOR_PAIR(n);
651 }
652
653 /*
654 * Lynx "knows" about 16 colors. ANSI colors (and most color terminal
655 * emulators) only go to 8, though some curses implementations (ncurses and
656 * PDCurses) handle 16. If lynx' configuration calls for a color past the
657 * number of colors that the terminal handles (COLORS), map the extra value
658 * to bold.
659 */
660 #define is_boldc(c) ((c) > (COLORS-1))
661 #define map2bold(c) (is_boldc(c) ? ((c) & (COLORS-1)) : (c))
662
663 /*
664 * Return the extra color as A_BOLD.
665 * If there is no extra color, return A_NORMAL.
666 */
lynx_color_cfg_attr(int code)667 static int lynx_color_cfg_attr(int code)
668 {
669 int result = A_NORMAL;
670
671 if (code >= 0 && code < COLOR_CFG_MAX) {
672 int fg = lynx_color_cfg[code].fg;
673
674 if (is_boldc(fg) && (fg & COLORS))
675 result = A_BOLD;
676 }
677 return result;
678 }
679
encode_color_attr(int color_attr)680 static int encode_color_attr(int color_attr)
681 {
682 int result;
683 int code = 0;
684 int offs = 1;
685
686 if ((unsigned) color_attr & A_BOLD)
687 code |= 1;
688 if ((unsigned) color_attr & (A_REVERSE | A_DIM))
689 code |= 2;
690 if ((unsigned) color_attr & A_UNDERLINE)
691 code |= 4;
692 result = lynx_color_cfg_attr(code);
693
694 if (code + offs < COLOR_PAIRS) {
695 result |= get_color_pair(code + offs);
696 }
697 return result;
698 }
699
decode_mono_code(int mono_code)700 static int decode_mono_code(int mono_code)
701 {
702 unsigned result = 0;
703
704 if (mono_code & 1)
705 result |= A_BOLD;
706 if (mono_code & 2)
707 result |= A_REVERSE;
708 if (mono_code & 4)
709 result |= A_UNDERLINE;
710
711 return (int) result;
712 }
713
714 /*
715 * Map the SGR attributes (0-7) into ANSI colors, modified with the actual BOLD
716 * attribute to get 16 colors.
717 */
LYgetTableAttr(void)718 int LYgetTableAttr(void)
719 {
720 int result;
721
722 if (lynx_has_color && LYShowColor >= SHOW_COLOR_ON) {
723 result = encode_color_attr(Current_Attr);
724 } else {
725 result = Current_Attr;
726 }
727 return result & ~Masked_Attr;
728 }
729
730 #ifdef USE_COLOR_STYLE
731 /*
732 * Return a string that corresponds to the attributes that would be returned by
733 * LYgetTableAttr().
734 */
LYgetTableString(int code)735 char *LYgetTableString(int code)
736 {
737 int mask = decode_mono_code(code);
738 int second = encode_color_attr(mask);
739 int pair = PAIR_NUMBER((unsigned) second);
740 int mono = (int) ((unsigned) mask & A_ATTRIBUTES);
741 int fg = lynx_color_pairs[pair].fg;
742 int bg = lynx_color_pairs[pair].bg;
743 unsigned n;
744 char *result = 0;
745
746 CTRACE((tfp, "LYgetTableString(%d)\n", code));
747
748 if (fg == 0 && bg == 0) {
749 fg = COLOR_WHITE;
750 }
751 CTRACE((tfp, "%#x -> %#x (mono %#x pair %d) fg=%d, bg=%d\n",
752 mask, second, mono, pair, fg, bg));
753 for (n = 0; n < TABLESIZE(Mono_Attrs); ++n) {
754 if ((Mono_Attrs[n].code & mono) != 0) {
755 if (result != 0)
756 StrAllocCat(result, "+");
757 StrAllocCat(result, Mono_Attrs[n].name);
758 }
759 }
760 if (result == 0)
761 StrAllocCopy(result, "normal");
762 StrAllocCat(result, ":");
763 StrAllocCat(result, lookup_color(fg));
764 if (bg >= 0) {
765 StrAllocCat(result, ":");
766 StrAllocCat(result, lookup_color(bg));
767 }
768 CTRACE((tfp, "->%s\n", result));
769 return result;
770 }
771 #endif
772
773 /*
774 * Initialize a curses color-pair based on our configured color values.
775 */
lynx_init_color_pair(int n)776 static void lynx_init_color_pair(int n)
777 {
778 #ifdef USE_COLOR_STYLE
779 (void) n; /* we only use lynx_color_pairs[] data */
780 #else
781 int m;
782
783 if (lynx_called_initscr) {
784 for (m = 0; m <= 16; m += 8) {
785 int pair = n + m + 1;
786
787 if (pair < COLOR_PAIRS)
788 init_pair((short) pair,
789 (short) map2bold(lynx_color_pairs[pair].fg),
790 (short) map2bold(lynx_color_pairs[pair].bg));
791 }
792 if (n == 0 && LYShowColor >= SHOW_COLOR_ON) {
793 wbkgd(LYwin, COLOR_BKGD | ' ');
794 }
795 }
796 #endif
797 }
798
lynx_map_color(int n)799 static void lynx_map_color(int n)
800 {
801 int j;
802
803 CTRACE((tfp, "lynx_map_color(%d)\n", n));
804
805 if (n + 1 < (int) TABLESIZE(lynx_color_pairs)
806 && n < (int) TABLESIZE(lynx_color_cfg)) {
807 for (j = n + 1; j < COLOR_PAIRS_MAX; j += COLOR_CFG_MAX) {
808 lynx_color_pairs[j].fg = lynx_color_cfg[n].fg;
809 lynx_color_pairs[j].bg = lynx_color_cfg[n].bg;
810 }
811
812 /* special case (does not apply to 3rd set) */
813 lynx_color_pairs[n + 1 + COLOR_CFG_MAX].bg = lynx_color_cfg[0].bg;
814 }
815
816 lynx_init_color_pair(n);
817 }
818
819 /*
820 * Change a configured color value. This may be called before initscr(), so
821 * we may not be able to call init_pair() to finish the change.
822 */
lynx_chg_color(int color,int fg,int bg)823 int lynx_chg_color(int color,
824 int fg,
825 int bg)
826 {
827 CTRACE((tfp, "lynx_chg_color(color=%d, fg=%d, bg=%d)\n", color, fg, bg));
828
829 if (fg == ERR_COLOR || bg == ERR_COLOR)
830 return -1;
831 if (color >= 0 && color < COLOR_CFG_MAX) {
832 lynx_color_cfg[color].fg = fg;
833 lynx_color_cfg[color].bg = bg;
834 lynx_map_color(color);
835 } else {
836 return -1;
837 }
838 return 0;
839 }
840
lynx_set_color(int a)841 void lynx_set_color(int a)
842 {
843 if (lynx_has_color && LYShowColor >= SHOW_COLOR_ON) {
844 (void) wattrset(LYwin, (unsigned) lynx_color_cfg_attr(a)
845 | (((a + 1) < COLOR_PAIRS)
846 ? (chtype) get_color_pair(a + 1)
847 : A_NORMAL));
848 }
849 }
850
lynx_standout(int flag)851 void lynx_standout(int flag)
852 {
853 if (flag)
854 LYaddAttr(A_REVERSE);
855 else
856 LYsubAttr(A_REVERSE);
857 }
858
lynx_init_colors(void)859 static void lynx_init_colors(void)
860 {
861 if (lynx_has_color) {
862 size_t n;
863
864 CTRACE((tfp, "lynx_init_colors (default %d/%d)\n",
865 default_fg, default_bg));
866
867 lynx_color_cfg[0].fg = default_fg;
868 lynx_color_cfg[0].bg = default_bg;
869
870 for (n = 0; n < TABLESIZE(lynx_color_cfg); n++) {
871 lynx_init_color_pair((int) n);
872 }
873 } else if (LYShowColor != SHOW_COLOR_NEVER) {
874 LYShowColor = SHOW_COLOR_OFF;
875 }
876 }
877
lynx_setup_colors(void)878 void lynx_setup_colors(void)
879 {
880 int n;
881
882 CTRACE((tfp, "lynx_setup_colors\n"));
883 #ifdef USE_DEFAULT_COLORS
884 if (!LYuse_default_colors) {
885 for (n = 0; n < COLOR_CFG_MAX; n++) {
886 if (lynx_color_cfg[n].dft_fg)
887 lynx_color_cfg[n].fg = COLOR_BLACK;
888 if (lynx_color_cfg[n].dft_bg)
889 lynx_color_cfg[n].bg = COLOR_WHITE;
890 }
891 }
892 #endif
893 for (n = 0; n < COLOR_CFG_MAX; n++)
894 lynx_map_color(n);
895 }
896 #endif /* USE_COLOR_TABLE */
897
LYnoVideo(int a)898 void LYnoVideo(int a)
899 {
900 CTRACE((tfp, "LYnoVideo(%d)\n", a));
901 #ifdef USE_SLANG
902 if (a & 1)
903 Masked_Attr |= (int) SLTT_BOLD_MASK;
904 if (a & 2)
905 Masked_Attr |= (int) SLTT_REV_MASK;
906 if (a & 4)
907 Masked_Attr |= (int) SLTT_ULINE_MASK;
908 lynx_setup_attrs();
909 #else
910 #ifdef USE_COLOR_TABLE
911 Masked_Attr = decode_mono_code(a);
912 #endif
913 #endif
914 }
915
916 #define NEWTERM_NAME "newterm"
917
918 #if !defined(VMS) && !defined(USE_SLANG)
919 #if defined(NCURSES) && defined(HAVE_RESIZETERM)
920
921 static SCREEN *LYscreen = NULL;
922
923 #define LYDELSCR() /* ncurses does not need this */
924
925 #elif defined(HAVE_NEWTERM) && defined(HAVE_DELSCREEN) && !defined(PDCURSES)
926
927 static SCREEN *LYscreen = NULL;
928
929 #define LYDELSCR() { \
930 if (recent_sizechange) { \
931 CTRACE((tfp, "Screen size: delscreen()\n")); \
932 delscreen(LYscreen); \
933 LYscreen = NULL; } }
934
935 #else /* HAVE_NEWTERM */
936
937 /*
938 * If newterm is not defined, assume a curses subset which
939 * supports only initscr. --gil
940 */
941 static WINDOW *LYscreen = NULL;
942
943 #undef NEWTERM_NAME
944 #define NEWTERM_NAME "initscr"
945 #undef newterm
946 #define newterm(type, out, in) (initscr())
947 #define LYDELSCR() /* nothing */
948 #endif /* HAVE_NEWTERM */
949
950 #else /* !defined(VMS) && !defined(USE_SLANG) */
951
952 /*
953 * Provide last recourse definitions of LYscreen and LYDELSCR for
954 * stop_curses, which only tests LYscreen for zero/nonzero but
955 * never uses it as a pointer or L-value.
956 */
957 #define LYscreen TRUE
958 #define LYDELSCR() /* nothing */
959 #endif /* !defined(VMS) && !defined(USE_SLANG) */
960
961 #if defined(PDCURSES) && defined(PDC_BUILD) && PDC_BUILD >= 2401
962 int saved_scrsize_x = 0;
963 int saved_scrsize_y = 0;
964
965 int saved_scrsize_x2 = 0;
966 int saved_scrsize_y2 = 0;
967 int saved_winpos_x2 = 0;
968 int saved_winpos_y2 = 0;
969 #endif
970
971 #ifdef USE_MAXSCREEN_TOGGLE
972 static HWND currentWindowHandle = NULL;
973 static char dummyWindowTitle[256];
974
EnumWindowsProc(HWND hwnd,LPARAM lParam)975 static int CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)
976 {
977 char this_title[256];
978
979 if (GetWindowText(hwnd, this_title, sizeof(this_title) - 1) &&
980 (strncmp(dummyWindowTitle, this_title, 256) == 0)) {
981 currentWindowHandle = hwnd;
982 return FALSE;
983 }
984 return TRUE;
985 }
986
setCurrentWindowHandle(void)987 static void setCurrentWindowHandle(void)
988 {
989 char org_title[256];
990 DWORD pid;
991 int i;
992
993 if (currentWindowHandle != NULL) {
994 return;
995 }
996 pid = GetCurrentProcessId();
997 sprintf(dummyWindowTitle, "Lynx for Win32 (pid=%ld)", pid);
998 GetConsoleTitle(org_title, sizeof(org_title) - 1);
999 SetConsoleTitle(dummyWindowTitle);
1000 for (i = 0; i < 10; i++) {
1001 EnumWindows(EnumWindowsProc, (LPARAM) 0);
1002 if (currentWindowHandle != NULL) {
1003 break;
1004 }
1005 CTRACE((tfp,
1006 "Failed to get current window handle. Try again...(%d)\n", i));
1007 Sleep(100);
1008 }
1009 SetConsoleTitle(org_title);
1010 }
1011
moveWindowHXY(HWND hwnd,int x,int y)1012 static void moveWindowHXY(HWND hwnd, int x, int y)
1013 {
1014 int win_height, win_width;
1015 RECT winrect;
1016
1017 GetWindowRect(hwnd, &winrect);
1018 win_width = winrect.right - winrect.left;
1019 win_height = winrect.bottom - winrect.top;
1020
1021 if ((x != winrect.left) || (y != winrect.top)) {
1022 MoveWindow(hwnd, x, y, win_width, win_height, TRUE);
1023 CTRACE((tfp, "move window from (%d,%d) to (%d,%d).\n",
1024 (int) winrect.left,
1025 (int) winrect.top, x, y));
1026 }
1027 }
1028
adjustWindowPos(void)1029 static void adjustWindowPos(void)
1030 {
1031 int disp_height, disp_width, win_height, win_width;
1032 int newwin_left, newwin_top;
1033 RECT winrect;
1034 DWORD pid;
1035
1036 setCurrentWindowHandle();
1037 if (currentWindowHandle == NULL) {
1038 return;
1039 }
1040 GetWindowThreadProcessId(currentWindowHandle, &pid);
1041 disp_width = GetSystemMetrics(SM_CXFULLSCREEN);
1042 disp_height = GetSystemMetrics(SM_CYFULLSCREEN);
1043 Sleep(100); /* If not, GetWindowRect sometimes return wrong value. */
1044 GetWindowRect(currentWindowHandle, &winrect);
1045 win_width = winrect.right - winrect.left;
1046 win_height = winrect.bottom - winrect.top;
1047 CTRACE((tfp, "Display Size: (%4d,%3d)\n", disp_width, disp_height));
1048 CTRACE((tfp, "Orig WinRect: (%4d,%4d,%3d,%3d), ",
1049 (int) winrect.left, (int) winrect.right,
1050 (int) winrect.top, (int) winrect.bottom));
1051 CTRACE((tfp, "Size: (%4d,%3d)\n", win_width, win_height));
1052
1053 newwin_left = winrect.left;
1054 newwin_top = winrect.top;
1055 if (disp_width < winrect.right) {
1056 if (win_width <= disp_width) {
1057 newwin_left = disp_width - win_width;
1058 } else {
1059 newwin_left = 0;
1060 }
1061 }
1062 if (disp_height < winrect.bottom) {
1063 if (win_height <= disp_height) {
1064 newwin_top = disp_height - win_height;
1065 } else {
1066 newwin_top = 0;
1067 }
1068 }
1069
1070 moveWindowHXY(currentWindowHandle, newwin_left, newwin_top);
1071 }
1072
maxmizeWindowSize(void)1073 void maxmizeWindowSize(void)
1074 {
1075 int disp_height, disp_width, win_height, win_width;
1076 RECT winrect;
1077 DWORD pid;
1078 int font_width, font_height;
1079
1080 setCurrentWindowHandle();
1081 if (currentWindowHandle == NULL) {
1082 return;
1083 }
1084 GetWindowThreadProcessId(currentWindowHandle, &pid);
1085 disp_width = GetSystemMetrics(SM_CXFULLSCREEN);
1086 disp_height = GetSystemMetrics(SM_CYFULLSCREEN);
1087 GetWindowRect(currentWindowHandle, &winrect);
1088 win_width = winrect.right - winrect.left;
1089 win_height = winrect.bottom - winrect.top;
1090 saved_winpos_x2 = winrect.left;
1091 saved_winpos_y2 = winrect.top;
1092
1093 if ((win_width <= disp_width) && (win_height <= disp_height)) {
1094 GetClientRect(currentWindowHandle, &winrect);
1095 win_width = winrect.right - winrect.left;
1096 win_height = winrect.bottom - winrect.top;
1097 CTRACE((tfp, "Current Rect: (%4d,%4d,%3d,%3d), ",
1098 (int) winrect.left, (int) winrect.right,
1099 (int) winrect.top, (int) winrect.bottom));
1100 CTRACE((tfp, "Size: (%4d,%3d)\n", win_width, win_height));
1101
1102 if (scrsize_x == 0) {
1103 scrsize_x = COLS;
1104 scrsize_y = LINES + 1;
1105 }
1106 if ((scrsize_x == 0) || (scrsize_y == 0)) {
1107 CTRACE((tfp, "Illegal value: scrsize_x=%d, scrsize_y=%d\n",
1108 scrsize_x, scrsize_y));
1109 } else {
1110 font_width = win_width / scrsize_x;
1111 font_height = win_height / scrsize_y;
1112 CTRACE((tfp, "Font Size: (%2d,%2d)\n", font_width, font_height));
1113 if ((font_width == 0) || (font_height == 0)) {
1114 CTRACE((tfp, "Illegal font size.\n"));
1115 } else {
1116 LYcols = scrsize_x = (disp_width - 4) / font_width;
1117 LYlines = scrsize_y = (disp_height - 32) / font_height;
1118 LYlines--;
1119 CTRACE((tfp, "Request maximum screen size: %dx%d\n",
1120 scrsize_y, scrsize_x));
1121 resize_term(scrsize_y, scrsize_x);
1122 Sleep(100);
1123 moveWindowHXY(currentWindowHandle, 0, 0);
1124 LYlines = LYscreenHeight();
1125 LYcols = LYscreenWidth();
1126 CTRACE((tfp, "...actual maximum screen size: %dx%d\n",
1127 LYlines, LYcols));
1128 LYStatusLine = -1;
1129 recent_sizechange = TRUE;
1130 }
1131 }
1132 }
1133 }
1134
recoverWindowSize(void)1135 void recoverWindowSize(void)
1136 {
1137 if ((0 < saved_scrsize_x2) && (0 < saved_scrsize_y2)) {
1138 LYcols = scrsize_x = saved_scrsize_x2;
1139 LYlines = scrsize_y = saved_scrsize_y2;
1140 LYlines--;
1141 LYStatusLine = -1;
1142 wclear(curscr);
1143 doupdate();
1144 resize_term(scrsize_y, scrsize_x);
1145
1146 setCurrentWindowHandle();
1147 if (currentWindowHandle != NULL) {
1148 Sleep(100);
1149 moveWindowHXY(currentWindowHandle, saved_winpos_x2, saved_winpos_y2);
1150 }
1151 recent_sizechange = TRUE;
1152 } else {
1153 CTRACE((tfp, "scrsize_{xy} is not saved yet.\n"));
1154 }
1155 }
1156 #endif
1157
1158 #if defined(USE_DEFAULT_COLORS)
restart_curses(void)1159 void restart_curses(void)
1160 {
1161 SCREEN *oldscreen = LYscreen;
1162
1163 if (!(LYscreen = newterm(NULL, stdout, stdin))) { /* start curses */
1164 fprintf(tfp, "%s\n",
1165 gettext("Terminal reinitialisation failed - unknown terminal type?"));
1166 exit_immediately(EXIT_FAILURE);
1167 }
1168
1169 /* force xterm mouse-mode off in the physical terminal */
1170 lynx_enable_mouse(0);
1171 keypad(LYwin, FALSE);
1172 wrefresh(LYwin);
1173
1174 LYwin = stdscr;
1175 /* reenable xterm mouse-mode in the new screen */
1176 keypad(LYwin, TRUE);
1177 lynx_enable_mouse(1);
1178
1179 if (-1 == lynx_initialize_keymaps()) {
1180 endwin();
1181 exit_immediately(EXIT_FAILURE);
1182 }
1183 if (has_colors()) {
1184 start_color();
1185 }
1186
1187 delscreen(oldscreen);
1188 }
1189 #endif
1190
start_curses(void)1191 void start_curses(void)
1192 {
1193 #ifdef USE_SLANG
1194 static int slinit;
1195
1196 if (LYCursesON) {
1197 CTRACE((tfp, "start_curses: Hmm, already ON.\n"));
1198 return;
1199 }
1200
1201 if (slinit == 0) {
1202 #if defined(HAVE_TTYNAME)
1203 if (isatty(fileno(stdout)) && LYReopenInput() < 0) {
1204 fprintf(stderr, "Cannot open tty input\n");
1205 exit_immediately(EXIT_FAILURE);
1206 }
1207 #endif
1208 #if defined(USE_KEYMAPS)
1209 if (-1 == lynx_initialize_keymaps())
1210 exit_immediately(EXIT_FAILURE);
1211 #else
1212 SLtt_get_terminfo();
1213 #endif
1214 #if (defined(__DJGPP__) && !defined(DJGPP_KEYHANDLER)) || defined(__CYGWIN__)
1215 SLkp_init();
1216 #endif /* __DJGPP__ && !DJGPP_KEYHANDLER */
1217
1218 #if defined(REAL_UNIX_SYSTEM) && !defined(__CYGWIN__)
1219 #if SLANG_VERSION >= 9935
1220 SLang_TT_Read_FD = fileno(stdin);
1221 #endif /* SLANG_VERSION >= 9935 */
1222 #endif /* REAL_UNIX_SYSTEM && !__CYGWIN__ */
1223
1224 #if !defined(USE_KEYMAPS) && defined(ENHANCED_LINEEDIT) && defined(ESCDELAY)
1225 /* way to get ESC that's not part of a recognized sequence through */
1226 ESCDELAY = 2000;
1227 #endif
1228 /*
1229 * Check whether a saved show_color:off override is in effect. - kw
1230 */
1231 if (LYrcShowColor == SHOW_COLOR_NEVER) {
1232 SLtt_Use_Ansi_Colors = 0;
1233 }
1234 /*
1235 * Check whether we're forcing color on. - FM
1236 */
1237 if ((LYShowColor > 1) && (Lynx_Color_Flags & SL_LYNX_USE_COLOR))
1238 SLtt_Use_Ansi_Colors = 1;
1239 /*
1240 * Check whether a -nocolor override is in effect. - kw
1241 */
1242 if (Lynx_Color_Flags & SL_LYNX_OVERRIDE_COLOR)
1243 SLtt_Use_Ansi_Colors = 0;
1244 /*
1245 * Make sure our flags are in register. - FM
1246 */
1247 if (SLtt_Use_Ansi_Colors == 1) {
1248 if (LYShowColor != SHOW_COLOR_ALWAYS) {
1249 LYShowColor = SHOW_COLOR_ON;
1250 }
1251 } else {
1252 if (LYShowColor != SHOW_COLOR_NEVER) {
1253 LYShowColor = SHOW_COLOR_OFF;
1254 }
1255 }
1256 size_change(0);
1257
1258 #if (defined(VMS) || defined(REAL_UNIX_SYSTEM)) && !defined(__CYGWIN__)
1259 if ((Masked_Attr & (int) SLTT_ULINE_MASK) == 0) {
1260 SLtt_add_color_attribute(4, SLTT_ULINE_MASK);
1261 SLtt_add_color_attribute(5, SLTT_ULINE_MASK);
1262 }
1263 /*
1264 * If set, the blink escape sequence will turn on high intensity
1265 * background (rxvt and maybe Linux console).
1266 */
1267 SLtt_Blink_Mode = term_blink_is_boldbg;
1268 #endif /* (VMS || REAL_UNIX_SYSTEM) && !__CYGWIN__ */
1269 }
1270 #ifdef __DJGPP__
1271 _eth_init();
1272 #endif /* __DJGPP__ */
1273
1274 slinit = 1;
1275 Current_Attr = 0;
1276 #ifndef VMS
1277 #if SLANG_VERSION > 9929
1278 SLang_init_tty(-1, 0, 1);
1279 #else
1280 SLang_init_tty(3, 0, 1);
1281 #endif /* SLANG_VERSION > 9929 */
1282 #endif /* !VMS */
1283 SLsmg_init_smg();
1284 SLsmg_Display_Eight_Bit = LYlowest_eightbit[current_char_set];
1285 if (SLsmg_Display_Eight_Bit > 191)
1286 SLsmg_Display_Eight_Bit = 191; /* may print ctrl chars otherwise - kw */
1287 scrollok(0, 0);
1288 SLsmg_Backspace_Moves = 1;
1289 #if SLANG_VERSION > 10306
1290 SLsmg_touch_screen();
1291 #endif
1292 #ifndef VMS
1293 #if defined(REAL_UNIX_SYSTEM) && !defined(__CYGWIN__)
1294 SLtty_set_suspend_state(1);
1295 #endif /* REAL_UNIX_SYSTEM && !__CYGWIN__ */
1296 #ifdef SIGTSTP
1297 if (!no_suspend)
1298 signal(SIGTSTP, sl_suspend);
1299 #endif /* SIGTSTP */
1300 signal(SIGINT, cleanup_sig);
1301 #endif /* !VMS */
1302
1303 lynx_enable_mouse(1);
1304
1305 #else /* USE_SLANG; Now using curses: */
1306 int keypad_on = 0;
1307
1308 #ifdef VMS
1309 /*
1310 * If we are VMS then do initscr() everytime start_curses() is called!
1311 */
1312 CTRACE((tfp, "Screen size: initscr()\n"));
1313 initscr(); /* start curses */
1314 #else /* Unix: */
1315
1316 #if defined(HAVE_TTYNAME)
1317 if (isatty(fileno(stdout)) && LYReopenInput() < 0) {
1318 fprintf(stderr, "Cannot open tty input\n");
1319 exit_immediately(EXIT_FAILURE);
1320 }
1321 #endif
1322
1323 #ifdef __CYGWIN__
1324 /*
1325 * Workaround for buggy Cygwin, which breaks subprocesses of a
1326 * full-screen application (tested with cygwin dll, dated
1327 * 2002/6/23 -TD)
1328 */
1329 if (!lynx_called_initscr) {
1330 FILE *fp = fopen("/dev/tty", "w");
1331
1332 if (fp != 0)
1333 stdout = fp;
1334 }
1335 #endif
1336
1337 if (!LYscreen) {
1338 /*
1339 * If we're not VMS then only do initscr() one time, and one time only!
1340 */
1341 #if defined(HAVE_NEWTERM)
1342 #if !(defined(NCURSES) && !defined(HAVE_RESIZETERM))
1343 BOOLEAN savesize;
1344
1345 savesize = recent_sizechange;
1346 size_change(0);
1347 recent_sizechange = savesize; /* avoid extra redraw */
1348 #if defined(__MVS__)
1349 {
1350 /*
1351 * The requirement to do this may be a bug in OS/390.
1352 *
1353 * Put screen geometry in environment variables used by
1354 * XOpen curses before calling newterm(). I believe this
1355 * completes work left unfinished by AJL & FM -- gil
1356 */
1357 static char lines_putenv[] = "LINES=abcde", cols_putenv[] = "COLUMNS=abcde";
1358
1359 sprintf(lines_putenv + 6, "%d", LYlines & 0xfff);
1360 sprintf(cols_putenv + 8, "%d", LYcols & 0xfff);
1361 putenv(lines_putenv);
1362 putenv(cols_putenv);
1363 CTRACE((tfp, "start_curses putenv %s, %s\n", lines_putenv, cols_putenv));
1364 }
1365 #endif /* defined(__MVS__) */
1366 #endif /* !(defined(NCURSES) && defined(HAVE_RESIZETERM)) */
1367 CTRACE((tfp, "Screen size: %s()\n", NEWTERM_NAME));
1368 if (!(LYscreen = newterm(NULL, stdout, stdin))) { /* start curses */
1369 fprintf(tfp, "%s\n",
1370 gettext("Terminal initialisation failed - unknown terminal type?"));
1371 exit_immediately(EXIT_FAILURE);
1372 }
1373 #else
1374 CTRACE((tfp, "Screen size: initscr()\n"));
1375 initscr();
1376 #endif /* HAVE_NEWTERM */
1377 lynx_called_initscr = TRUE;
1378 LYlines = LYscreenHeight();
1379 LYcols = LYscreenWidth();
1380
1381 #if defined(SIGWINCH) && defined(NCURSES_VERSION)
1382 size_change(0);
1383 recent_sizechange = FALSE; /* prevent mainloop drawing 1st doc twice */
1384 #endif /* SIGWINCH */
1385 CTRACE((tfp, "Screen size is now %d x %d\n", LYlines, LYcols));
1386
1387 #ifdef USE_CURSES_PADS
1388 if (LYuseCursesPads) {
1389 CTRACE((tfp, "using curses-pads\n"));
1390 LYwin = newpad(LYlines, MAX_COLS);
1391 LYshiftWin = 0;
1392 LYwideLines = FALSE;
1393 } else {
1394 LYwin = stdscr;
1395 }
1396 #endif
1397
1398 #if defined(USE_KEYMAPS) && defined(NCURSES_VERSION)
1399 # if HAVE_KEYPAD
1400 /* Need to switch keypad on before initializing keymaps, otherwise
1401 when the keypad is switched on, some keybindings may be overriden. */
1402 keypad(LYwin, TRUE);
1403 keypad_on = 1;
1404 # endif /* HAVE_KEYPAD */
1405
1406 if (-1 == lynx_initialize_keymaps()) {
1407 endwin();
1408 exit_immediately(EXIT_FAILURE);
1409 }
1410 #endif
1411
1412 /*
1413 * This is a workaround for a bug in SVr4 curses, observed on Solaris
1414 * 2.4: if your terminal's alternate-character set contains codes in
1415 * the range 128-255, they'll be sign-extended in the acs_map[] table,
1416 * which in turn causes their values to be emitted as 255 (0xff).
1417 * "Fix" this by forcing the table to 8-bit codes (it has to be
1418 * anyway).
1419 */
1420 #if defined(ALT_CHAR_SET) && !defined(NCURSES_VERSION)
1421 {
1422 int n;
1423
1424 for (n = 0; n < 128; n++)
1425 if (ALT_CHAR_SET[n] & 0x80) {
1426 ALT_CHAR_SET[n] &= 0xff;
1427 ALT_CHAR_SET[n] |= A_ALTCHARSET;
1428 }
1429 }
1430 #endif
1431
1432 #if defined(USE_COLOR_STYLE) || defined(USE_COLOR_TABLE)
1433 if (has_colors()) {
1434 lynx_has_color = TRUE;
1435 start_color();
1436
1437 #ifndef COLORS
1438 /* map2boldc() relies on COLORS being a power of 2 */
1439 if (COLORS > 16)
1440 COLORS = 16;
1441 if (COLORS < 8)
1442 COLORS = 2;
1443 if (COLORS > 8 && COLORS != 16)
1444 COLORS = 8;
1445 #endif
1446
1447 #ifdef USE_DEFAULT_COLORS
1448 update_default_colors();
1449 if (LYuse_default_colors) {
1450 #if defined(EXP_ASSUMED_COLOR) && defined(USE_COLOR_TABLE)
1451 /*
1452 * Adjust the color mapping table to match the ASSUMED_COLOR
1453 * setting in lynx.cfg
1454 */
1455 if (assume_default_colors(default_fg, default_bg) != OK) {
1456 default_fg = COLOR_WHITE;
1457 default_bg = COLOR_BLACK;
1458 }
1459 CTRACE((tfp, "initializing default colors %d/%d\n",
1460 default_fg, default_bg));
1461 if (default_fg >= 0 || default_bg >= 0) {
1462 unsigned n;
1463
1464 for (n = 0; n < TABLESIZE(lynx_color_cfg); n++) {
1465 if (default_fg >= 0 && lynx_color_cfg[n].fg < 0)
1466 lynx_color_cfg[n].fg = default_fg;
1467 if (default_bg >= 0 && lynx_color_cfg[n].bg < 0)
1468 lynx_color_cfg[n].bg = default_bg;
1469 CTRACE((tfp, "color_cfg[%u] = %d/%d\n", n,
1470 lynx_color_cfg[n].fg,
1471 lynx_color_cfg[n].bg));
1472 }
1473 lynx_setup_colors();
1474 }
1475 #else
1476 #if defined(HAVE_USE_DEFAULT_COLORS)
1477 if (!default_color_reset) {
1478 if (lynx_called_initscr) {
1479 if (LYuse_default_colors && (use_default_colors() == OK)) {
1480 default_fg = DEFAULT_COLOR;
1481 default_bg = DEFAULT_COLOR;
1482 } else {
1483 default_fg = COLOR_WHITE;
1484 default_bg = COLOR_BLACK;
1485 default_color_reset = TRUE;
1486 }
1487 }
1488 }
1489 #endif /* HAVE_USE_DEFAULT_COLORS */
1490 #endif /* EXP_ASSUMED_COLOR */
1491 }
1492 #endif /* USE_DEFAULT_COLORS */
1493 }
1494 #endif /* USE_COLOR_STYLE || USE_COLOR_TABLE */
1495
1496 #ifdef USE_COLOR_STYLE
1497 /* Curses forgets color settings when we call delscreen() */
1498 if (non_empty(lynx_lss_file) && LYCanReadFile(lynx_lss_file)) {
1499 style_readFromFile(lynx_lss_file);
1500 }
1501 parse_userstyles();
1502 #endif
1503 #ifdef USE_COLOR_TABLE
1504 lynx_init_colors();
1505 #endif
1506 }
1507 #ifdef __DJGPP__
1508 _eth_init();
1509 #endif /* __DJGPP__ */
1510 #endif /* not VMS */
1511
1512 #ifdef VMS
1513 crmode();
1514 raw();
1515 #else
1516 #ifdef HAVE_CBREAK
1517 cbreak();
1518 #else
1519 crmode();
1520 #endif /* HAVE_CBREAK */
1521 signal(SIGINT, cleanup_sig);
1522 #endif /* VMS */
1523
1524 noecho();
1525
1526 #ifdef HAVE_KEYPAD
1527 if (!keypad_on)
1528 keypad(LYwin, TRUE);
1529 #endif /* HAVE_KEYPAD */
1530
1531 lynx_enable_mouse(1);
1532
1533 fflush(stdin);
1534 fflush(stdout);
1535 fflush(stderr);
1536 #endif /* USE_SLANG */
1537
1538 #if defined(WIN_EX)
1539 LYclear();
1540 #endif
1541
1542 #if defined(USE_BLINK) && defined(__EMX__)
1543 if (term_blink_is_boldbg) /* Now actually make it so! */
1544 make_blink_boldbg();
1545 #endif
1546
1547 LYCursesON = TRUE;
1548 #if defined(PDCURSES) && defined(PDC_BUILD) && PDC_BUILD >= 2401
1549 if ((scrsize_x != 0) && (scrsize_y != 0)) {
1550 if (saved_scrsize_x == 0) {
1551 saved_scrsize_x = COLS;
1552 saved_scrsize_y = LINES + 1;
1553 }
1554 CTRACE((tfp, "resize_term: x=%d, y=%d\n", scrsize_x, scrsize_y));
1555 CTRACE((tfp, "saved terminal size: x=%d, y=%d\n", saved_scrsize_x, saved_scrsize_y));
1556 resize_term(scrsize_y, scrsize_x);
1557 LYlines = LYscreenHeight();
1558 LYcols = LYscreenWidth();
1559 LYStatusLine = -1;
1560 LYclear();
1561 #ifdef _WINDOWS
1562 adjustWindowPos();
1563 #endif
1564 }
1565 if (saved_scrsize_x2 == 0) {
1566 if (saved_scrsize_x == 0) {
1567 saved_scrsize_x2 = COLS;
1568 saved_scrsize_y2 = LINES + 1;
1569 } else {
1570 saved_scrsize_x2 = scrsize_x;
1571 saved_scrsize_y2 = scrsize_y;
1572 }
1573 }
1574 #endif
1575 CTRACE((tfp, "start_curses: done.\n"));
1576 } /* end of start_curses() */
1577
lynx_enable_mouse(int state)1578 void lynx_enable_mouse(int state)
1579 {
1580 #ifdef USE_MOUSE
1581 /***********************************************************************/
1582
1583 #if defined(WIN_EX)
1584 /* modify lynx_enable_mouse() for pdcurses configuration so that mouse support
1585 is disabled unless -use_mouse is specified
1586 */
1587 HANDLE hConIn = INVALID_HANDLE_VALUE;
1588
1589 hConIn = GetStdHandle(STD_INPUT_HANDLE);
1590 if (LYUseMouse == 0) {
1591 SetConsoleMode(hConIn, ENABLE_WINDOW_INPUT);
1592 FlushConsoleInputBuffer(hConIn);
1593 return;
1594 }
1595 #endif
1596
1597 (void) state;
1598
1599 if (LYUseMouse == 0)
1600 return;
1601
1602 #if defined(USE_SLANG)
1603 SLtt_set_mouse_mode(state, 0);
1604 SLtt_flush_output();
1605 #else
1606
1607 #if defined(WIN_EX) && defined(PDCURSES)
1608 if (state) {
1609 SetConsoleMode(hConIn, ENABLE_MOUSE_INPUT | ENABLE_WINDOW_INPUT);
1610 FlushConsoleInputBuffer(hConIn);
1611 }
1612 #else
1613 #if defined(NCURSES)
1614 if (state) {
1615 /* Compensate for small value of maxclick in ncurses. */
1616 static int was = 0;
1617
1618 if (!was) {
1619 int old = mouseinterval(-1);
1620
1621 was++;
1622 if (old < 200) /* Default 166 */
1623 mouseinterval(300);
1624 }
1625 /* Inform ncurses which mouse events we're interested in.
1626 * We shouldn't need to include BUTTONn_PRESSED and BUTTONn_RELEASED
1627 * events, since ncurses should translate them to click events. - kw
1628 * However, if we do not include them, then ncurses effectively
1629 * ignores mouseinterval(), thus translates *any* sequence of
1630 * press/release to a click, which leads to inconveniences.
1631 * We special-case these events in LYStrings.c.
1632 */
1633 mousemask(BUTTON_CTRL | BUTTON_ALT
1634 | BUTTON1_PRESSED | BUTTON1_RELEASED
1635 | BUTTON1_CLICKED
1636 | BUTTON1_DOUBLE_CLICKED | BUTTON1_TRIPLE_CLICKED
1637 | BUTTON2_PRESSED | BUTTON2_RELEASED
1638 | BUTTON2_CLICKED
1639 | BUTTON3_PRESSED | BUTTON3_RELEASED
1640 | BUTTON3_CLICKED
1641 | BUTTON3_DOUBLE_CLICKED | BUTTON3_TRIPLE_CLICKED
1642 #if NCURSES_MOUSE_VERSION >= 2
1643 | BUTTON4_PRESSED | BUTTON4_RELEASED
1644 | BUTTON4_CLICKED
1645 | BUTTON4_DOUBLE_CLICKED | BUTTON4_TRIPLE_CLICKED
1646 | BUTTON5_PRESSED | BUTTON5_RELEASED
1647 | BUTTON5_CLICKED
1648 | BUTTON5_DOUBLE_CLICKED | BUTTON5_TRIPLE_CLICKED
1649 #endif
1650 ,NULL);
1651 } else
1652 mousemask(0, NULL);
1653 #endif /* NCURSES */
1654 #endif /* WIN_EX and PDCURSES */
1655
1656 #if defined(PDCURSES)
1657 if (state)
1658 mouse_set(
1659 BUTTON1_CLICKED | BUTTON1_PRESSED | BUTTON1_RELEASED |
1660 BUTTON2_CLICKED | BUTTON2_PRESSED | BUTTON2_RELEASED |
1661 BUTTON3_CLICKED | BUTTON3_PRESSED | BUTTON3_RELEASED);
1662 #endif
1663 #endif /* NOT USE_SLANG */
1664
1665 /***********************************************************************/
1666 #endif /* USE_MOUSE */
1667 }
1668
1669 /*
1670 * SVr4 curses (and ncurses) initialize the terminal I/O to raw mode, and
1671 * simulate other modes in the library. This means that when running, it
1672 * simulates the OCRNL setting. Normally that is not a problem. However, when
1673 * spawning a subprocess (e.g., xli), the subprocess may write to the screen.
1674 * Fine so far - curses resets the terminal I/O to the normal state on exit.
1675 * But the subprocess' messages can still be coming to the screen when lynx
1676 * returns to the screen mode. This function delays restoring OCRNL until
1677 * after the first getch() call.
1678 *
1679 * The OCRNL setting is controlled by nl()/nonl() of course - but we do not
1680 * want to give up that optimization since it would be a bit slower. (Note -
1681 * slang does not use this optimization; if it did, the same screen glitch
1682 * would occur).
1683 *
1684 * FIXME: for simplicity, only ncurses is implemented here - the TTY and
1685 * SET_TTY definitions are ncurses-specific. The same effect could be done for
1686 * other curses implementations, since the "cur_term->Nttyb" part is common to
1687 * SVr4 curses.
1688 */
lynx_nl2crlf(int normal GCC_UNUSED)1689 void lynx_nl2crlf(int normal GCC_UNUSED)
1690 {
1691 #if defined(NCURSES_VERSION_PATCH) && defined(SET_TTY) && defined(TERMIOS) && defined(ONLCR)
1692 static TTY saved_tty;
1693 static int did_save = FALSE;
1694 static int waiting = FALSE;
1695 static int can_fix = TRUE;
1696
1697 if (!did_save) {
1698 if (cur_term == 0) {
1699 can_fix = FALSE;
1700 } else {
1701 saved_tty = cur_term->Nttyb;
1702 did_save = TRUE;
1703 #if NCURSES_VERSION_PATCH < 20010529
1704 /* workaround for optimizer bug with nonl() */
1705 if ((tigetstr("cud1") != 0 && *tigetstr("cud1") == '\n')
1706 || (tigetstr("ind") != 0 && *tigetstr("ind") == '\n'))
1707 can_fix = FALSE;
1708 #endif
1709 }
1710 }
1711 if (can_fix) {
1712 if (normal) {
1713 if (!waiting) {
1714 cur_term->Nttyb.c_oflag |= ONLCR;
1715 waiting = TRUE;
1716 nonl();
1717 }
1718 } else {
1719 if (waiting) {
1720 cur_term->Nttyb = saved_tty;
1721 SET_TTY(fileno(stdout), &saved_tty);
1722 waiting = FALSE;
1723 nl();
1724 LYrefresh();
1725 }
1726 }
1727 }
1728 #endif
1729 }
1730
stop_curses(void)1731 void stop_curses(void)
1732 {
1733 if (LYCursesON) {
1734 #ifdef USE_COLOR_STYLE
1735 FreeCachedStyles();
1736 #endif
1737 echo();
1738 }
1739 #if defined(PDCURSES) && defined(PDC_BUILD) && PDC_BUILD >= 2401
1740 resetty();
1741 #endif
1742
1743 #ifdef __DJGPP__
1744 _eth_release();
1745 #endif /* __DJGPP__ */
1746
1747 /* ifdefs for non-Unix curses or slang */
1748 #if defined(__MINGW32__)
1749 chtype bb;
1750
1751 bb = getbkgd(stdscr);
1752 bkgdset(0);
1753 clear();
1754 refresh();
1755 bkgdset(bb);
1756 #if defined(PDCURSES)
1757 endwin();
1758 #endif /* PDCURSES */
1759
1760 #elif defined(DOSPATH) && !(defined(USE_SLANG) || defined(_WIN_CC))
1761
1762 #if defined(PDCURSES)
1763 endwin();
1764 #endif /* PDCURSES */
1765
1766 #ifdef __DJGPP__
1767 ScreenClear();
1768 #elif !defined(PDCURSES) /* some flavor of win32? */
1769 clrscr();
1770 #endif /* win32 */
1771
1772 #else /* Unix, etc */
1773
1774 if (LYCursesON == TRUE) {
1775 lynx_nl2crlf(TRUE);
1776 lynx_enable_mouse(0);
1777 if (LYscreen || lynx_called_initscr) {
1778 endwin(); /* stop curses */
1779 LYDELSCR();
1780 }
1781 } else {
1782 #ifdef SH_EX
1783 int i;
1784
1785 for (i = 0; i <= 3; i++) {
1786 printf("\r\n");
1787 }
1788 #endif
1789 }
1790
1791 fflush(stdout);
1792 #endif /* ifdefs for non-Unix curses or slang */
1793 fflush(stderr);
1794
1795 LYCursesON = FALSE;
1796 CTRACE((tfp, "stop_curses: done.\n"));
1797
1798 #if defined(SIGTSTP) && defined(USE_SLANG)
1799 #ifndef VMS
1800 if (!no_suspend)
1801 signal(SIGTSTP, SIG_DFL);
1802 #endif /* !VMS */
1803 #endif /* SIGTSTP && USE_SLANG */
1804
1805 #ifndef VMS
1806 signal(SIGINT, SIG_DFL);
1807 #endif /* !VMS */
1808 }
1809
1810 #ifdef VMS
1811
1812 #ifdef USE_SLANG
1813 extern void longname(char *, char *);
1814 #endif /* USE_SLANG */
1815
1816 /*
1817 * Check terminal type, start curses & setup terminal.
1818 */
setup(char * terminal)1819 BOOLEAN setup(char *terminal)
1820 {
1821 int c;
1822 int status;
1823 char *dummy = 0, *cp, term[81];
1824
1825 /*
1826 * If the display was not set by a command line option then see if it is
1827 * available from the environment.
1828 */
1829 if ((cp = LYgetXDisplay()) != 0) {
1830 StrAllocCopy(x_display, cp);
1831 } else {
1832 FREE(x_display);
1833 }
1834
1835 /*
1836 * Get terminal type, and convert to lower case.
1837 */
1838 term[0] = '\0';
1839 longname(dummy, term);
1840 if (term[0] == '\0' && (form_get_data || form_post_data)) {
1841 /*
1842 * Some yoyo used these under conditions which require -dump, so force
1843 * that mode here. - FM
1844 */
1845 dump_output_immediately = TRUE;
1846 LYcols = DFT_COLS;
1847 if (keypad_mode == NUMBERS_AS_ARROWS)
1848 keypad_mode = LINKS_ARE_NUMBERED;
1849 status = mainloop();
1850 exit_immediately(status);
1851 }
1852 LYLowerCase(term);
1853
1854 printf("%s%s\n", gettext("Terminal ="), term);
1855 if ((strlen(term) < 5) ||
1856 StrNCmp(term, "vt", 2) || !isdigit(term[2])) {
1857 printf("%s\n",
1858 gettext("You must use a vt100, 200, etc. terminal with this program."));
1859 printf(CONFIRM_PROCEED, "n/y");
1860 c = getchar();
1861 if (c != 'y' && c != 'Y') {
1862 printf("\n");
1863 return (FALSE);
1864 }
1865 strcpy(term, "vt100");
1866 }
1867
1868 ttopen();
1869 start_curses();
1870
1871 LYlines = LYscreenHeight();
1872 LYcols = LYscreenWidth();
1873
1874 return (TRUE);
1875 }
1876
1877 #else /* Not VMS: */
1878
1879 /*
1880 * Check terminal type, start curses & setup terminal.
1881 */
setup(char * terminal)1882 BOOLEAN setup(char *terminal)
1883 {
1884 char *term_putenv = NULL;
1885 char *buffer = NULL;
1886 char *cp;
1887
1888 /*
1889 * If the display was not set by a command line option then see if it is
1890 * available from the environment .
1891 */
1892 if ((cp = LYgetXDisplay()) != NULL) {
1893 StrAllocCopy(x_display, cp);
1894 } else {
1895 FREE(x_display);
1896 }
1897
1898 if (terminal != NULL) {
1899 HTSprintf0(&term_putenv, "TERM=%.106s", terminal);
1900 (void) putenv(term_putenv);
1901 }
1902
1903 /*
1904 * Query the terminal type.
1905 */
1906 if (dumbterm(LYGetEnv("TERM"))) {
1907 printf("\n\n %s\n\n", gettext("Your Terminal type is unknown!"));
1908 printf(" %s [vt100] ", gettext("Enter a terminal type:"));
1909
1910 if (LYSafeGets(&buffer, stdin) != 0) {
1911 LYTrimLeading(buffer);
1912 LYTrimTrailing(buffer);
1913 }
1914
1915 if (isEmpty(buffer))
1916 StrAllocCopy(buffer, "vt100");
1917
1918 HTSprintf0(&term_putenv, "TERM=%.106s", buffer);
1919 FREE(buffer);
1920
1921 (void) putenv(term_putenv);
1922 printf("\n%s %s\n", gettext("TERMINAL TYPE IS SET TO"),
1923 LYGetEnv("TERM"));
1924 LYSleepMsg();
1925 }
1926
1927 start_curses();
1928
1929 #ifdef HAVE_TTYTYPE
1930 /*
1931 * Account for lossage on the 'sun' terminal type (80x24) Sun text console
1932 * driver. It only supports reverse video, but all SGR sequences produce
1933 * that same reverse video, and the terminfo entry lists different SGRs for
1934 * 'bold' and 'rev'. As a result, the current link is indistinguishable
1935 * from all other links. The workaround here is to disable the 'rev'
1936 * capability.
1937 */
1938 if ((StrNCmp((const char *) ttytype, "sun", 3) == 0)) {
1939 LYnoVideo(2);
1940 }
1941 #endif /* HAVE_TTYTYPE */
1942
1943 LYlines = LYscreenHeight();
1944 LYcols = LYscreenWidth();
1945
1946 return (1);
1947 }
1948
dumbterm(char * terminal)1949 static int dumbterm(char *terminal)
1950 {
1951 int dumb = FALSE;
1952
1953 /*
1954 * Began checking for terminal == NULL in case that TERM environment
1955 * variable is not set. Thanks to Dick Wesseling (ftu@fi.ruu.nl).
1956 */
1957 if (terminal == NULL ||
1958 !strcasecomp(terminal, "network") ||
1959 !strcasecomp(terminal, "unknown") ||
1960 !strcasecomp(terminal, "dialup") ||
1961 !strcasecomp(terminal, "dumb") ||
1962 !strcasecomp(terminal, "switch") ||
1963 !strcasecomp(terminal, "ethernet"))
1964 dumb = TRUE;
1965 return (dumb);
1966 }
1967
1968 #ifdef FANCY_CURSES
1969 #ifndef USE_COLOR_STYLE
1970 #ifdef USE_COLOR_TABLE
LYsetWAttr(WINDOW * win)1971 static void LYsetWAttr(WINDOW * win)
1972 {
1973 (void) wattrset(win, LYgetTableAttr());
1974 }
1975
LYaddWAttr(WINDOW * win,int a)1976 void LYaddWAttr(WINDOW * win, int a)
1977 {
1978 Current_Attr |= a;
1979 LYsetWAttr(win);
1980 }
1981
LYaddAttr(int a)1982 void LYaddAttr(int a)
1983 {
1984 LYaddWAttr(LYwin, a);
1985 }
1986
LYsubWAttr(WINDOW * win,int a)1987 void LYsubWAttr(WINDOW * win, int a)
1988 {
1989 Current_Attr &= ~a;
1990 LYsetWAttr(win);
1991 }
1992
LYsubAttr(int a)1993 void LYsubAttr(int a)
1994 {
1995 LYsubWAttr(LYwin, a);
1996 }
1997 #endif /* USE_COLOR_TABLE */
1998 #endif /* !USE_COLOR_STYLE */
1999 #endif /* FANCY_CURSES */
2000 #endif /* VMS */
2001
2002 /* Use this rather than the 'wprintw()' function to write a blank-padded
2003 * string to the given window, since someone's asserted that printw doesn't
2004 * handle 8-bit characters unlike addstr (though more info would be useful).
2005 *
2006 * We're blank-filling so that with SVr4 curses, it'll show the background
2007 * color to a uniform width in the popup-menu.
2008 */
2009 #ifndef USE_SLANG
LYpaddstr(WINDOW * the_window,int width,const char * the_string)2010 void LYpaddstr(WINDOW * the_window, int width, const char *the_string)
2011 {
2012 int y, x1, x2;
2013 int length = (int) strlen(the_string);
2014
2015 #ifdef WIDEC_CURSES
2016 int actual = (int) LYstrCells(the_string);
2017 #endif
2018
2019 getyx(the_window, y, x1);
2020 (void) y;
2021 if (width + x1 > LYcolLimit)
2022 width = LYcolLimit - x1;
2023 #ifdef WIDEC_CURSES
2024 if (actual > width) {
2025 actual = width;
2026 /* FIXME: a binary search might be faster */
2027 while (LYstrExtent(the_string, length, length) > actual) {
2028 --length;
2029 }
2030 }
2031 #endif
2032 LYwaddnstr(the_window, the_string, (size_t) length);
2033 getyx(the_window, y, x2);
2034 width -= (x2 - x1);
2035 while (width-- > 0)
2036 waddstr(the_window, " ");
2037 }
2038
2039 /*
2040 * Work around limitation of curses' order-of-refresh by setting a pointer to
2041 * the topmost window that should be displayed.
2042 *
2043 * FIXME: the associated call on 'keypad()' is not needed for Unix, but
2044 * something in the OS/2 EMX port requires it.
2045 */
2046 static WINDOW *my_subwindow;
2047
LYsubwindow(WINDOW * param)2048 void LYsubwindow(WINDOW * param)
2049 {
2050 if (param != 0) {
2051 my_subwindow = param;
2052 #if defined(NCURSES) || defined(PDCURSES)
2053 keypad(my_subwindow, TRUE);
2054 #if defined(USE_COLOR_STYLE)
2055 LynxWChangeStyle(my_subwindow, s_menu_bg, STACK_ON);
2056 {
2057 long b = LYgetattrs(my_subwindow);
2058
2059 wbkgd(my_subwindow, (chtype) (b | ' '));
2060 }
2061 LynxWChangeStyle(my_subwindow, s_menu_bg, STACK_OFF);
2062 #elif defined(HAVE_GETBKGD) /* not defined in ncurses 1.8.7 */
2063 wbkgd(my_subwindow, getbkgd(LYwin));
2064 #endif
2065 #endif
2066 scrollok(my_subwindow, TRUE);
2067 } else {
2068 touchwin(LYwin);
2069 delwin(my_subwindow);
2070 my_subwindow = 0;
2071 }
2072 }
2073
LYtopwindow(void)2074 WINDOW *LYtopwindow(void)
2075 {
2076 return (my_subwindow ? my_subwindow : LYwin);
2077 }
2078 #endif
2079
LYstartPopup(int * top_y,int * left_x,int * height,int * width)2080 WINDOW *LYstartPopup(int *top_y,
2081 int *left_x,
2082 int *height,
2083 int *width)
2084 {
2085 WINDOW *form_window = 0;
2086
2087 #ifdef USE_SLANG
2088 static WINDOW fake_window;
2089
2090 if (*left_x < 1 || (*left_x + *width + 4) >= LYcolLimit) {
2091 *left_x = 1;
2092 *width = LYcolLimit - 5;
2093 }
2094
2095 SLsmg_fill_region(*top_y,
2096 *left_x - 1,
2097 (unsigned) *height,
2098 (unsigned) *width + 4,
2099 ' ');
2100 form_window = &fake_window;
2101 form_window->top_y = *top_y;
2102 form_window->left_x = *left_x;
2103 form_window->height = *height;
2104 form_window->width = *width;
2105 #else
2106 if (*left_x > 0 && (*left_x + *width + 4) < LYcolLimit)
2107 form_window = newwin(*height, *width + 4, *top_y, *left_x - 1);
2108 if (form_window == 0) {
2109 if (*width > LYcolLimit - 4) {
2110 *width = LYcolLimit - 4;
2111 *left_x = 1;
2112 } else {
2113 *left_x = LYcolLimit - 4 - *width;
2114 if (*left_x <= 0)
2115 *left_x = 1;
2116 }
2117 form_window = newwin(*height, *width + 4, *top_y, *left_x - 1);
2118 }
2119 if (form_window == 0) {
2120 HTAlert(POPUP_FAILED);
2121 } else {
2122 LYsubwindow(form_window);
2123 }
2124 #endif /* USE_SLANG */
2125 return form_window;
2126 }
2127
LYstartTargetEmphasis(void)2128 void LYstartTargetEmphasis(void)
2129 {
2130 #ifdef USE_COLOR_STYLE
2131 if (s_whereis != NOSTYLE) {
2132 curses_style(s_whereis, STACK_ON);
2133 return;
2134 }
2135 #endif
2136 #if defined(FANCY_CURSES) || defined(USE_SLANG)
2137 lynx_start_bold();
2138 lynx_start_reverse();
2139 #endif /* FANCY_CURSES || USE_SLANG */
2140 lynx_start_underline();
2141 }
2142
LYstopTargetEmphasis(void)2143 void LYstopTargetEmphasis(void)
2144 {
2145 #ifdef USE_COLOR_STYLE
2146 if (s_whereis != NOSTYLE) {
2147 curses_style(s_whereis, STACK_OFF);
2148 return;
2149 }
2150 #endif
2151 lynx_stop_underline();
2152 #if defined(FANCY_CURSES) || defined(USE_SLANG)
2153 lynx_stop_reverse();
2154 lynx_stop_bold();
2155 #endif /* FANCY_CURSES || USE_SLANG */
2156 }
2157
2158 /*
2159 * Accommodate the different flavors of touchline
2160 */
LYtouchline(int row)2161 void LYtouchline(int row)
2162 {
2163 #if defined(HAVE_WREDRAWLN) && !defined(NCURSES_VERSION)
2164 wredrawln(LYwin, row, 1);
2165 #else
2166 #if defined(HAVE_TOUCHLINE)
2167 /* touchline() is not available on VMS before version 7.0, and then only on
2168 * Alpha, since prior ports of curses were broken. BSD touchline() has a
2169 * 4th parameter since it is used internally by touchwin().
2170 */
2171 #if defined(HAVE_BSD_TOUCHLINE)
2172 touchline(LYwin, row, 0, COLS);
2173 #else
2174 touchline(LYwin, row, 1);
2175 #endif
2176 #else
2177 #if !defined(USE_SLANG)
2178 touchwin(LYwin);
2179 #else
2180 SLsmg_touch_lines(row, 1);
2181 #endif
2182 #endif
2183 #endif
2184 }
2185
2186 /*
2187 * Wrapper for waddnstr().
2188 */
LYwaddnstr(WINDOW * w GCC_UNUSED,const char * src,size_t len)2189 void LYwaddnstr(WINDOW * w GCC_UNUSED,
2190 const char *src,
2191 size_t len)
2192 {
2193 int y0, x0;
2194 int y, x;
2195 size_t inx;
2196
2197 #ifdef USE_CURSES_PADS
2198 /*
2199 * If we've configured to use pads for left/right scrolling, that can
2200 * interfere with calls to this function that assume they're wrapping.
2201 * Writing to a pad which is wider than the screen will simply not wrap.
2202 *
2203 * Link-highlighting uses wrapping. You can see this by viewing the
2204 * options screen in a terminal which is narrower than 80 columns.
2205 *
2206 * Check for that case, and use curses' wrapping in a derived window to
2207 * simplify things, e.g., in case the string contains multibyte or
2208 * multicolumn characters.
2209 */
2210 getyx(LYwin, y0, x0);
2211
2212 if (LYuseCursesPads
2213 && (LYwin == w)
2214 && (LYshiftWin == 0)
2215 && LYwideLines == FALSE
2216 && ((int) len > (LYcolLimit - x0))
2217 && (y0 >= 0)
2218 && (x0 >= 0)
2219 && (x0 < LYcolLimit)) {
2220 WINDOW *sub = derwin(LYwin, LYlines, LYcolLimit, 0, 0);
2221
2222 if (sub != 0) {
2223 wmove(sub, y0, x0);
2224 LYwideLines = TRUE;
2225 LYwaddnstr(sub, src, len);
2226 getyx(sub, y0, x0);
2227 delwin(sub);
2228 wmove(LYwin, y0, x0);
2229 }
2230 LYwideLines = FALSE;
2231
2232 return;
2233 }
2234 #endif
2235 /*
2236 * We only want to trace this function for the color-style code. It would
2237 * be too much logging if not needed.
2238 */
2239 #ifdef USE_COLOR_STYLE
2240 if (TRACE) {
2241 LYGetYX(y, x);
2242 CTRACE2(TRACE_STYLE, (tfp, "[%2d,%2d] LYwaddnstr(%.*s, %u)\n",
2243 y, x, (int) len, src, (unsigned) len));
2244 }
2245 #endif
2246 LYGetYX(y0, x0);
2247
2248 for (inx = 0; inx < len; ++inx) {
2249 /*
2250 * Do tab-expansion relative to the base of the string (rather than
2251 * the screen) so that tabs in a TEXTAREA will look right.
2252 */
2253 if (src[inx] == '\t') {
2254 LYGetYX(y, x);
2255 while ((++x - x0) % 8)
2256 waddch(w, ' ');
2257 waddch(w, ' ');
2258 } else {
2259 waddch(w, UCH(src[inx]));
2260 }
2261 }
2262 }
2263
2264 /*
2265 * Determine the number of cells the given string would take up on the screen,
2266 * limited (in the case of wide characters) by the maxCells parameter.
2267 *
2268 * If the returnCellNum parameter is TRUE, return the number of cells;
2269 * otherwise, return the length (limited by the len parameter) of the prefix of
2270 * the string that fits in maxCells cells.
2271 */
2272 static
LYstrExtent0(const char * string,int len,int maxCells GCC_UNUSED,int retCellNum GCC_UNUSED)2273 int LYstrExtent0(const char *string,
2274 int len,
2275 int maxCells GCC_UNUSED,
2276 int retCellNum GCC_UNUSED)
2277 {
2278 int used = (len < 0 ? (int) strlen(string) : len);
2279 int result = used;
2280
2281 #ifdef WIDEC_CURSES
2282 if (used > 0 && lynx_called_initscr) {
2283 static WINDOW *fake_win;
2284 static int fake_max;
2285
2286 if (fake_max < maxCells) {
2287 fake_max = (maxCells + 1) * 2;
2288 if (fake_win != 0) {
2289 delwin(fake_win);
2290 fake_win = 0;
2291 }
2292 }
2293 if (fake_win == 0) {
2294 fake_win = newwin(2, fake_max, 0, 0);
2295 }
2296 if (fake_win != 0) {
2297 int new_x = 0;
2298 int new_y = 0;
2299 int x = 0;
2300 int n;
2301
2302 wmove(fake_win, 0, 0);
2303 for (n = 0; n < used; ++n) {
2304 if (IsNormalChar(string[n])) {
2305 waddch(fake_win, UCH(string[n]));
2306 getyx(fake_win, new_y, new_x);
2307 if (new_y > 0 || new_x > maxCells)
2308 break;
2309 x = new_x;
2310 }
2311 }
2312 result = (retCellNum ? x : n);
2313 }
2314 }
2315 #endif
2316 return result;
2317 }
2318
2319 /*
2320 * Determine the number of cells the given string would take up on the screen,
2321 * limited by the maxCells parameter. This is used for constructing aligned
2322 * text in the options and similar forms.
2323 *
2324 * FIXME: make this account for wrapping, too.
2325 * FIXME: make this useful for "lynx -dump", which hasn't initialized curses.
2326 */
LYstrExtent(const char * string,int len,int maxCells)2327 int LYstrExtent(const char *string, int len, int maxCells)
2328 {
2329 int result = LYstrExtent0(string, len, maxCells, TRUE);
2330
2331 return (result > maxCells ? maxCells : result);
2332 }
2333
2334 /*
2335 * Return the number of cells in the first 'len' bytes of the string.
2336 *
2337 * This relies upon the coincidence that multicell characters use at least as
2338 * many bytes as cells. But we have to account for tab, which can use 8, and
2339 * control characters which use 2.
2340 */
LYstrExtent2(const char * string,int len)2341 int LYstrExtent2(const char *string, int len)
2342 {
2343 return LYstrExtent(string, len, 8 * len);
2344 }
2345
2346 /*
2347 * Determine the longest prefix of a string that fits in a given number of
2348 * cells and return its length.
2349 */
LYstrFittable(const char * string,int maxCells)2350 int LYstrFittable(const char *string, int maxCells)
2351 {
2352 return LYstrExtent0(string, -1, maxCells, FALSE);
2353 }
2354
2355 /*
2356 * Returns the total number of cells that the string would use.
2357 */
LYstrCells(const char * string)2358 int LYstrCells(const char *string)
2359 {
2360 return LYstrExtent2(string, (int) strlen(string));
2361 }
2362
2363 #ifdef VMS
2364 /*
2365 * Cut-down termio --
2366 * Do character-oriented stream input for Jeff.
2367 * Code ripped off from Micro-Emacs 3.7 by Daniel Lawrence.
2368 *
2369 * Ever-so-slightly modified by Kathryn Huxtable. 29-Jan-1991.
2370 * Cut down for Lou. 8 Sep 1992.
2371 * Cut down farther for Lou. 19 Apr 1993.
2372 * We don't set PASSALL or PASTHRU since we don't
2373 * want to block CTRL/C, CTRL/Y, CTRL/S or CTRL/Q.
2374 * Simply setting NOECHO and doing timed reads
2375 * is sufficient.
2376 * Further mods by Fote. 29-June-1993
2377 * ttopen() and ttclose() are now terminal initialization
2378 * and restoration procedures, called once at startup
2379 * and at exit, respectively, of the LYNX image.
2380 * ttclose() should be called before an exit from LYNX
2381 * no matter how the exit is invoked.
2382 * setup(terminal) does the ttopen().
2383 * cleanup() calls cleanup_files() and ttclose().
2384 * ttgetc() now handles NOECHO and NOFLITR (instead of
2385 * setting the terminal itself to NOECHO in ttopen()).
2386 * VMSsignal() added for handling both Ctrl-C *and* Ctrl-Y
2387 * interrupts, and disabling system response to Ctrl-T.
2388 * Further mods by Fote. 15-Dec-1993
2389 * Added edit handler in ttopen() which will invoke
2390 * VMSexit() and behave intelligently on ACCVIO's.
2391 * Further mods by Fote. 29-Dec-1993
2392 * Simplified ttgetc().
2393 * Further mods by Fote. 16-Jan-1994
2394 * Added code in ttopen() which will invoke VMSVersion()
2395 * to get the version of VMS as VersionVMS for use by
2396 * by new or modified interrupt or spawning routines.
2397 * Further mods by Fote. 27-Jan-1994
2398 * Added back a typeahead() which supports 'z' or 'Z' as
2399 * an "Zap transfer" command via HTCheckForInterrupt()
2400 * in LYUtils.c.
2401 */
2402
2403 #include <descrip.h>
2404 #include <iodef.h>
2405 #include <ssdef.h>
2406 #include <msgdef.h>
2407 #include <ttdef.h>
2408 #include <tt2def.h>
2409 #include <libclidef.h>
2410 #include <lib$routines.h>
2411 #include <starlet.h>
2412 #include <clidef.h>
2413 #include <syidef.h>
2414 #ifdef signal
2415 #undef signal
2416 #endif /* signal */
2417 #include <signal.h>
2418 #ifdef system
2419 #undef system
2420 #endif /* system */
2421 #include <processes.h>
2422 #include <LYVMSdef.h>
2423
2424 #define EFN 0 /* Event flag */
2425
2426 static unsigned char buffer[20]; /* Input buffer */
2427 static int in_pos, in_len; /* For escape sequences */
2428 static int oldmode[3]; /* Old TTY mode bits */
2429 static int newmode[3]; /* New TTY mode bits */
2430 static short iochan; /* TTY I/O channel */
2431 static $DESCRIPTOR(term_nam_dsc, "TT"); /* Descriptor for iochan */
2432 static unsigned long mask = LIB$M_CLI_CTRLY | LIB$M_CLI_CTRLT; /* ^Y and ^T */
2433 static unsigned long old_msk; /* Saved control mask */
2434 static short trap_flag = FALSE; /* TRUE if AST is set */
2435 BOOLEAN DidCleanup = FALSE; /* Exit handler flag */
2436 static char VersionVMS[20]; /* Version of VMS */
2437
VMSVersion(char * VerString,int VerLen)2438 int VMSVersion(char *VerString,
2439 int VerLen)
2440 {
2441 unsigned long status, itm_cod = SYI$_VERSION;
2442 int i, verlen = 0;
2443 struct dsc$descriptor version;
2444 char *m;
2445
2446 version.dsc$a_pointer = VerString;
2447 version.dsc$w_length = VerLen - 1;
2448 version.dsc$b_dtype = DSC$K_DTYPE_B;
2449 version.dsc$b_class = DSC$K_CLASS_S;
2450
2451 status = lib$getsyi(&itm_cod, 0, &version, &verlen, 0, 0);
2452 if (!(status & 1) || verlen == 0)
2453 return 0;
2454
2455 /*
2456 * Cut out trailing spaces
2457 */
2458 for (m = VerString + verlen, i = verlen - 1; i > 0 && VerString[i] == ' '; --i)
2459 *(--m) = '\0';
2460
2461 return strlen(VerString) + 1; /* Transmit ending 0 too */
2462 }
2463
VMSexit(void)2464 void VMSexit(void)
2465 {
2466 /*
2467 * If we get here and DidCleanup is not set, it was via an ACCVIO, or
2468 * outofmemory forced exit, so make *sure* we attempt a cleanup and reset
2469 * the terminal.
2470 */
2471 if (!DidCleanup) {
2472 if (LYOutOfMemory == FALSE) {
2473 fprintf(stderr,
2474 gettext("\nA Fatal error has occurred in %s Ver. %s\n"),
2475 LYNX_NAME, LYNX_VERSION);
2476 fprintf(stderr,
2477 gettext("\nPlease notify your system administrator to confirm a bug, and if\n\
2478 confirmed, to notify the lynx-dev list. Bug reports should have concise\n\
2479 descriptions of the command and/or URL which causes the problem, the\n\
2480 operating system name with version number, the TCPIP implementation, the\n\
2481 TRACEBACK if it can be captured, and any other relevant information.\n"));
2482
2483 if (LYTraceLogFP == NULL) {
2484 fprintf(stderr, RETURN_TO_CLEANUP);
2485 (void) getchar();
2486 }
2487 } else if (LYCursesON) {
2488 HTAlert(MEMORY_EXHAUSTED_ABORT);
2489 }
2490 cleanup();
2491 }
2492 if (LYOutOfMemory == TRUE) {
2493 printf("\r\n%s\r\n\r\n", MEMORY_EXHAUSTED_ABORT);
2494 fflush(stdout);
2495 fflush(stderr);
2496 }
2497 }
2498
2499 /*
2500 * TTOPEN --
2501 * This function is called once to set up the terminal
2502 * device streams. It translates TT until it finds
2503 * the terminal, then assigns a channel to it, sets it
2504 * to EDIT, and sets up the Ctrl-C and Ctrl-Y interrupt
2505 * handling.
2506 */
ttopen(void)2507 int ttopen(void)
2508 {
2509 int iosb[2];
2510 int status;
2511 static unsigned long condition;
2512 static struct _exit_block {
2513 unsigned long forward;
2514 unsigned long address;
2515 unsigned long zero;
2516 unsigned long condition;
2517 } exit_handler_block;
2518
2519 status = sys$assign(&term_nam_dsc, &iochan, 0, 0);
2520 if (status != SS$_NORMAL)
2521 exit_immediately(status);
2522
2523 status = sys$qiow(EFN, iochan, IO$_SENSEMODE, &iosb, 0, 0,
2524 &oldmode, sizeof(oldmode), 0, 0, 0, 0);
2525 if (status != SS$_NORMAL)
2526 exit_immediately(status);
2527
2528 status = iosb[0] & 0xFFFF;
2529 if (status != SS$_NORMAL)
2530 exit_immediately(status);
2531
2532 newmode[0] = oldmode[0];
2533 newmode[1] = oldmode[1];
2534 newmode[2] = oldmode[2] | TT2$M_EDIT;
2535
2536 status = sys$qiow(EFN, iochan, IO$_SETMODE, &iosb, 0, 0,
2537 &newmode, sizeof(newmode), 0, 0, 0, 0);
2538 if (status != SS$_NORMAL)
2539 exit_immediately(status);
2540
2541 status = iosb[0] & 0xFFFF;
2542 if (status != SS$_NORMAL)
2543 exit_immediately(status);
2544
2545 /*
2546 * Declare the exit handler block.
2547 */
2548 exit_handler_block.forward = 0;
2549 exit_handler_block.address = (unsigned long) &VMSexit;
2550 exit_handler_block.zero = 0;
2551 exit_handler_block.condition = (unsigned long) &condition;
2552 status = sys$dclexh(&exit_handler_block);
2553 if (status != SS$_NORMAL)
2554 exit_immediately(status);
2555
2556 /*
2557 * Set the AST.
2558 */
2559 lib$disable_ctrl(&mask, &old_msk);
2560 trap_flag = TRUE;
2561 status = sys$qiow(EFN, iochan,
2562 IO$_SETMODE | IO$M_CTRLCAST | IO$M_CTRLYAST,
2563 &iosb, 0, 0,
2564 &cleanup_sig, SIGINT, 0, 0, 0, 0);
2565 if (status != SS$_NORMAL) {
2566 lib$enable_ctrl(&old_msk);
2567 exit_immediately(status);
2568 }
2569
2570 /*
2571 * Get the version of VMS.
2572 */
2573 if (VMSVersion(VersionVMS, 20) < 3)
2574 /*
2575 * Load zeros on error.
2576 */
2577 strcpy(VersionVMS, "V0.0-0");
2578
2579 return (0);
2580 } /* ttopen */
2581
2582 /*
2583 * TTCLOSE --
2584 * This function gets called just before we go back home
2585 * to the command interpreter. It puts the terminal back
2586 * in a reasonable state.
2587 */
ttclose(void)2588 int ttclose(void)
2589 {
2590 int status;
2591 int iosb[1];
2592
2593 status = sys$qiow(EFN, iochan, IO$_SETMODE, &iosb, 0, 0,
2594 &oldmode, sizeof(oldmode), 0, 0, 0, 0);
2595
2596 if (status != SS$_NORMAL || (iosb[0] & 0xFFFF) != SS$_NORMAL)
2597 exit_immediately(status);
2598
2599 if (trap_flag) {
2600 status = sys$dassgn(iochan);
2601 status = lib$enable_ctrl(&old_msk);
2602 trap_flag = FALSE;
2603 }
2604 return (0);
2605 } /* ttclose */
2606
2607 /*
2608 * TTGETC --
2609 * Read a character from the terminal, with NOECHO and NOFILTR.
2610 */
ttgetc(void)2611 int ttgetc(void)
2612 {
2613 int status;
2614 unsigned short iosb[4];
2615
2616 if (in_pos < in_len)
2617 return (buffer[in_pos++]);
2618
2619 status = sys$qiow(EFN, iochan,
2620 IO$_READVBLK | IO$M_NOECHO | IO$M_NOFILTR,
2621 &iosb, 0, 0,
2622 &buffer, 1, 0, 0, 0, 0);
2623 if ((status & 1) == 1)
2624 status = iosb[0];
2625 if (status == SS$_PARTESCAPE) {
2626 /*
2627 * Escape sequence in progress. Fake a successful read.
2628 */
2629 status = 1;
2630 }
2631 if ((status & 1) != 1 && status != SS$_DATAOVERUN)
2632 exit_immediately(status);
2633 in_pos = 1;
2634 in_len = iosb[1] + iosb[3];
2635 return (buffer[0]);
2636 }
2637
2638 /*
2639 * TYPEAHEAD -- Fote Macrides 27-Jan-1994
2640 * Check whether a keystroke has been entered, and return
2641 * it, or -1 if none was entered.
2642 */
typeahead(void)2643 int typeahead(void)
2644 {
2645 int status;
2646 unsigned short iosb[4];
2647
2648 if (dump_output_immediately)
2649 return -1;
2650
2651 if (in_pos < in_len)
2652 return (buffer[in_pos++]);
2653
2654 again:
2655 status = sys$qiow(EFN, iochan,
2656 IO$_READVBLK | IO$M_TIMED | IO$M_NOECHO | IO$M_NOFILTR,
2657 &iosb, 0, 0,
2658 &buffer, 1, 0, 0, 0, 0);
2659 if ((status & 1) == 1)
2660 status = iosb[0];
2661 if (status == SS$_PARTESCAPE) {
2662 /*
2663 * Escape sequence in progress, finish reading it.
2664 */
2665 goto again;
2666 }
2667
2668 in_pos = 1;
2669 in_len = iosb[1] + iosb[3];
2670 if (status == SS$_TIMEOUT || status == SS$_DATAOVERUN)
2671 return (-1);
2672 return (buffer[0]);
2673 }
2674
2675 /*
2676 * VMSSIGNAL -- Fote Macrides 29-Jun-1993
2677 * Sets up AST for both Ctrl-C and Ctrl-Y, with system response
2678 * to Ctrl-T disabled. If called with a sig other than SIGINT,
2679 * it will use the C library's system(sig, func).
2680 * The equivalent of VMSsignal(SIGINT, cleanup_sig) is done on
2681 * intialization by ttopen(), so don't do it again.
2682 * VMSsignal(SIGINT, SIG_DFL) is treated as a call to ttclose().
2683 * Call VMSsignal(SIGINT, SIG_IGN) before system() calls to
2684 * enable Ctrl-C and Ctrl-Y in the subprocess, and then call
2685 * VMSsignal(SIG_INT, cleanup_sig) on return from the subprocess.
2686 * For funcs which set flags and do not invoke an exit from
2687 * LYNX, the func should reassert itself.
2688 * The VMS signal() calls do not fully emulate the Unix calls,
2689 * and VMSsignal() is just a "helper", also not a full emulation.
2690 */
2691
VMSsignal(int sig,void (* func)())2692 void VMSsignal(int sig,
2693 void (*func) ())
2694 {
2695 int status;
2696 short iosb[4];
2697 static int SIG_IGN_flag;
2698
2699 /*
2700 * Pass all signals other than SIGINT to signal().
2701 * Also pass SIGINT to signal() if we're dumping.
2702 */
2703 if (sig != SIGINT || dump_output_immediately) {
2704 signal(sig, func);
2705 return;
2706 }
2707
2708 /*
2709 * If func is SIG_DFL, treat it as ttclose().
2710 */
2711 if (func == SIG_DFL) {
2712 ttclose();
2713 return;
2714 }
2715
2716 /*
2717 * Clear any previous AST.
2718 */
2719 if (trap_flag) {
2720 status = sys$dassgn(iochan);
2721 status = lib$enable_ctrl(&old_msk);
2722 trap_flag = FALSE;
2723 }
2724
2725 /*
2726 * If func is SIG_IGN, leave the TT channel closed and the system response
2727 * to interrupts enabled for system() calls.
2728 */
2729 if (func == SIG_IGN)
2730 return;
2731
2732 /*
2733 * If we get to here, we have a LYNX func, so set the AST.
2734 */
2735 lib$disable_ctrl(&mask, &old_msk);
2736 trap_flag = TRUE;
2737 status = sys$assign(&term_nam_dsc, &iochan, 0, 0);
2738 status = sys$qiow(EFN, iochan,
2739 IO$_SETMODE | IO$M_CTRLCAST | IO$M_CTRLYAST,
2740 &iosb, 0, 0,
2741 func, SIGINT, 0, 0, 0, 0);
2742
2743 } /* VMSsignal */
2744
2745 /*
2746 * DCLspawn_exception, spawn_DCLprocess, DCLsystem -- F.Macrides 16-Jan-1994
2747 * Exception-handler routines for regulating interrupts and enabling
2748 * Control-T during spawns. Includes TRUSTED flag for versions of VMS
2749 * which require it in captive accounts. This code should be used
2750 * instead of the VAXC or DECC system(), by including LYUtils.h in
2751 * modules which have system() calls. It helps ensure that we return
2752 * to Lynx instead of breaking out to DCL if a user issues interrupts
2753 * or generates an ACCVIO during spawns.
2754 */
2755 #ifdef __DECC
DCLspawn_exception(void * sigarr,void * mecharr)2756 static unsigned int DCLspawn_exception(void *sigarr,
2757 void *mecharr)
2758 #else
2759 static int DCLspawn_exception(void *sigarr,
2760 void *mecharr)
2761 #endif /* __DECC */
2762 {
2763 int status;
2764
2765 status = lib$sig_to_ret(sigarr, mecharr);
2766 return (SS$_UNWIND);
2767 }
2768
spawn_DCLprocess(char * command)2769 static int spawn_DCLprocess(char *command)
2770 {
2771 int status;
2772 unsigned long Status = 0;
2773
2774 /*
2775 * Keep DECC from complaining.
2776 */
2777 struct dsc$descriptor_s command_desc;
2778
2779 command_desc.dsc$w_length = strlen(command);
2780 command_desc.dsc$b_class = DSC$K_CLASS_S;
2781 command_desc.dsc$b_dtype = DSC$K_DTYPE_T;
2782 command_desc.dsc$a_pointer = command;
2783
2784 VAXC$ESTABLISH(DCLspawn_exception);
2785
2786 #ifdef __ALPHA /** OpenVMS/AXP lacked the TRUSTED flag before v6.1 **/
2787 if (VersionVMS[1] > '6' ||
2788 (VersionVMS[1] == '6' && VersionVMS[2] == '.' &&
2789 VersionVMS[3] >= '1'))
2790 #else
2791 if (VersionVMS[1] >= '6')
2792 #endif /* __ALPHA */
2793 {
2794 /*
2795 * Include TRUSTED flag.
2796 */
2797 unsigned long trusted = CLI$M_TRUSTED;
2798
2799 status = lib$spawn(&command_desc, 0, 0, &trusted,
2800 0, 0, &Status);
2801 /*
2802 * If it was invalid, try again without the flag.
2803 */
2804 if (status == LIB$_INVARG)
2805 status = lib$spawn(&command_desc, 0, 0, 0,
2806 0, 0, &Status);
2807 } else
2808 status = lib$spawn(&command_desc, 0, 0, 0,
2809 0, 0, &Status);
2810 /*
2811 * Return -1 on error.
2812 */
2813 if ((status & 1) != 1 || (Status & 1) != 1)
2814 return (-1);
2815 /*
2816 * Return 0 on success.
2817 */
2818 return (0);
2819 }
2820
DCLsystem(char * command)2821 int DCLsystem(char *command)
2822 {
2823 int status;
2824
2825 VMSsignal(SIGINT, SIG_IGN);
2826 status = spawn_DCLprocess(command);
2827 VMSsignal(SIGINT, cleanup_sig);
2828 /*
2829 * Returns 0 on success, -1 any error.
2830 */
2831 return (status);
2832 }
2833 #endif /* VMS */
2834
2835 /*
2836 * Return the physical screen dimensions that we're allowed to use.
2837 */
LYscreenHeight(void)2838 int LYscreenHeight(void)
2839 {
2840 int result = LINES;
2841
2842 if (result <= 0)
2843 result = DFT_ROWS;
2844 return result;
2845 }
2846
LYscreenWidth(void)2847 int LYscreenWidth(void)
2848 {
2849 int result = COLS;
2850
2851 #if defined(PDCURSES_EXP) && defined(WIN_EX) && defined(CJK_EX) /* 1999/08/26 (Thu) 17:53:38 */
2852 {
2853 extern int current_codepage; /* PDCurses lib. */
2854
2855 if (current_codepage == 932)
2856 result--;
2857 }
2858 #endif
2859 if (result <= 0)
2860 result = DFT_COLS;
2861 return result;
2862 }
2863
2864 /*
2865 * Set the window's background color (make the pad's color agree), e.g., when
2866 * we have just parsed it from the config file, or after clearing the screen.
2867 */
LYnormalColor(void)2868 void LYnormalColor(void)
2869 {
2870 #if defined(USE_COLOR_STYLE) && defined(USE_CURSES_PADS)
2871 if (LYwin != stdscr) {
2872 int color = displayStyles[DSTYLE_NORMAL].color;
2873
2874 if (color >= 0) {
2875 wbkgd(LYwin, (chtype) (color | ' '));
2876 LYrefresh();
2877 }
2878 }
2879 #endif
2880 }
2881
2882 /*
2883 * The functions ifdef'd with USE_CURSES_PADS are implemented that way so we
2884 * don't break the slang configuration.
2885 */
LYclear(void)2886 void LYclear(void)
2887 {
2888 #ifdef USE_CURSES_PADS
2889 wclear(LYwin);
2890 #else
2891 clear();
2892 #endif
2893 LYnormalColor();
2894 }
2895
LYclrtoeol(void)2896 void LYclrtoeol(void)
2897 {
2898 #ifdef USE_CURSES_PADS
2899 wclrtoeol(LYwin);
2900 #else
2901 clrtoeol();
2902 #endif
2903 }
2904
LYerase(void)2905 void LYerase(void)
2906 {
2907 #ifdef USE_CURSES_PADS
2908 werase(LYwin);
2909 #else
2910 erase();
2911 #endif
2912 LYnormalColor();
2913 }
2914
LYmove(int y,int x)2915 void LYmove(int y, int x)
2916 {
2917 #ifdef USE_CURSES_PADS
2918 wmove(LYwin, y, x);
2919 #else
2920 move(y, x);
2921 #endif
2922 }
2923
LYrefresh(void)2924 void LYrefresh(void)
2925 {
2926 #ifdef USE_CURSES_PADS
2927 if (LYwin != stdscr) {
2928 /*
2929 * Workaround for special case where lynx is prompting for a mailto,
2930 * and has a subject line that is wider than the screen. The
2931 * wnoutrefresh() call resets newscr's position to match stdscr's,
2932 * which happens to be the window's origin because we were not updating
2933 * that, and other stray wmoves in lynx fail because the coordinate
2934 * is on/after the right margin. Force things to look ok here.
2935 */
2936 int y, x;
2937
2938 getyx(LYwin, y, x);
2939 if (y < 0)
2940 y = 0;
2941 if (x < 0)
2942 x = 0;
2943 if (x > LYcolLimit)
2944 x = LYcolLimit;
2945 wmove(stdscr, y, x);
2946
2947 wnoutrefresh(stdscr);
2948 pnoutrefresh(LYwin, 0, LYshiftWin, 0, 0, LYlines, LYscreenWidth() - 1);
2949
2950 /*
2951 * Keep a popup window visible. This can happen if the user presses
2952 * '/' to do a search within a popup.
2953 */
2954 if (my_subwindow != 0) {
2955 touchwin(my_subwindow);
2956 wnoutrefresh(my_subwindow);
2957 }
2958 doupdate();
2959 } else {
2960 refresh();
2961 }
2962 #else
2963 refresh();
2964 #endif
2965 }
2966
lynx_force_repaint(void)2967 void lynx_force_repaint(void)
2968 {
2969 clearok(curscr, TRUE);
2970 }
2971
lynx_start_title_color(void)2972 void lynx_start_title_color(void)
2973 {
2974 #ifdef SH_EX
2975 lynx_start_reverse();
2976 #endif
2977 }
2978
lynx_stop_title_color(void)2979 void lynx_stop_title_color(void)
2980 {
2981 #ifdef SH_EX
2982 lynx_stop_reverse();
2983 #endif
2984 }
2985
lynx_start_link_color(int flag,int pending)2986 void lynx_start_link_color(int flag,
2987 int pending)
2988 {
2989 if (flag) {
2990 /* makes some terminals work wrong because
2991 * they can't handle two attributes at the
2992 * same time
2993 */
2994 /* lynx_start_bold(); */
2995 lynx_start_reverse();
2996 #if defined(USE_SLANG)
2997 #ifndef __DJGPP__
2998 if (SLtt_Use_Ansi_Colors)
2999 #endif /* !__DJGPP__ */
3000 lynx_start_underline();
3001 #endif /* USE_SLANG */
3002 #if defined(FANCY_CURSES) && defined(COLOR_CURSES)
3003 if (lynx_has_color && LYShowColor >= SHOW_COLOR_ON)
3004 lynx_start_underline();
3005 #endif /* USE_SLANG */
3006 } else {
3007 lynx_start_bold();
3008 /*
3009 * Make sure when flag is OFF that "unhighlighted" links will be
3010 * underlined if appropriate. - LE & FM
3011 */
3012 if (pending)
3013 lynx_start_underline();
3014 }
3015 }
3016
lynx_stop_link_color(int flag,int pending GCC_UNUSED)3017 void lynx_stop_link_color(int flag,
3018 int pending GCC_UNUSED)
3019 {
3020 #ifdef USE_COLOR_STYLE
3021 LynxChangeStyle(flag == TRUE ? s_alink : s_a, ABS_OFF);
3022 #else
3023 if (flag) {
3024 lynx_stop_reverse();
3025 #if defined(USE_SLANG)
3026 #ifndef __DJGPP__
3027 if (SLtt_Use_Ansi_Colors)
3028 #endif /* !__DJGPP__ */
3029 lynx_stop_underline();
3030 #endif /* USE_SLANG */
3031 #if defined(FANCY_CURSES) && defined(COLOR_CURSES)
3032 if (lynx_has_color && LYShowColor >= SHOW_COLOR_ON)
3033 lynx_stop_underline();
3034 #endif /* FANCY_CURSES && COLOR_CURSES */
3035 } else {
3036 lynx_stop_bold();
3037 /*
3038 * If underlining was turned on above, turn it off. - LE & FM
3039 */
3040 if (pending)
3041 lynx_stop_underline();
3042 }
3043 #endif
3044 }
3045
3046 /* FIXME: consider inlining these */
3047
lynx_stop_target_color(void)3048 void lynx_stop_target_color(void)
3049 {
3050 lynx_stop_underline();
3051 lynx_stop_reverse();
3052 lynx_stop_bold();
3053 }
3054
lynx_start_target_color(void)3055 void lynx_start_target_color(void)
3056 {
3057 lynx_start_bold();
3058 lynx_start_reverse();
3059 lynx_start_underline();
3060 }
3061
lynx_start_status_color(void)3062 void lynx_start_status_color(void)
3063 {
3064 #if defined(USE_COLOR_TABLE) && defined(COLOR_CURSES)
3065 if (lynx_has_color && LYShowColor >= SHOW_COLOR_ON)
3066 lynx_set_color(2);
3067 else
3068 #endif
3069 lynx_start_reverse();
3070 }
3071
lynx_stop_status_color(void)3072 void lynx_stop_status_color(void)
3073 {
3074 #if defined(USE_COLOR_TABLE) && defined(COLOR_CURSES)
3075 if (lynx_has_color && LYShowColor >= SHOW_COLOR_ON)
3076 lynx_set_color(0);
3077 else
3078 #endif
3079 lynx_stop_reverse();
3080 }
3081
lynx_start_h1_color(void)3082 void lynx_start_h1_color(void)
3083 {
3084 if (bold_H1 || bold_headers)
3085 lynx_start_bold();
3086 }
3087
lynx_stop_h1_color(void)3088 void lynx_stop_h1_color(void)
3089 {
3090 if (bold_H1 || bold_headers)
3091 lynx_stop_bold();
3092 }
3093
lynx_start_prompt_color(void)3094 void lynx_start_prompt_color(void)
3095 {
3096 lynx_start_reverse();
3097 }
3098
lynx_stop_prompt_color(void)3099 void lynx_stop_prompt_color(void)
3100 {
3101 lynx_stop_reverse();
3102 }
3103
lynx_start_radio_color(void)3104 void lynx_start_radio_color(void)
3105 {
3106 lynx_start_bold();
3107 }
3108
lynx_stop_radio_color(void)3109 void lynx_stop_radio_color(void)
3110 {
3111 lynx_stop_bold();
3112 }
3113
lynx_stop_all_colors(void)3114 void lynx_stop_all_colors(void)
3115 {
3116 lynx_stop_underline();
3117 lynx_stop_reverse();
3118 lynx_stop_bold();
3119 }
3120
3121 /*
3122 * Wrappers for LYUnderlineLinks flag.
3123 */
lynx_start_bold(void)3124 void lynx_start_bold(void)
3125 {
3126 start_bold();
3127 }
3128
lynx_start_reverse(void)3129 void lynx_start_reverse(void)
3130 {
3131 start_reverse();
3132 }
3133
lynx_start_underline(void)3134 void lynx_start_underline(void)
3135 {
3136 start_underline();
3137 }
3138
lynx_stop_bold(void)3139 void lynx_stop_bold(void)
3140 {
3141 stop_bold();
3142 }
3143
lynx_stop_reverse(void)3144 void lynx_stop_reverse(void)
3145 {
3146 stop_reverse();
3147 }
3148
lynx_stop_underline(void)3149 void lynx_stop_underline(void)
3150 {
3151 stop_underline();
3152 }
3153
LYSetDisplayLines(void)3154 void LYSetDisplayLines(void)
3155 {
3156 if (!no_title) {
3157 if (user_mode == NOVICE_MODE)
3158 display_lines = LYlines - 4;
3159 else
3160 display_lines = LYlines - 2;
3161 } else if (user_mode == NOVICE_MODE) {
3162 display_lines = LYlines - 3;
3163 } else {
3164 display_lines = LYlines - 1;
3165 }
3166 }
3167
3168 /*
3169 * If LYShowCursor is ON, move the cursor to the left of the current option, so
3170 * that blind users, who are most likely to have LYShowCursor ON, will have
3171 * its string spoken or passed to the braille interface as each option is made
3172 * current. Otherwise, move it to the bottom, right column of the screen, to
3173 * "hide" the cursor as for the main document, and let sighted users rely on
3174 * the current option's highlighting or color without the distraction of a
3175 * blinking cursor in the window. - FM
3176 */
LYstowCursor(WINDOW * win,int row,int col)3177 void LYstowCursor(WINDOW * win, int row, int col)
3178 {
3179 if (LYShowCursor) {
3180 wmove(win, row, col);
3181 } else {
3182 LYHideCursor();
3183 }
3184 #ifdef USE_SLANG
3185 SLsmg_refresh();
3186 #else
3187 wrefresh(win);
3188 #endif /* USE_SLANG */
3189 }
3190
3191 #if defined(USE_BLINK) && defined(__EMX__) /* Can't put it earler due to BOOLEAN conflict */
3192 # define BOOLEAN os2BOOLEAN
3193 # define INCL_VIO
3194 # include "os2.h"
make_blink_boldbg(void)3195 static void make_blink_boldbg(void)
3196 {
3197 VIOINTENSITY buf; /* VIO windows have it anyway, */
3198
3199 /* but FS session need a switch */
3200 buf.cb = sizeof(buf);
3201 buf.type = 2; /* VIOINTENSITY request */
3202 buf.fs = 1; /* Intensity == boldbg */
3203 VioSetState(&buf, 0);
3204 }
3205 #endif
3206
3207 #if defined(HAVE_WATTR_GET)
3208 /*
3209 * getattrs() is not in X/Open curses, but it is more convenient than this.
3210 */
LYgetattrs(WINDOW * win)3211 long LYgetattrs(WINDOW * win)
3212 {
3213 long result;
3214
3215 #if ( defined(HAVE_GETATTRS) && ( !defined(NCURSES_VERSION_MAJOR) || NCURSES_VERSION_MAJOR < 5 ) )
3216
3217 result = getattrs(win);
3218 #else
3219 attr_t attrs = 0;
3220 short pair = 0;
3221
3222 /*
3223 * FIXME: this ignores the color-pair, which for most implementations is
3224 * not stored in the attribute value.
3225 */
3226 (void) wattr_get(win, &attrs, &pair, NULL);
3227 result = (long) attrs;
3228 #endif
3229 return result;
3230 }
3231 #endif /* HAVE_WATTR_GET */
3232
3233 #if defined(NCURSES_VERSION_PATCH) && NCURSES_VERSION_PATCH > 20021012
3234 #ifndef HAVE_USE_LEGACY_CODING
3235 /*
3236 * Between ncurses 5.3 and 5.4 as part of fixes for wide-character mode, the
3237 * locale support no longer allows characters in the range 128-159 to be
3238 * treated as printable characters. Here is a workaround to fool
3239 * waddch_nosync() into treating "all" 8-bit characters as printable.
3240 */
unctrl(chtype ch)3241 NCURSES_CONST char *unctrl(chtype ch)
3242 {
3243 static char result[3];
3244 unsigned data = (unsigned char) ch;
3245
3246 if (data < 32) {
3247 result[0] = '^';
3248 result[1] = ch | '@';
3249 result[2] = 0;
3250 } else if (data == 127) {
3251 result[0] = '^';
3252 result[1] = '?';
3253 result[2] = 0;
3254 } else {
3255 result[0] = data;
3256 result[1] = 0;
3257 }
3258 return result;
3259 }
3260 #endif /* HAVE_USE_LEGACY_CODING */
3261 #endif
3262