+ Fdefine_key (Vfunction_key_map, build_string (sequence),
+ Fmake_vector (make_number (1),
+ intern (keys[i].name)));
+ }
+
+ /* The uses of the "k0" capability are inconsistent; sometimes it
+ describes F10, whereas othertimes it describes F0 and "k;" describes F10.
+ We will attempt to politely accommodate both systems by testing for
+ "k;", and if it is present, assuming that "k0" denotes F0, otherwise F10.
+ */
+ {
+ char *k_semi = tgetstr ("k;", address);
+ char *k0 = tgetstr ("k0", address);
+ char *k0_name = "f10";
+
+ if (k_semi)
+ {
+ Fdefine_key (Vfunction_key_map, build_string (k_semi),
+ Fmake_vector (make_number (1), intern ("f10")));
+ k0_name = "f0";
+ }
+
+ if (k0)
+ Fdefine_key (Vfunction_key_map, build_string (k0),
+ Fmake_vector (make_number (1), intern (k0_name)));
+ }
+
+ /* Set up cookies for numbered function keys above f10. */
+ {
+ char fcap[3], fkey[4];
+
+ fcap[0] = 'F'; fcap[2] = '\0';
+ for (i = 11; i < 64; i++)
+ {
+ if (i <= 19)
+ fcap[1] = '1' + i - 11;
+ else if (i <= 45)
+ fcap[1] = 'A' + i - 20;
+ else
+ fcap[1] = 'a' + i - 46;
+
+ {
+ char *sequence = tgetstr (fcap, address);
+ if (sequence)
+ {
+ sprintf (fkey, "f%d", i);
+ Fdefine_key (Vfunction_key_map, build_string (sequence),
+ Fmake_vector (make_number (1),
+ intern (fkey)));
+ }
+ }
+ }
+ }
+
+ /*
+ * Various mappings to try and get a better fit.
+ */
+ {
+#define CONDITIONAL_REASSIGN(cap1, cap2, sym) \
+ if (!tgetstr (cap1, address)) \
+ { \
+ char *sequence = tgetstr (cap2, address); \
+ if (sequence) \
+ Fdefine_key (Vfunction_key_map, build_string (sequence), \
+ Fmake_vector (make_number (1), \
+ intern (sym))); \
+ }
+
+ /* if there's no key_next keycap, map key_npage to `next' keysym */
+ CONDITIONAL_REASSIGN ("%5", "kN", "next");
+ /* if there's no key_prev keycap, map key_ppage to `previous' keysym */
+ CONDITIONAL_REASSIGN ("%8", "kP", "prior");
+ /* if there's no key_dc keycap, map key_ic to `insert' keysym */
+ CONDITIONAL_REASSIGN ("kD", "kI", "insert");
+ /* if there's no key_end keycap, map key_ll to 'end' keysym */
+ CONDITIONAL_REASSIGN ("@7", "kH", "end");
+
+ /* IBM has their own non-standard dialect of terminfo.
+ If the standard name isn't found, try the IBM name. */
+ CONDITIONAL_REASSIGN ("kB", "KO", "backtab");
+ CONDITIONAL_REASSIGN ("@4", "kJ", "execute"); /* actually "action" */
+ CONDITIONAL_REASSIGN ("@4", "kc", "execute"); /* actually "command" */
+ CONDITIONAL_REASSIGN ("%7", "ki", "menu");
+ CONDITIONAL_REASSIGN ("@7", "kw", "end");
+ CONDITIONAL_REASSIGN ("F1", "k<", "f11");
+ CONDITIONAL_REASSIGN ("F2", "k>", "f12");
+ CONDITIONAL_REASSIGN ("%1", "kq", "help");
+ CONDITIONAL_REASSIGN ("*6", "kU", "select");
+#undef CONDITIONAL_REASSIGN
+ }
+
+ return Qnil;
+}
+
+\f
+/***********************************************************************
+ 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.code = it->c;
+ glyph->u.ch.face_id = it->face_id;
+ glyph->u.ch.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_IMAGE
+ || it->what == IT_STRETCH);
+
+ /* Nothing but characters are supported on terminal frames. */
+ xassert (it->what == IT_CHARACTER);
+
+ 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->prompt_width
+ + 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
+ {
+ /* A multi-byte character. The display width is a per character
+ value for characters of set CHARSET_COMPOSITION; otherwise
+ it 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);
+
+ if (charset == CHARSET_COMPOSITION)
+ it->pixel_width = cmpchar_table[COMPOSITE_CHAR_ID (it->c)]->width;
+ else
+ 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 = 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_LEN (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_LEN (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
+ ***********************************************************************/
+
+
+/* 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);
+
+ xassert (face != NULL);
+
+ if (face->tty_bold_p)
+ OUTPUT1_IF (TS_enter_bold_mode);
+ else if (face->tty_dim_p)
+ OUTPUT1_IF (TS_enter_dim_mode);
+
+ /* Alternate charset and blinking not yet used. */
+ if (face->tty_alt_charset_p)
+ OUTPUT1_IF (TS_enter_alt_charset_mode);
+
+ if (face->tty_blinking_p)
+ OUTPUT1_IF (TS_enter_blink_mode);
+
+ if (face->tty_underline_p
+ /* Don't underline if that's difficult. */
+ && TN_magic_cookie_glitch_ul <= 0)
+ OUTPUT1_IF (TS_enter_underline_mode);
+
+ if (face->tty_reverse_p)
+ OUTPUT1_IF (TS_enter_reverse_mode);
+
+ if (TN_max_colors > 0)
+ {
+ char *p;
+
+ if (face->foreground != FACE_TTY_DEFAULT_COLOR
+ && TS_set_foreground)
+ {
+ p = tparam (TS_set_foreground, NULL, 0, (int) face->foreground);
+ OUTPUT (p);
+ xfree (p);
+ }
+
+ if (face->background != FACE_TTY_DEFAULT_COLOR
+ && TS_set_background)
+ {
+ p = tparam (TS_set_background, NULL, 0, (int) face->background);
+ OUTPUT (p);
+ xfree (p);
+ }