home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / gnu / nethack-3.1 / win / tty / termcap.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-01-23  |  19.2 KB  |  895 lines

  1. /*    SCCS Id: @(#)termcap.c    3.1    92/11/15    */
  2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  3. /* NetHack may be freely redistributed.  See license for details. */
  4.  
  5. #include "hack.h"
  6. #include "wintty.h"
  7.  
  8. #include "termcap.h"
  9.  
  10.  
  11. #ifdef MICROPORT_286_BUG
  12. #define Tgetstr(key) (tgetstr(key,tbuf))
  13. #else
  14. #define Tgetstr(key) (tgetstr(key,&tbufptr))
  15. #endif /* MICROPORT_286_BUG **/
  16.  
  17. void FDECL(cmov, (int, int));
  18. void FDECL(nocmov, (int, int));
  19. #ifdef TEXTCOLOR
  20. # ifdef TERMLIB
  21. #  ifdef OVLB
  22. #   ifndef TOS
  23. static void FDECL(analyze_seq, (char *, int *, int *));
  24. #   endif
  25. static void NDECL(init_hilite);
  26. #  endif /* OVLB */
  27. # endif
  28. #endif
  29.  
  30. #ifdef OVLB
  31.     /* (see termcap.h) -- CM, ND, CD, HI,HE, US,UE, ul_hack */
  32. struct tc_lcl_data tc_lcl_data = { 0, 0, 0, 0,0, 0,0, FALSE };
  33. #endif /* OVLB */
  34.  
  35. STATIC_VAR char *HO, *CL, *CE, *UP, *XD, *BC, *SO, *SE, *TI, *TE;
  36. STATIC_VAR char *VS, *VE;
  37. #if 0
  38. STATIC_VAR char *MR, *ME;
  39. STATIC_VAR char *MB, *MH;
  40. STATIC_VAR char *MD;     /* may already be in use below */
  41. #endif
  42. #ifdef TERMLIB
  43. # ifdef TEXTCOLOR
  44. STATIC_VAR char *MD;
  45. # endif
  46. STATIC_VAR int SG;
  47. #ifdef OVLB
  48. STATIC_OVL char PC = '\0';
  49. #else /* OVLB */
  50. STATIC_DCL char PC;
  51. #endif /* OVLB */
  52. STATIC_VAR char tbuf[512];
  53. #endif
  54.  
  55. #ifdef TEXTCOLOR
  56. # ifdef TOS
  57. const char *hilites[MAXCOLORS];    /* terminal escapes for the various colors */
  58. # else
  59. char NEARDATA *hilites[MAXCOLORS]; /* terminal escapes for the various colors */
  60. # endif
  61. #endif
  62.  
  63. #ifdef OVLB
  64. static char *KS = NULL, *KE = NULL;    /* keypad sequences */
  65. static char nullstr[] = "";
  66. #endif /* OVLB */
  67.  
  68. #ifndef TERMLIB
  69. STATIC_VAR char tgotobuf[20];
  70. # ifdef TOS
  71. #define tgoto(fmt, x, y)    (Sprintf(tgotobuf, fmt, y+' ', x+' '), tgotobuf)
  72. # else
  73. #define tgoto(fmt, x, y)    (Sprintf(tgotobuf, fmt, y+1, x+1), tgotobuf)
  74. # endif
  75. #endif /* TERMLIB */
  76.  
  77. #ifdef OVLB
  78.  
  79. void
  80. tty_startup(wid, hgt)
  81.     int *wid, *hgt;
  82. {
  83. #ifdef TERMLIB
  84.     register const char *term;
  85.     register char *tptr;
  86.     char *tbufptr, *pc;
  87. #endif
  88.     register int i;
  89.  
  90. #ifdef TERMLIB
  91. # ifdef VMS
  92.     if (!(term = verify_termcap()))
  93. # endif
  94.     term = getenv("TERM");
  95. #endif
  96.  
  97. #ifdef TERMLIB
  98.     if(!term)
  99. #endif
  100. #if defined(TOS) && defined(__GNUC__) && defined(TERMLIB)
  101.         term = "builtin";        /* library has a default */
  102. #else
  103. #  ifdef ANSI_DEFAULT
  104. #   ifdef TOS
  105.     {
  106.         CO = 80; LI = 25;
  107.         TI = VS = VE = TE = nullstr;
  108.         HO = "\033H";
  109.         CL = "\033E";        /* the VT52 termcap */
  110.         CE = "\033K";
  111.         UP = "\033A";
  112.         CM = "\033Y%c%c";    /* used with function tgoto() */
  113.         ND = "\033C";
  114.         XD = "\033B";
  115.         BC = "\033D";
  116.         SO = "\033p";
  117.         SE = "\033q";
  118.     /* HI and HE will be updated in init_hilite if we're using color */
  119.         HI = "\033p";
  120.         HE = "\033q";
  121.     }
  122. #   else /* TOS */
  123.     {
  124. #    ifdef MICRO
  125.         get_scr_size();
  126. #     ifdef CLIPPING
  127.         if(CO < COLNO || LI < ROWNO+3)
  128.             setclipped();
  129. #     endif
  130. #    endif
  131.         HO = "\033[H";
  132.         CL = "\033[2J";        /* the ANSI termcap */
  133. /*        CD = "\033[J"; */
  134.         CE = "\033[K";
  135. #    ifndef TERMLIB
  136.         CM = "\033[%d;%dH";
  137. #    else
  138.         CM = "\033[%i%d;%dH";
  139. #    endif
  140.         UP = "\033[A";
  141.         ND = "\033[C";
  142.         XD = "\033[B";
  143. #    ifdef MICRO    /* backspaces are non-destructive */
  144.         BC = "\b";
  145. #    else
  146.         BC = "\033[D";
  147. #    endif
  148.         HI = SO = "\033[1m";
  149.         US = "\033[4m";
  150. #    if 0
  151.         MR = "\033[7m";
  152.         ME = "\033[0m";
  153. #    endif
  154.         TI = HE = SE = UE = "\033[0m";
  155.         /* strictly, SE should be 2, and UE should be 24,
  156.            but we can't trust all ANSI emulators to be
  157.            that complete.  -3. */
  158. #    ifndef MICRO
  159.         AS = "\016";
  160.         AE = "\017";
  161. #    endif
  162.         TE = VS = VE = nullstr;
  163. #    ifdef TEXTCOLOR
  164.         for (i = 0; i < MAXCOLORS / 2; i++)
  165.             if (i != BLACK) {
  166.             hilites[i|BRIGHT] = (char *) alloc(sizeof("\033[1;3%dm"));
  167.             Sprintf(hilites[i|BRIGHT], "\033[1;3%dm", i);
  168.             if (i != GRAY)
  169. #     ifdef MICRO
  170.                 if (i == BLUE) hilites[BLUE] = hilites[BLUE|BRIGHT];
  171.                 else
  172. #     endif
  173.                 {
  174.                 hilites[i] = (char *) alloc(sizeof("\033[0;3%dm"));
  175.                 Sprintf(hilites[i], "\033[0;3%dm", i);
  176.                 }
  177.             }
  178. #    endif
  179.         *wid = CO;
  180.         *hgt = LI;
  181.         return;
  182.     }
  183. #   endif /* TOS */
  184. #  else
  185.         error("Can't get TERM.");
  186. #  endif /* ANSI_DEFAULT */
  187. #endif /* __GNUC__ && TOS && TERMCAP */
  188. #ifdef TERMLIB
  189.     tptr = (char *) alloc(1024);
  190.  
  191.     tbufptr = tbuf;
  192.     if(!strncmp(term, "5620", 4))
  193.         flags.null = FALSE;    /* this should be a termcap flag */
  194.     if(tgetent(tptr, term) < 1)
  195.         error("Unknown terminal type: %s.", term);
  196.     if ((pc = Tgetstr("pc")) != 0)
  197.         PC = *pc;
  198.  
  199.     if(!(BC = Tgetstr("le")))    /* both termcap and terminfo use le */    
  200. # ifdef TERMINFO
  201.         error("Terminal must backspace.");
  202. # else
  203.         if(!(BC = Tgetstr("bc"))) {    /* termcap also uses bc/bs */
  204. #  if !defined(MINIMAL_TERM)
  205.         if(!tgetflag("bs"))
  206.             error("Terminal must backspace.");
  207. #  endif
  208.         BC = tbufptr;
  209.         tbufptr += 2;
  210.         *BC = '\b';
  211.         }
  212. # endif
  213.  
  214. # ifdef MINIMAL_TERM
  215.     HO = NULL;
  216. # else
  217.     HO = Tgetstr("ho");
  218. # endif
  219.     /*
  220.      * LI and CO are set in ioctl.c via a TIOCGWINSZ if available.  If
  221.      * the kernel has values for either we should use them rather than
  222.      * the values from TERMCAP ...
  223.      */
  224. # ifndef MICRO
  225.     if (!CO) CO = tgetnum("co");
  226.     if (!LI) LI = tgetnum("li");
  227. # else
  228. #  if defined(TOS) && defined(__GNUC__)
  229.     if (!strcmp(term, "builtin"))
  230.         get_scr_size();
  231.     else {
  232. #  endif
  233.     CO = tgetnum("co");
  234.     LI = tgetnum("li");
  235.     if (!LI || !CO)            /* if we don't override it */
  236.         get_scr_size();
  237. #  if defined(TOS) && defined(__GNUC__)
  238.     }
  239. #  endif
  240. # endif
  241. # ifdef CLIPPING
  242.     if(CO < COLNO || LI < ROWNO+3)
  243.         setclipped();
  244. # endif
  245.     if(!(CL = Tgetstr("cl")))
  246.         error("Hack needs CL.");
  247.     ND = Tgetstr("nd");
  248.     if(tgetflag("os"))
  249.         error("Hack can't have OS.");
  250.     if(tgetflag("ul"))
  251.         ul_hack = TRUE;
  252.     CE = Tgetstr("ce");
  253.     UP = Tgetstr("up");
  254.     /* It seems that xd is no longer supported, and we should use
  255.        a linefeed instead; unfortunately this requires resetting
  256.        CRMOD, and many output routines will have to be modified
  257.        slightly. Let's leave that till the next release. */
  258.     XD = Tgetstr("xd");
  259. /* not:         XD = Tgetstr("do"); */
  260.     if(!(CM = Tgetstr("cm"))) {
  261.         if(!UP && !HO)
  262.             error("Hack needs CM or UP or HO.");
  263.         tty_raw_print("Playing hack on terminals without cm is suspect...");
  264.         tty_wait_synch();
  265.     }
  266.     SO = Tgetstr("so");
  267.     SE = Tgetstr("se");
  268.     US = Tgetstr("us");
  269.     UE = Tgetstr("ue");
  270.     SG = tgetnum("sg");    /* -1: not fnd; else # of spaces left by so */
  271.     if(!SO || !SE || (SG > 0)) SO = SE = US = UE = nullstr;
  272.     TI = Tgetstr("ti");
  273.     TE = Tgetstr("te");
  274.     VS = VE = nullstr;
  275. # ifdef TERMINFO
  276.     VS = Tgetstr("eA");    /* enable graphics */
  277. # endif
  278.     KS = Tgetstr("ks");    /* keypad start (special mode) */
  279.     KE = Tgetstr("ke");    /* keypad end (ordinary mode [ie, digits]) */
  280. # if 0
  281.     MR = Tgetstr("mr");    /* reverse */
  282.     MB = Tgetstr("mb");    /* blink */
  283.     MD = Tgetstr("md");    /* boldface */
  284.     MH = Tgetstr("mh");    /* dim */
  285.     ME = Tgetstr("me");
  286. # endif
  287.  
  288.     /* Get rid of padding numbers for HI and HE.  Hope they
  289.      * aren't really needed!!!  HI and HE are ouputted to the
  290.      * pager as a string - so how can you send it NULLS???
  291.      *  -jsb
  292.      */
  293.         HI = (char *) alloc((unsigned)(strlen(SO)+1));
  294.         HE = (char *) alloc((unsigned)(strlen(SE)+1));
  295.         i = 0;
  296.         while (digit(SO[i])) i++;
  297.         Strcpy(HI, &SO[i]);
  298.         i = 0;
  299.         while (digit(SE[i])) i++;
  300.         Strcpy(HE, &SE[i]);
  301.     AS = Tgetstr("as");
  302.     AE = Tgetstr("ae");
  303.     CD = Tgetstr("cd");
  304. # ifdef TEXTCOLOR
  305.     MD = Tgetstr("md");
  306. # endif
  307.     if(tbufptr-tbuf > sizeof(tbuf)) error("TERMCAP entry too big...\n");
  308.     free((genericptr_t)tptr);
  309. # ifdef TEXTCOLOR
  310. #  if defined(TOS) && defined(__GNUC__)
  311.     if (!strcmp(term, "builtin") || !strcmp(term, "tw52")) {
  312.         init_hilite();
  313.     }
  314. #  else
  315.     init_hilite();
  316. #  endif
  317. # endif
  318. #endif /* TERMLIB */
  319.     *wid = CO;
  320.     *hgt = LI;
  321. }
  322.  
  323. void
  324. tty_number_pad(state)
  325. int state;
  326. {
  327.     switch (state) {
  328.         case -1:    /* activate keypad mode (escape sequences) */
  329.             if (KS && *KS) xputs(KS);
  330.             break;
  331.         case  1:    /* activate numeric mode for keypad (digits) */
  332.             if (KE && *KE) xputs(KE);
  333.             break;
  334.         case  0:    /* don't need to do anything--leave terminal as-is */
  335.         default:
  336.             break;
  337.     }
  338. }
  339.  
  340. #ifdef TERMLIB
  341. extern void NDECL((*decgraphics_mode_callback));    /* defined in drawing.c */
  342. static void NDECL(tty_decgraphics_termcap_fixup);
  343.  
  344. /*
  345.    We call this routine whenever DECgraphics mode is enabled, even if it
  346.    has been previously set, in case the user manages to reset the fonts.
  347.    The actual termcap fixup only needs to be done once, but we can't
  348.    call xputs() from the option setting or graphics assigning routines,
  349.    so this is a convenient hook.
  350.  */
  351. static void
  352. tty_decgraphics_termcap_fixup()
  353. {
  354.     static char ctrlN[]   = "\016";
  355.     static char ctrlO[]   = "\017";
  356.     static char appMode[] = "\033=";
  357.     static char numMode[] = "\033>";
  358.  
  359.     /* these values are missing from some termcaps */
  360.     if (!AS) AS = ctrlN;    /* ^N (shift-out [graphics font]) */
  361.     if (!AE) AE = ctrlO;    /* ^O (shift-in  [regular font])  */
  362.     if (!KS) KS = appMode;    /* ESC= (application keypad mode) */
  363.     if (!KE) KE = numMode;    /* ESC> (numeric keypad mode)      */
  364.     /*
  365.      * Select the line-drawing character set as the alternate font.
  366.      * Do not select NA ASCII as the primary font since people may
  367.      * reasonably be using the UK character set.
  368.      */
  369.     if (flags.DECgraphics) xputs("\033)0");
  370. }
  371. #endif
  372.  
  373. void
  374. tty_start_screen()
  375. {
  376.     xputs(TI);
  377.     xputs(VS);
  378. #ifdef TERMLIB
  379.     if (flags.DECgraphics) tty_decgraphics_termcap_fixup();
  380.     /* set up callback in case option is not set yet but toggled later */
  381.     decgraphics_mode_callback = tty_decgraphics_termcap_fixup;
  382. #endif
  383.     if (flags.num_pad) tty_number_pad(1);    /* make keypad send digits */
  384. }
  385.  
  386. void
  387. tty_end_screen()
  388. {
  389.     clear_screen();
  390.     xputs(VE);
  391.     xputs(TE);
  392. }
  393.  
  394. /* Cursor movements */
  395.  
  396. #endif /* OVLB */
  397.  
  398. #ifdef OVL0
  399. /* Note to OVLx tinkerers.  The placement of this overlay controls the location
  400.    of the function xputc().  This function is not currently in trampoli.[ch]
  401.    files for what is deemed to be performance reasons.  If this define is moved
  402.    and or xputc() is taken out of the ROOT overlay, then action must be taken
  403.    in trampoli.[ch]. */
  404.  
  405. void
  406. nocmov(x, y)
  407. int x,y;
  408. {
  409.     if ((int) ttyDisplay->cury > y) {
  410.         if(UP) {
  411.             while ((int) ttyDisplay->cury > y) {    /* Go up. */
  412.                 xputs(UP);
  413.                 ttyDisplay->cury--;
  414.             }
  415.         } else if(CM) {
  416.             cmov(x, y);
  417.         } else if(HO) {
  418.             home();
  419.             tty_curs(BASE_WINDOW, x+1, y);
  420.         } /* else impossible("..."); */
  421.     } else if ((int) ttyDisplay->cury < y) {
  422.         if(XD) {
  423.             while((int) ttyDisplay->cury < y) {
  424.                 xputs(XD);
  425.                 ttyDisplay->cury++;
  426.             }
  427.         } else if(CM) {
  428.             cmov(x, y);
  429.         } else {
  430.             while((int) ttyDisplay->cury < y) {
  431.                 xputc('\n');
  432.                 ttyDisplay->curx = 0;
  433.                 ttyDisplay->cury++;
  434.             }
  435.         }
  436.     }
  437.     if ((int) ttyDisplay->curx < x) {        /* Go to the right. */
  438.         if(!ND) cmov(x, y); else    /* bah */
  439.             /* should instead print what is there already */
  440.         while ((int) ttyDisplay->curx < x) {
  441.             xputs(ND);
  442.             ttyDisplay->curx++;
  443.         }
  444.     } else if ((int) ttyDisplay->curx > x) {
  445.         while ((int) ttyDisplay->curx > x) {    /* Go to the left. */
  446.             xputs(BC);
  447.             ttyDisplay->curx--;
  448.         }
  449.     }
  450. }
  451.  
  452. void
  453. cmov(x, y)
  454. register int x, y;
  455. {
  456.     xputs(tgoto(CM, x, y));
  457.     ttyDisplay->cury = y;
  458.     ttyDisplay->curx = x;
  459. }
  460.  
  461. /* See note at OVLx ifdef above.   xputc() is a special function. */
  462. void
  463. xputc(c)
  464. #if defined(apollo)
  465. int c;
  466. #else
  467. char c;
  468. #endif
  469. {
  470.     (void) putchar(c);
  471. }
  472.  
  473. void
  474. xputs(s)
  475. const char *s;
  476. {
  477. # ifndef TERMLIB
  478.     (void) fputs(s, stdout);
  479. # else
  480. #  if defined(NHSTDC) || defined(ULTRIX_PROTO)
  481.     tputs(s, 1, (int (*)())xputc);
  482. #  else
  483.     tputs(s, 1, xputc);
  484. #  endif
  485. # endif
  486. }
  487.  
  488. void
  489. cl_end()
  490. {
  491.     if(CE)
  492.         xputs(CE);
  493.     else {    /* no-CE fix - free after Harold Rynes */
  494.         /* this looks terrible, especially on a slow terminal
  495.            but is better than nothing */
  496.         register int cx = ttyDisplay->curx+1;
  497.  
  498.         while(cx < CO) {
  499.             xputc(' ');
  500.             cx++;
  501.         }
  502.         tty_curs(BASE_WINDOW, (int)ttyDisplay->curx+1,
  503.                         (int)ttyDisplay->cury);
  504.     }
  505. }
  506.  
  507. #endif /* OVL0 */
  508. #ifdef OVLB
  509.  
  510. void
  511. clear_screen()
  512. {
  513.     /* note: if CL is null, then termcap initialization failed,
  514.         so don't attempt screen-oriented I/O during final cleanup.
  515.      */
  516.     if (CL) {
  517.         xputs(CL);
  518.         home();
  519.     }
  520. }
  521.  
  522. #endif /* OVLB */
  523. #ifdef OVL0
  524.  
  525. void
  526. home()
  527. {
  528.     if(HO)
  529.         xputs(HO);
  530.     else if(CM)
  531.         xputs(tgoto(CM, 0, 0));
  532.     else
  533.         tty_curs(BASE_WINDOW, 1, 0);    /* using UP ... */
  534.     ttyDisplay->curx = ttyDisplay->cury = 0;
  535. }
  536.  
  537. void
  538. standoutbeg()
  539. {
  540.     if(SO) xputs(SO);
  541. }
  542.  
  543. void
  544. standoutend()
  545. {
  546.     if(SE) xputs(SE);
  547. }
  548.  
  549. #if 0    /* if you need one of these, uncomment it (here and in extern.h) */
  550. void
  551. revbeg()
  552. {
  553.     if(MR) xputs(MR);
  554. }
  555.  
  556. void
  557. boldbeg()
  558. {
  559.     if(MD) xputs(MD);
  560. }
  561.  
  562. void
  563. blinkbeg()
  564. {
  565.     if(MB) xputs(MB);
  566. }
  567.  
  568. void
  569. dimbeg()
  570. /* not in most termcap entries */
  571. {
  572.     if(MH) xputs(MH);
  573. }
  574.  
  575. void
  576. m_end()
  577. {
  578.     if(ME) xputs(ME);
  579. }
  580. #endif
  581.  
  582. #endif /* OVL0 */
  583. #ifdef OVLB
  584.  
  585. void
  586. backsp()
  587. {
  588.     xputs(BC);
  589. }
  590.  
  591. void
  592. tty_nhbell()
  593. {
  594.     if (flags.silent) return;
  595.     (void) putchar('\007');        /* curx does not change */
  596.     (void) fflush(stdout);
  597. }
  598.  
  599. #endif /* OVLB */
  600. #ifdef OVL0
  601.  
  602. #ifdef ASCIIGRAPH
  603. void
  604. graph_on() {
  605.     if (AS) xputs(AS);
  606. }
  607.  
  608. void
  609. graph_off() {
  610.     if (AE) xputs(AE);
  611. }
  612. #endif
  613.  
  614. #endif /* OVL0 */
  615. #ifdef OVL1
  616.  
  617. #if !defined(MICRO)
  618. # ifdef VMS
  619. static const short tmspc10[] = {        /* from termcap */
  620.     0, 2000, 1333, 909, 743, 666, 333, 166, 83, 55, 50, 41, 27, 20, 13, 10,
  621.     5
  622. };
  623. # else
  624. static const short tmspc10[] = {        /* from termcap */
  625.     0, 2000, 1333, 909, 743, 666, 500, 333, 166, 83, 55, 41, 20, 10, 5
  626. };
  627. # endif
  628. #endif
  629.  
  630. void
  631. tty_delay_output()
  632. {
  633.     /* delay 50 ms - could also use a 'nap'-system call */
  634.     /* BUG: if the padding character is visible, as it is on the 5620
  635.        then this looks terrible. */
  636. #if defined(MICRO)
  637.     /* simulate the delay with "cursor here" */
  638.     register int i;
  639.     for (i = 0; i < 3; i++) {
  640.         cmov(ttyDisplay->curx, ttyDisplay->cury);
  641.         (void) fflush(stdout);
  642.     }
  643. #else /* MICRO */
  644.     if(flags.null)
  645. # ifdef TERMINFO
  646.         /* cbosgd!cbcephus!pds for SYS V R2 */
  647. #  ifdef NHSTDC
  648.         tputs("$<50>", 1, (int (*)())xputc);
  649. #  else
  650.         tputs("$<50>", 1, xputc);
  651. #  endif
  652. # else
  653. #  if defined(NHSTDC) || defined(ULTRIX_PROTO)
  654.         tputs("50", 1, (int (*)())xputc);
  655. #  else
  656.         tputs("50", 1, xputc);
  657. #  endif
  658. # endif
  659.  
  660.     else if(ospeed > 0 && ospeed < SIZE(tmspc10)) if(CM) {
  661.         /* delay by sending cm(here) an appropriate number of times */
  662.         register int cmlen = strlen(tgoto(CM, ttyDisplay->curx, ttyDisplay->cury));
  663.         register int i = 500 + tmspc10[ospeed]/2;
  664.  
  665.         while(i > 0) {
  666.             cmov((int)ttyDisplay->curx, (int)ttyDisplay->cury);
  667.             i -= cmlen*tmspc10[ospeed];
  668.         }
  669.     }
  670. #endif /* MICRO */
  671. }
  672.  
  673. #endif /* OVL1 */
  674. #ifdef OVLB
  675.  
  676. void
  677. cl_eos()            /* free after Robert Viduya */
  678. {                /* must only be called with curx = 1 */
  679.  
  680.     if(CD)
  681.         xputs(CD);
  682.     else {
  683.         register int cy = ttyDisplay->cury+1;
  684.         while(cy <= LI-2) {
  685.             cl_end();
  686.             xputc('\n');
  687.             cy++;
  688.         }
  689.         cl_end();
  690.         tty_curs(BASE_WINDOW, (int)ttyDisplay->curx+1,
  691.                         (int)ttyDisplay->cury);
  692.     }
  693. }
  694.  
  695. #if defined(TEXTCOLOR) && defined(TERMLIB)
  696. # if defined(UNIX) && defined(TERMINFO)
  697. /*
  698.  * Sets up color highlighting, using terminfo(4) escape sequences (highlight
  699.  * code found in print.c).  It is assumed that the background color is black.
  700.  */
  701. /* terminfo indexes for the basic colors it guarantees */
  702. #define COLOR_BLACK   1        /* fake out to avoid black on black */
  703. #define COLOR_BLUE    1
  704. #define COLOR_GREEN   2
  705. #define COLOR_CYAN    3
  706. #define COLOR_RED     4
  707. #define COLOR_MAGENTA 5
  708. #define COLOR_YELLOW  6
  709. #define COLOR_WHITE   7
  710.  
  711. /* map ANSI RGB to terminfo BGR */
  712. const int ti_map[8] = {
  713.     COLOR_BLACK, COLOR_RED, COLOR_GREEN, COLOR_YELLOW,
  714.     COLOR_BLUE, COLOR_MAGENTA, COLOR_CYAN, COLOR_WHITE };
  715.  
  716. static void
  717. init_hilite()
  718. {
  719.     register int c;
  720.     char *setf, *scratch;
  721.     extern char *tparm();
  722.  
  723.     for (c = 0; c < SIZE(hilites); c++)
  724.         hilites[c] = HI;
  725.     hilites[GRAY] = hilites[NO_COLOR] = NULL;
  726.  
  727.     if (tgetnum("Co") < 8 || (setf = tgetstr("Sf", (char **)0)) == NULL)
  728.         return;
  729.  
  730.     for (c = 0; c < MAXCOLORS / 2; c++) {
  731.           scratch = tparm(setf, ti_map[c]);
  732.         if (c != GRAY) {
  733.             hilites[c] = (char *) alloc(strlen(scratch) + 1);
  734.             Strcpy(hilites[c], scratch);
  735.         }
  736.         if (c != BLACK) {
  737.             hilites[c|BRIGHT] = (char*) alloc(strlen(scratch)+strlen(MD)+1);
  738.             Strcpy(hilites[c|BRIGHT], MD);
  739.             Strcat(hilites[c|BRIGHT], scratch);
  740.             }
  741.         
  742.     }
  743. }
  744.  
  745. # else /* UNIX && TERMINFO */
  746.  
  747. #  ifndef TOS
  748. /* find the foreground and background colors set by HI or HE */
  749. static void
  750. analyze_seq (str, fg, bg)
  751. char *str;
  752. int *fg, *bg;
  753. {
  754.     register int c, code;
  755.     int len;
  756.  
  757. #   ifdef MICRO
  758.     *fg = GRAY; *bg = BLACK;
  759. #   else
  760.     *fg = *bg = NO_COLOR;
  761. #   endif
  762.  
  763.     if (str[0] != '\033' || str[1] != '[' ||
  764.         str[len = strlen(str) - 1] != 'm' || len < 3)
  765.         return;
  766.  
  767.     c = 2;
  768.     while (c < len) {
  769.         if ((code = atoi(&str[c])) == 0) { /* reset */
  770.         /* this also catches errors */
  771. #   ifdef MICRO
  772.         *fg = GRAY; *bg = BLACK;
  773. #   else
  774.         *fg = *bg = NO_COLOR;
  775. #   endif
  776.         } else if (code == 1) { /* bold */
  777.         *fg |= BRIGHT;
  778. #   if 0
  779.     /* I doubt we'll ever resort to using blinking characters,
  780.        unless we want a pulsing glow for something.  But, in case
  781.        we do... - 3. */
  782.         } else if (code == 5) { /* blinking */
  783.         *fg |= BLINK;
  784.         } else if (code == 25) { /* stop blinking */
  785.         *fg &= ~BLINK;
  786. #   endif
  787.         } else if (code == 7 || code == 27) { /* reverse */
  788.         code = *fg & ~BRIGHT;
  789.         *fg = *bg | (*fg & BRIGHT);
  790.         *bg = code;
  791.         } else if (code >= 30 && code <= 37) { /* hi_foreground RGB */
  792.         *fg = code - 30;
  793.         } else if (code >= 40 && code <= 47) { /* hi_background RGB */
  794.         *bg = code - 40;
  795.         }
  796.         while (digit(str[++c]));
  797.         c++;
  798.     }
  799. }
  800. #  endif
  801.  
  802. /*
  803.  * Sets up highlighting sequences, using ANSI escape sequences (highlight code
  804.  * found in print.c).  The HI and HE sequences (usually from SO) is scanned to
  805.  * find foreground and background colors.
  806.  */
  807.  
  808. static void
  809. init_hilite()
  810. {
  811.     register int c;
  812. #  ifdef TOS
  813.     extern unsigned long tos_numcolors;    /* in tos.c */
  814.     static const char NOCOL[] = "\033b0", COLHE[] = "\033q\033b0";
  815.  
  816.     HI = "\033p";
  817. #  else
  818.     int backg, foreg, hi_backg, hi_foreg;
  819. #  endif
  820.  
  821.     for (c = 0; c < SIZE(hilites); c++)
  822.         hilites[c] = HI;
  823.     hilites[GRAY] = hilites[NO_COLOR] = NULL;
  824.  
  825. #  ifdef TOS
  826.     if (tos_numcolors <= 2) {
  827.         return;
  828.     }
  829. /* Under TOS, the "bright" and "dim" colors are reversed. Moreover,
  830.  * on the Falcon the dim colors are *really* dim; so we make most
  831.  * of the colors the bright versions, with a few exceptions where
  832.  * the dim ones look OK.
  833.  */
  834.     hilites[0] = NOCOL;
  835.     for (c = 1; c < SIZE(hilites); c++) {
  836.         hilites[c] = (char *) alloc(sizeof("\033b0"));
  837.         if (tos_numcolors > 4)
  838.             Sprintf(hilites[c], "\033b%c", (c&~BRIGHT)+'0');
  839.         else
  840.             Strcpy(hilites[c], HI);
  841.     }
  842.  
  843.     if (tos_numcolors == 4) {
  844.         TI = "\033b0\033c3\033E\033e";
  845.         TE = "\033b3\033c0\033J";
  846.         HE = COLHE;
  847.         hilites[GREEN] = hilites[GREEN|BRIGHT] = "\033b2";
  848.         hilites[RED] = hilites[RED|BRIGHT] = "\033b1";
  849.     } else {
  850.         sprintf(hilites[BROWN], "\033b%c", (BROWN^BRIGHT)+'0');
  851.         sprintf(hilites[GREEN], "\033b%c", (GREEN^BRIGHT)+'0');
  852.  
  853.         TI = "\033b0\033c\017\033E\033e";
  854.         TE = "\033b\017\033c0\033J";
  855.         HE = COLHE;
  856.         hilites[WHITE] = hilites[BLACK] = NOCOL;
  857.         hilites[NO_COLOR] = hilites[GRAY];
  858.     }
  859.  
  860. #  else /* TOS */
  861.     analyze_seq(HI, &hi_foreg, &hi_backg);
  862.     analyze_seq(HE, &foreg, &backg);
  863.  
  864.     for (c = 0; c < SIZE(hilites); c++)
  865.         /* avoid invisibility */
  866.         if ((backg & ~BRIGHT) != c) {
  867. #   ifdef MICRO
  868.         if (c == BLUE) continue;
  869. #   endif
  870.         if (c == foreg)
  871.             hilites[c] = NULL;
  872.         else if (c != hi_foreg && backg != hi_backg) {
  873.             hilites[c] = (char *) alloc(sizeof("\033[%d;3%d;4%dm"));
  874.             Sprintf(hilites[c], "\033[%d", !!(c & BRIGHT));
  875.             if ((c | BRIGHT) != (foreg | BRIGHT))
  876.             Sprintf(eos(hilites[c]), ";3%d", c & ~BRIGHT);
  877.             if (backg != BLACK)
  878.             Sprintf(eos(hilites[c]), ";4%d", backg & ~BRIGHT);
  879.             Strcat(hilites[c], "m");
  880.         }
  881.         }
  882.  
  883. #   ifdef MICRO
  884.     /* brighten low-visibility colors */
  885.     hilites[BLUE] = hilites[BLUE|BRIGHT];
  886. #   endif
  887. #  endif /* TOS */
  888. }
  889. # endif /* UNIX */
  890. #endif /* TEXTCOLOR */
  891.  
  892. #endif /* OVLB */
  893.  
  894. /*termcap.c*/
  895.