1 /* NetHack 3.6 termcap.c $NHDT-Date: 1456907853 2016/03/02 08:37:33 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.24 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /*-Copyright (c) Pasi Kallinen, 2018. */
4 /* NetHack may be freely redistributed. See license for details. */
8 #if defined(TTY_GRAPHICS) && !defined(NO_TERMS)
13 #ifdef MICROPORT_286_BUG
14 #define Tgetstr(key) (tgetstr(key, tbuf))
16 #define Tgetstr(key) (tgetstr(key, &tbufptr))
17 #endif /* MICROPORT_286_BUG **/
19 static char *FDECL(s_atr2str, (int));
20 static char *FDECL(e_atr2str, (int));
22 void FDECL(cmov, (int, int));
23 void FDECL(nocmov, (int, int));
24 #if defined(TEXTCOLOR) && defined(TERMLIB)
25 #if !defined(UNIX) || !defined(TERMINFO)
27 static void FDECL(analyze_seq, (char *, int *, int *));
30 static void NDECL(init_hilite);
31 static void NDECL(kill_hilite);
34 /* (see tcap.h) -- nh_CM, nh_ND, nh_CD, nh_HI,nh_HE, nh_US,nh_UE, ul_hack */
35 struct tc_lcl_data tc_lcl_data = { 0, 0, 0, 0, 0, 0, 0, FALSE };
37 STATIC_VAR char *HO, *CL, *CE, *UP, *XD, *BC, *SO, *SE, *TI, *TE;
38 STATIC_VAR char *VS, *VE;
42 STATIC_VAR char *MB, *MH;
43 STATIC_VAR char *MD; /* may already be in use below */
47 boolean dynamic_HIHE = FALSE;
52 STATIC_OVL char PC = '\0';
53 STATIC_VAR char tbuf[512];
58 const char *hilites[CLR_MAX]; /* terminal escapes for the various colors */
60 char NEARDATA *hilites[CLR_MAX]; /* terminal escapes for the various colors */
64 static char *KS = (char *) 0, *KE = (char *) 0; /* keypad sequences */
65 static char nullstr[] = "";
67 #if defined(ASCIIGRAPH) && !defined(NO_TERMS)
68 extern boolean HE_resets_AS;
72 STATIC_VAR char tgotobuf[20];
74 #define tgoto(fmt, x, y) (Sprintf(tgotobuf, fmt, y + ' ', x + ' '), tgotobuf)
76 #define tgoto(fmt, x, y) (Sprintf(tgotobuf, fmt, y + 1, x + 1), tgotobuf)
86 register const char *term;
91 term = verify_termcap();
94 term = getenv("TERM");
96 #if defined(TOS) && defined(__GNUC__)
98 term = "builtin"; /* library has a default */
103 error("Can't get TERM.");
109 TI = VS = VE = TE = nullstr;
111 CE = "\033K"; /* the VT52 termcap */
113 nh_CM = "\033Y%c%c"; /* used with function tgoto() */
119 /* HI and HE will be updated in init_hilite if we're using color */
124 CL = "\033E"; /* last thing set */
132 if (CO < COLNO || LI < ROWNO + 3)
137 /* nh_CD = "\033[J"; */
138 CE = "\033[K"; /* the ANSI termcap */
140 nh_CM = "\033[%d;%dH";
142 nh_CM = "\033[%i%d;%dH";
147 #ifdef MICRO /* backspaces are non-destructive */
152 nh_HI = SO = "\033[1m";
155 TI = nh_HE = ME = SE = nh_UE = "\033[0m";
156 /* strictly, SE should be 2, and nh_UE should be 24,
157 but we can't trust all ANSI emulators to be
158 that complete. -3. */
163 TE = VS = VE = nullstr;
165 for (i = 0; i < CLR_MAX / 2; i++)
166 if (i != CLR_BLACK) {
167 hilites[i | BRIGHT] = (char *) alloc(sizeof("\033[1;3%dm"));
168 Sprintf(hilites[i | BRIGHT], "\033[1;3%dm", i);
172 hilites[CLR_BLUE] = hilites[CLR_BLUE | BRIGHT];
176 hilites[i] = (char *) alloc(sizeof("\033[0;3%dm"));
177 Sprintf(hilites[i], "\033[0;3%dm", i);
183 CL = "\033[2J"; /* last thing set */
187 #endif /* ANSI_DEFAULT */
190 tptr = (char *) alloc(1024);
193 if (!strncmp(term, "5620", 4))
194 flags.null = FALSE; /* this should be a termcap flag */
195 if (tgetent(tptr, term) < 1) {
197 (void) strncpy(buf, term,
198 (BUFSZ - 1) - (sizeof("Unknown terminal type: . ")));
199 buf[BUFSZ - 1] = '\0';
200 error("Unknown terminal type: %s.", term);
202 if ((pc = Tgetstr("pc")) != 0)
205 if (!(BC = Tgetstr("le"))) /* both termcap and terminfo use le */
207 error("Terminal must backspace.");
209 if (!(BC = Tgetstr("bc"))) { /* termcap also uses bc/bs */
212 error("Terminal must backspace.");
226 * LI and CO are set in ioctl.c via a TIOCGWINSZ if available. If
227 * the kernel has values for either we should use them rather than
228 * the values from TERMCAP ...
236 #if defined(TOS) && defined(__GNUC__)
237 if (!strcmp(term, "builtin")) {
244 if (!LI || !CO) /* if we don't override it */
249 if (CO < COLNO || LI < ROWNO + 3)
252 nh_ND = Tgetstr("nd");
254 error("NetHack can't have OS.");
259 /* It seems that xd is no longer supported, and we should use
260 a linefeed instead; unfortunately this requires resetting
261 CRMOD, and many output routines will have to be modified
262 slightly. Let's leave that till the next release. */
264 /* not: XD = Tgetstr("do"); */
265 if (!(nh_CM = Tgetstr("cm"))) {
267 error("NetHack needs CM or UP or HO.");
268 tty_raw_print("Playing NetHack on terminals without CM is suspect.");
273 nh_US = Tgetstr("us");
274 nh_UE = Tgetstr("ue");
275 SG = tgetnum("sg"); /* -1: not fnd; else # of spaces left by so */
276 if (!SO || !SE || (SG > 0))
277 SO = SE = nh_US = nh_UE = nullstr;
282 VS = Tgetstr("eA"); /* enable graphics */
284 KS = Tgetstr("ks"); /* keypad start (special mode) */
285 KE = Tgetstr("ke"); /* keypad end (ordinary mode [ie, digits]) */
286 MR = Tgetstr("mr"); /* reverse */
288 MB = Tgetstr("mb"); /* blink */
289 MD = Tgetstr("md"); /* boldface */
290 MH = Tgetstr("mh"); /* dim */
292 ME = Tgetstr("me"); /* turn off all attributes */
293 if (!ME || (SE == nullstr))
294 ME = SE; /* default to SE value */
296 /* Get rid of padding numbers for nh_HI and nh_HE. Hope they
297 * aren't really needed!!! nh_HI and nh_HE are outputted to the
298 * pager as a string - so how can you send it NULs???
301 for (i = 0; digit(SO[i]); ++i)
303 nh_HI = dupstr(&SO[i]);
304 for (i = 0; digit(ME[i]); ++i)
306 nh_HE = dupstr(&ME[i]);
311 nh_CD = Tgetstr("cd");
316 #if defined(TOS) && defined(__GNUC__)
317 if (!strcmp(term, "builtin") || !strcmp(term, "tw52")
318 || !strcmp(term, "st52")) {
327 if (!(CL = Tgetstr("cl"))) /* last thing set */
328 error("NetHack needs CL.");
329 if ((int) (tbufptr - tbuf) > (int) (sizeof tbuf))
330 error("TERMCAP entry too big...\n");
331 free((genericptr_t) tptr);
335 /* note: at present, this routine is not part of the formal window interface
337 /* deallocate resources prior to final termination */
341 /* we only attempt to clean up a few individual termcap variables */
347 free((genericptr_t) nh_HI), nh_HI = (char *) 0;
348 free((genericptr_t) nh_HE), nh_HE = (char *) 0;
349 dynamic_HIHE = FALSE;
356 tty_number_pad(state)
360 case -1: /* activate keypad mode (escape sequences) */
364 case 1: /* activate numeric mode for keypad (digits) */
368 case 0: /* don't need to do anything--leave terminal as-is */
375 extern void NDECL((*decgraphics_mode_callback)); /* defined in drawing.c */
376 static void NDECL(tty_decgraphics_termcap_fixup);
379 We call this routine whenever DECgraphics mode is enabled, even if it
380 has been previously set, in case the user manages to reset the fonts.
381 The actual termcap fixup only needs to be done once, but we can't
382 call xputs() from the option setting or graphics assigning routines,
383 so this is a convenient hook.
386 tty_decgraphics_termcap_fixup()
388 static char ctrlN[] = "\016";
389 static char ctrlO[] = "\017";
390 static char appMode[] = "\033=";
391 static char numMode[] = "\033>";
393 /* these values are missing from some termcaps */
395 AS = ctrlN; /* ^N (shift-out [graphics font]) */
397 AE = ctrlO; /* ^O (shift-in [regular font]) */
399 KS = appMode; /* ESC= (application keypad mode) */
401 KE = numMode; /* ESC> (numeric keypad mode) */
403 * Select the line-drawing character set as the alternate font.
404 * Do not select NA ASCII as the primary font since people may
405 * reasonably be using the UK character set.
407 if (SYMHANDLING(H_DEC))
413 #if defined(ASCIIGRAPH) && !defined(NO_TERMS)
414 /* some termcaps suffer from the bizarre notion that resetting
415 video attributes should also reset the chosen character set */
417 const char *nh_he = nh_HE, *ae = AE;
418 int he_limit, ae_length;
420 if (digit(*ae)) { /* skip over delay prefix, if any */
432 /* can't use nethack's case-insensitive strstri() here, and some old
433 systems don't have strstr(), so use brute force substring search */
434 ae_length = strlen(ae), he_limit = strlen(nh_he);
435 while (he_limit >= ae_length) {
436 if (strncmp(nh_he, ae, ae_length) == 0) {
447 #if defined(ASCIIGRAPH) && defined(PC9800)
448 extern void NDECL((*ibmgraphics_mode_callback)); /* defined in drawing.c */
452 extern void NDECL((*ascgraphics_mode_callback)); /* defined in drawing.c */
453 static void NDECL(tty_ascgraphics_hilite_fixup);
456 tty_ascgraphics_hilite_fixup()
460 for (c = 0; c < CLR_MAX / 2; c++)
461 if (c != CLR_BLACK) {
462 hilites[c | BRIGHT] = (char *) alloc(sizeof("\033[1;3%dm"));
463 Sprintf(hilites[c | BRIGHT], "\033[1;3%dm", c);
465 hilites[c] = (char *) alloc(sizeof("\033[0;3%dm"));
466 Sprintf(hilites[c], "\033[0;3%dm", c);
478 if (!SYMHANDLING(H_IBM))
479 tty_ascgraphics_hilite_fixup();
480 /* set up callback in case option is not set yet but toggled later */
481 ascgraphics_mode_callback = tty_ascgraphics_hilite_fixup;
483 if (SYMHANDLING(H_IBM))
485 /* set up callback in case option is not set yet but toggled later */
486 ibmgraphics_mode_callback = init_hilite;
491 if (SYMHANDLING(H_DEC))
492 tty_decgraphics_termcap_fixup();
493 /* set up callback in case option is not set yet but toggled later */
494 decgraphics_mode_callback = tty_decgraphics_termcap_fixup;
497 tty_number_pad(1); /* make keypad send digits */
508 /* Cursor movements */
510 /* Note to overlay tinkerers. The placement of this overlay controls the
512 of the function xputc(). This function is not currently in trampoli.[ch]
513 files for what is deemed to be performance reasons. If this define is
515 and or xputc() is taken out of the ROOT overlay, then action must be taken
522 if ((int) ttyDisplay->cury > y) {
524 while ((int) ttyDisplay->cury > y) { /* Go up. */
532 tty_curs(BASE_WINDOW, x + 1, y);
533 } /* else impossible("..."); */
534 } else if ((int) ttyDisplay->cury < y) {
536 while ((int) ttyDisplay->cury < y) {
543 while ((int) ttyDisplay->cury < y) {
545 ttyDisplay->curx = 0;
550 if ((int) ttyDisplay->curx < x) { /* Go to the right. */
554 /* should instead print what is there already */
555 while ((int) ttyDisplay->curx < x) {
560 } else if ((int) ttyDisplay->curx > x) {
561 while ((int) ttyDisplay->curx > x) { /* Go to the left. */
572 xputs(tgoto(nh_CM, x, y));
573 ttyDisplay->cury = y;
574 ttyDisplay->curx = x;
577 /* See note above. xputc() is a special function. */
598 (void) jputchar('\0');
600 (void) fputs(s, stdout);
602 #if defined(NHSTDC) || defined(ULTRIX_PROTO)
603 tputs(s, 1, (int (*) ()) xputc);
615 } else { /* no-CE fix - free after Harold Rynes */
616 register int cx = ttyDisplay->curx + 1;
618 /* this looks terrible, especially on a slow terminal
619 but is better than nothing */
624 tty_curs(BASE_WINDOW, (int) ttyDisplay->curx + 1,
625 (int) ttyDisplay->cury);
632 /* note: if CL is null, then termcap initialization failed,
633 so don't attempt screen-oriented I/O during final cleanup.
647 xputs(tgoto(nh_CM, 0, 0));
649 tty_curs(BASE_WINDOW, 1, 0); /* using UP ... */
650 ttyDisplay->curx = ttyDisplay->cury = 0;
667 #if 0 /* if you need one of these, uncomment it (here and in extern.h) */
692 /* not in most termcap entries */
717 (void) putchar('\007'); /* curx does not change */
719 (void) cputchar('\007'); /* curx does not change */
721 (void) fflush(stdout);
742 static const short tmspc10[] = { /* from termcap */
743 0, 2000, 1333, 909, 743, 666, 333, 166, 83,
744 55, 50, 41, 27, 20, 13, 10, 5
747 static const short tmspc10[] = { /* from termcap */
748 0, 2000, 1333, 909, 743, 666, 500, 333, 166,
749 83, 55, 41, 20, 10, 5
763 (void) fflush(stdout);
764 msleep(50); /* sleep for 50 milliseconds */
769 /* simulate the delay with "cursor here" */
770 #if 1 /*JP*//*JPTB need?*/
774 for (i = 0; i < 3; i++) {
775 cmov(ttyDisplay->curx, ttyDisplay->cury);
776 (void) fflush(stdout);
782 /* BUG: if the padding character is visible, as it is on the 5620
783 then this looks terrible. */
786 /* cbosgd!cbcephus!pds for SYS V R2 */
788 tputs("$<50>", 1, (int (*) ()) xputc);
790 tputs("$<50>", 1, xputc);
793 #if defined(NHSTDC) || defined(ULTRIX_PROTO)
794 tputs("50", 1, (int (*) ()) xputc);
796 tputs("50", 1, xputc);
800 } else if (ospeed > 0 && ospeed < SIZE(tmspc10) && nh_CM) {
801 /* delay by sending cm(here) an appropriate number of times */
803 strlen(tgoto(nh_CM, ttyDisplay->curx, ttyDisplay->cury));
804 register int i = 500 + tmspc10[ospeed] / 2;
807 cmov((int) ttyDisplay->curx, (int) ttyDisplay->cury);
808 i -= cmlen * tmspc10[ospeed];
814 /* must only be called with curx = 1 */
816 cl_eos() /* free after Robert Viduya */
821 register int cy = ttyDisplay->cury + 1;
823 while (cy <= LI - 2) {
829 tty_curs(BASE_WINDOW, (int) ttyDisplay->curx + 1,
830 (int) ttyDisplay->cury);
834 #if defined(TEXTCOLOR) && defined(TERMLIB)
835 #if defined(UNIX) && defined(TERMINFO)
837 * Sets up color highlighting, using terminfo(4) escape sequences.
839 * Having never seen a terminfo system without curses, we assume this
840 * inclusion is safe. On systems with color terminfo, it should define
841 * the 8 COLOR_FOOs, and avoid us having to guess whether this particular
842 * terminfo uses BGR or RGB for its indexes.
844 * If we don't get the definitions, then guess. Original color terminfos
845 * used BGR for the original Sf (setf, Standard foreground) codes, but
846 * there was a near-total lack of user documentation, so some subsequent
847 * terminfos, such as early Linux ncurses and SCO UNIX, used RGB. Possibly
848 * as a result of the confusion, AF (setaf, ANSI Foreground) codes were
849 * introduced, but this caused yet more confusion. Later Linux ncurses
850 * have BGR Sf, RGB AF, and RGB COLOR_FOO, which appears to be the SVR4
851 * standard. We could switch the colors around when using Sf with ncurses,
852 * which would help things on later ncurses and hurt things on early ncurses.
853 * We'll try just preferring AF and hoping it always agrees with COLOR_FOO,
854 * and falling back to Sf if AF isn't defined.
856 * In any case, treat black specially so we don't try to display black
857 * characters on the assumed black background.
860 /* `curses' is aptly named; various versions don't like these
861 macros used elsewhere within nethack; fortunately they're
862 not needed beyond this point, so we don't need to worry
863 about reconstructing them after the header file inclusion. */
867 #define m_move curses_m_move /* Some curses.h decl m_move(), not used here \
872 #if !defined(LINUX) && !defined(__FreeBSD__) && !defined(NOTPARMDECL)
873 extern char *tparm();
876 #ifndef COLOR_BLACK /* trust include file */
877 #ifndef _M_UNIX /* guess BGR */
878 #define COLOR_BLACK 0
880 #define COLOR_GREEN 2
883 #define COLOR_MAGENTA 5
884 #define COLOR_YELLOW 6
885 #define COLOR_WHITE 7
886 #else /* guess RGB */
887 #define COLOR_BLACK 0
889 #define COLOR_GREEN 2
890 #define COLOR_YELLOW 3
892 #define COLOR_MAGENTA 5
894 #define COLOR_WHITE 7
898 /* Mapping data for the six terminfo colors that resolve to pairs of nethack
899 * colors. Black and white are handled specially.
902 int ti_color, nh_color, nh_bright_color;
903 } ti_map[6] = { { COLOR_RED, CLR_RED, CLR_ORANGE },
904 { COLOR_GREEN, CLR_GREEN, CLR_BRIGHT_GREEN },
905 { COLOR_YELLOW, CLR_BROWN, CLR_YELLOW },
906 { COLOR_BLUE, CLR_BLUE, CLR_BRIGHT_BLUE },
907 { COLOR_MAGENTA, CLR_MAGENTA, CLR_BRIGHT_MAGENTA },
908 { COLOR_CYAN, CLR_CYAN, CLR_BRIGHT_CYAN } };
910 static char nilstring[] = "";
916 char *setf, *scratch;
919 if (tgetnum("Co") < 8 || (MD == NULL) || (strlen(MD) == 0)
920 || ((setf = tgetstr("AF", (char **) 0)) == (char *) 0
921 && (setf = tgetstr("Sf", (char **) 0)) == (char *) 0)) {
922 /* Fallback when colors not available
923 * It's arbitrary to collapse all colors except gray
924 * together, but that's what the previous code did.
926 hilites[CLR_BLACK] = nh_HI;
927 hilites[CLR_RED] = nh_HI;
928 hilites[CLR_GREEN] = nh_HI;
929 hilites[CLR_BROWN] = nh_HI;
930 hilites[CLR_BLUE] = nh_HI;
931 hilites[CLR_MAGENTA] = nh_HI;
932 hilites[CLR_CYAN] = nh_HI;
933 hilites[CLR_GRAY] = nilstring;
934 hilites[NO_COLOR] = nilstring;
935 hilites[CLR_ORANGE] = nh_HI;
936 hilites[CLR_BRIGHT_GREEN] = nh_HI;
937 hilites[CLR_YELLOW] = nh_HI;
938 hilites[CLR_BRIGHT_BLUE] = nh_HI;
939 hilites[CLR_BRIGHT_MAGENTA] = nh_HI;
940 hilites[CLR_BRIGHT_CYAN] = nh_HI;
941 hilites[CLR_WHITE] = nh_HI;
950 scratch = tparm(setf, ti_map[c].ti_color);
951 work = (char *) alloc(strlen(scratch) + md_len + 1);
953 hilites[ti_map[c].nh_bright_color] = work;
955 Strcpy(work, scratch);
956 hilites[ti_map[c].nh_color] = work;
959 scratch = tparm(setf, COLOR_WHITE);
960 hilites[CLR_WHITE] = (char *) alloc(strlen(scratch) + md_len + 1);
961 Strcpy(hilites[CLR_WHITE], MD);
962 Strcat(hilites[CLR_WHITE], scratch);
964 hilites[CLR_GRAY] = nilstring;
965 hilites[NO_COLOR] = nilstring;
967 if (iflags.wc2_darkgray) {
968 /* On many terminals, esp. those using classic PC CGA/EGA/VGA
969 * textmode, specifying "hilight" and "black" simultaneously
970 * produces a dark shade of gray that is visible against a
971 * black background. We can use it to represent black objects.
973 scratch = tparm(setf, COLOR_BLACK);
974 hilites[CLR_BLACK] = (char *) alloc(strlen(scratch) + md_len + 1);
975 Strcpy(hilites[CLR_BLACK], MD);
976 Strcat(hilites[CLR_BLACK], scratch);
978 /* But it's concievable that hilighted black-on-black could
979 * still be invisible on many others. We substitute blue for
982 hilites[CLR_BLACK] = hilites[CLR_BLUE];
989 /* if colors weren't available, no freeing needed */
990 if (hilites[CLR_BLACK] == nh_HI)
993 if (hilites[CLR_BLACK] != hilites[CLR_BLUE])
994 free(hilites[CLR_BLACK]);
996 /* CLR_BLUE overlaps CLR_BRIGHT_BLUE, do not free */
997 /* CLR_GREEN overlaps CLR_BRIGHT_GREEN, do not free */
998 /* CLR_CYAN overlaps CLR_BRIGHT_CYAN, do not free */
999 /* CLR_RED overlaps CLR_ORANGE, do not free */
1000 /* CLR_MAGENTA overlaps CLR_BRIGHT_MAGENTA, do not free */
1001 /* CLR_BROWN overlaps CLR_YELLOW, do not free */
1002 /* CLR_GRAY is static 'nilstring', do not free */
1003 /* NO_COLOR is static 'nilstring', do not free */
1004 free(hilites[CLR_BRIGHT_BLUE]);
1005 free(hilites[CLR_BRIGHT_GREEN]);
1006 free(hilites[CLR_BRIGHT_CYAN]);
1007 free(hilites[CLR_YELLOW]);
1008 free(hilites[CLR_ORANGE]);
1009 free(hilites[CLR_BRIGHT_MAGENTA]);
1010 free(hilites[CLR_WHITE]);
1013 #else /* UNIX && TERMINFO */
1016 /* find the foreground and background colors set by nh_HI or nh_HE */
1018 analyze_seq(str, fg, bg)
1022 register int c, code;
1029 *fg = *bg = NO_COLOR;
1032 c = (str[0] == '\233') ? 1 : 2; /* index of char beyond esc prefix */
1033 len = strlen(str) - 1; /* length excluding attrib suffix */
1034 if ((c != 1 && (str[0] != '\033' || str[1] != '[')) || (len - c) < 1
1039 if ((code = atoi(&str[c])) == 0) { /* reset */
1040 /* this also catches errors */
1045 *fg = *bg = NO_COLOR;
1047 } else if (code == 1) { /* bold */
1050 /* I doubt we'll ever resort to using blinking characters,
1051 unless we want a pulsing glow for something. But, in case
1053 } else if (code == 5) { /* blinking */
1055 } else if (code == 25) { /* stop blinking */
1058 } else if (code == 7 || code == 27) { /* reverse */
1059 code = *fg & ~BRIGHT;
1060 *fg = *bg | (*fg & BRIGHT);
1062 } else if (code >= 30 && code <= 37) { /* hi_foreground RGB */
1064 } else if (code >= 40 && code <= 47) { /* hi_background RGB */
1067 while (digit(str[++c]))
1075 * Sets up highlighting sequences, using ANSI escape sequences (highlight code
1076 * found in print.c). The nh_HI and nh_HE sequences (usually from SO) are
1077 * scanned to find foreground and background colors.
1085 extern unsigned long tos_numcolors; /* in tos.c */
1086 static char NOCOL[] = "\033b0", COLHE[] = "\033q\033b0";
1088 if (tos_numcolors <= 2) {
1091 /* Under TOS, the "bright" and "dim" colors are reversed. Moreover,
1092 * on the Falcon the dim colors are *really* dim; so we make most
1093 * of the colors the bright versions, with a few exceptions where
1094 * the dim ones look OK.
1097 for (c = 1; c < SIZE(hilites); c++) {
1099 foo = (char *) alloc(sizeof("\033b0"));
1100 if (tos_numcolors > 4)
1101 Sprintf(foo, "\033b%c", (c & ~BRIGHT) + '0');
1103 Strcpy(foo, "\033b0");
1107 if (tos_numcolors == 4) {
1108 TI = "\033b0\033c3\033E\033e";
1109 TE = "\033b3\033c0\033J";
1111 hilites[CLR_GREEN] = hilites[CLR_GREEN | BRIGHT] = "\033b2";
1112 hilites[CLR_RED] = hilites[CLR_RED | BRIGHT] = "\033b1";
1114 sprintf(hilites[CLR_BROWN], "\033b%c", (CLR_BROWN ^ BRIGHT) + '0');
1115 sprintf(hilites[CLR_GREEN], "\033b%c", (CLR_GREEN ^ BRIGHT) + '0');
1117 TI = "\033b0\033c\017\033E\033e";
1118 TE = "\033b\017\033c0\033J";
1120 hilites[CLR_WHITE] = hilites[CLR_BLACK] = NOCOL;
1121 hilites[NO_COLOR] = hilites[CLR_GRAY];
1126 int backg, foreg, hi_backg, hi_foreg;
1128 for (c = 0; c < SIZE(hilites); c++)
1130 hilites[CLR_GRAY] = hilites[NO_COLOR] = (char *) 0;
1132 analyze_seq(nh_HI, &hi_foreg, &hi_backg);
1133 analyze_seq(nh_HE, &foreg, &backg);
1135 for (c = 0; c < SIZE(hilites); c++)
1136 /* avoid invisibility */
1137 if ((backg & ~BRIGHT) != c) {
1143 hilites[c] = (char *) 0;
1144 else if (c != hi_foreg || backg != hi_backg) {
1145 hilites[c] = (char *) alloc(sizeof("\033[%d;3%d;4%dm"));
1146 Sprintf(hilites[c], "\033[%d", !!(c & BRIGHT));
1147 if ((c | BRIGHT) != (foreg | BRIGHT))
1148 Sprintf(eos(hilites[c]), ";3%d", c & ~BRIGHT);
1149 if (backg != CLR_BLACK)
1150 Sprintf(eos(hilites[c]), ";4%d", backg & ~BRIGHT);
1151 Strcat(hilites[c], "m");
1156 /* brighten low-visibility colors */
1157 hilites[CLR_BLUE] = hilites[CLR_BLUE | BRIGHT];
1168 for (c = 0; c < CLR_MAX / 2; c++) {
1169 if (hilites[c | BRIGHT] == hilites[c])
1170 hilites[c | BRIGHT] = 0;
1171 if (hilites[c] && (hilites[c] != nh_HI))
1172 free((genericptr_t) hilites[c]), hilites[c] = 0;
1173 if (hilites[c | BRIGHT] && (hilites[c | BRIGHT] != nh_HI))
1174 free((genericptr_t) hilites[c | BRIGHT]), hilites[c | BRIGHT] = 0;
1180 #endif /* TEXTCOLOR */
1182 static char nulstr[] = "";
1195 #if defined(TERMLIB) && defined(TEXTCOLOR)
1225 term_start_attr(attr)
1229 xputs(s_atr2str(attr));
1238 xputs(e_atr2str(attr));
1243 term_start_raw_bold()
1263 term_start_color(color)
1266 xputs(hilites[color]);
1269 /* not to be confused with has_colors() in unixtty.c */
1275 /* XXX has_color() should be added to windowprocs */
1276 if (windowprocs.name != NULL && !strcmpi(windowprocs.name, "X11"))
1280 /* XXX has_color() should be added to windowprocs */
1281 if (windowprocs.name != NULL && !strcmpi(windowprocs.name, "Gem"))
1285 /* XXX has_color() should be added to windowprocs */
1286 if (windowprocs.name != NULL && !strcmpi(windowprocs.name, "Qt"))
1289 #ifdef AMII_GRAPHICS
1290 /* hilites[] not used */
1291 return iflags.use_color ? 1 : 0;
1293 return hilites[color] != (char *) 0;
1297 #endif /* TEXTCOLOR */
1299 #endif /* TTY_GRAPHICS */