+/***********************************************************************
+ Character Display Information
+ ***********************************************************************/
+
+static void append_glyph P_ ((struct it *));
+
+
+/* Append glyphs to IT's glyph_row. Called from produce_glyphs for
+ terminal frames if IT->glyph_row != NULL. IT->c is the character
+ for which to produce glyphs; IT->face_id contains the character's
+ face. Padding glyphs are appended if IT->c has a IT->pixel_width >
+ 1. */
+
+static void
+append_glyph (it)
+ struct it *it;
+{
+ struct glyph *glyph, *end;
+ int i;
+
+ xassert (it->glyph_row);
+ glyph = (it->glyph_row->glyphs[it->area]
+ + it->glyph_row->used[it->area]);
+ end = it->glyph_row->glyphs[1 + it->area];
+
+ for (i = 0;
+ i < it->pixel_width && glyph < end;
+ ++i)
+ {
+ glyph->type = CHAR_GLYPH;
+ glyph->pixel_width = 1;
+ glyph->u.ch = it->c;
+ glyph->face_id = it->face_id;
+ glyph->padding_p = i > 0;
+ glyph->charpos = CHARPOS (it->position);
+ glyph->object = it->object;
+
+ ++it->glyph_row->used[it->area];
+ ++glyph;
+ }
+}
+
+
+/* Produce glyphs for the display element described by IT. The
+ function fills output fields of IT with pixel information like the
+ pixel width and height of a character, and maybe produces glyphs at
+ the same time if IT->glyph_row is non-null. See the explanation of
+ struct display_iterator in dispextern.h for an overview. */
+
+void
+produce_glyphs (it)
+ struct it *it;
+{
+ /* If a hook is installed, let it do the work. */
+ xassert (it->what == IT_CHARACTER
+ || it->what == IT_COMPOSITION
+ || it->what == IT_IMAGE
+ || it->what == IT_STRETCH);
+
+ /* Nothing but characters are supported on terminal frames. For a
+ composition sequence, it->c is the first character of the
+ sequence. */
+ xassert (it->what == IT_CHARACTER
+ || it->what == IT_COMPOSITION);
+
+ if (it->c >= 040 && it->c < 0177)
+ {
+ it->pixel_width = it->nglyphs = 1;
+ if (it->glyph_row)
+ append_glyph (it);
+ }
+ else if (it->c == '\n')
+ it->pixel_width = it->nglyphs = 0;
+ else if (it->c == '\t')
+ {
+ int absolute_x = (it->current_x
+ + it->continuation_lines_width);
+ int next_tab_x
+ = (((1 + absolute_x + it->tab_width - 1)
+ / it->tab_width)
+ * it->tab_width);
+ int nspaces;
+
+ /* If part of the TAB has been displayed on the previous line
+ which is continued now, continuation_lines_width will have
+ been incremented already by the part that fitted on the
+ continued line. So, we will get the right number of spaces
+ here. */
+ nspaces = next_tab_x - absolute_x;
+
+ if (it->glyph_row)
+ {
+ int n = nspaces;
+
+ it->c = ' ';
+ it->pixel_width = it->len = 1;
+
+ while (n--)
+ append_glyph (it);
+
+ it->c = '\t';
+ }
+
+ it->pixel_width = nspaces;
+ it->nglyphs = nspaces;
+ }
+ else if (SINGLE_BYTE_CHAR_P (it->c))
+ {
+ /* Coming here means that it->c is from display table, thus we
+ must send the code as is to the terminal. Although there's
+ no way to know how many columns it occupies on a screen, it
+ is a good assumption that a single byte code has 1-column
+ width. */
+ it->pixel_width = it->nglyphs = 1;
+ if (it->glyph_row)
+ append_glyph (it);
+ }
+ else
+ {
+ /* A multi-byte character. The display width is fixed for all
+ characters of the set. Some of the glyphs may have to be
+ ignored because they are already displayed in a continued
+ line. */
+ int charset = CHAR_CHARSET (it->c);
+
+ it->pixel_width = CHARSET_WIDTH (charset);
+ it->nglyphs = it->pixel_width;
+
+ if (it->glyph_row)
+ append_glyph (it);
+ }
+
+ /* Advance current_x by the pixel width as a convenience for
+ the caller. */
+ if (it->area == TEXT_AREA)
+ it->current_x += it->pixel_width;
+ it->ascent = it->max_ascent = it->phys_ascent = it->max_phys_ascent = 0;
+ it->descent = it->max_descent = it->phys_descent = it->max_phys_descent = 1;
+}
+
+
+/* Get information about special display element WHAT in an
+ environment described by IT. WHAT is one of IT_TRUNCATION or
+ IT_CONTINUATION. Maybe produce glyphs for WHAT if IT has a
+ non-null glyph_row member. This function ensures that fields like
+ face_id, c, len of IT are left untouched. */
+
+void
+produce_special_glyphs (it, what)
+ struct it *it;
+ enum display_element_type what;
+{
+ struct it temp_it;
+
+ temp_it = *it;
+ temp_it.dp = NULL;
+ temp_it.what = IT_CHARACTER;
+ temp_it.len = 1;
+ temp_it.object = make_number (0);
+ bzero (&temp_it.current, sizeof temp_it.current);
+
+ if (what == IT_CONTINUATION)
+ {
+ /* Continuation glyph. */
+ if (it->dp
+ && INTEGERP (DISP_CONTINUE_GLYPH (it->dp))
+ && GLYPH_CHAR_VALID_P (XINT (DISP_CONTINUE_GLYPH (it->dp))))
+ {
+ temp_it.c = FAST_GLYPH_CHAR (XINT (DISP_CONTINUE_GLYPH (it->dp)));
+ temp_it.len = CHAR_BYTES (temp_it.c);
+ }
+ else
+ temp_it.c = '\\';
+
+ produce_glyphs (&temp_it);
+ it->pixel_width = temp_it.pixel_width;
+ it->nglyphs = temp_it.pixel_width;
+ }
+ else if (what == IT_TRUNCATION)
+ {
+ /* Truncation glyph. */
+ if (it->dp
+ && INTEGERP (DISP_TRUNC_GLYPH (it->dp))
+ && GLYPH_CHAR_VALID_P (XINT (DISP_TRUNC_GLYPH (it->dp))))
+ {
+ temp_it.c = FAST_GLYPH_CHAR (XINT (DISP_TRUNC_GLYPH (it->dp)));
+ temp_it.len = CHAR_BYTES (temp_it.c);
+ }
+ else
+ temp_it.c = '$';
+
+ produce_glyphs (&temp_it);
+ it->pixel_width = temp_it.pixel_width;
+ it->nglyphs = temp_it.pixel_width;
+ }
+ else
+ abort ();
+}
+
+
+/* Return an estimation of the pixel height of mode or top lines on
+ frame F. FACE_ID specifies what line's height to estimate. */
+
+int
+estimate_mode_line_height (f, face_id)
+ struct frame *f;
+ enum face_id face_id;
+{
+ if (estimate_mode_line_height_hook)
+ return estimate_mode_line_height_hook (f, face_id);
+ else
+ return 1;
+}
+
+
+\f
+/***********************************************************************
+ 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 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 FRAME. */)
+ (frame)
+ Lisp_Object frame;
+{
+ return TN_max_colors > 0 ? Qt : Qnil;
+}
+
+
+
+\f
+/***********************************************************************
+ Initialization
+ ***********************************************************************/
+
+void