1 /* aNetHack 0.0.1 termcap.c $ANH-Date: 1456907853 2016/03/02 08:37:33 $ $ANH-Branch: aNetHack-3.6.0 $:$ANH-Revision: 1.24 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /* aNetHack may be freely redistributed. See license for details. */
7 #if defined(TTY_GRAPHICS) && !defined(NO_TERMS)
12 #ifdef MICROPORT_286_BUG
13 #define Tgetstr(key) (tgetstr(key, tbuf))
15 #define Tgetstr(key) (tgetstr(key, &tbufptr))
16 #endif /* MICROPORT_286_BUG **/
18 static char *FDECL(s_atr2str
, (int));
19 static char *FDECL(e_atr2str
, (int));
21 void FDECL(cmov
, (int, int));
22 void FDECL(nocmov
, (int, int));
23 #if defined(TEXTCOLOR) && defined(TERMLIB)
24 #if !defined(UNIX) || !defined(TERMINFO)
26 static void FDECL(analyze_seq
, (char *, int *, int *));
29 static void NDECL(init_hilite
);
30 static void NDECL(kill_hilite
);
33 /* (see tcap.h) -- nh_CM, nh_ND, nh_CD, nh_HI,nh_HE, nh_US,nh_UE, ul_hack */
34 struct tc_lcl_data tc_lcl_data
= { 0, 0, 0, 0, 0, 0, 0, FALSE
};
36 STATIC_VAR
char *HO
, *CL
, *CE
, *UP
, *XD
, *BC
, *SO
, *SE
, *TI
, *TE
;
37 STATIC_VAR
char *VS
, *VE
;
41 STATIC_VAR
char *MB
, *MH
;
42 STATIC_VAR
char *MD
; /* may already be in use below */
46 boolean dynamic_HIHE
= FALSE
;
51 STATIC_OVL
char PC
= '\0';
52 STATIC_VAR
char tbuf
[512];
57 const char *hilites
[CLR_MAX
]; /* terminal escapes for the various colors */
59 char NEARDATA
*hilites
[CLR_MAX
]; /* terminal escapes for the various colors */
63 static char *KS
= (char *) 0, *KE
= (char *) 0; /* keypad sequences */
64 static char nullstr
[] = "";
66 #if defined(ASCIIGRAPH) && !defined(NO_TERMS)
67 extern boolean HE_resets_AS
;
71 STATIC_VAR
char tgotobuf
[20];
73 #define tgoto(fmt, x, y) (Sprintf(tgotobuf, fmt, y + ' ', x + ' '), tgotobuf)
75 #define tgoto(fmt, x, y) (Sprintf(tgotobuf, fmt, y + 1, x + 1), tgotobuf)
85 register const char *term
;
90 term
= verify_termcap();
93 term
= getenv("TERM");
95 #if defined(TOS) && defined(__GNUC__)
97 term
= "builtin"; /* library has a default */
102 error("Can't get TERM.");
108 TI
= VS
= VE
= TE
= nullstr
;
110 CE
= "\033K"; /* the VT52 termcap */
112 nh_CM
= "\033Y%c%c"; /* used with function tgoto() */
118 /* HI and HE will be updated in init_hilite if we're using color */
123 CL
= "\033E"; /* last thing set */
131 if (CO
< COLNO
|| LI
< ROWNO
+ 3)
136 /* nh_CD = "\033[J"; */
137 CE
= "\033[K"; /* the ANSI termcap */
139 nh_CM
= "\033[%d;%dH";
141 nh_CM
= "\033[%i%d;%dH";
146 #ifdef MICRO /* backspaces are non-destructive */
151 nh_HI
= SO
= "\033[1m";
154 TI
= nh_HE
= ME
= SE
= nh_UE
= "\033[0m";
155 /* strictly, SE should be 2, and nh_UE should be 24,
156 but we can't trust all ANSI emulators to be
157 that complete. -3. */
162 TE
= VS
= VE
= nullstr
;
164 for (i
= 0; i
< CLR_MAX
/ 2; i
++)
165 if (i
!= CLR_BLACK
) {
166 hilites
[i
| BRIGHT
] = (char *) alloc(sizeof("\033[1;3%dm"));
167 Sprintf(hilites
[i
| BRIGHT
], "\033[1;3%dm", i
);
171 hilites
[CLR_BLUE
] = hilites
[CLR_BLUE
| BRIGHT
];
175 hilites
[i
] = (char *) alloc(sizeof("\033[0;3%dm"));
176 Sprintf(hilites
[i
], "\033[0;3%dm", i
);
182 CL
= "\033[2J"; /* last thing set */
186 #endif /* ANSI_DEFAULT */
189 tptr
= (char *) alloc(1024);
192 if (!strncmp(term
, "5620", 4))
193 flags
.null
= FALSE
; /* this should be a termcap flag */
194 if (tgetent(tptr
, term
) < 1) {
196 (void) strncpy(buf
, term
,
197 (BUFSZ
- 1) - (sizeof("Unknown terminal type: . ")));
198 buf
[BUFSZ
- 1] = '\0';
199 error("Unknown terminal type: %s.", term
);
201 if ((pc
= Tgetstr("pc")) != 0)
204 if (!(BC
= Tgetstr("le"))) /* both termcap and terminfo use le */
206 error("Terminal must backspace.");
208 if (!(BC
= Tgetstr("bc"))) { /* termcap also uses bc/bs */
211 error("Terminal must backspace.");
225 * LI and CO are set in ioctl.c via a TIOCGWINSZ if available. If
226 * the kernel has values for either we should use them rather than
227 * the values from TERMCAP ...
235 #if defined(TOS) && defined(__GNUC__)
236 if (!strcmp(term
, "builtin")) {
243 if (!LI
|| !CO
) /* if we don't override it */
248 if (CO
< COLNO
|| LI
< ROWNO
+ 3)
251 nh_ND
= Tgetstr("nd");
253 error("aNetHack can't have OS.");
258 /* It seems that xd is no longer supported, and we should use
259 a linefeed instead; unfortunately this requires resetting
260 CRMOD, and many output routines will have to be modified
261 slightly. Let's leave that till the next release. */
263 /* not: XD = Tgetstr("do"); */
264 if (!(nh_CM
= Tgetstr("cm"))) {
266 error("aNetHack needs CM or UP or HO.");
267 tty_raw_print("Playing aNetHack on terminals without CM is suspect.");
272 nh_US
= Tgetstr("us");
273 nh_UE
= Tgetstr("ue");
274 SG
= tgetnum("sg"); /* -1: not fnd; else # of spaces left by so */
275 if (!SO
|| !SE
|| (SG
> 0))
276 SO
= SE
= nh_US
= nh_UE
= nullstr
;
281 VS
= Tgetstr("eA"); /* enable graphics */
283 KS
= Tgetstr("ks"); /* keypad start (special mode) */
284 KE
= Tgetstr("ke"); /* keypad end (ordinary mode [ie, digits]) */
285 MR
= Tgetstr("mr"); /* reverse */
287 MB
= Tgetstr("mb"); /* blink */
288 MD
= Tgetstr("md"); /* boldface */
289 MH
= Tgetstr("mh"); /* dim */
291 ME
= Tgetstr("me"); /* turn off all attributes */
292 if (!ME
|| (SE
== nullstr
))
293 ME
= SE
; /* default to SE value */
295 /* Get rid of padding numbers for nh_HI and nh_HE. Hope they
296 * aren't really needed!!! nh_HI and nh_HE are outputted to the
297 * pager as a string - so how can you send it NULs???
300 for (i
= 0; digit(SO
[i
]); ++i
)
302 nh_HI
= dupstr(&SO
[i
]);
303 for (i
= 0; digit(ME
[i
]); ++i
)
305 nh_HE
= dupstr(&ME
[i
]);
310 nh_CD
= Tgetstr("cd");
315 #if defined(TOS) && defined(__GNUC__)
316 if (!strcmp(term
, "builtin") || !strcmp(term
, "tw52")
317 || !strcmp(term
, "st52")) {
326 if (!(CL
= Tgetstr("cl"))) /* last thing set */
327 error("aNetHack needs CL.");
328 if ((int) (tbufptr
- tbuf
) > (int) (sizeof tbuf
))
329 error("TERMCAP entry too big...\n");
330 free((genericptr_t
) tptr
);
334 /* note: at present, this routine is not part of the formal window interface
336 /* deallocate resources prior to final termination */
340 /* we only attempt to clean up a few individual termcap variables */
346 free((genericptr_t
) nh_HI
), nh_HI
= (char *) 0;
347 free((genericptr_t
) nh_HE
), nh_HE
= (char *) 0;
348 dynamic_HIHE
= FALSE
;
355 tty_number_pad(state
)
359 case -1: /* activate keypad mode (escape sequences) */
363 case 1: /* activate numeric mode for keypad (digits) */
367 case 0: /* don't need to do anything--leave terminal as-is */
374 extern void NDECL((*decgraphics_mode_callback
)); /* defined in drawing.c */
375 static void NDECL(tty_decgraphics_termcap_fixup
);
378 We call this routine whenever DECgraphics mode is enabled, even if it
379 has been previously set, in case the user manages to reset the fonts.
380 The actual termcap fixup only needs to be done once, but we can't
381 call xputs() from the option setting or graphics assigning routines,
382 so this is a convenient hook.
385 tty_decgraphics_termcap_fixup()
387 static char ctrlN
[] = "\016";
388 static char ctrlO
[] = "\017";
389 static char appMode
[] = "\033=";
390 static char numMode
[] = "\033>";
392 /* these values are missing from some termcaps */
394 AS
= ctrlN
; /* ^N (shift-out [graphics font]) */
396 AE
= ctrlO
; /* ^O (shift-in [regular font]) */
398 KS
= appMode
; /* ESC= (application keypad mode) */
400 KE
= numMode
; /* ESC> (numeric keypad mode) */
402 * Select the line-drawing character set as the alternate font.
403 * Do not select NA ASCII as the primary font since people may
404 * reasonably be using the UK character set.
406 if (SYMHANDLING(H_DEC
))
412 #if defined(ASCIIGRAPH) && !defined(NO_TERMS)
413 /* some termcaps suffer from the bizarre notion that resetting
414 video attributes should also reset the chosen character set */
416 const char *nh_he
= nh_HE
, *ae
= AE
;
417 int he_limit
, ae_length
;
419 if (digit(*ae
)) { /* skip over delay prefix, if any */
431 /* can't use anethack's case-insensitive strstri() here, and some old
432 systems don't have strstr(), so use brute force substring search */
433 ae_length
= strlen(ae
), he_limit
= strlen(nh_he
);
434 while (he_limit
>= ae_length
) {
435 if (strncmp(nh_he
, ae
, ae_length
) == 0) {
446 #if defined(ASCIIGRAPH) && defined(PC9800)
447 extern void NDECL((*ibmgraphics_mode_callback
)); /* defined in drawing.c */
451 extern void NDECL((*ascgraphics_mode_callback
)); /* defined in drawing.c */
452 static void NDECL(tty_ascgraphics_hilite_fixup
);
455 tty_ascgraphics_hilite_fixup()
459 for (c
= 0; c
< CLR_MAX
/ 2; c
++)
460 if (c
!= CLR_BLACK
) {
461 hilites
[c
| BRIGHT
] = (char *) alloc(sizeof("\033[1;3%dm"));
462 Sprintf(hilites
[c
| BRIGHT
], "\033[1;3%dm", c
);
464 hilites
[c
] = (char *) alloc(sizeof("\033[0;3%dm"));
465 Sprintf(hilites
[c
], "\033[0;3%dm", c
);
477 if (!SYMHANDLING(H_IBM
))
478 tty_ascgraphics_hilite_fixup();
479 /* set up callback in case option is not set yet but toggled later */
480 ascgraphics_mode_callback
= tty_ascgraphics_hilite_fixup
;
482 if (SYMHANDLING(H_IBM
))
484 /* set up callback in case option is not set yet but toggled later */
485 ibmgraphics_mode_callback
= init_hilite
;
490 if (SYMHANDLING(H_DEC
))
491 tty_decgraphics_termcap_fixup();
492 /* set up callback in case option is not set yet but toggled later */
493 decgraphics_mode_callback
= tty_decgraphics_termcap_fixup
;
496 tty_number_pad(1); /* make keypad send digits */
507 /* Cursor movements */
509 /* Note to overlay tinkerers. The placement of this overlay controls the
511 of the function xputc(). This function is not currently in trampoli.[ch]
512 files for what is deemed to be performance reasons. If this define is
514 and or xputc() is taken out of the ROOT overlay, then action must be taken
521 if ((int) ttyDisplay
->cury
> y
) {
523 while ((int) ttyDisplay
->cury
> y
) { /* Go up. */
531 tty_curs(BASE_WINDOW
, x
+ 1, y
);
532 } /* else impossible("..."); */
533 } else if ((int) ttyDisplay
->cury
< y
) {
535 while ((int) ttyDisplay
->cury
< y
) {
542 while ((int) ttyDisplay
->cury
< y
) {
544 ttyDisplay
->curx
= 0;
549 if ((int) ttyDisplay
->curx
< x
) { /* Go to the right. */
553 /* should instead print what is there already */
554 while ((int) ttyDisplay
->curx
< x
) {
559 } else if ((int) ttyDisplay
->curx
> x
) {
560 while ((int) ttyDisplay
->curx
> x
) { /* Go to the left. */
571 xputs(tgoto(nh_CM
, x
, y
));
572 ttyDisplay
->cury
= y
;
573 ttyDisplay
->curx
= x
;
576 /* See note above. xputc() is a special function. */
593 (void) fputs(s
, stdout
);
595 #if defined(NHSTDC) || defined(ULTRIX_PROTO)
596 tputs(s
, 1, (int (*) ()) xputc
);
608 } else { /* no-CE fix - free after Harold Rynes */
609 register int cx
= ttyDisplay
->curx
+ 1;
611 /* this looks terrible, especially on a slow terminal
612 but is better than nothing */
617 tty_curs(BASE_WINDOW
, (int) ttyDisplay
->curx
+ 1,
618 (int) ttyDisplay
->cury
);
625 /* note: if CL is null, then termcap initialization failed,
626 so don't attempt screen-oriented I/O during final cleanup.
640 xputs(tgoto(nh_CM
, 0, 0));
642 tty_curs(BASE_WINDOW
, 1, 0); /* using UP ... */
643 ttyDisplay
->curx
= ttyDisplay
->cury
= 0;
660 #if 0 /* if you need one of these, uncomment it (here and in extern.h) */
685 /* not in most termcap entries */
709 (void) putchar('\007'); /* curx does not change */
710 (void) fflush(stdout
);
731 static const short tmspc10
[] = { /* from termcap */
732 0, 2000, 1333, 909, 743, 666, 333, 166, 83,
733 55, 50, 41, 27, 20, 13, 10, 5
736 static const short tmspc10
[] = { /* from termcap */
737 0, 2000, 1333, 909, 743, 666, 500, 333, 166,
738 83, 55, 41, 20, 10, 5
752 (void) fflush(stdout
);
753 msleep(50); /* sleep for 50 milliseconds */
758 /* simulate the delay with "cursor here" */
759 for (i
= 0; i
< 3; i
++) {
760 cmov(ttyDisplay
->curx
, ttyDisplay
->cury
);
761 (void) fflush(stdout
);
764 /* BUG: if the padding character is visible, as it is on the 5620
765 then this looks terrible. */
768 /* cbosgd!cbcephus!pds for SYS V R2 */
770 tputs("$<50>", 1, (int (*) ()) xputc
);
772 tputs("$<50>", 1, xputc
);
775 #if defined(NHSTDC) || defined(ULTRIX_PROTO)
776 tputs("50", 1, (int (*) ()) xputc
);
778 tputs("50", 1, xputc
);
782 } else if (ospeed
> 0 && ospeed
< SIZE(tmspc10
) && nh_CM
) {
783 /* delay by sending cm(here) an appropriate number of times */
785 strlen(tgoto(nh_CM
, ttyDisplay
->curx
, ttyDisplay
->cury
));
786 register int i
= 500 + tmspc10
[ospeed
] / 2;
789 cmov((int) ttyDisplay
->curx
, (int) ttyDisplay
->cury
);
790 i
-= cmlen
* tmspc10
[ospeed
];
796 /* must only be called with curx = 1 */
798 cl_eos() /* free after Robert Viduya */
803 register int cy
= ttyDisplay
->cury
+ 1;
805 while (cy
<= LI
- 2) {
811 tty_curs(BASE_WINDOW
, (int) ttyDisplay
->curx
+ 1,
812 (int) ttyDisplay
->cury
);
816 #if defined(TEXTCOLOR) && defined(TERMLIB)
817 #if defined(UNIX) && defined(TERMINFO)
819 * Sets up color highlighting, using terminfo(4) escape sequences.
821 * Having never seen a terminfo system without curses, we assume this
822 * inclusion is safe. On systems with color terminfo, it should define
823 * the 8 COLOR_FOOs, and avoid us having to guess whether this particular
824 * terminfo uses BGR or RGB for its indexes.
826 * If we don't get the definitions, then guess. Original color terminfos
827 * used BGR for the original Sf (setf, Standard foreground) codes, but
828 * there was a near-total lack of user documentation, so some subsequent
829 * terminfos, such as early Linux ncurses and SCO UNIX, used RGB. Possibly
830 * as a result of the confusion, AF (setaf, ANSI Foreground) codes were
831 * introduced, but this caused yet more confusion. Later Linux ncurses
832 * have BGR Sf, RGB AF, and RGB COLOR_FOO, which appears to be the SVR4
833 * standard. We could switch the colors around when using Sf with ncurses,
834 * which would help things on later ncurses and hurt things on early ncurses.
835 * We'll try just preferring AF and hoping it always agrees with COLOR_FOO,
836 * and falling back to Sf if AF isn't defined.
838 * In any case, treat black specially so we don't try to display black
839 * characters on the assumed black background.
842 /* `curses' is aptly named; various versions don't like these
843 macros used elsewhere within anethack; fortunately they're
844 not needed beyond this point, so we don't need to worry
845 about reconstructing them after the header file inclusion. */
849 #define m_move curses_m_move /* Some curses.h decl m_move(), not used here \
854 #if !defined(LINUX) && !defined(__FreeBSD__) && !defined(NOTPARMDECL)
855 extern char *tparm();
858 #ifndef COLOR_BLACK /* trust include file */
859 #ifndef _M_UNIX /* guess BGR */
860 #define COLOR_BLACK 0
862 #define COLOR_GREEN 2
865 #define COLOR_MAGENTA 5
866 #define COLOR_YELLOW 6
867 #define COLOR_WHITE 7
868 #else /* guess RGB */
869 #define COLOR_BLACK 0
871 #define COLOR_GREEN 2
872 #define COLOR_YELLOW 3
874 #define COLOR_MAGENTA 5
876 #define COLOR_WHITE 7
880 /* Mapping data for the six terminfo colors that resolve to pairs of anethack
881 * colors. Black and white are handled specially.
884 int ti_color
, nh_color
, nh_bright_color
;
885 } ti_map
[6] = { { COLOR_RED
, CLR_RED
, CLR_ORANGE
},
886 { COLOR_GREEN
, CLR_GREEN
, CLR_BRIGHT_GREEN
},
887 { COLOR_YELLOW
, CLR_BROWN
, CLR_YELLOW
},
888 { COLOR_BLUE
, CLR_BLUE
, CLR_BRIGHT_BLUE
},
889 { COLOR_MAGENTA
, CLR_MAGENTA
, CLR_BRIGHT_MAGENTA
},
890 { COLOR_CYAN
, CLR_CYAN
, CLR_BRIGHT_CYAN
} };
892 static char nilstring
[] = "";
898 char *setf
, *scratch
;
901 if (tgetnum("Co") < 8 || (MD
== NULL
) || (strlen(MD
) == 0)
902 || ((setf
= tgetstr("AF", (char **) 0)) == (char *) 0
903 && (setf
= tgetstr("Sf", (char **) 0)) == (char *) 0)) {
904 /* Fallback when colors not available
905 * It's arbitrary to collapse all colors except gray
906 * together, but that's what the previous code did.
908 hilites
[CLR_BLACK
] = nh_HI
;
909 hilites
[CLR_RED
] = nh_HI
;
910 hilites
[CLR_GREEN
] = nh_HI
;
911 hilites
[CLR_BROWN
] = nh_HI
;
912 hilites
[CLR_BLUE
] = nh_HI
;
913 hilites
[CLR_MAGENTA
] = nh_HI
;
914 hilites
[CLR_CYAN
] = nh_HI
;
915 hilites
[CLR_GRAY
] = nilstring
;
916 hilites
[NO_COLOR
] = nilstring
;
917 hilites
[CLR_ORANGE
] = nh_HI
;
918 hilites
[CLR_BRIGHT_GREEN
] = nh_HI
;
919 hilites
[CLR_YELLOW
] = nh_HI
;
920 hilites
[CLR_BRIGHT_BLUE
] = nh_HI
;
921 hilites
[CLR_BRIGHT_MAGENTA
] = nh_HI
;
922 hilites
[CLR_BRIGHT_CYAN
] = nh_HI
;
923 hilites
[CLR_WHITE
] = nh_HI
;
932 scratch
= tparm(setf
, ti_map
[c
].ti_color
);
933 work
= (char *) alloc(strlen(scratch
) + md_len
+ 1);
935 hilites
[ti_map
[c
].nh_bright_color
] = work
;
937 Strcpy(work
, scratch
);
938 hilites
[ti_map
[c
].nh_color
] = work
;
941 scratch
= tparm(setf
, COLOR_WHITE
);
942 hilites
[CLR_WHITE
] = (char *) alloc(strlen(scratch
) + md_len
+ 1);
943 Strcpy(hilites
[CLR_WHITE
], MD
);
944 Strcat(hilites
[CLR_WHITE
], scratch
);
946 hilites
[CLR_GRAY
] = nilstring
;
947 hilites
[NO_COLOR
] = nilstring
;
949 if (iflags
.wc2_darkgray
) {
950 /* On many terminals, esp. those using classic PC CGA/EGA/VGA
951 * textmode, specifying "hilight" and "black" simultaneously
952 * produces a dark shade of gray that is visible against a
953 * black background. We can use it to represent black objects.
955 scratch
= tparm(setf
, COLOR_BLACK
);
956 hilites
[CLR_BLACK
] = (char *) alloc(strlen(scratch
) + md_len
+ 1);
957 Strcpy(hilites
[CLR_BLACK
], MD
);
958 Strcat(hilites
[CLR_BLACK
], scratch
);
960 /* But it's concievable that hilighted black-on-black could
961 * still be invisible on many others. We substitute blue for
964 hilites
[CLR_BLACK
] = hilites
[CLR_BLUE
];
971 /* if colors weren't available, no freeing needed */
972 if (hilites
[CLR_BLACK
] == nh_HI
)
975 if (hilites
[CLR_BLACK
] != hilites
[CLR_BLUE
])
976 free(hilites
[CLR_BLACK
]);
978 /* CLR_BLUE overlaps CLR_BRIGHT_BLUE, do not free */
979 /* CLR_GREEN overlaps CLR_BRIGHT_GREEN, do not free */
980 /* CLR_CYAN overlaps CLR_BRIGHT_CYAN, do not free */
981 /* CLR_RED overlaps CLR_ORANGE, do not free */
982 /* CLR_MAGENTA overlaps CLR_BRIGHT_MAGENTA, do not free */
983 /* CLR_BROWN overlaps CLR_YELLOW, do not free */
984 /* CLR_GRAY is static 'nilstring', do not free */
985 /* NO_COLOR is static 'nilstring', do not free */
986 free(hilites
[CLR_BRIGHT_BLUE
]);
987 free(hilites
[CLR_BRIGHT_GREEN
]);
988 free(hilites
[CLR_BRIGHT_CYAN
]);
989 free(hilites
[CLR_YELLOW
]);
990 free(hilites
[CLR_ORANGE
]);
991 free(hilites
[CLR_BRIGHT_MAGENTA
]);
992 free(hilites
[CLR_WHITE
]);
995 #else /* UNIX && TERMINFO */
998 /* find the foreground and background colors set by nh_HI or nh_HE */
1000 analyze_seq(str
, fg
, bg
)
1004 register int c
, code
;
1011 *fg
= *bg
= NO_COLOR
;
1014 c
= (str
[0] == '\233') ? 1 : 2; /* index of char beyond esc prefix */
1015 len
= strlen(str
) - 1; /* length excluding attrib suffix */
1016 if ((c
!= 1 && (str
[0] != '\033' || str
[1] != '[')) || (len
- c
) < 1
1021 if ((code
= atoi(&str
[c
])) == 0) { /* reset */
1022 /* this also catches errors */
1027 *fg
= *bg
= NO_COLOR
;
1029 } else if (code
== 1) { /* bold */
1032 /* I doubt we'll ever resort to using blinking characters,
1033 unless we want a pulsing glow for something. But, in case
1035 } else if (code
== 5) { /* blinking */
1037 } else if (code
== 25) { /* stop blinking */
1040 } else if (code
== 7 || code
== 27) { /* reverse */
1041 code
= *fg
& ~BRIGHT
;
1042 *fg
= *bg
| (*fg
& BRIGHT
);
1044 } else if (code
>= 30 && code
<= 37) { /* hi_foreground RGB */
1046 } else if (code
>= 40 && code
<= 47) { /* hi_background RGB */
1049 while (digit(str
[++c
]))
1057 * Sets up highlighting sequences, using ANSI escape sequences (highlight code
1058 * found in print.c). The nh_HI and nh_HE sequences (usually from SO) are
1059 * scanned to find foreground and background colors.
1067 extern unsigned long tos_numcolors
; /* in tos.c */
1068 static char NOCOL
[] = "\033b0", COLHE
[] = "\033q\033b0";
1070 if (tos_numcolors
<= 2) {
1073 /* Under TOS, the "bright" and "dim" colors are reversed. Moreover,
1074 * on the Falcon the dim colors are *really* dim; so we make most
1075 * of the colors the bright versions, with a few exceptions where
1076 * the dim ones look OK.
1079 for (c
= 1; c
< SIZE(hilites
); c
++) {
1081 foo
= (char *) alloc(sizeof("\033b0"));
1082 if (tos_numcolors
> 4)
1083 Sprintf(foo
, "\033b%c", (c
& ~BRIGHT
) + '0');
1085 Strcpy(foo
, "\033b0");
1089 if (tos_numcolors
== 4) {
1090 TI
= "\033b0\033c3\033E\033e";
1091 TE
= "\033b3\033c0\033J";
1093 hilites
[CLR_GREEN
] = hilites
[CLR_GREEN
| BRIGHT
] = "\033b2";
1094 hilites
[CLR_RED
] = hilites
[CLR_RED
| BRIGHT
] = "\033b1";
1096 sprintf(hilites
[CLR_BROWN
], "\033b%c", (CLR_BROWN
^ BRIGHT
) + '0');
1097 sprintf(hilites
[CLR_GREEN
], "\033b%c", (CLR_GREEN
^ BRIGHT
) + '0');
1099 TI
= "\033b0\033c\017\033E\033e";
1100 TE
= "\033b\017\033c0\033J";
1102 hilites
[CLR_WHITE
] = hilites
[CLR_BLACK
] = NOCOL
;
1103 hilites
[NO_COLOR
] = hilites
[CLR_GRAY
];
1108 int backg
, foreg
, hi_backg
, hi_foreg
;
1110 for (c
= 0; c
< SIZE(hilites
); c
++)
1112 hilites
[CLR_GRAY
] = hilites
[NO_COLOR
] = (char *) 0;
1114 analyze_seq(nh_HI
, &hi_foreg
, &hi_backg
);
1115 analyze_seq(nh_HE
, &foreg
, &backg
);
1117 for (c
= 0; c
< SIZE(hilites
); c
++)
1118 /* avoid invisibility */
1119 if ((backg
& ~BRIGHT
) != c
) {
1125 hilites
[c
] = (char *) 0;
1126 else if (c
!= hi_foreg
|| backg
!= hi_backg
) {
1127 hilites
[c
] = (char *) alloc(sizeof("\033[%d;3%d;4%dm"));
1128 Sprintf(hilites
[c
], "\033[%d", !!(c
& BRIGHT
));
1129 if ((c
| BRIGHT
) != (foreg
| BRIGHT
))
1130 Sprintf(eos(hilites
[c
]), ";3%d", c
& ~BRIGHT
);
1131 if (backg
!= CLR_BLACK
)
1132 Sprintf(eos(hilites
[c
]), ";4%d", backg
& ~BRIGHT
);
1133 Strcat(hilites
[c
], "m");
1138 /* brighten low-visibility colors */
1139 hilites
[CLR_BLUE
] = hilites
[CLR_BLUE
| BRIGHT
];
1150 for (c
= 0; c
< CLR_MAX
/ 2; c
++) {
1151 if (hilites
[c
| BRIGHT
] == hilites
[c
])
1152 hilites
[c
| BRIGHT
] = 0;
1153 if (hilites
[c
] && (hilites
[c
] != nh_HI
))
1154 free((genericptr_t
) hilites
[c
]), hilites
[c
] = 0;
1155 if (hilites
[c
| BRIGHT
] && (hilites
[c
| BRIGHT
] != nh_HI
))
1156 free((genericptr_t
) hilites
[c
| BRIGHT
]), hilites
[c
| BRIGHT
] = 0;
1162 #endif /* TEXTCOLOR */
1164 static char nulstr
[] = "";
1176 #if defined(TERMLIB) && defined(TEXTCOLOR)
1205 term_start_attr(attr
)
1209 xputs(s_atr2str(attr
));
1218 xputs(e_atr2str(attr
));
1223 term_start_raw_bold()
1243 term_start_color(color
)
1246 xputs(hilites
[color
]);
1249 /* not to be confused with has_colors() in unixtty.c */
1255 /* XXX has_color() should be added to windowprocs */
1256 if (windowprocs
.name
!= NULL
&& !strcmpi(windowprocs
.name
, "X11"))
1260 /* XXX has_color() should be added to windowprocs */
1261 if (windowprocs
.name
!= NULL
&& !strcmpi(windowprocs
.name
, "Gem"))
1265 /* XXX has_color() should be added to windowprocs */
1266 if (windowprocs
.name
!= NULL
&& !strcmpi(windowprocs
.name
, "Qt"))
1269 #ifdef AMII_GRAPHICS
1270 /* hilites[] not used */
1271 return iflags
.use_color
? 1 : 0;
1273 return hilites
[color
] != (char *) 0;
1277 #endif /* TEXTCOLOR */
1279 #endif /* TTY_GRAPHICS */