home *** CD-ROM | disk | FTP | other *** search
/ Dream 52 / Amiga_Dream_52.iso / Linux / Divers / lynx2.8.1dev.10.tar.gz / lynx2.8.1dev.10.tar / lynx2-8 / src / LYCurses.c < prev    next >
C/C++ Source or Header  |  1998-05-10  |  43KB  |  1,824 lines

  1. #include <HTUtils.h>
  2. #include <tcp.h>
  3. #include <LYCurses.h>
  4. #include <LYStyle.h>
  5. #include <LYUtils.h>
  6. #include <LYGlobalDefs.h>
  7. #include <LYMainLoop.h>
  8. #include <LYSignal.h>
  9. #include <LYClean.h>
  10. #include <LYReadCFG.h>
  11. #include <LYStrings.h>
  12. #include <LYCharSets.h>
  13. #include <UCAux.h>
  14.  
  15. #include <LYexit.h>
  16. #include <LYLeaks.h>
  17.  
  18. #define FREE(x) if (x) {free(x); x = NULL;}
  19.  
  20. #ifdef VMS
  21. #define DISPLAY "DECW$DISPLAY"
  22. #else
  23. #define DISPLAY "DISPLAY"
  24. #endif /* VMS */
  25.  
  26. #if defined(VMS) && defined(__GNUC__)
  27. #include <gnu_hacks.h>
  28. #undef LINES
  29. #undef COLS
  30. #define LINES lines
  31. #define COLS cols
  32. extern int _NOSHARE(LINES);
  33. extern int _NOSHARE(COLS);
  34. #endif /* VMS && __GNUC__ */
  35.  
  36. #ifdef USE_COLOR_STYLE
  37. #include <AttrList.h>
  38. #include <LYHash.h>
  39. #endif
  40.  
  41. #if defined(COLOR_CURSES)
  42. int lynx_has_color = FALSE;
  43. #endif
  44.  
  45. #define COLOR_BKGD ((COLOR_PAIRS >= 9) ? COLOR_PAIR(9) : A_NORMAL)
  46.  
  47. /*
  48.  *  These are routines to start and stop curses and to cleanup
  49.  *  the screen at the end.
  50.  */
  51.  
  52. PRIVATE int dumbterm PARAMS((char *terminal));
  53. BOOLEAN LYCursesON = FALSE;
  54.  
  55. #if USE_COLOR_TABLE || defined(USE_SLANG)
  56. PRIVATE int Current_Attr;
  57. #endif
  58.  
  59. #ifdef USE_SLANG
  60. PUBLIC unsigned int Lynx_Color_Flags = 0;
  61. PUBLIC BOOLEAN FullRefresh = FALSE;
  62. PUBLIC int curscr = 0;
  63. #ifdef SLANG_MBCS_HACK
  64. /*
  65.  *  Will be set by size_change. - KW
  66.  */
  67. PUBLIC int PHYSICAL_SLtt_Screen_Cols = 10;
  68. #endif /* SLANG_MBCS_HACK */
  69.  
  70. PUBLIC void LY_SLrefresh NOARGS
  71. {
  72.     if (FullRefresh) {
  73.     SLsmg_suspend_smg();
  74.     SLsmg_resume_smg();
  75.     FullRefresh = FALSE;
  76.     } else {
  77.     SLsmg_refresh();
  78.     }
  79.  
  80.     return;
  81. }
  82.  
  83. /* the following renamed from LY_SLclear since it is more like erase()
  84.    described in curses man pages than like clear(); but for USE_SLANG
  85.    clear() is still a macro calling this, and will do the same thing as
  86.    erase(). - kw */
  87. PUBLIC void LY_SLerase NOARGS
  88. {
  89.     SLsmg_gotorc (0, 0);
  90.     SLsmg_erase_eos ();
  91. }
  92.  
  93. #ifdef VMS
  94. PUBLIC void VTHome NOARGS
  95. {
  96.     printf("\033[;H");
  97.  
  98.     return;
  99. }
  100. #endif /* VMS */
  101.  
  102. PUBLIC void LYaddAttr ARGS1(
  103.     int,        a)
  104. {
  105.     Current_Attr |= a;
  106.     SLsmg_set_color(Current_Attr);
  107. }
  108.  
  109. PUBLIC void LYsubAttr ARGS1(
  110.     int,        a)
  111. {
  112.     Current_Attr &= ~a;
  113.     SLsmg_set_color(Current_Attr);
  114. }
  115.  
  116. PUBLIC void lynx_setup_colors NOARGS
  117. {
  118.     SLtt_set_color(0, NULL, DEFAULT_FG, DEFAULT_BG);
  119.     SLtt_set_color(1, NULL, "blue",    DEFAULT_BG); /* bold */
  120.     SLtt_set_color(2, NULL, "yellow",    "blue");     /* reverse */
  121.     SLtt_set_color(4, NULL, "magenta",    DEFAULT_BG); /* underline */
  122.     /*
  123.      *    The other objects are '|'ed together to get rest.
  124.      */
  125.     SLtt_set_color(3, NULL, "green",    DEFAULT_BG); /* bold-reverse */
  126.     SLtt_set_color(5, NULL, "blue",    DEFAULT_BG); /* bold-underline */
  127.     SLtt_set_color(6, NULL, "red",    DEFAULT_BG); /* reverse-underline */
  128.     SLtt_set_color(7, NULL, "magenta",    "cyan");     /* reverse-underline-bold */
  129.  
  130.     /*
  131.      *    Now set monochrome attributes.
  132.      */
  133.     SLtt_set_mono(1, NULL, SLTT_BOLD_MASK);
  134.     SLtt_set_mono(2, NULL, SLTT_REV_MASK);
  135.     SLtt_set_mono(3, NULL, SLTT_REV_MASK | SLTT_BOLD_MASK);
  136.     SLtt_set_mono(4, NULL, SLTT_ULINE_MASK);
  137.     SLtt_set_mono(5, NULL, SLTT_ULINE_MASK | SLTT_BOLD_MASK);
  138.     SLtt_set_mono(6, NULL, SLTT_ULINE_MASK | SLTT_REV_MASK);
  139.     SLtt_set_mono(7, NULL, SLTT_ULINE_MASK | SLTT_BOLD_MASK | SLTT_REV_MASK);
  140. }
  141.  
  142. PRIVATE void sl_suspend ARGS1(
  143.     int,        sig)
  144. {
  145. #ifdef SIGSTOP
  146. #ifndef VMS
  147.     int r, c;
  148.  
  149.     lynx_enable_mouse (0);
  150.     if (sig == SIGTSTP)
  151.     SLsmg_suspend_smg();
  152.     SLang_reset_tty();
  153.     kill(getpid(),SIGSTOP);
  154. #if SLANG_VERSION > 9929
  155.     SLang_init_tty(-1, 0, 1);
  156. #else
  157.     SLang_init_tty(3, 0, 1);
  158. #endif /* SLANG_VERSION > 9929 */
  159.     signal(SIGTSTP, sl_suspend);
  160. #if !defined(_WINDOWS) && !defined(__DJGPP__)
  161.     SLtty_set_suspend_state(1);
  162. #endif
  163.     if (sig == SIGTSTP)
  164.     SLsmg_resume_smg();
  165.     /*
  166.      *    Get new window size in case it changed.
  167.      */
  168.     r = SLtt_Screen_Rows;
  169.     c = SLtt_Screen_Cols;
  170.     size_change(0);
  171.     if ((r != SLtt_Screen_Rows) || (c != SLtt_Screen_Cols)) {
  172.     recent_sizechange = TRUE;
  173.     }
  174.     lynx_enable_mouse (1);
  175. #endif /* !VMS */
  176. #endif /* SIGSTOP */
  177.    return;
  178. }
  179.  
  180. #else  /* Not slang: */
  181.  
  182. #ifdef VMS
  183. /*
  184. **  This function boxes windows with graphic characters for
  185. **  VMS curses.  Pass it the window, it's height, and it's
  186. **  width. - FM
  187. */
  188. PUBLIC void VMSbox ARGS3(
  189.     WINDOW *,    win,
  190.     int,        height,
  191.     int,        width)
  192. {
  193.     int i;
  194.  
  195.     wmove(win, 0, 0);
  196.     waddstr(win, "\033)0\016l");
  197.     for (i = 1; i < width; i++)
  198.        waddch(win, 'q');
  199.     waddch(win, 'k');
  200.     for (i = 1; i < height-1; i++) {
  201.     wmove(win, i, 0);
  202.     waddch(win, 'x');
  203.     wmove(win, i, width-1);
  204.     waddch(win, 'x');
  205.     }
  206.     wmove(win, i, 0);
  207.     waddch(win, 'm');
  208.     for (i = 1; i < width; i++)
  209.        waddch(win, 'q');
  210.     waddstr(win, "j\017");
  211. }
  212. #else
  213. /*
  214. **  This function boxes windows for non-VMS (n)curses.
  215. **  Pass it the window. - FM
  216. */
  217. PUBLIC void LYbox ARGS2(
  218.     WINDOW *,    win,
  219.     BOOLEAN,    formfield)
  220. {
  221.     /*
  222.      *    If the terminal is in UTF-8 mode, it probably cannot understand
  223.      *    box drawing characters as (n)curses handles them.  (This may also
  224.      *    be true for other display character sets, but isn't currently
  225.      *    checked.)  In that case, substitute ASCII characters for BOXVERT
  226.      *    and BOXHORI if they were defined to 0 for automatic use of box
  227.      *    drawing characters.  They'll stay as they are otherwise. - KW & FM
  228.      */
  229.     int boxvert, boxhori;
  230.  
  231.     UCSetBoxChars(current_char_set, &boxvert, &boxhori, BOXVERT, BOXHORI);
  232. #ifdef CSS
  233.     if (formfield)
  234.     wcurses_css(win, "frame", ABS_ON);
  235. #endif
  236.     /*
  237.      *    If we don't have explicitly specified characters for either
  238.      *    vertical or horizontal lines, the characters that box() would
  239.      *    use for the corners probably also won't work well.  So we
  240.      *    specify our own ASCII characters for the corners and call
  241.      *    wborder() instead of box(). - kw
  242.      */
  243. #ifdef HAVE_WBORDER
  244.     if (!boxvert || !boxhori)
  245.     box(win, boxvert, boxhori);
  246.     else if (boxvert == '*' || boxhori == '*')
  247.     wborder(win, boxvert, boxvert, boxhori, boxhori, '*', '*', '*', '*');
  248.     else
  249.     wborder(win, boxvert, boxvert, boxhori, boxhori, '/', '\\', '\\', '/');
  250. #else
  251.     box(win, boxvert, boxhori);
  252. #endif
  253. #ifdef CSS
  254.     if (formfield)
  255.     wcurses_css(win, "frame", ABS_OFF);
  256. #endif
  257. }
  258. #endif /* VMS */
  259. #endif /* USE_SLANG */
  260.  
  261. #if defined(USE_COLOR_STYLE)
  262. PRIVATE int last_styles[128];
  263. PRIVATE int last_ptr=0;
  264. #endif
  265.  
  266. #if defined(USE_COLOR_STYLE)
  267. /* Ok, explanation of the USE_COLOR_STYLE styles.  The basic styles (ie non
  268.  * HTML) are set the same as the SLANG version for ease of programming.  The
  269.  * other styles are simply the HTML enum from HTMLDTD.h + 16.
  270.  */
  271. PUBLIC HTCharStyle displayStyles[DSTYLE_ELEMENTS];
  272.  
  273. /*
  274.  * set a style's attributes - RP
  275.  */
  276. PUBLIC void setStyle ARGS4(int,style,int,color,int,cattr,int,mono)
  277. {
  278.     displayStyles[style].color=color;
  279.     displayStyles[style].cattr=cattr;
  280.     displayStyles[style].mono=mono;
  281. }
  282.  
  283. PUBLIC void setHashStyle ARGS5(int,style,int,color,int,cattr,int,mono,char*,element)
  284. {
  285.     bucket* ds=&hashStyles[style];
  286.     CTRACE(tfp, "CSS(SET): <%s> hash=%d, ca=%d, ma=%d\n", element, style, color, mono);
  287.     ds->color=color;
  288.     ds->cattr=cattr;
  289.     ds->mono=mono;
  290.     ds->code=style;
  291.     FREE(ds->name);
  292.     ds->name=malloc(sizeof(char)*(strlen(element)+2));
  293.     strcpy(ds->name, element);
  294. }
  295.  
  296. /*
  297.  * set the curses attributes to be color or mono - RP
  298.  */
  299. PRIVATE int LYAttrset ARGS3(WINDOW*,win,int,color,int,mono)
  300. {
  301.     CTRACE(tfp, "CSS:LYAttrset (%#x, %#x)\n", color, mono);
  302.     if (lynx_has_color && LYShowColor >= SHOW_COLOR_ON && color > -1)
  303.     {
  304.         wattrset(win,color);
  305.         return color;
  306.     }
  307.     if (mono > -1)
  308.     {
  309.         wattrset(win,mono);
  310.         return mono;
  311.     }
  312.     wattrset(win,A_NORMAL);
  313.     return A_NORMAL;
  314. }
  315.  
  316. PUBLIC void curses_w_style ARGS4(WINDOW*,win,int,style,int,dir,int,previous)
  317. {
  318.     int YP,XP;
  319.     bucket* ds=&hashStyles[style];
  320.  
  321.     if (!ds->name)
  322.     {
  323.         CTRACE(tfp, "CSS.CS:Style %d not configured\n",style);
  324.         return;
  325.     }
  326.     CTRACE(tfp, "CSS.CS:<%s%s> (%d)\n",(dir?"":"/"),ds->name,ds->code);
  327.  
  328.     getyx (win, YP, XP);
  329.  
  330.     if (style == s_normal && dir)
  331.     {
  332.         wattrset(win,A_NORMAL);
  333.         if (win==stdscr) cached_styles[YP][XP]=s_normal;
  334.         return;
  335.     }
  336.  
  337.     switch (dir)
  338.     {
  339.         /* ABS_OFF is the same as STACK_OFF for the moment */
  340.     case STACK_OFF:
  341.         if (last_ptr)
  342.             LYAttrset(win,last_styles[--last_ptr],-1);
  343.         else
  344.             LYAttrset(win,A_NORMAL,-1);
  345.         return;
  346.  
  347.     case STACK_ON: /* remember the current attributes */
  348.         if (last_ptr > 127) {
  349.             CTRACE(tfp,"........... %s (0x%x) %s\r\n",
  350.                 "attribute cache FULL, dropping last",
  351.                 last_styles[last_ptr],
  352.                 "in LynxChangStyle(curses_w_style)");
  353.             last_ptr--;
  354.         }
  355.         last_styles[last_ptr++] = getattrs(stdscr);
  356.         /* don't cache style changes for active links */
  357.         if (style != s_alink)
  358.         {
  359.             CTRACE(tfp, "CACHED: <%s> @(%d,%d)\n", ds->name, YP, XP);
  360.             if (win==stdscr) cached_styles[YP][XP]=style;
  361.             LYAttrset(win, ds->color, ds->mono);
  362.         }
  363.         else
  364.         {
  365.             LYAttrset(win, ds->color, ds->mono);
  366.         }
  367.         return;
  368.  
  369.     case ABS_ON: /* change without remembering the previous style */
  370.         /* don't cache style changes for active links */
  371.         if (style != s_alink)
  372.         {
  373.             CTRACE(tfp, "CACHED: <%s> @(%d,%d)\n", ds->name, YP, XP);
  374.             if (win==stdscr) cached_styles[YP][XP]=style;
  375.             LYAttrset(win, ds->color, ds->mono);
  376.         }
  377.         else
  378.         {
  379.             LYAttrset(win, ds->color, ds->mono);
  380.         }
  381.         return;
  382.     }
  383. }
  384.  
  385. /*
  386.  * wrapper function to set on-screen styles - RP
  387.  */
  388. PUBLIC void wcurses_css ARGS3(WINDOW *,win,char*,name,int,dir)
  389. {
  390.     int try_again=1;
  391.     while (try_again)
  392.     {
  393.         int tmpHash=hash_code(name);
  394.         CTRACE(tfp, "CSSTRIM:trying to set [%s] style - ", name);
  395.         if (tmpHash==NOSTYLE) {
  396.             char *class=strrchr(name, '.');
  397.             CTRACE(tfp, "undefined, trimming at %p\n", class);
  398.             if (class)    *class='\0';
  399.             else        try_again=0;
  400.         } else {
  401.             CTRACE(tfp, "ok (%d)\n", hash_code(name));
  402.             curses_w_style(win, hash_code(name), dir, 0);
  403.             try_again=0;
  404.         }
  405.     }
  406. }
  407.  
  408. PUBLIC void curses_css ARGS2(char *,name,int,dir)
  409. {
  410.     wcurses_css(stdscr, name, dir);
  411. }
  412.  
  413. PUBLIC void curses_style ARGS3(int,style,int,dir,int,previous)
  414. {
  415.     curses_w_style(stdscr, style, dir, previous);
  416. }
  417.  
  418. #ifdef NOT_USED
  419. void attribute ARGS2(int,style,int,dir)
  420. {
  421.     curses_style(style, dir, 0);
  422. }
  423. #endif
  424. #endif /* USE_COLOR_STYLE */
  425.  
  426. #if USE_COLOR_TABLE && defined(COLOR_CURSES)
  427. /*
  428.  * This block of code is designed to produce the same color effects using SVr4
  429.  * curses as the slang library's implementation in this module.  That maps the
  430.  * SGR codes into a 0-7 index into the color table, with special treatment for
  431.  * backgrounds.  There's a bit of convoluted (but necessary) code handling the
  432.  * special case of initialization before 'initscr()' is called.
  433.  * 1997/1/19 - T.E.Dickey <dickey@clark.net>
  434.  */
  435. PRIVATE int lynx_called_initscr;
  436.  
  437. PRIVATE struct {
  438.     int fg, bg;
  439.     chtype attr;
  440. } lynx_color_cfg[] = {
  441.     /*0*/ { DEFAULT_FG,    DEFAULT_BG,    A_NORMAL}, /* A_NORMAL */
  442.     /*1*/ { COLOR_BLUE,    DEFAULT_BG,    A_NORMAL}, /* A_BOLD */
  443.     /*2*/ { COLOR_YELLOW,  COLOR_BLUE,    A_BOLD},   /* A_REVERSE */
  444.     /*3*/ { COLOR_GREEN,   DEFAULT_BG,    A_NORMAL}, /* A_REVERSE | A_BOLD */
  445.     /*4*/ { COLOR_MAGENTA, DEFAULT_BG,    A_NORMAL}, /* A_UNDERLINE */
  446.     /*5*/ { COLOR_BLUE,    DEFAULT_BG,    A_NORMAL}, /* A_UNDERLINE | A_BOLD */
  447.     /*6*/ { COLOR_RED,       DEFAULT_BG,    A_NORMAL}, /* A_UNDERLINE | A_REVERSE */
  448.     /*7*/ { COLOR_MAGENTA, COLOR_CYAN,    A_NORMAL}  /* A_UNDERLINE | A_BOLD | A_REVERSE */
  449. };
  450.  
  451. /*
  452.  * Hold the codes for color-pairs here until 'initscr()' is called.
  453.  */
  454. PRIVATE struct {
  455.     int fg;
  456.     int bg;
  457. } lynx_color_pairs[25];
  458.  
  459. /*
  460.  * Map the SGR attributes (0-7) into ANSI colors, modified with the actual BOLD
  461.  * attribute we'll get 16 colors.
  462.  */
  463. PRIVATE void LYsetWAttr ARGS1(WINDOW *, win)
  464. {
  465.     if (lynx_has_color && LYShowColor >= SHOW_COLOR_ON) {
  466.     int code = 0;
  467.     int attr = A_NORMAL;
  468.     int offs = 1;
  469.  
  470. #ifdef UNIX
  471.     static int NoColorVideo = -1;
  472.  
  473.     if (NoColorVideo < 0) {
  474.         NoColorVideo = tigetnum("ncv");
  475.     }
  476.     if (NoColorVideo < 0)
  477.         NoColorVideo = 0;
  478. #else /* PDCurses */
  479.     static int NoColorVideo = 0;
  480. #endif /* UNIX */
  481.  
  482.     if (Current_Attr & A_BOLD)
  483.         code |= 1;
  484.     if (Current_Attr & A_REVERSE)
  485.         code |= 2;
  486.     if (Current_Attr & A_UNDERLINE)
  487.         code |= 4;
  488.     attr = lynx_color_cfg[code].attr;
  489.  
  490.     /*
  491.      * no_color_video isn't implemented (97/4/14) in ncurses 4.1, but may
  492.      * be in SVr4 (which would make this redundant for the latter).
  493.      */
  494.     if ((Current_Attr & A_BOLD) && !(NoColorVideo & 33)) {
  495.         attr |= A_BOLD;
  496.     }
  497.  
  498.     if ((Current_Attr == A_UNDERLINE) && !(NoColorVideo & 2)) {
  499.         attr |= A_UNDERLINE;
  500.     }
  501.  
  502.     if (code+offs < COLOR_PAIRS) {
  503.         attr |= COLOR_PAIR(code+offs);
  504.     }
  505.  
  506.     wattrset(win, attr);
  507.     } else {
  508.     wattrset(win, Current_Attr);
  509.     }
  510. }
  511.  
  512. PRIVATE void lynx_map_color ARGS1(int, n)
  513. {
  514.     int m;
  515.  
  516.     lynx_color_pairs[n+1].fg = lynx_color_cfg[n].fg;
  517.     lynx_color_pairs[n+1].bg = lynx_color_cfg[n].bg;
  518.  
  519.     lynx_color_pairs[n+9].fg = lynx_color_cfg[n].fg;
  520.     lynx_color_pairs[n+9].bg = lynx_color_cfg[0].bg;
  521.  
  522.     lynx_color_pairs[n+17].fg = lynx_color_cfg[n].bg;
  523.     lynx_color_pairs[n+17].bg = lynx_color_cfg[n].bg;
  524.  
  525.     if (lynx_called_initscr) {
  526.     for (m = 0; m <= 16; m += 8) {
  527.         int pair = n + m + 1;
  528.         if (pair < COLOR_PAIRS)
  529.         init_pair(pair,
  530.             lynx_color_pairs[pair].fg,
  531.             lynx_color_pairs[pair].bg);
  532.     }
  533.     if (n == 0 && LYShowColor >= SHOW_COLOR_ON)
  534.         bkgd(COLOR_BKGD | ' ');
  535.     }
  536. }
  537.  
  538. PUBLIC int lynx_chg_color ARGS3(
  539.     int, color,
  540.     int, fg,
  541.     int, bg
  542.     )
  543. {
  544.     if (color >= 0 && color < 8) {
  545.     lynx_color_cfg[color].fg = (fg > 7) ? (fg & 7) : fg;
  546.     lynx_color_cfg[color].bg = (bg > 7) ? (bg & 7) : bg;
  547.     lynx_color_cfg[color].attr = ((fg > 7) && (fg & 8)) ? A_BOLD : A_NORMAL;
  548.     lynx_map_color(color);
  549.     } else {
  550.     return -1;
  551.     }
  552.     return 0;
  553. }
  554.  
  555. PUBLIC void lynx_set_color ARGS1(int, a)
  556. {
  557.     if (lynx_has_color && LYShowColor >= SHOW_COLOR_ON) {
  558.     attrset(lynx_color_cfg[a].attr
  559.         | (((a+1) < COLOR_PAIRS)
  560.             ? COLOR_PAIR(a+1)
  561.             : A_NORMAL));
  562.     }
  563. }
  564.  
  565. PUBLIC void lynx_standout ARGS1(int, flag)
  566. {
  567.     if (flag)
  568.     LYaddAttr(A_REVERSE);
  569.     else
  570.     LYsubAttr(A_REVERSE);
  571. }
  572.  
  573. PRIVATE void lynx_init_colors NOARGS
  574. {
  575.     if (lynx_has_color) {
  576.     size_t n, m;
  577.  
  578.     lynx_color_cfg[0].fg = default_fg;
  579.     lynx_color_cfg[0].bg = default_bg;
  580.  
  581.     for (n = 0; n < sizeof(lynx_color_cfg)/sizeof(lynx_color_cfg[0]); n++) {
  582.         for (m = 0; m <= 16; m += 8) {
  583.         int pair = n + m + 1;
  584.         if (pair < COLOR_PAIRS)
  585.             init_pair(pair,
  586.             lynx_color_pairs[pair].fg,
  587.             lynx_color_pairs[pair].bg);
  588.         }
  589.         if (n == 0 && LYShowColor >= SHOW_COLOR_ON)
  590.         bkgd(COLOR_BKGD | ' ');
  591.     }
  592.     } else if (LYShowColor != SHOW_COLOR_NEVER) {
  593.     LYShowColor = SHOW_COLOR_OFF;
  594.     }
  595. }
  596.  
  597. PUBLIC void lynx_setup_colors NOARGS
  598. {
  599.     int n;
  600.     for (n = 0; n < 8; n++)
  601.     lynx_map_color(n);
  602. }
  603. #endif /* USE_COLOR_TABLE */
  604.  
  605. #if defined (DJGPP) && !defined (USE_SLANG)
  606. /*
  607.  * Sorry about making a completely new function,
  608.  * but the real one is messy! WB
  609.  */
  610. PUBLIC void start_curses NOARGS
  611. {
  612.     static BOOLEAN first_time = TRUE;
  613.  
  614.     if(first_time)
  615.     {
  616.     initscr();        /* start curses */
  617.     first_time = FALSE;
  618.     cbreak();
  619.     keypad(stdscr, TRUE);
  620.     fflush(stdin);
  621.     fflush(stdout);
  622.     if (has_colors()) {
  623.         lynx_has_color = TRUE;
  624.         start_color();
  625.     }
  626.     lynx_init_colors();
  627.     lynx_called_initscr = TRUE;
  628.  
  629.     /* Inform pdcurses that we're interested in knowing when mouse buttons
  630.      * are clicked.  Maybe someday pdcurses will support it.
  631.      */
  632.     if (LYUseMouse)
  633.         lynx_enable_mouse (1);
  634.  
  635.     } else
  636.     sock_init();
  637.  
  638.     LYCursesON = TRUE;
  639.     clear();
  640.     noecho();
  641. }
  642. #else
  643. PUBLIC void start_curses NOARGS
  644. {
  645. #ifdef USE_SLANG
  646.     static int slinit;
  647.  
  648.     if (LYCursesON)
  649.     return;
  650.  
  651.     if (slinit == 0) {
  652.     SLtt_get_terminfo();
  653. #ifdef __DJGPP__
  654.     SLkp_init ();
  655. #endif /* __DJGPP__ */
  656.  
  657. #ifdef UNIX
  658. #if SLANG_VERSION >= 9935
  659.     SLang_TT_Read_FD = fileno(stdin);
  660. #endif /* SLANG_VERSION >= 9935 */
  661. #endif /* UNIX */
  662.  
  663.     /*
  664.      *  Check whether a saved show_color:off override is in effect. - kw
  665.      */
  666.     if (LYrcShowColor == SHOW_COLOR_NEVER) {
  667.         SLtt_Use_Ansi_Colors = 0;
  668.     }
  669.     /*
  670.      *  Check whether we're forcing color on. - FM
  671.      */
  672.     if ((LYShowColor > 1) && (Lynx_Color_Flags & SL_LYNX_USE_COLOR))
  673.         SLtt_Use_Ansi_Colors = 1;
  674.     /*
  675.      *  Check whether a -nocolor override is in effect. - kw
  676.      */
  677.     if (Lynx_Color_Flags & SL_LYNX_OVERRIDE_COLOR)
  678.         SLtt_Use_Ansi_Colors = 0;
  679.     /*
  680.      *  Make sure our flags are in register. - FM
  681.      */
  682.     if (SLtt_Use_Ansi_Colors == 1) {
  683.         if (LYShowColor != SHOW_COLOR_ALWAYS) {
  684.         LYShowColor = SHOW_COLOR_ON;
  685.         }
  686.     } else {
  687.         if (LYShowColor != SHOW_COLOR_NEVER) {
  688.         LYShowColor = SHOW_COLOR_OFF;
  689.         }
  690.     }
  691.     size_change(0);
  692.  
  693. #if defined(VMS) || defined(UNIX)
  694.     SLtt_add_color_attribute(4, SLTT_ULINE_MASK);
  695.     SLtt_add_color_attribute(5, SLTT_ULINE_MASK);
  696.     /*
  697.      *  If set, the blink escape sequence will turn on high
  698.      *  intensity background (rxvt and maybe Linux console).
  699.      */
  700.     if (LYShowColor && (Lynx_Color_Flags & SL_LYNX_USE_BLINK)) {
  701.         SLtt_Blink_Mode = 1;
  702.     } else {
  703.         SLtt_Blink_Mode = 0;
  704.     }
  705. #endif /* VMS || UNIX */
  706.     }
  707. #ifdef __DJGPP__
  708.     else sock_init();
  709. #endif /* __DJGPP__ */
  710.  
  711.     slinit = 1;
  712.     Current_Attr = 0;
  713. #ifndef VMS
  714. #if SLANG_VERSION > 9929
  715.     SLang_init_tty(-1, 0, 1);
  716. #else
  717.     SLang_init_tty(3, 0, 1);
  718. #endif /* SLANG_VERSION > 9929 */
  719. #endif /* !VMS */
  720.     SLsmg_init_smg();
  721.     SLsmg_Display_Eight_Bit = LYlowest_eightbit[current_char_set];
  722.     if (SLsmg_Display_Eight_Bit > 191)
  723.     SLsmg_Display_Eight_Bit = 191; /* may print ctrl chars otherwise - kw */
  724.     scrollok(0,0);
  725.     SLsmg_Backspace_Moves = 1;
  726. #ifndef VMS
  727. #if defined(_WINDOWS) || defined(__DJGPP__)
  728.     /* SLgetkey_map_to_ansi (1); -- FIXME: is this needed? */
  729. #else
  730.     SLtty_set_suspend_state(1);
  731. #endif /* !_WINDOWS */
  732. #ifdef SIGTSTP
  733.     if (!no_suspend)
  734.     signal(SIGTSTP, sl_suspend);
  735. #endif /* SIGTSTP */
  736.     signal(SIGINT, cleanup_sig);
  737. #endif /* !VMS */
  738.  
  739.    lynx_enable_mouse (1);
  740.  
  741. #else /* Using curses: */
  742.  
  743. #ifdef VMS
  744.     /*
  745.      *    If we are VMS then do initscr() everytime start_curses()
  746.      *    is called!
  747.      */
  748.     initscr();    /* start curses */
  749. #else /* Unix: */
  750.     static BOOLEAN first_time = TRUE;
  751.  
  752.     if (first_time) {
  753.     /*
  754.      *  If we're not VMS then only do initscr() one time,
  755.      *  and one time only!
  756.      */
  757.     if (initscr() == NULL) {  /* start curses */
  758.         fprintf(tfp,
  759.         "Terminal initialisation failed - unknown terminal type?\n");
  760. #ifndef NOSIGHUP
  761.         (void) signal(SIGHUP, SIG_DFL);
  762. #endif /* !NOSIGHUP */
  763.         (void) signal(SIGTERM, SIG_DFL);
  764.         (void) signal(SIGINT, SIG_DFL);
  765. #ifdef SIGTSTP
  766.         if (no_suspend)
  767.         (void) signal(SIGTSTP,SIG_DFL);
  768. #endif /* SIGTSTP */
  769.         exit (-1);
  770.     }
  771. #if defined(SIGWINCH) && defined(NCURSES_VERSION)
  772.     size_change(0);
  773. #endif /* SIGWINCH */
  774.  
  775.     /*
  776.      * This is a workaround for a bug in SVr4 curses, observed on Solaris
  777.      * 2.4:  if your terminal's alternate-character set contains codes in
  778.      * the range 128-255, they'll be sign-extended in the acs_map[] table,
  779.      * which in turn causes their values to be emitted as 255 (0xff).
  780.      * "Fix" this by forcing the table to 8-bit codes (it has to be
  781.      * anyway).
  782.      */
  783. #if defined(ALT_CHAR_SET) && !defined(NCURSES_VERSION)
  784.     {
  785.         int n;
  786.         for (n = 0; n < 128; n++)
  787.         if (ALT_CHAR_SET[n] & 0x80) {
  788.             ALT_CHAR_SET[n] &= 0xff;
  789.             ALT_CHAR_SET[n] |= A_ALTCHARSET;
  790.         }
  791.     }
  792. #endif
  793.  
  794. #if defined(USE_COLOR_STYLE) || defined(USE_COLOR_TABLE)
  795.     if (has_colors()) {
  796.         lynx_has_color = TRUE;
  797.         start_color();
  798. #if HAVE_USE_DEFAULT_COLORS
  799.         if (use_default_colors() == OK) {
  800.         default_fg = DEFAULT_COLOR;
  801.         default_bg = DEFAULT_COLOR;
  802.         }
  803. #endif /* HAVE_USE_DEFAULT_COLORS */
  804.     }
  805. #endif /* USE_COLOR_STYLE || USE_COLOR_TABLE */
  806.  
  807. #ifdef USE_COLOR_STYLE
  808.     parse_userstyles();
  809. #endif
  810.     first_time = FALSE;
  811. #if USE_COLOR_TABLE
  812.     lynx_init_colors();
  813.     lynx_called_initscr = TRUE;
  814. #endif /* USE_COLOR_TABLE */
  815.     }
  816. #endif /* VMS */
  817.  
  818.     /* nonl();     */ /* seems to slow things down */
  819.  
  820. #ifdef VMS
  821.     crmode();
  822.     raw();
  823. #else
  824. #if HAVE_CBREAK
  825.     cbreak();
  826. #else
  827.     crmode();
  828. #endif /* HAVE_CBREAK */
  829.     signal(SIGINT, cleanup_sig);
  830. #endif /* VMS */
  831.  
  832.     noecho();
  833.  
  834. #if HAVE_KEYPAD
  835.     keypad(stdscr,TRUE);
  836. #endif /* HAVE_KEYPAD */
  837.  
  838.    lynx_enable_mouse (1);
  839.  
  840.     fflush(stdin);
  841.     fflush(stdout);
  842.     fflush(stderr);
  843. #endif /* USE_SLANG */
  844.  
  845. #ifdef _WINDOWS
  846.     clear();
  847. #endif
  848.  
  849.     LYCursesON = TRUE;
  850. }
  851. #endif /* defined (DJGPP) && !defined (USE_SLANG) */
  852.  
  853. PUBLIC void lynx_enable_mouse ARGS1(int,state)
  854. {
  855.     if (LYUseMouse == 0)
  856.     return;
  857.  
  858. #ifdef USE_SLANG_MOUSE
  859.     SLtt_set_mouse_mode (state, 0);
  860.     SLtt_flush_output ();
  861. #else
  862. #ifdef NCURSES_MOUSE_VERSION
  863.     /* Inform ncurses that we're interested in knowing when mouse
  864.      * button 1 is clicked */
  865. #ifndef _WINDOWS
  866.     if (state)
  867.     mousemask(BUTTON1_CLICKED | BUTTON3_CLICKED, NULL);
  868.     else
  869.     mousemask(0, NULL);
  870. #else
  871.     if (state)
  872.     mouse_set(BUTTON1_CLICKED && BUTTON2_CLICKED && BUTTON3_CLICKED);
  873. #endif /* !_WINDOWS */
  874. #endif /* NCURSES_MOUSE_VERSION */
  875.  
  876. #if defined(DJGPP) && !defined(USE_SLANG)
  877.     if (state)
  878.     mouse_set(BUTTON1_CLICKED | BUTTON2_CLICKED | BUTTON3_CLICKED);
  879. #endif
  880. #endif                       /* NOT USE_SLANG_MOUSE */
  881. }
  882.  
  883. PUBLIC void stop_curses NOARGS
  884. {
  885.     echo();
  886. #ifdef DJGPP
  887.     sock_exit();
  888. #endif
  889. #if defined (DOSPATH) && !defined(USE_SLANG)
  890.     clrscr();
  891. #else
  892.  
  893.     /*
  894.      *    Fixed for better dumb terminal support.
  895.      *    05-28-94 Lynx 2-3-1 Garrett Arch Blythe
  896.      */
  897.     if(LYCursesON == TRUE)    {
  898.      lynx_enable_mouse (0);
  899.      endwin();    /* stop curses */
  900.     }
  901.  
  902.     fflush(stdout);
  903. #endif /* DJGPP */
  904.     fflush(stderr);
  905.  
  906.     LYCursesON = FALSE;
  907.  
  908. #if defined(SIGTSTP) && defined(USE_SLANG)
  909. #ifndef VMS
  910.     if (!no_suspend)
  911.     signal(SIGTSTP, SIG_DFL);
  912. #endif /* !VMS */
  913. #endif /* SIGTSTP && USE_SLANG */
  914.  
  915. #ifndef VMS
  916.     signal(SIGINT, SIG_DFL);
  917. #endif /* !VMS */
  918. }
  919.  
  920. #ifdef VMS
  921. /*
  922.  *  Check terminal type, start curses & setup terminal.
  923.  */
  924. PUBLIC BOOLEAN setup ARGS1(
  925.     char *,     terminal)
  926. {
  927.     int c;
  928.     int status;
  929.     char *dummy, *cp, term[81];
  930. #ifdef USE_SLANG
  931.     extern void longname();
  932. #endif /* USE_SLANG */
  933.  
  934.     /*
  935.      *    If the display was not set by a command line option then
  936.      *    see if it is available from the environment.
  937.      */
  938.     if ((cp = getenv(DISPLAY)) != NULL && *cp != '\0') {
  939.     StrAllocCopy(display, cp);
  940.     } else {
  941.     FREE(display);
  942.     }
  943.  
  944.     /*
  945.      *    Get terminal type, and convert to lower case.
  946.      */
  947.     term[0] = '\0';
  948.     longname(dummy, term);
  949.     if (term[0] == '\0' && (form_get_data || form_post_data)) {
  950.     /*
  951.      *  Some yoyo used these under conditions which require
  952.      *  -dump, so force that mode here. - FM
  953.      */
  954.     dump_output_immediately = TRUE;
  955.     LYcols = 80;
  956.     if (keypad_mode == NUMBERS_AS_ARROWS)
  957.         keypad_mode = LINKS_ARE_NUMBERED;
  958.     status = mainloop();
  959.     (void) signal (SIGHUP, SIG_DFL);
  960.     (void) signal (SIGTERM, SIG_DFL);
  961. #ifdef SIGTSTP
  962.     if (no_suspend)
  963.       (void) signal(SIGTSTP,SIG_DFL);
  964. #endif /* SIGTSTP */
  965.     exit(status);
  966.     }
  967.     LYLowerCase(term);
  968.  
  969.     printf("Terminal = %s\n", term);
  970.     sleep(InfoSecs);
  971.     if ((strlen(term) < 5) ||
  972.     strncmp(term, "vt", 2) || !isdigit(term[2])) {
  973.     printf(
  974.         "You must use a vt100, 200, etc. terminal with this program.\n");
  975.     printf("Proceed (n/y)? ");
  976.     c = getchar();
  977.     if (c != 'y' && c != 'Y') {
  978.         printf("\n");
  979.         return(FALSE);
  980.     }
  981.     strcpy(term,"vt100");
  982.     }
  983.  
  984.     ttopen();
  985.     start_curses();
  986.  
  987.     LYlines = LINES;
  988.     LYcols = COLS;
  989.     if (LYlines <= 0)
  990.     LYlines = 24;
  991.     if (LYcols <= 0)
  992.     LYcols = 80;
  993.  
  994.     return(TRUE);
  995. }
  996.  
  997. #else    /* Not VMS: */
  998.  
  999. /*
  1000.  *  Check terminal type, start curses & setup terminal.
  1001.  */
  1002. PUBLIC BOOLEAN setup ARGS1(
  1003.     char *,     terminal)
  1004. {
  1005.     static char term_putenv[120];
  1006.     char buffer[120];
  1007.     char *cp;
  1008. #if defined(HAVE_SIZECHANGE) && !defined(USE_SLANG) && defined(NOTDEFINED)
  1009. /*
  1010.  *  Hack to deal with a problem in sysV curses, that screen can't be
  1011.  *  resized to greater than the size used by initscr, which can only
  1012.  *  be called once.  So set environment variables LINES and COLUMNS
  1013.  *  to some suitably large size to force initscr to allocate enough
  1014.  *  space.  Later we get the real window size for setting LYlines
  1015.  *  and LYcols. - AJL & FM
  1016.  *
  1017.  *  Has problems, so we don't use this hack, but the code is here
  1018.  *  if someone wants to play with it some more. - FM
  1019.  */
  1020.     char *lines_putenv = NULL;
  1021.     char *cols_putenv = NULL;
  1022.  
  1023.     if (getenv("LINES") == NULL && getenv("COLUMNS") == NULL) {
  1024.     StrAllocCopy(lines_putenv, "LINES=120");
  1025.     (void) putenv(lines_putenv);
  1026.     StrAllocCopy(cols_putenv, "COLUMNS=240");
  1027.     (void) putenv(cols_putenv);
  1028.     }
  1029. #endif /* HAVE_SIZECHANGE && !USE_SLANG && NOTDEFINED */
  1030.  
  1031.    /*
  1032.     *  If the display was not set by a command line option then
  1033.     *  see if it is available from the environment .
  1034.     */
  1035.     if ((cp = getenv(DISPLAY)) != NULL && *cp != '\0') {
  1036.     StrAllocCopy(display, cp);
  1037.     } else {
  1038.     FREE(display);
  1039.     }
  1040.  
  1041.     if (terminal != NULL) {
  1042.     sprintf(term_putenv, "TERM=%s", terminal);
  1043.     (void) putenv(term_putenv);
  1044.     }
  1045.  
  1046.     /*
  1047.      *    Query the terminal type.
  1048.      */
  1049.     if (dumbterm(getenv("TERM"))) {
  1050.     char *s;
  1051.  
  1052.     printf("\n\n  Your Terminal type is unknown!\n\n");
  1053.     printf("  Enter a terminal type: [vt100] ");
  1054.     *buffer = '\0';
  1055.     fgets(buffer, sizeof(buffer), stdin);
  1056.     if ((s = strchr(buffer, '\n')) != NULL)
  1057.         *s = '\0';
  1058.  
  1059.     if (strlen(buffer) == 0)
  1060.         strcpy(buffer,"vt100");
  1061.  
  1062.     sprintf(term_putenv,"TERM=%s", buffer);
  1063.     putenv(term_putenv);
  1064.     printf("\nTERMINAL TYPE IS SET TO %s\n",getenv("TERM"));
  1065.     sleep(MESSAGESECS);
  1066.     }
  1067.  
  1068.     start_curses();
  1069.  
  1070. #if HAVE_TTYTYPE
  1071.     /*
  1072.      *    Get terminal type (strip 'dec-' from vms style types).
  1073.      */
  1074.     if (strncmp((CONST char*)ttytype, "dec-vt", 6) == 0) {
  1075.     (void) setterm(ttytype + 4);
  1076.     }
  1077. #endif /* HAVE_TTYTYPE */
  1078.  
  1079. #if defined(HAVE_SIZECHANGE) && !defined(USE_SLANG) && defined(NOTDEFINED)
  1080.     if (lines_putenv != NULL) {
  1081.     /*
  1082.      *  Use SIGWINCH handler to set the true window size. - AJL && FM
  1083.      *
  1084.      *  Has problems, so we don't use this hack, but the code is here
  1085.      *  if someone wants to play with it some more. - FM
  1086.      */
  1087.     size_change(0);
  1088.     lines_putenv[6] = '\0';
  1089.     (void) putenv(lines_putenv);
  1090.     cols_putenv[8] = '\0';
  1091.     (void) putenv(cols_putenv);
  1092.     FREE(lines_putenv);
  1093.     FREE(cols_putenv);
  1094.     } else {
  1095.     LYlines = LINES;
  1096.     LYcols = COLS;
  1097.     }
  1098. #else
  1099.     LYlines = LINES;
  1100.     LYcols = COLS;
  1101. #endif /* HAVE_SIZECHANGE && !USE_SLANG && USE_NOTDEFINED */
  1102.     if (LYlines <= 0)
  1103.     LYlines = 24;
  1104.     if (LYcols <= 0)
  1105.     LYcols = 80;
  1106.  
  1107.     return(1);
  1108. }
  1109.  
  1110. PRIVATE int dumbterm ARGS1(
  1111.     char *,     terminal)
  1112. {
  1113.     int dumb = FALSE;
  1114.  
  1115.     /*
  1116.      *    Began checking for terminal == NULL in case that TERM environment
  1117.      *    variable is not set.  Thanks to Dick Wesseling (ftu@fi.ruu.nl).
  1118.      */
  1119.     if (terminal == NULL ||
  1120.     !strcasecomp(terminal, "network") ||
  1121.     !strcasecomp(terminal, "unknown") ||
  1122.     !strcasecomp(terminal, "dialup")  ||
  1123.     !strcasecomp(terminal, "dumb")      ||
  1124.     !strcasecomp(terminal, "switch")  ||
  1125.     !strcasecomp(terminal, "ethernet")  )
  1126.     dumb = TRUE;
  1127.     return(dumb);
  1128. }
  1129.  
  1130. #ifdef FANCY_CURSES
  1131. #ifndef USE_COLOR_STYLE
  1132. #if USE_COLOR_TABLE
  1133. PUBLIC void LYaddWAttr ARGS2(
  1134.     WINDOW *,    win,
  1135.     int,        a)
  1136. {
  1137.     Current_Attr |= a;
  1138.     LYsetWAttr(win);
  1139. }
  1140.  
  1141. PUBLIC void LYaddAttr ARGS1(
  1142.     int,        a)
  1143. {
  1144.     LYaddWAttr(stdscr, a);
  1145. }
  1146.  
  1147. PUBLIC void LYsubWAttr ARGS2(
  1148.     WINDOW *,    win,
  1149.     int,        a)
  1150. {
  1151.     Current_Attr &= ~a;
  1152.     LYsetWAttr(win);
  1153. }
  1154.  
  1155. PUBLIC void LYsubAttr ARGS1(
  1156.     int,        a)
  1157. {
  1158.     LYsubWAttr(stdscr, a);
  1159. }
  1160. #endif /* USE_COLOR_TABLE */
  1161. #endif /* !USE_COLOR_STYLE */
  1162. #endif /* FANCY_CURSES */
  1163. #endif /* VMS */
  1164.  
  1165. PUBLIC void LYstartTargetEmphasis NOARGS
  1166. {
  1167. #if defined(FANCY_CURSES) || defined(USE_SLANG)
  1168.     start_bold();
  1169.     start_reverse();
  1170. #endif /* FANCY_CURSES || USE_SLANG */
  1171.     start_underline();
  1172. }
  1173.  
  1174. PUBLIC void LYstopTargetEmphasis NOARGS
  1175. {
  1176.     stop_underline();
  1177. #if defined(FANCY_CURSES) || defined(USE_SLANG)
  1178.     stop_reverse();
  1179.     stop_bold();
  1180. #endif /* FANCY_CURSES || USE_SLANG */
  1181. }
  1182.  
  1183. #ifdef VMS
  1184. /*
  1185.  *    Cut-down termio --
  1186.  *        Do character-oriented stream input for Jeff.
  1187.  *        Code ripped off from Micro-Emacs 3.7 by Daniel Lawrence.
  1188.  *
  1189.  *        Ever-so-slightly modified by Kathryn Huxtable.    29-Jan-1991.
  1190.  *        Cut down for Lou.  8 Sep 1992.
  1191.  *        Cut down farther for Lou.  19 Apr 1993.
  1192.  *            We don't set PASSALL or PASTHRU since we don't
  1193.  *            want to block CTRL/C, CTRL/Y, CTRL/S or CTRL/Q.
  1194.  *            Simply setting NOECHO and doing timed reads
  1195.  *            is sufficient.
  1196.  *        Further mods by Fote.  29-June-1993
  1197.  *            ttopen() and ttclose() are now terminal initialization
  1198.  *             and restoration procedures, called once at startup
  1199.  *             and at exit, respectively, of the LYNX image.
  1200.  *            ttclose() should be called before an exit from LYNX
  1201.  *             no matter how the exit is invoked.
  1202.  *            setup(terminal) does the ttopen().
  1203.  *            cleanup() calls cleanup_files() and ttclose().
  1204.  *            ttgetc() now handles NOECHO and NOFLITR (instead of
  1205.  *             setting the terminal itself to NOECHO in ttopen()).
  1206.  *            VMSsignal() added for handling both Ctrl-C *and* Ctrl-Y
  1207.  *             interrupts, and disabling system response to Ctrl-T.
  1208.  *        Further mods by Fote.  15-Dec-1993
  1209.  *            Added edit handler in ttopen() which will invoke
  1210.  *             VMSexit() and behave intelligently on ACCVIO's.
  1211.  *        Further mods by Fote.  29-Dec-1993
  1212.  *            Simplified ttgetc().
  1213.  *        Further mods by Fote.  16-Jan-1994
  1214.  *            Added code in ttopen() which will invoke VMSVersion()
  1215.  *             to get the version of VMS as VersionVMS for use by
  1216.  *             by new or modified interrupt or spawning routines.
  1217.  *        Further mods by Fote.  27-Jan-1994
  1218.  *            Added back a typeahead() which supports 'z' or 'Z' as
  1219.  *            an "Zap transfer" command via HTCheckForInterrupt()
  1220.  *            in LYUtils.c.
  1221.  */
  1222.  
  1223. #include <descrip.h>
  1224. #include <iodef.h>
  1225. #include <ssdef.h>
  1226. #include <stdlib.h>
  1227. #include <msgdef.h>
  1228. #include <ttdef.h>
  1229. #include <tt2def.h>
  1230. #include <libclidef.h>
  1231. #include <lib$routines.h>
  1232. #include <starlet.h>
  1233. #include <clidef.h>
  1234. #include <syidef.h>
  1235. #ifdef signal
  1236. #undef signal
  1237. #endif /* signal */
  1238. #include <signal.h>
  1239. #ifdef system
  1240. #undef system
  1241. #endif /* system */
  1242. #include <processes.h>
  1243. #include <LYVMSdef.h>
  1244.  
  1245. #define EFN    0            /* Event flag            */
  1246.  
  1247. static    unsigned char buffer[20];    /* Input buffer         */
  1248. static    int    in_pos, in_len;     /* For escape sequences     */
  1249. static    int    oldmode[3];        /* Old TTY mode bits        */
  1250. static    int    newmode[3];        /* New TTY mode bits        */
  1251. static    short    iochan;         /* TTY I/O channel        */
  1252. static    $DESCRIPTOR(term_nam_dsc,"TT"); /* Descriptor for iochan    */
  1253. static    unsigned long mask = LIB$M_CLI_CTRLY|LIB$M_CLI_CTRLT; /* ^Y and ^T */
  1254. static    unsigned long old_msk;        /* Saved control mask        */
  1255. static    short    trap_flag = FALSE;    /* TRUE if AST is set        */
  1256. BOOLEAN DidCleanup = FALSE;        /* Exit handler flag        */
  1257. static char VersionVMS[20];        /* Version of VMS        */
  1258.  
  1259. PUBLIC int VMSVersion ARGS2(
  1260.     char *,     VerString,
  1261.     int,        VerLen)
  1262. {
  1263.      unsigned long status, itm_cod = SYI$_VERSION;
  1264.      int i, verlen = 0;
  1265.      struct dsc$descriptor version;
  1266.      char *m;
  1267.  
  1268.      version.dsc$a_pointer = VerString;
  1269.      version.dsc$w_length = VerLen - 1;
  1270.      version.dsc$b_dtype = DSC$K_DTYPE_B;
  1271.      version.dsc$b_class = DSC$K_CLASS_S;
  1272.  
  1273.      status = lib$getsyi(&itm_cod, 0, &version, &verlen, 0, 0);
  1274.      if (!(status&1) || verlen == 0)
  1275.       return 0;
  1276.  
  1277.      /*
  1278.       *  Cut out trailing spaces
  1279.       */
  1280.      for (m = VerString+verlen, i = verlen-1; i > 0 && VerString[i] == ' '; --i)
  1281.       *(--m) = '\0';
  1282.  
  1283.      return strlen(VerString)+1;    /* Transmit ending 0 too */
  1284. }
  1285.  
  1286. PUBLIC void VMSexit NOARGS
  1287. {
  1288.     /*
  1289.      *    If we get here and DidCleanup is not set, it was via an
  1290.      *    ACCVIO, or outofmemory forced exit, so make *sure* we
  1291.      *    attempt a cleanup and reset the terminal.
  1292.      */
  1293.     if (!DidCleanup) {
  1294.     if (LYOutOfMemory == FALSE) {
  1295.         fprintf(stderr,
  1296. "\nA Fatal error has occurred in %s Ver. %s\n", LYNX_NAME, LYNX_VERSION);
  1297.         fprintf(stderr,
  1298. "\nPlease notify your system administrator to confirm a bug, and if\n");
  1299.         fprintf(stderr,
  1300. "confirmed, to notify the lynx-dev list.  Bug reports should have concise\n");
  1301.         fprintf(stderr,
  1302. "descriptions of the command and/or URL which causes the problem, the\n");
  1303.         fprintf(stderr,
  1304. "operating system name with version number, the TCPIP implementation, the\n");
  1305.         fprintf(stderr,
  1306. "TRACEBACK if it can be captured, and any other relevant information.\n");
  1307.  
  1308.         if (LYTraceLogFP == NULL) {
  1309.         fprintf(stderr,"\nPress RETURN to clean up: ");
  1310.         (void) getchar();
  1311.         }
  1312.     } else if (LYCursesON) {
  1313.         _statusline(MEMORY_EXHAUSTED_ABORT);
  1314.         sleep(AlertSecs);
  1315.     }
  1316.     cleanup();
  1317.     }
  1318.     if (LYOutOfMemory == TRUE) {
  1319.     printf("\r\n%s\r\n\r\n", MEMORY_EXHAUSTED_ABORT);
  1320.     fflush(stdout);
  1321.     fflush(stderr);
  1322.     }
  1323. }
  1324.  
  1325. /*
  1326.  *    TTOPEN --
  1327.  *        This function is called once to set up the terminal
  1328.  *        device streams.  It translates TT until it finds
  1329.  *        the terminal, then assigns a channel to it, sets it
  1330.  *        to EDIT, and sets up the Ctrl-C and Ctrl-Y interrupt
  1331.  *        handling.
  1332.  */
  1333. PUBLIC int ttopen NOARGS
  1334. {
  1335.     extern    void cleanup_sig();
  1336.     int    iosb[2];
  1337.     int    status;
  1338.     static unsigned long condition;
  1339.     static struct _exit_block {
  1340.         unsigned long forward;
  1341.         unsigned long address;
  1342.         unsigned long zero;
  1343.         unsigned long condition;
  1344.     } exit_handler_block;
  1345.  
  1346.     status = sys$assign( &term_nam_dsc, &iochan, 0, 0 );
  1347.     if( status != SS$_NORMAL )
  1348.         exit( status );
  1349.  
  1350.     status = sys$qiow( EFN, iochan, IO$_SENSEMODE, &iosb, 0, 0,
  1351.               &oldmode, sizeof(oldmode), 0, 0, 0, 0 );
  1352.     if( status != SS$_NORMAL )
  1353.         exit( status );
  1354.  
  1355.     status = iosb[0] & 0xFFFF;
  1356.     if( status != SS$_NORMAL )
  1357.         exit( status );
  1358.  
  1359.     newmode[0] = oldmode[0];
  1360.     newmode[1] = oldmode[1];
  1361.     newmode[2] = oldmode[2] | TT2$M_EDIT;
  1362.  
  1363.     status = sys$qiow( EFN, iochan, IO$_SETMODE, &iosb, 0, 0,
  1364.               &newmode, sizeof(newmode), 0, 0, 0, 0 );
  1365.     if( status != SS$_NORMAL )
  1366.         exit( status );
  1367.  
  1368.     status = iosb[0] & 0xFFFF;
  1369.     if( status != SS$_NORMAL )
  1370.         exit( status );
  1371.  
  1372.     /*
  1373.      *  Declare the exit handler block.
  1374.      */
  1375.     exit_handler_block.forward   = 0;
  1376.     exit_handler_block.address   = (unsigned long) &VMSexit;
  1377.     exit_handler_block.zero      = 0;
  1378.     exit_handler_block.condition = (unsigned long) &condition;
  1379.     status = sys$dclexh(&exit_handler_block);
  1380.     if (status != SS$_NORMAL)
  1381.         exit( status );
  1382.  
  1383.     /*
  1384.      *  Set the AST.
  1385.      */
  1386.     lib$disable_ctrl(&mask, &old_msk);
  1387.     trap_flag = TRUE;
  1388.     status = sys$qiow ( EFN, iochan,
  1389.                 IO$_SETMODE|IO$M_CTRLCAST|IO$M_CTRLYAST,
  1390.                 &iosb, 0, 0,
  1391.                 &cleanup_sig, SIGINT, 0, 0, 0, 0 );
  1392.     if ( status != SS$_NORMAL ) {
  1393.         lib$enable_ctrl(&old_msk);
  1394.         exit ( status );
  1395.     }
  1396.  
  1397.     /*
  1398.      *  Get the version of VMS.
  1399.      */
  1400.     if (VMSVersion(VersionVMS, 20) < 3)
  1401.         /*
  1402.          *  Load zeros on error.
  1403.          */
  1404.         strcpy(VersionVMS, "V0.0-0");
  1405.  
  1406.     return(0);
  1407. }    /*  ttopen  */
  1408.  
  1409. /*
  1410.  *    TTCLOSE --
  1411.  *        This function gets called just before we go back home
  1412.  *        to the command interpreter.  It puts the terminal back
  1413.  *        in a reasonable state.
  1414.  */
  1415. PUBLIC int ttclose NOARGS
  1416. {
  1417.     int    status;
  1418.     int    iosb[1];
  1419.  
  1420.     status = sys$qiow( EFN, iochan, IO$_SETMODE, &iosb, 0, 0,
  1421.               &oldmode, sizeof(oldmode), 0, 0, 0, 0 );
  1422.  
  1423.     if( status != SS$_NORMAL || (iosb[0] & 0xFFFF) != SS$_NORMAL )
  1424.         exit( status );
  1425.  
  1426.     if (trap_flag) {
  1427.         status = sys$dassgn (iochan);
  1428.         status = lib$enable_ctrl(&old_msk);
  1429.         trap_flag = FALSE;
  1430.     }
  1431.     return(0);
  1432. }    /*  ttclose  */
  1433.  
  1434. /*
  1435.  *    TTGETC --
  1436.  *        Read a character from the terminal, with NOECHO and NOFILTR.
  1437.  */
  1438. PUBLIC int ttgetc NOARGS
  1439. {
  1440.     int status;
  1441.     unsigned short iosb[4];
  1442.  
  1443.     if (in_pos < in_len)
  1444.     return(buffer[in_pos++]);
  1445.  
  1446.     status = sys$qiow(EFN, iochan,
  1447.               IO$_READVBLK|IO$M_NOECHO|IO$M_NOFILTR,
  1448.               &iosb, 0, 0,
  1449.               &buffer, 1, 0, 0, 0, 0);
  1450.     if ((status&1) == 1)
  1451.     status = iosb[0];
  1452.     if (status == SS$_PARTESCAPE) {
  1453.     /*
  1454.      *  Escape sequence in progress.  Fake a successful read.
  1455.      */
  1456.     status = 1;
  1457.     }
  1458.     if ((status&1) != 1 && status != SS$_DATAOVERUN)
  1459.     exit(status);
  1460.     in_pos = 1;
  1461.     in_len = iosb[1] + iosb[3];
  1462.     return(buffer[0]);
  1463. }
  1464.  
  1465. /*
  1466.  *    TYPEAHEAD -- Fote Macrides 27-Jan-1994
  1467.  *        Check whether a keystroke has been entered, and return
  1468.  *         it, or -1 if none was entered.
  1469.  */
  1470. PUBLIC int typeahead NOARGS
  1471. {
  1472.     int status;
  1473.     unsigned short iosb[4];
  1474.  
  1475.     if (dump_output_immediately)
  1476.     return -1;
  1477.  
  1478.     if (in_pos < in_len)
  1479.     return(buffer[in_pos++]);
  1480.  
  1481. again:
  1482.     status = sys$qiow (EFN, iochan,
  1483.                IO$_READVBLK|IO$M_TIMED|IO$M_NOECHO|IO$M_NOFILTR,
  1484.                &iosb, 0, 0,
  1485.                &buffer, 1, 0, 0, 0, 0);
  1486.     if ((status&1) == 1)
  1487.     status = iosb[0];
  1488.     if (status == SS$_PARTESCAPE) {
  1489.     /*
  1490.      *  Escape sequence in progress, finish reading it.
  1491.      */
  1492.     goto again;
  1493.     }
  1494.  
  1495.     in_pos = 1;
  1496.     in_len = iosb[1] + iosb[3];
  1497.     if (status == SS$_TIMEOUT || status == SS$_DATAOVERUN)
  1498.     return(-1);
  1499.     return (buffer[0]);
  1500. }
  1501.  
  1502. /*
  1503.  *    VMSSIGNAL -- Fote Macrides 29-Jun-1993
  1504.  *        Sets up AST for both Ctrl-C and Ctrl-Y, with system response
  1505.  *         to Ctrl-T disabled.  If called with a sig other than SIGINT,
  1506.  *         it will use the C library's system(sig, func).
  1507.  *        The equivalent of VMSsignal(SIGINT, cleanup_sig) is done on
  1508.  *         intialization by ttopen(), so don't do it again.
  1509.  *        VMSsignal(SIGINT, SIG_DFL) is treated as a call to ttclose().
  1510.  *        Call VMSsignal(SIGINT, SIG_IGN) before system() calls to
  1511.  *         enable Ctrl-C and Ctrl-Y in the subprocess, and then call
  1512.  *         VMSsignal(SIG_INT, cleanup_sig) on return from the subprocess.
  1513.  *        For func's which set flags and do not invoke an exit from
  1514.  *         LYNX, the func should reassert itself.
  1515.  *        The VMS signal() calls do not fully emulate the Unix calls,
  1516.  *         and VMSsignal() is just a "helper", also not a full emulation.
  1517.  */
  1518.  
  1519. PUBLIC void *VMSsignal (sig,func)
  1520. int sig;
  1521. void (*func)();
  1522. {
  1523.     int status;
  1524.     short iosb[4];
  1525.     static int SIG_IGN_flag;
  1526.  
  1527.     /*
  1528.      *  Pass all signals other than SIGINT to signal().
  1529.      *  Also pass SIGINT to signal() if we're dumping.
  1530.      */
  1531.     if (sig != SIGINT || dump_output_immediately) {
  1532.         signal(sig, func);
  1533.         return;
  1534.     }
  1535.  
  1536.     /*
  1537.      *  If func is SIG_DFL, treat it as ttclose().
  1538.      */
  1539.     if (func == SIG_DFL) {
  1540.         ttclose();
  1541.         return;
  1542.     }
  1543.  
  1544.     /*
  1545.      *  Clear any previous AST.
  1546.      */
  1547.     if (trap_flag) {
  1548.         status = sys$dassgn (iochan);
  1549.         status = lib$enable_ctrl(&old_msk);
  1550.         trap_flag = FALSE;
  1551.     }
  1552.  
  1553.     /*
  1554.      *  If func is SIG_IGN, leave the TT channel closed and the
  1555.      *  system response to interrupts enabled for system() calls.
  1556.      */
  1557.     if (func == SIG_IGN)
  1558.         return;
  1559.  
  1560.     /*
  1561.      *  If we get to here, we have a LYNX func, so set the AST.
  1562.      */
  1563.     lib$disable_ctrl(&mask, &old_msk);
  1564.     trap_flag = TRUE;
  1565.     status = sys$assign (&term_nam_dsc, &iochan, 0, 0 );
  1566.     status = sys$qiow ( EFN, iochan,
  1567.                 IO$_SETMODE|IO$M_CTRLCAST|IO$M_CTRLYAST,
  1568.                 &iosb, 0, 0,
  1569.                 func, SIGINT, 0, 0, 0, 0 );
  1570.  
  1571. }    /* VMSsignal */
  1572.  
  1573. /*
  1574.  *  DCLspawn_exception, spawn_DCLprocess, DCLsystem -- F.Macrides 16-Jan-1994
  1575.  *    Exception-handler routines for regulating interrupts and enabling
  1576.  *    Control-T during spawns.  Includes TRUSTED flag for versions of VMS
  1577.  *    which require it in captive accounts.  This code should be used
  1578.  *    instead of the VAXC or DECC system(), by including LYSystem.h in
  1579.  *    modules which have system() calls.  It helps ensure that we return
  1580.  *    to Lynx instead of breaking out to DCL if a user issues interrupts
  1581.  *    or generates an ACCVIO during spawns.
  1582.  */
  1583. #ifdef __DECC
  1584. PRIVATE unsigned int DCLspawn_exception ARGS2(
  1585.     void *,     sigarr,
  1586.     void *,     mecharr)
  1587. {
  1588. #else
  1589. PRIVATE int DCLspawn_exception ARGS2(
  1590.     void *,     sigarr,
  1591.     void *,     mecharr)
  1592. {
  1593. #endif /* __DECC */
  1594.      int status;
  1595.  
  1596.      status = lib$sig_to_ret(sigarr, mecharr);
  1597.      return(SS$_UNWIND);
  1598. }
  1599.  
  1600. PRIVATE int spawn_DCLprocess ARGS1(
  1601.     char *,     command)
  1602. {
  1603.      int status;
  1604.      unsigned long Status = 0;
  1605.      /*
  1606.       *  Keep DECC from complaining.
  1607.       */
  1608.      struct dsc$descriptor_s  command_desc;
  1609.      command_desc.dsc$w_length    = strlen(command);
  1610.      command_desc.dsc$b_class    = DSC$K_CLASS_S;
  1611.      command_desc.dsc$b_dtype    = DSC$K_DTYPE_T;
  1612.      command_desc.dsc$a_pointer = command;
  1613.  
  1614.      VAXC$ESTABLISH(DCLspawn_exception);
  1615.  
  1616. #ifdef __ALPHA /** OpenVMS/AXP lacked the TRUSTED flag before v6.1 **/
  1617.      if (VersionVMS[1] > '6' ||
  1618.      (VersionVMS[1] == '6' && VersionVMS[2] == '.' &&
  1619.       VersionVMS[3] >= '1')) {
  1620. #else
  1621.      if (VersionVMS[1] >= '6') {
  1622. #endif /* __ALPHA */
  1623.      /*
  1624.       *  Include TRUSTED flag.
  1625.       */
  1626.      unsigned long trusted = CLI$M_TRUSTED;
  1627.      status = lib$spawn(&command_desc,0,0,&trusted,
  1628.                 0,0,&Status);
  1629.      /*
  1630.       *  If it was invalid, try again without the flag.
  1631.       */
  1632.      if (status == LIB$_INVARG)
  1633.         status = lib$spawn(&command_desc,0,0,0,
  1634.                    0,0,&Status );
  1635.      } else
  1636.      status = lib$spawn(&command_desc,0,0,0,
  1637.                 0,0,&Status);
  1638.      /*
  1639.       *  Return -1 on error.
  1640.       */
  1641.      if ((status&1) != 1 || (Status&1) != 1)
  1642.      return(-1);
  1643.      /*
  1644.       *  Return 0 on success.
  1645.       */
  1646.      return(0);
  1647. }
  1648.  
  1649. PUBLIC int DCLsystem ARGS1(
  1650.     char *,     command)
  1651. {
  1652.      int status;
  1653.      extern void controlc();
  1654.  
  1655.      VMSsignal(SIGINT, SIG_IGN);
  1656.      status = spawn_DCLprocess(command);
  1657.      VMSsignal(SIGINT, cleanup_sig);
  1658.      /*
  1659.       *  Returns 0 on success, -1 any error.
  1660.       */
  1661.      return(status);
  1662. }
  1663. #endif /* VMS */
  1664.  
  1665. PUBLIC void lynx_force_repaint NOARGS
  1666. {
  1667. #if defined(COLOR_CURSES)
  1668.     chtype a;
  1669. #ifndef USE_COLOR_STYLE
  1670.     if (LYShowColor >= SHOW_COLOR_ON)
  1671.     a = COLOR_BKGD;
  1672.     else
  1673. #endif
  1674.     a = A_NORMAL;
  1675.     bkgdset(a | ' ');
  1676. #ifndef USE_COLOR_STYLE
  1677.     bkgd(a | ' ');
  1678. #endif
  1679.     attrset(a);
  1680. #endif /* COLOR_CURSES */
  1681.     clearok(curscr, TRUE);
  1682. }
  1683.  
  1684. PUBLIC void lynx_start_title_color NOARGS
  1685. {
  1686. }
  1687.  
  1688. PUBLIC void lynx_stop_title_color NOARGS
  1689. {
  1690. }
  1691.  
  1692. PUBLIC void lynx_start_link_color ARGS2(
  1693.     int,    flag,
  1694.     int,    pending)
  1695. {
  1696.     if (flag) {
  1697.     /* makes some terminals work wrong because
  1698.      * they can't handle two attributes at the
  1699.      * same time
  1700.      */
  1701.     /* start_bold();  */
  1702.     start_reverse();
  1703. #if defined(USE_SLANG)
  1704.     if (SLtt_Use_Ansi_Colors)
  1705.         start_underline ();
  1706. #endif /* USE_SLANG */
  1707. #if defined(FANCY_CURSES) && defined(COLOR_CURSES)
  1708.     if (lynx_has_color && LYShowColor >= SHOW_COLOR_ON)
  1709.         start_underline ();
  1710. #endif /* USE_SLANG */
  1711.      } else {
  1712.     start_bold();
  1713.     /*
  1714.      *  Make sure when flag is OFF that "unhighlighted" links
  1715.      *  will be underlined if appropriate. - LE & FM
  1716.      */
  1717.     if (pending)
  1718.         start_underline();
  1719.      }
  1720. }
  1721.  
  1722. PUBLIC void lynx_stop_link_color ARGS2(
  1723.     int,    flag,
  1724.     int,    pending)
  1725. {
  1726. #ifdef USE_COLOR_STYLE
  1727.     LynxChangeStyle(flag == ON ? s_alink : s_a, ABS_OFF, 0);
  1728. #else
  1729.     if (flag) {
  1730.     stop_reverse();
  1731. #if defined(USE_SLANG)
  1732.     if (SLtt_Use_Ansi_Colors)
  1733.     stop_underline ();
  1734. #endif /* USE_SLANG */
  1735. #if defined(FANCY_CURSES) && defined(COLOR_CURSES)
  1736.     if (lynx_has_color && LYShowColor >= SHOW_COLOR_ON)
  1737.         stop_underline ();
  1738. #endif /* FANCY_CURSES && COLOR_CURSES */
  1739.     } else {
  1740.     stop_bold();
  1741.     /*
  1742.      *  If underlining was turned on above, turn it off. - LE & FM
  1743.      */
  1744.     if (pending)
  1745.         stop_underline();
  1746.     }
  1747. #endif
  1748. }
  1749.  
  1750.  
  1751. PUBLIC void lynx_stop_target_color NOARGS
  1752. {
  1753.    stop_underline();
  1754.    stop_reverse();
  1755.    stop_bold();
  1756. }
  1757.  
  1758. PUBLIC void lynx_start_target_color NOARGS
  1759. {
  1760.    start_bold();
  1761.    start_reverse();
  1762.    start_underline();
  1763. }
  1764.  
  1765.  
  1766. PUBLIC void lynx_start_status_color NOARGS
  1767. {
  1768. #if USE_COLOR_TABLE && defined(COLOR_CURSES)
  1769.     if (lynx_has_color && LYShowColor >= SHOW_COLOR_ON)
  1770.     lynx_set_color (2);
  1771.     else
  1772. #endif
  1773.     start_reverse ();
  1774. }
  1775.  
  1776. PUBLIC void lynx_stop_status_color NOARGS
  1777. {
  1778. #if USE_COLOR_TABLE && defined(COLOR_CURSES)
  1779.     if (lynx_has_color && LYShowColor >= SHOW_COLOR_ON)
  1780.     lynx_set_color (0);
  1781.     else
  1782. #endif
  1783.     stop_reverse ();
  1784. }
  1785.  
  1786. PUBLIC void lynx_start_h1_color NOARGS
  1787. {
  1788.    if (bold_H1 || bold_headers)
  1789.      start_bold();
  1790. }
  1791.  
  1792. PUBLIC void lynx_stop_h1_color NOARGS
  1793. {
  1794.    if (bold_H1 || bold_headers)
  1795.      stop_bold();
  1796. }
  1797.  
  1798. PUBLIC void lynx_start_prompt_color NOARGS
  1799. {
  1800.    start_reverse ();
  1801. }
  1802.  
  1803. PUBLIC void lynx_stop_prompt_color NOARGS
  1804. {
  1805.    stop_reverse ();
  1806. }
  1807.  
  1808. PUBLIC void lynx_start_radio_color NOARGS
  1809. {
  1810.    start_bold ();
  1811. }
  1812.  
  1813. PUBLIC void lynx_stop_radio_color NOARGS
  1814. {
  1815.    stop_bold ();
  1816. }
  1817.  
  1818. PUBLIC void lynx_stop_all_colors NOARGS
  1819. {
  1820.    stop_underline ();
  1821.    stop_reverse ();
  1822.    stop_bold ();
  1823. }
  1824.