+/***********************************************************************
+ Faces
+ ***********************************************************************/
+
+/* Value is non-zero if attribute ATTR may be used. ATTR should be
+ one of the enumerators from enum no_color_bit, or a bit set built
+ from them. Some display attributes may not be used together with
+ color; the termcap capability `NC' specifies which ones. */
+
+#define MAY_USE_WITH_COLORS_P(ATTR) \
+ (TN_max_colors > 0 \
+ ? (TN_no_color_video & (ATTR)) == 0 \
+ : 1)
+
+/* Turn appearances of face FACE_ID on tty frame F on. */
+
+static void
+turn_on_face (f, face_id)
+ struct frame *f;
+ int face_id;
+{
+ struct face *face = FACE_FROM_ID (f, face_id);
+ long fg = face->foreground;
+ long bg = face->background;
+
+ /* Do this first because TS_end_standout_mode may be the same
+ as TS_exit_attribute_mode, which turns all appearances off. */
+ if (MAY_USE_WITH_COLORS_P (NC_REVERSE))
+ {
+ if (TN_max_colors > 0)
+ {
+ if (fg >= 0 && bg >= 0)
+ {
+ /* If the terminal supports colors, we can set them
+ below without using reverse video. The face's fg
+ and bg colors are set as they should appear on
+ the screen, i.e. they take the inverse-video'ness
+ of the face already into account. */
+ }
+ else if (inverse_video)
+ {
+ if (fg == FACE_TTY_DEFAULT_FG_COLOR
+ || bg == FACE_TTY_DEFAULT_BG_COLOR)
+ toggle_highlight ();
+ }
+ else
+ {
+ if (fg == FACE_TTY_DEFAULT_BG_COLOR
+ || bg == FACE_TTY_DEFAULT_FG_COLOR)
+ toggle_highlight ();
+ }
+ }
+ else
+ {
+ /* If we can't display colors, use reverse video
+ if the face specifies that. */
+ if (inverse_video)
+ {
+ if (fg == FACE_TTY_DEFAULT_FG_COLOR
+ || bg == FACE_TTY_DEFAULT_BG_COLOR)
+ toggle_highlight ();
+ }
+ else
+ {
+ if (fg == FACE_TTY_DEFAULT_BG_COLOR
+ || bg == FACE_TTY_DEFAULT_FG_COLOR)
+ toggle_highlight ();
+ }
+ }
+ }
+
+ if (face->tty_bold_p)
+ {
+ if (MAY_USE_WITH_COLORS_P (NC_BOLD))
+ OUTPUT1_IF (TS_enter_bold_mode);
+ }
+ else if (face->tty_dim_p)
+ if (MAY_USE_WITH_COLORS_P (NC_DIM))
+ OUTPUT1_IF (TS_enter_dim_mode);
+
+ /* Alternate charset and blinking not yet used. */
+ if (face->tty_alt_charset_p
+ && MAY_USE_WITH_COLORS_P (NC_ALT_CHARSET))
+ OUTPUT1_IF (TS_enter_alt_charset_mode);
+
+ if (face->tty_blinking_p
+ && MAY_USE_WITH_COLORS_P (NC_BLINK))
+ OUTPUT1_IF (TS_enter_blink_mode);
+
+ if (face->tty_underline_p && MAY_USE_WITH_COLORS_P (NC_UNDERLINE))
+ OUTPUT1_IF (TS_enter_underline_mode);
+
+ if (TN_max_colors > 0)
+ {
+ char *p;
+
+ if (fg >= 0 && TS_set_foreground)
+ {
+ p = tparam (TS_set_foreground, NULL, 0, (int) fg);
+ OUTPUT (p);
+ xfree (p);
+ }
+
+ if (bg >= 0 && TS_set_background)
+ {
+ p = tparam (TS_set_background, NULL, 0, (int) bg);
+ OUTPUT (p);
+ xfree (p);
+ }
+ }
+}
+
+
+/* Turn off appearances of face FACE_ID on tty frame F. */
+
+static void
+turn_off_face (f, face_id)
+ struct frame *f;
+ int face_id;
+{
+ struct face *face = FACE_FROM_ID (f, face_id);
+
+ xassert (face != NULL);
+
+ if (TS_exit_attribute_mode)
+ {
+ /* Capability "me" will turn off appearance modes double-bright,
+ half-bright, reverse-video, standout, underline. It may or
+ may not turn off alt-char-mode. */
+ if (face->tty_bold_p
+ || face->tty_dim_p
+ || face->tty_reverse_p
+ || face->tty_alt_charset_p
+ || face->tty_blinking_p
+ || face->tty_underline_p)
+ {
+ OUTPUT1_IF (TS_exit_attribute_mode);
+ if (strcmp (TS_exit_attribute_mode, TS_end_standout_mode) == 0)
+ standout_mode = 0;
+ }
+
+ if (face->tty_alt_charset_p)
+ OUTPUT_IF (TS_exit_alt_charset_mode);
+ }
+ else
+ {
+ /* If we don't have "me" we can only have those appearances
+ that have exit sequences defined. */
+ if (face->tty_alt_charset_p)
+ OUTPUT_IF (TS_exit_alt_charset_mode);
+
+ if (face->tty_underline_p)
+ OUTPUT_IF (TS_exit_underline_mode);
+ }
+
+ /* Switch back to default colors. */
+ if (TN_max_colors > 0
+ && ((face->foreground != FACE_TTY_DEFAULT_COLOR
+ && face->foreground != FACE_TTY_DEFAULT_FG_COLOR)
+ || (face->background != FACE_TTY_DEFAULT_COLOR
+ && face->background != FACE_TTY_DEFAULT_BG_COLOR)))
+ OUTPUT1_IF (TS_orig_pair);
+}
+
+
+/* Return non-zero if the terminal on frame F supports all of the
+ capabilities in CAPS simultaneously, with foreground and background
+ colors FG and BG. */
+
+int
+tty_capable_p (f, caps, fg, bg)
+ struct frame *f;
+ unsigned caps;
+ unsigned long fg, bg;
+{
+#define TTY_CAPABLE_P_TRY(cap, TS, NC_bit) \
+ if ((caps & (cap)) && (!(TS) || !MAY_USE_WITH_COLORS_P(NC_bit))) \
+ return 0;
+
+ TTY_CAPABLE_P_TRY (TTY_CAP_INVERSE, TS_standout_mode, NC_REVERSE);
+ TTY_CAPABLE_P_TRY (TTY_CAP_UNDERLINE, TS_enter_underline_mode, NC_UNDERLINE);
+ TTY_CAPABLE_P_TRY (TTY_CAP_BOLD, TS_enter_bold_mode, NC_BOLD);
+ TTY_CAPABLE_P_TRY (TTY_CAP_DIM, TS_enter_dim_mode, NC_DIM);
+ TTY_CAPABLE_P_TRY (TTY_CAP_BLINK, TS_enter_blink_mode, NC_BLINK);
+ TTY_CAPABLE_P_TRY (TTY_CAP_ALT_CHARSET, TS_enter_alt_charset_mode, NC_ALT_CHARSET);
+
+ /* We can do it! */
+ return 1;
+}
+
+
+/* Return non-zero if the terminal is capable to display colors. */
+
+DEFUN ("tty-display-color-p", Ftty_display_color_p, Stty_display_color_p,
+ 0, 1, 0,
+ doc: /* Return non-nil if TTY can display colors on DISPLAY. */)
+ (display)
+ Lisp_Object display;
+{
+ return TN_max_colors > 0 ? Qt : Qnil;
+}
+
+/* Return the number of supported colors. */
+DEFUN ("tty-display-color-cells", Ftty_display_color_cells,
+ Stty_display_color_cells, 0, 1, 0,
+ doc: /* Return the number of colors supported by TTY on DISPLAY. */)
+ (display)
+ Lisp_Object display;
+{
+ return make_number (TN_max_colors);
+}
+
+#ifndef WINDOWSNT
+
+/* Save or restore the default color-related capabilities of this
+ terminal. */
+static void
+tty_default_color_capabilities (save)
+ int save;
+{
+ static char
+ *default_orig_pair, *default_set_foreground, *default_set_background;
+ static int default_max_colors, default_max_pairs, default_no_color_video;
+
+ if (save)
+ {
+ if (default_orig_pair)
+ xfree (default_orig_pair);
+ default_orig_pair = TS_orig_pair ? xstrdup (TS_orig_pair) : NULL;
+
+ if (default_set_foreground)
+ xfree (default_set_foreground);
+ default_set_foreground = TS_set_foreground ? xstrdup (TS_set_foreground)
+ : NULL;
+
+ if (default_set_background)
+ xfree (default_set_background);
+ default_set_background = TS_set_background ? xstrdup (TS_set_background)
+ : NULL;
+
+ default_max_colors = TN_max_colors;
+ default_max_pairs = TN_max_pairs;
+ default_no_color_video = TN_no_color_video;
+ }
+ else
+ {
+ TS_orig_pair = default_orig_pair;
+ TS_set_foreground = default_set_foreground;
+ TS_set_background = default_set_background;
+ TN_max_colors = default_max_colors;
+ TN_max_pairs = default_max_pairs;
+ TN_no_color_video = default_no_color_video;
+ }
+}
+
+/* Setup one of the standard tty color schemes according to MODE.
+ MODE's value is generally the number of colors which we want to
+ support; zero means set up for the default capabilities, the ones
+ we saw at term_init time; -1 means turn off color support. */
+void
+tty_setup_colors (mode)
+ int mode;
+{
+ switch (mode)
+ {
+ case -1: /* no colors at all */
+ TN_max_colors = 0;
+ TN_max_pairs = 0;
+ TN_no_color_video = 0;
+ TS_set_foreground = TS_set_background = TS_orig_pair = NULL;
+ break;
+ case 0: /* default colors, if any */
+ default:
+ tty_default_color_capabilities (0);
+ break;
+ case 8: /* 8 standard ANSI colors */
+ TS_orig_pair = "\033[0m";
+#ifdef TERMINFO
+ TS_set_foreground = "\033[3%p1%dm";
+ TS_set_background = "\033[4%p1%dm";
+#else
+ TS_set_foreground = "\033[3%dm";
+ TS_set_background = "\033[4%dm";
+#endif
+ TN_max_colors = 8;
+ TN_max_pairs = 64;
+ TN_no_color_video = 0;
+ break;
+ }
+}
+
+void
+set_tty_color_mode (f, val)
+ struct frame *f;
+ Lisp_Object val;
+{
+ Lisp_Object color_mode_spec, current_mode_spec;
+ Lisp_Object color_mode, current_mode;
+ int mode, old_mode;
+ extern Lisp_Object Qtty_color_mode;
+ Lisp_Object tty_color_mode_alist;
+
+ tty_color_mode_alist = Fintern_soft (build_string ("tty-color-mode-alist"),
+ Qnil);
+
+ if (NATNUMP (val))
+ color_mode = val;
+ else
+ {
+ if (NILP (tty_color_mode_alist))
+ color_mode_spec = Qnil;
+ else
+ color_mode_spec = Fassq (val, XSYMBOL (tty_color_mode_alist)->value);
+ current_mode_spec = assq_no_quit (Qtty_color_mode, f->param_alist);
+
+ if (CONSP (color_mode_spec))
+ color_mode = XCDR (color_mode_spec);
+ else
+ color_mode = Qnil;
+ }
+ if (CONSP (current_mode_spec))
+ current_mode = XCDR (current_mode_spec);
+ else
+ current_mode = Qnil;
+ if (NATNUMP (color_mode))
+ mode = XINT (color_mode);
+ else
+ mode = 0; /* meaning default */
+ if (NATNUMP (current_mode))
+ old_mode = XINT (current_mode);
+ else
+ old_mode = 0;
+
+ if (mode != old_mode)
+ {
+ tty_setup_colors (mode);
+ /* This recomputes all the faces given the new color
+ definitions. */
+ call0 (intern ("tty-set-up-initial-frame-faces"));
+ redraw_frame (f);
+ }
+}
+
+#endif /* !WINDOWSNT */
+
+\f
+/***********************************************************************
+ Initialization
+ ***********************************************************************/
+
+void