root/src/term.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. tty_ring_bell
  2. tty_send_additional_strings
  3. tty_set_terminal_modes
  4. tty_reset_terminal_modes
  5. tty_update_end
  6. tty_set_terminal_window
  7. tty_set_scroll_region
  8. tty_turn_on_insert
  9. tty_turn_off_insert
  10. tty_turn_off_highlight
  11. tty_turn_on_highlight
  12. tty_toggle_highlight
  13. tty_hide_cursor
  14. tty_show_cursor
  15. tty_background_highlight
  16. tty_highlight_if_desired
  17. tty_cursor_to
  18. tty_raw_cursor_to
  19. tty_clear_to_end
  20. tty_clear_frame
  21. tty_clear_end_of_line
  22. encode_terminal_code
  23. tty_write_glyphs
  24. tty_write_glyphs_with_face
  25. tty_insert_glyphs
  26. tty_delete_glyphs
  27. tty_ins_del_lines
  28. string_cost
  29. string_cost_one_line
  30. per_line_cost
  31. calculate_ins_del_char_costs
  32. calculate_costs
  33. term_get_fkeys
  34. term_get_fkeys_1
  35. append_glyph
  36. tty_append_glyph
  37. produce_glyphs
  38. append_composite_glyph
  39. produce_composite_glyph
  40. append_glyphless_glyph
  41. produce_glyphless_glyph
  42. turn_on_face
  43. turn_off_face
  44. tty_capable_p
  45. DEFUN
  46. DEFUN
  47. tty_default_color_capabilities
  48. tty_setup_colors
  49. set_tty_color_mode
  50. tty_type_name
  51. DEFUN
  52. DEFUN
  53. DEFUN
  54. DEFUN
  55. DEFUN
  56. DEFUN
  57. DEFUN
  58. tty_draw_row_with_mouse_face
  59. term_mouse_moveto
  60. current_Time
  61. term_mouse_position
  62. term_mouse_click
  63. handle_one_term_event
  64. DEFUN
  65. close_gpm
  66. DEFUN
  67. tty_menu_create
  68. tty_menu_make_room
  69. tty_menu_search_pane
  70. tty_menu_calc_size
  71. mouse_get_xy
  72. tty_menu_display
  73. tty_menu_add_pane
  74. tty_menu_add_selection
  75. tty_menu_locate
  76. save_and_enable_current_matrix
  77. restore_desired_matrix
  78. free_saved_screen
  79. screen_update
  80. read_menu_input
  81. tty_menu_activate
  82. tty_menu_destroy
  83. tty_menu_help_callback
  84. tty_pop_down_menu
  85. tty_menu_last_menubar_item
  86. tty_menu_new_item_coords
  87. tty_menu_show
  88. create_tty_output
  89. tty_free_frame_resources
  90. tty_free_frame_resources
  91. clear_tty_hooks
  92. set_tty_hooks
  93. dissociate_if_controlling_tty
  94. init_tty
  95. vfatal
  96. maybe_fatal
  97. fatal
  98. delete_tty
  99. syms_of_term

     1 /* Terminal control module for terminals described by TERMCAP
     2    Copyright (C) 1985-1987, 1993-1995, 1998, 2000-2023 Free Software
     3    Foundation, Inc.
     4 
     5 This file is part of GNU Emacs.
     6 
     7 GNU Emacs is free software: you can redistribute it and/or modify
     8 it under the terms of the GNU General Public License as published by
     9 the Free Software Foundation, either version 3 of the License, or (at
    10 your option) any later version.
    11 
    12 GNU Emacs is distributed in the hope that it will be useful,
    13 but WITHOUT ANY WARRANTY; without even the implied warranty of
    14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    15 GNU General Public License for more details.
    16 
    17 You should have received a copy of the GNU General Public License
    18 along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.  */
    19 
    20 /* New redisplay, TTY faces by Gerd Moellmann <gerd@gnu.org>.  */
    21 
    22 #include <config.h>
    23 #include <errno.h>
    24 #include <fcntl.h>
    25 #include <stdlib.h>
    26 #include <sys/file.h>
    27 #include <sys/time.h>
    28 #include <unistd.h>
    29 
    30 #include "lisp.h"
    31 #include "termchar.h"
    32 #include "tparam.h"
    33 #include "character.h"
    34 #include "buffer.h"
    35 #include "charset.h"
    36 #include "coding.h"
    37 #include "composite.h"
    38 #include "keyboard.h"
    39 #include "frame.h"
    40 #include "disptab.h"
    41 #include "termhooks.h"
    42 #include "dispextern.h"
    43 #include "window.h"
    44 #include "keymap.h"
    45 #include "blockinput.h"
    46 #include "syssignal.h"
    47 #include "sysstdio.h"
    48 #ifdef MSDOS
    49 #include "msdos.h"
    50 static int been_here = -1;
    51 #endif
    52 
    53 #ifdef USE_X_TOOLKIT
    54 #include "../lwlib/lwlib.h"
    55 #endif
    56 
    57 #include "cm.h"
    58 #include "menu.h"
    59 
    60 /* The name of the default console device.  */
    61 #ifdef WINDOWSNT
    62 #include "w32term.h"
    63 #endif
    64 
    65 static void tty_set_scroll_region (struct frame *f, int start, int stop);
    66 static void turn_on_face (struct frame *, int face_id);
    67 static void turn_off_face (struct frame *, int face_id);
    68 static void tty_turn_off_highlight (struct tty_display_info *);
    69 static void tty_show_cursor (struct tty_display_info *);
    70 static void tty_hide_cursor (struct tty_display_info *);
    71 static void tty_background_highlight (struct tty_display_info *tty);
    72 static void clear_tty_hooks (struct terminal *terminal);
    73 static void set_tty_hooks (struct terminal *terminal);
    74 static void dissociate_if_controlling_tty (int fd);
    75 static void delete_tty (struct terminal *);
    76 static AVOID maybe_fatal (bool, struct terminal *, const char *, const char *,
    77                           ...)
    78   ATTRIBUTE_FORMAT_PRINTF (3, 5) ATTRIBUTE_FORMAT_PRINTF (4, 5);
    79 static AVOID vfatal (const char *, va_list) ATTRIBUTE_FORMAT_PRINTF (1, 0);
    80 
    81 
    82 #define OUTPUT(tty, a)                                          \
    83   emacs_tputs ((tty), a,                                        \
    84                FRAME_TOTAL_LINES (XFRAME (selected_frame)) - curY (tty),        \
    85                cmputc)
    86 
    87 #define OUTPUT1(tty, a) emacs_tputs ((tty), a, 1, cmputc)
    88 #define OUTPUTL(tty, a, lines) emacs_tputs ((tty), a, lines, cmputc)
    89 
    90 #define OUTPUT_IF(tty, a)                                               \
    91   do {                                                                  \
    92     if (a)                                                              \
    93       OUTPUT (tty, a);                                                  \
    94   } while (0)
    95 
    96 #define OUTPUT1_IF(tty, a) do { if (a) emacs_tputs ((tty), a, 1, cmputc); } while (0)
    97 
    98 /* Display space properties.  */
    99 
   100 /* Chain of all tty device parameters.  */
   101 struct tty_display_info *tty_list;
   102 
   103 /* Meaning of bits in no_color_video.  Each bit set means that the
   104    corresponding attribute cannot be combined with colors.  */
   105 
   106 enum no_color_bit
   107 {
   108   NC_STANDOUT            = 1 << 0,
   109   NC_UNDERLINE           = 1 << 1,
   110   NC_REVERSE             = 1 << 2,
   111   NC_ITALIC              = 1 << 3,
   112   NC_DIM                 = 1 << 4,
   113   NC_BOLD                = 1 << 5,
   114   NC_STRIKE_THROUGH      = 1 << 6,
   115   NC_PROTECT             = 1 << 7
   116 };
   117 
   118 /* internal state */
   119 
   120 /* The largest frame width in any call to calculate_costs.  */
   121 
   122 static int max_frame_cols;
   123 
   124 
   125 
   126 #ifdef HAVE_GPM
   127 #include <sys/fcntl.h>
   128 
   129 /* The device for which we have enabled gpm support (or NULL).  */
   130 struct tty_display_info *gpm_tty = NULL;
   131 
   132 /* Last recorded mouse coordinates.  */
   133 static int last_mouse_x, last_mouse_y;
   134 #endif /* HAVE_GPM */
   135 
   136 /* Ring the bell on a tty. */
   137 
   138 static void
   139 tty_ring_bell (struct frame *f)
   140 {
   141   struct tty_display_info *tty = FRAME_TTY (f);
   142 
   143   if (tty->output)
   144     {
   145       OUTPUT (tty, (tty->TS_visible_bell && visible_bell
   146                     ? tty->TS_visible_bell
   147                     : tty->TS_bell));
   148       fflush (tty->output);
   149     }
   150 }
   151 
   152 /* Set up termcap modes for Emacs. */
   153 
   154 static void
   155 tty_send_additional_strings (struct terminal *terminal, Lisp_Object sym)
   156 {
   157   /* Use only accessors like CDR_SAFE and assq_no_quit to avoid any
   158      form of quitting or signaling an error, since this function can
   159      run as part of the "emergency escape" procedure invoked in the
   160      middle of GC, where quitting means crashing (Bug#17406).  */
   161   if (! terminal->name)
   162     return;
   163   struct tty_display_info *tty = terminal->display_info.tty;
   164 
   165   for (Lisp_Object extra_codes
   166          = CDR_SAFE (assq_no_quit (sym, terminal->param_alist));
   167        CONSP (extra_codes);
   168        extra_codes = XCDR (extra_codes))
   169     {
   170       Lisp_Object string = XCAR (extra_codes);
   171       if (STRINGP (string))
   172         {
   173           fwrite (SDATA (string), 1, SBYTES (string), tty->output);
   174           if (tty->termscript)
   175             fwrite (SDATA (string), 1, SBYTES (string), tty->termscript);
   176         }
   177     }
   178 }
   179 
   180 static void
   181 tty_set_terminal_modes (struct terminal *terminal)
   182 {
   183   struct tty_display_info *tty = terminal->display_info.tty;
   184 
   185   if (tty->output)
   186     {
   187       if (tty->TS_termcap_modes)
   188         OUTPUT (tty, tty->TS_termcap_modes);
   189       else
   190         {
   191           /* Output enough newlines to scroll all the old screen contents
   192              off the screen, so it won't be overwritten and lost.  */
   193           int i;
   194           current_tty = tty;
   195           for (i = 0; i < FRAME_TOTAL_LINES (XFRAME (selected_frame)); i++)
   196             cmputc ('\n');
   197         }
   198 
   199       OUTPUT_IF (tty, visible_cursor ? tty->TS_cursor_visible : tty->TS_cursor_normal);
   200       OUTPUT_IF (tty, tty->TS_keypad_mode);
   201       losecursor (tty);
   202       tty_send_additional_strings (terminal, Qtty_mode_set_strings);
   203       fflush (tty->output);
   204     }
   205 }
   206 
   207 /* Reset termcap modes before exiting Emacs. */
   208 
   209 static void
   210 tty_reset_terminal_modes (struct terminal *terminal)
   211 {
   212   struct tty_display_info *tty = terminal->display_info.tty;
   213 
   214   if (tty->output)
   215     {
   216       tty_send_additional_strings (terminal, Qtty_mode_reset_strings);
   217       tty_turn_off_highlight (tty);
   218       tty_turn_off_insert (tty);
   219       OUTPUT_IF (tty, tty->TS_end_keypad_mode);
   220       OUTPUT_IF (tty, tty->TS_cursor_normal);
   221       OUTPUT_IF (tty, tty->TS_end_termcap_modes);
   222       OUTPUT_IF (tty, tty->TS_orig_pair);
   223       /* Output raw CR so kernel can track the cursor hpos.  */
   224       current_tty = tty;
   225       cmputc ('\r');
   226       fflush (tty->output);
   227     }
   228 }
   229 
   230 /* Flag the end of a display update on a termcap terminal. */
   231 
   232 static void
   233 tty_update_end (struct frame *f)
   234 {
   235   struct tty_display_info *tty = FRAME_TTY (f);
   236 
   237   if (!XWINDOW (selected_window)->cursor_off_p)
   238     tty_show_cursor (tty);
   239   tty_turn_off_insert (tty);
   240   tty_background_highlight (tty);
   241   fflush (tty->output);
   242 }
   243 
   244 /* The implementation of set_terminal_window for termcap frames. */
   245 
   246 static void
   247 tty_set_terminal_window (struct frame *f, int size)
   248 {
   249   struct tty_display_info *tty = FRAME_TTY (f);
   250 
   251   tty->specified_window = size ? size : FRAME_TOTAL_LINES (f);
   252   if (FRAME_SCROLL_REGION_OK (f))
   253     tty_set_scroll_region (f, 0, tty->specified_window);
   254 }
   255 
   256 static void
   257 tty_set_scroll_region (struct frame *f, int start, int stop)
   258 {
   259   char *buf;
   260   struct tty_display_info *tty = FRAME_TTY (f);
   261 
   262   if (tty->TS_set_scroll_region)
   263     buf = tparam (tty->TS_set_scroll_region, 0, 0, start, stop - 1, 0, 0);
   264   else if (tty->TS_set_scroll_region_1)
   265     buf = tparam (tty->TS_set_scroll_region_1, 0, 0,
   266                   FRAME_TOTAL_LINES (f), start,
   267                   FRAME_TOTAL_LINES (f) - stop,
   268                   FRAME_TOTAL_LINES (f));
   269   else
   270     buf = tparam (tty->TS_set_window, 0, 0, start, 0, stop, FRAME_COLS (f));
   271 
   272   OUTPUT (tty, buf);
   273   xfree (buf);
   274   losecursor (tty);
   275 }
   276 
   277 
   278 static void
   279 tty_turn_on_insert (struct tty_display_info *tty)
   280 {
   281   if (!tty->insert_mode)
   282     OUTPUT (tty, tty->TS_insert_mode);
   283   tty->insert_mode = 1;
   284 }
   285 
   286 void
   287 tty_turn_off_insert (struct tty_display_info *tty)
   288 {
   289   if (tty->insert_mode)
   290     OUTPUT (tty, tty->TS_end_insert_mode);
   291   tty->insert_mode = 0;
   292 }
   293 
   294 /* Handle highlighting.  */
   295 
   296 static void
   297 tty_turn_off_highlight (struct tty_display_info *tty)
   298 {
   299   if (tty->standout_mode)
   300     OUTPUT_IF (tty, tty->TS_end_standout_mode);
   301   tty->standout_mode = 0;
   302 }
   303 
   304 static void
   305 tty_turn_on_highlight (struct tty_display_info *tty)
   306 {
   307   if (!tty->standout_mode)
   308     OUTPUT_IF (tty, tty->TS_standout_mode);
   309   tty->standout_mode = 1;
   310 }
   311 
   312 static void
   313 tty_toggle_highlight (struct tty_display_info *tty)
   314 {
   315   if (tty->standout_mode)
   316     tty_turn_off_highlight (tty);
   317   else
   318     tty_turn_on_highlight (tty);
   319 }
   320 
   321 
   322 /* Make cursor invisible.  */
   323 
   324 static void
   325 tty_hide_cursor (struct tty_display_info *tty)
   326 {
   327   if (tty->cursor_hidden == 0)
   328     {
   329       tty->cursor_hidden = 1;
   330 #ifdef WINDOWSNT
   331       w32con_hide_cursor ();
   332 #else
   333       OUTPUT_IF (tty, tty->TS_cursor_invisible);
   334 #endif
   335     }
   336 }
   337 
   338 
   339 /* Ensure that cursor is visible.  */
   340 
   341 static void
   342 tty_show_cursor (struct tty_display_info *tty)
   343 {
   344   if (tty->cursor_hidden)
   345     {
   346       tty->cursor_hidden = 0;
   347 #ifdef WINDOWSNT
   348       w32con_show_cursor ();
   349 #else
   350       OUTPUT_IF (tty, tty->TS_cursor_normal);
   351       if (visible_cursor)
   352         OUTPUT_IF (tty, tty->TS_cursor_visible);
   353 #endif
   354     }
   355 }
   356 
   357 
   358 /* Set standout mode to the state it should be in for
   359    empty space inside windows.  What this is,
   360    depends on the user option inverse-video.  */
   361 
   362 static void
   363 tty_background_highlight (struct tty_display_info *tty)
   364 {
   365   if (inverse_video)
   366     tty_turn_on_highlight (tty);
   367   else
   368     tty_turn_off_highlight (tty);
   369 }
   370 
   371 /* Set standout mode to the mode specified for the text to be output.  */
   372 
   373 static void
   374 tty_highlight_if_desired (struct tty_display_info *tty)
   375 {
   376   if (inverse_video)
   377     tty_turn_on_highlight (tty);
   378   else
   379     tty_turn_off_highlight (tty);
   380 }
   381 
   382 
   383 /* Move cursor to row/column position VPOS/HPOS.  HPOS/VPOS are
   384    frame-relative coordinates.  */
   385 
   386 static void
   387 tty_cursor_to (struct frame *f, int vpos, int hpos)
   388 {
   389   struct tty_display_info *tty = FRAME_TTY (f);
   390 
   391   /* Detect the case where we are called from reset_sys_modes
   392      and the costs have never been calculated.  Do nothing.  */
   393   if (! tty->costs_set)
   394     return;
   395 
   396   if (curY (tty) == vpos
   397       && curX (tty) == hpos)
   398     return;
   399   if (!tty->TF_standout_motion)
   400     tty_background_highlight (tty);
   401   if (!tty->TF_insmode_motion)
   402     tty_turn_off_insert (tty);
   403   cmgoto (tty, vpos, hpos);
   404 }
   405 
   406 /* Similar but don't take any account of the wasted characters.  */
   407 
   408 static void
   409 tty_raw_cursor_to (struct frame *f, int row, int col)
   410 {
   411   struct tty_display_info *tty = FRAME_TTY (f);
   412 
   413   if (curY (tty) == row
   414       && curX (tty) == col)
   415     return;
   416   if (!tty->TF_standout_motion)
   417     tty_background_highlight (tty);
   418   if (!tty->TF_insmode_motion)
   419     tty_turn_off_insert (tty);
   420   cmgoto (tty, row, col);
   421 }
   422 
   423 /* Erase operations */
   424 
   425 /* Clear from cursor to end of frame on a termcap device. */
   426 
   427 static void
   428 tty_clear_to_end (struct frame *f)
   429 {
   430   register int i;
   431   struct tty_display_info *tty = FRAME_TTY (f);
   432 
   433   if (tty->TS_clr_to_bottom)
   434     {
   435       tty_background_highlight (tty);
   436       OUTPUT (tty, tty->TS_clr_to_bottom);
   437     }
   438   else
   439     {
   440       for (i = curY (tty); i < FRAME_TOTAL_LINES (f); i++)
   441         {
   442           cursor_to (f, i, 0);
   443           clear_end_of_line (f, FRAME_COLS (f));
   444         }
   445     }
   446 }
   447 
   448 /* Clear an entire termcap frame. */
   449 
   450 static void
   451 tty_clear_frame (struct frame *f)
   452 {
   453   struct tty_display_info *tty = FRAME_TTY (f);
   454 
   455   if (tty->TS_clr_frame)
   456     {
   457       tty_background_highlight (tty);
   458       OUTPUT (tty, tty->TS_clr_frame);
   459       cmat (tty, 0, 0);
   460     }
   461   else
   462     {
   463       cursor_to (f, 0, 0);
   464       clear_to_end (f);
   465     }
   466 }
   467 
   468 /* An implementation of clear_end_of_line for termcap frames.
   469 
   470    Note that the cursor may be moved, on terminals lacking a `ce' string.  */
   471 
   472 static void
   473 tty_clear_end_of_line (struct frame *f, int first_unused_hpos)
   474 {
   475   register int i;
   476   struct tty_display_info *tty = FRAME_TTY (f);
   477 
   478   /* Detect the case where we are called from reset_sys_modes
   479      and the costs have never been calculated.  Do nothing.  */
   480   if (! tty->costs_set)
   481     return;
   482 
   483   if (curX (tty) >= first_unused_hpos)
   484     return;
   485   tty_background_highlight (tty);
   486   if (tty->TS_clr_line)
   487     {
   488       OUTPUT1 (tty, tty->TS_clr_line);
   489     }
   490   else
   491     {                   /* have to do it the hard way */
   492       tty_turn_off_insert (tty);
   493 
   494       /* Do not write in last row last col with Auto-wrap on. */
   495       if (AutoWrap (tty)
   496           && curY (tty) == FrameRows (tty) - 1
   497           && first_unused_hpos == FrameCols (tty))
   498         first_unused_hpos--;
   499 
   500       for (i = curX (tty); i < first_unused_hpos; i++)
   501         {
   502           if (tty->termscript)
   503             putc (' ', tty->termscript);
   504           putc (' ', tty->output);
   505         }
   506       cmplus (tty, first_unused_hpos - curX (tty));
   507     }
   508 }
   509 
   510 /* Buffers to store the source and result of code conversion for terminal.  */
   511 static unsigned char *encode_terminal_src;
   512 static unsigned char *encode_terminal_dst;
   513 /* Allocated sizes of the above buffers.  */
   514 static ptrdiff_t encode_terminal_src_size;
   515 static ptrdiff_t encode_terminal_dst_size;
   516 
   517 /* Encode SRC_LEN glyphs starting at SRC to terminal output codes.
   518    Set CODING->produced to the byte-length of the resulting byte
   519    sequence, and return a pointer to that byte sequence.  */
   520 
   521 unsigned char *
   522 encode_terminal_code (struct glyph *src, int src_len,
   523                       struct coding_system *coding)
   524 {
   525   struct glyph *src_end = src + src_len;
   526   unsigned char *buf;
   527   ptrdiff_t nchars, nbytes, required;
   528   ptrdiff_t tlen = GLYPH_TABLE_LENGTH;
   529   register Lisp_Object *tbase = GLYPH_TABLE_BASE;
   530   Lisp_Object charset_list;
   531 
   532   /* Allocate sufficient size of buffer to store all characters in
   533      multibyte-form.  But, it may be enlarged on demand if
   534      Vglyph_table contains a string or a composite glyph is
   535      encountered.  */
   536   if (INT_MULTIPLY_WRAPV (src_len, MAX_MULTIBYTE_LENGTH, &required))
   537     memory_full (SIZE_MAX);
   538   if (encode_terminal_src_size < required)
   539     encode_terminal_src = xpalloc (encode_terminal_src,
   540                                    &encode_terminal_src_size,
   541                                    required - encode_terminal_src_size,
   542                                    -1, sizeof *encode_terminal_src);
   543 
   544   charset_list = coding_charset_list (coding);
   545 
   546   buf = encode_terminal_src;
   547   nchars = 0;
   548   while (src < src_end)
   549     {
   550       if (src->type == COMPOSITE_GLYPH)
   551         {
   552           struct composition *cmp;
   553           Lisp_Object gstring UNINIT;
   554           int i;
   555 
   556           nbytes = buf - encode_terminal_src;
   557           if (src->u.cmp.automatic)
   558             {
   559               cmp = NULL;
   560               gstring = composition_gstring_from_id (src->u.cmp.id);
   561               required = src->slice.cmp.to - src->slice.cmp.from + 1;
   562             }
   563           else
   564             {
   565               cmp = composition_table[src->u.cmp.id];
   566               required = cmp->glyph_len;
   567             }
   568           required *= MAX_MULTIBYTE_LENGTH;
   569 
   570           if (encode_terminal_src_size - nbytes < required)
   571             {
   572               encode_terminal_src =
   573                 xpalloc (encode_terminal_src, &encode_terminal_src_size,
   574                          required - (encode_terminal_src_size - nbytes),
   575                          -1, 1);
   576               buf = encode_terminal_src + nbytes;
   577             }
   578 
   579           if (!cmp)
   580             for (i = src->slice.cmp.from; i <= src->slice.cmp.to; i++)
   581               {
   582                 Lisp_Object g = LGSTRING_GLYPH (gstring, i);
   583                 int c = LGLYPH_CHAR (g);
   584 
   585                 if (! char_charset (c, charset_list, NULL))
   586                   c = '?';
   587                 buf += CHAR_STRING (c, buf);
   588                 nchars++;
   589               }
   590           else
   591             for (i = 0; i < cmp->glyph_len; i++)
   592               {
   593                 int c = COMPOSITION_GLYPH (cmp, i);
   594 
   595                 /* TAB in a composition means display glyphs with
   596                    padding space on the left or right.  */
   597                 if (c == '\t')
   598                   continue;
   599                 if (char_charset (c, charset_list, NULL))
   600                   {
   601                     if (CHARACTER_WIDTH (c) == 0
   602                         && i > 0 && COMPOSITION_GLYPH (cmp, i - 1) == '\t')
   603                       /* Should be left-padded */
   604                       {
   605                         buf += CHAR_STRING (' ', buf);
   606                         nchars++;
   607                       }
   608                   }
   609                 else
   610                   c = '?';
   611                 buf += CHAR_STRING (c, buf);
   612                 nchars++;
   613               }
   614         }
   615       /* We must skip glyphs to be padded for a wide character.  */
   616       else if (! CHAR_GLYPH_PADDING_P (*src))
   617         {
   618           GLYPH g;
   619           int c UNINIT;
   620           Lisp_Object string;
   621 
   622           string = Qnil;
   623           SET_GLYPH_FROM_CHAR_GLYPH (g, src[0]);
   624 
   625           if (GLYPH_INVALID_P (g) || GLYPH_SIMPLE_P (tbase, tlen, g))
   626             {
   627               /* This glyph doesn't have an entry in Vglyph_table.  */
   628               c = src->u.ch;
   629             }
   630           else
   631             {
   632               /* This glyph has an entry in Vglyph_table,
   633                  so process any alias before testing for simpleness.  */
   634               GLYPH_FOLLOW_ALIASES (tbase, tlen, g);
   635 
   636               if (GLYPH_SIMPLE_P (tbase, tlen, g))
   637                 /* We set the multi-byte form of a character in G
   638                    (that should be an ASCII character) at WORKBUF.  */
   639                 c = GLYPH_CHAR (g);
   640               else
   641                 /* We have a string in Vglyph_table.  */
   642                 string = tbase[GLYPH_CHAR (g)];
   643             }
   644 
   645           if (NILP (string))
   646             {
   647               nbytes = buf - encode_terminal_src;
   648               if (encode_terminal_src_size - nbytes < MAX_MULTIBYTE_LENGTH)
   649                 {
   650                   encode_terminal_src =
   651                     xpalloc (encode_terminal_src, &encode_terminal_src_size,
   652                              MAX_MULTIBYTE_LENGTH, -1, 1);
   653                   buf = encode_terminal_src + nbytes;
   654                 }
   655               if (CHAR_BYTE8_P (c)
   656                   || char_charset (c, charset_list, NULL))
   657                 {
   658                   /* Store the multibyte form of C at BUF.  */
   659                   buf += CHAR_STRING (c, buf);
   660                   nchars++;
   661                 }
   662               else
   663                 {
   664                   /* C is not encodable.  */
   665                   *buf++ = '?';
   666                   nchars++;
   667                   while (src + 1 < src_end && CHAR_GLYPH_PADDING_P (src[1]))
   668                     {
   669                       *buf++ = '?';
   670                       nchars++;
   671                       src++;
   672                     }
   673                 }
   674             }
   675           else
   676             {
   677               if (! STRING_MULTIBYTE (string))
   678                 string = string_to_multibyte (string);
   679               nbytes = buf - encode_terminal_src;
   680               if (encode_terminal_src_size - nbytes < SBYTES (string))
   681                 {
   682                   encode_terminal_src =
   683                     xpalloc (encode_terminal_src, &encode_terminal_src_size,
   684                              (SBYTES (string)
   685                               - (encode_terminal_src_size - nbytes)),
   686                              -1, 1);
   687                   buf = encode_terminal_src + nbytes;
   688                 }
   689               memcpy (buf, SDATA (string), SBYTES (string));
   690               buf += SBYTES (string);
   691               nchars += SCHARS (string);
   692             }
   693         }
   694       src++;
   695     }
   696 
   697   if (nchars == 0)
   698     {
   699       coding->produced = 0;
   700       return NULL;
   701     }
   702 
   703   nbytes = buf - encode_terminal_src;
   704   coding->source = encode_terminal_src;
   705   if (encode_terminal_dst_size == 0)
   706     {
   707       encode_terminal_dst = xrealloc (encode_terminal_dst,
   708                                       encode_terminal_src_size);
   709       encode_terminal_dst_size = encode_terminal_src_size;
   710     }
   711   coding->destination = encode_terminal_dst;
   712   coding->dst_bytes = encode_terminal_dst_size;
   713   encode_coding_object (coding, Qnil, 0, 0, nchars, nbytes, Qnil);
   714   /* coding->destination may have been reallocated.  */
   715   encode_terminal_dst = coding->destination;
   716   encode_terminal_dst_size = coding->dst_bytes;
   717 
   718   return (encode_terminal_dst);
   719 }
   720 
   721 
   722 
   723 /* An implementation of write_glyphs for termcap frames. */
   724 
   725 static void
   726 tty_write_glyphs (struct frame *f, struct glyph *string, int len)
   727 {
   728   unsigned char *conversion_buffer;
   729   struct coding_system *coding;
   730   int n, stringlen;
   731 
   732   struct tty_display_info *tty = FRAME_TTY (f);
   733 
   734   tty_turn_off_insert (tty);
   735   tty_hide_cursor (tty);
   736 
   737   /* Don't dare write in last column of bottom line, if Auto-Wrap,
   738      since that would scroll the whole frame on some terminals.  */
   739 
   740   if (AutoWrap (tty)
   741       && curY (tty) + 1 == FRAME_TOTAL_LINES (f)
   742       && (curX (tty) + len) == FRAME_COLS (f))
   743     len --;
   744   if (len <= 0)
   745     return;
   746 
   747   cmplus (tty, len);
   748 
   749   /* If terminal_coding does any conversion, use it, otherwise use
   750      safe_terminal_coding.  We can't use CODING_REQUIRE_ENCODING here
   751      because it always return 1 if the member src_multibyte is 1.  */
   752   coding = (FRAME_TERMINAL_CODING (f)->common_flags & CODING_REQUIRE_ENCODING_MASK
   753             ? FRAME_TERMINAL_CODING (f) : &safe_terminal_coding);
   754   /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
   755      the tail.  */
   756   coding->mode &= ~CODING_MODE_LAST_BLOCK;
   757 
   758   for (stringlen = len; stringlen != 0; stringlen -= n)
   759     {
   760       /* Identify a run of glyphs with the same face.  */
   761       int face_id = string->face_id;
   762 
   763       for (n = 1; n < stringlen; ++n)
   764         if (string[n].face_id != face_id)
   765           break;
   766 
   767       /* Turn appearance modes of the face of the run on.  */
   768       tty_highlight_if_desired (tty);
   769       turn_on_face (f, face_id);
   770 
   771       if (n == stringlen)
   772         /* This is the last run.  */
   773         coding->mode |= CODING_MODE_LAST_BLOCK;
   774       conversion_buffer = encode_terminal_code (string, n, coding);
   775       if (coding->produced > 0)
   776         {
   777           block_input ();
   778           fwrite (conversion_buffer, 1, coding->produced, tty->output);
   779           clearerr (tty->output);
   780           if (tty->termscript)
   781             fwrite (conversion_buffer, 1, coding->produced, tty->termscript);
   782           unblock_input ();
   783         }
   784       string += n;
   785 
   786       /* Turn appearance modes off.  */
   787       turn_off_face (f, face_id);
   788       tty_turn_off_highlight (tty);
   789     }
   790 
   791   cmcheckmagic (tty);
   792 }
   793 
   794 #ifndef DOS_NT
   795 
   796 static void
   797 tty_write_glyphs_with_face (register struct frame *f, register struct glyph *string,
   798                             register int len, register int face_id)
   799 {
   800   unsigned char *conversion_buffer;
   801   struct coding_system *coding;
   802 
   803   struct tty_display_info *tty = FRAME_TTY (f);
   804 
   805   tty_turn_off_insert (tty);
   806   tty_hide_cursor (tty);
   807 
   808   /* Don't dare write in last column of bottom line, if Auto-Wrap,
   809      since that would scroll the whole frame on some terminals.  */
   810 
   811   if (AutoWrap (tty)
   812       && curY (tty) + 1 == FRAME_TOTAL_LINES (f)
   813       && (curX (tty) + len) == FRAME_COLS (f))
   814     len --;
   815   if (len <= 0)
   816     return;
   817 
   818   cmplus (tty, len);
   819 
   820   /* If terminal_coding does any conversion, use it, otherwise use
   821      safe_terminal_coding.  We can't use CODING_REQUIRE_ENCODING here
   822      because it always return 1 if the member src_multibyte is 1.  */
   823   coding = (FRAME_TERMINAL_CODING (f)->common_flags & CODING_REQUIRE_ENCODING_MASK
   824             ? FRAME_TERMINAL_CODING (f) : &safe_terminal_coding);
   825   /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
   826      the tail.  */
   827   coding->mode &= ~CODING_MODE_LAST_BLOCK;
   828 
   829   /* Turn appearance modes of the face.  */
   830   tty_highlight_if_desired (tty);
   831   turn_on_face (f, face_id);
   832 
   833   coding->mode |= CODING_MODE_LAST_BLOCK;
   834   conversion_buffer = encode_terminal_code (string, len, coding);
   835   if (coding->produced > 0)
   836     {
   837       block_input ();
   838       fwrite (conversion_buffer, 1, coding->produced, tty->output);
   839       clearerr (tty->output);
   840       if (tty->termscript)
   841         fwrite (conversion_buffer, 1, coding->produced, tty->termscript);
   842       unblock_input ();
   843     }
   844 
   845   /* Turn appearance modes off.  */
   846   turn_off_face (f, face_id);
   847   tty_turn_off_highlight (tty);
   848 
   849   cmcheckmagic (tty);
   850 }
   851 
   852 #endif
   853 
   854 /* An implementation of insert_glyphs for termcap frames. */
   855 
   856 static void
   857 tty_insert_glyphs (struct frame *f, struct glyph *start, int len)
   858 {
   859   char *buf;
   860   struct glyph *glyph = NULL;
   861   unsigned char *conversion_buffer;
   862   unsigned char space[1];
   863   struct coding_system *coding;
   864 
   865   struct tty_display_info *tty = FRAME_TTY (f);
   866 
   867   if (tty->TS_ins_multi_chars)
   868     {
   869       buf = tparam (tty->TS_ins_multi_chars, 0, 0, len, 0, 0, 0);
   870       OUTPUT1 (tty, buf);
   871       xfree (buf);
   872       if (start)
   873         write_glyphs (f, start, len);
   874       return;
   875     }
   876 
   877   tty_turn_on_insert (tty);
   878   cmplus (tty, len);
   879 
   880   if (! start)
   881     space[0] = SPACEGLYPH;
   882 
   883   /* If terminal_coding does any conversion, use it, otherwise use
   884      safe_terminal_coding.  We can't use CODING_REQUIRE_ENCODING here
   885      because it always return 1 if the member src_multibyte is 1.  */
   886   coding = (FRAME_TERMINAL_CODING (f)->common_flags & CODING_REQUIRE_ENCODING_MASK
   887             ? FRAME_TERMINAL_CODING (f) : &safe_terminal_coding);
   888   /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
   889      the tail.  */
   890   coding->mode &= ~CODING_MODE_LAST_BLOCK;
   891 
   892   while (len-- > 0)
   893     {
   894       OUTPUT1_IF (tty, tty->TS_ins_char);
   895       if (!start)
   896         {
   897           conversion_buffer = space;
   898           coding->produced = 1;
   899         }
   900       else
   901         {
   902           tty_highlight_if_desired (tty);
   903           turn_on_face (f, start->face_id);
   904           glyph = start;
   905           ++start;
   906           /* We must open sufficient space for a character which
   907              occupies more than one column.  */
   908           while (len && CHAR_GLYPH_PADDING_P (*start))
   909             {
   910               OUTPUT1_IF (tty, tty->TS_ins_char);
   911               start++, len--;
   912             }
   913 
   914           if (len <= 0)
   915             /* This is the last glyph.  */
   916             coding->mode |= CODING_MODE_LAST_BLOCK;
   917 
   918           conversion_buffer = encode_terminal_code (glyph, 1, coding);
   919         }
   920 
   921       if (coding->produced > 0)
   922         {
   923           block_input ();
   924           fwrite (conversion_buffer, 1, coding->produced, tty->output);
   925           clearerr (tty->output);
   926           if (tty->termscript)
   927             fwrite (conversion_buffer, 1, coding->produced, tty->termscript);
   928           unblock_input ();
   929         }
   930 
   931       OUTPUT1_IF (tty, tty->TS_pad_inserted_char);
   932       if (start)
   933         {
   934           turn_off_face (f, glyph->face_id);
   935           tty_turn_off_highlight (tty);
   936         }
   937     }
   938 
   939   cmcheckmagic (tty);
   940 }
   941 
   942 /* An implementation of delete_glyphs for termcap frames. */
   943 
   944 static void
   945 tty_delete_glyphs (struct frame *f, int n)
   946 {
   947   char *buf;
   948   register int i;
   949 
   950   struct tty_display_info *tty = FRAME_TTY (f);
   951 
   952   if (tty->delete_in_insert_mode)
   953     {
   954       tty_turn_on_insert (tty);
   955     }
   956   else
   957     {
   958       tty_turn_off_insert (tty);
   959       OUTPUT_IF (tty, tty->TS_delete_mode);
   960     }
   961 
   962   if (tty->TS_del_multi_chars)
   963     {
   964       buf = tparam (tty->TS_del_multi_chars, 0, 0, n, 0, 0, 0);
   965       OUTPUT1 (tty, buf);
   966       xfree (buf);
   967     }
   968   else
   969     for (i = 0; i < n; i++)
   970       OUTPUT1 (tty, tty->TS_del_char);
   971   if (!tty->delete_in_insert_mode)
   972     OUTPUT_IF (tty, tty->TS_end_delete_mode);
   973 }
   974 
   975 /* An implementation of ins_del_lines for termcap frames. */
   976 
   977 static void
   978 tty_ins_del_lines (struct frame *f, int vpos, int n)
   979 {
   980   struct tty_display_info *tty = FRAME_TTY (f);
   981   const char *multi =
   982     n > 0 ? tty->TS_ins_multi_lines : tty->TS_del_multi_lines;
   983   const char *single = n > 0 ? tty->TS_ins_line : tty->TS_del_line;
   984   const char *scroll = n > 0 ? tty->TS_rev_scroll : tty->TS_fwd_scroll;
   985 
   986   int i = eabs (n);
   987   char *buf;
   988 
   989   /* If the lines below the insertion are being pushed
   990      into the end of the window, this is the same as clearing;
   991      and we know the lines are already clear, since the matching
   992      deletion has already been done.  So can ignore this.  */
   993   /* If the lines below the deletion are blank lines coming
   994      out of the end of the window, don't bother,
   995      as there will be a matching inslines later that will flush them. */
   996   if (FRAME_SCROLL_REGION_OK (f)
   997       && vpos + i >= tty->specified_window)
   998     return;
   999   if (!FRAME_MEMORY_BELOW_FRAME (f)
  1000       && vpos + i >= FRAME_TOTAL_LINES (f))
  1001     return;
  1002 
  1003   if (multi)
  1004     {
  1005       raw_cursor_to (f, vpos, 0);
  1006       tty_background_highlight (tty);
  1007       buf = tparam (multi, 0, 0, i, 0, 0, 0);
  1008       OUTPUT (tty, buf);
  1009       xfree (buf);
  1010     }
  1011   else if (single)
  1012     {
  1013       raw_cursor_to (f, vpos, 0);
  1014       tty_background_highlight (tty);
  1015       while (--i >= 0)
  1016         OUTPUT (tty, single);
  1017       if (tty->TF_teleray)
  1018         curX (tty) = 0;
  1019     }
  1020   else
  1021     {
  1022       tty_set_scroll_region (f, vpos, tty->specified_window);
  1023       if (n < 0)
  1024         raw_cursor_to (f, tty->specified_window - 1, 0);
  1025       else
  1026         raw_cursor_to (f, vpos, 0);
  1027       tty_background_highlight (tty);
  1028       while (--i >= 0)
  1029         OUTPUTL (tty, scroll, tty->specified_window - vpos);
  1030       tty_set_scroll_region (f, 0, tty->specified_window);
  1031     }
  1032 
  1033   if (!FRAME_SCROLL_REGION_OK (f)
  1034       && FRAME_MEMORY_BELOW_FRAME (f)
  1035       && n < 0)
  1036     {
  1037       cursor_to (f, FRAME_TOTAL_LINES (f) + n, 0);
  1038       clear_to_end (f);
  1039     }
  1040 }
  1041 
  1042 /* Compute cost of sending "str", in characters,
  1043    not counting any line-dependent padding.  */
  1044 
  1045 int
  1046 string_cost (const char *str)
  1047 {
  1048   cost = 0;
  1049   if (str)
  1050     tputs (str, 0, evalcost);
  1051   return cost;
  1052 }
  1053 
  1054 /* Compute cost of sending "str", in characters,
  1055    counting any line-dependent padding at one line.  */
  1056 
  1057 static int
  1058 string_cost_one_line (const char *str)
  1059 {
  1060   cost = 0;
  1061   if (str)
  1062     tputs (str, 1, evalcost);
  1063   return cost;
  1064 }
  1065 
  1066 /* Compute per line amount of line-dependent padding,
  1067    in tenths of characters.  */
  1068 
  1069 int
  1070 per_line_cost (const char *str)
  1071 {
  1072   cost = 0;
  1073   if (str)
  1074     tputs (str, 0, evalcost);
  1075   cost = - cost;
  1076   if (str)
  1077     tputs (str, 10, evalcost);
  1078   return cost;
  1079 }
  1080 
  1081 /* char_ins_del_cost[n] is cost of inserting N characters.
  1082    char_ins_del_cost[-n] is cost of deleting N characters.
  1083    The length of this vector is based on max_frame_cols.  */
  1084 
  1085 int *char_ins_del_vector;
  1086 
  1087 #define char_ins_del_cost(f) (&char_ins_del_vector[FRAME_COLS ((f))])
  1088 
  1089 static void
  1090 calculate_ins_del_char_costs (struct frame *f)
  1091 {
  1092   struct tty_display_info *tty = FRAME_TTY (f);
  1093   int ins_startup_cost, del_startup_cost;
  1094   int ins_cost_per_char, del_cost_per_char;
  1095   register int i;
  1096   register int *p;
  1097 
  1098   if (tty->TS_ins_multi_chars)
  1099     {
  1100       ins_cost_per_char = 0;
  1101       ins_startup_cost = string_cost_one_line (tty->TS_ins_multi_chars);
  1102     }
  1103   else if (tty->TS_ins_char || tty->TS_pad_inserted_char
  1104            || (tty->TS_insert_mode && tty->TS_end_insert_mode))
  1105     {
  1106       ins_startup_cost = (30 * (string_cost (tty->TS_insert_mode)
  1107                                 + string_cost (tty->TS_end_insert_mode))) / 100;
  1108       ins_cost_per_char = (string_cost_one_line (tty->TS_ins_char)
  1109                            + string_cost_one_line (tty->TS_pad_inserted_char));
  1110     }
  1111   else
  1112     {
  1113       ins_startup_cost = 9999;
  1114       ins_cost_per_char = 0;
  1115     }
  1116 
  1117   if (tty->TS_del_multi_chars)
  1118     {
  1119       del_cost_per_char = 0;
  1120       del_startup_cost = string_cost_one_line (tty->TS_del_multi_chars);
  1121     }
  1122   else if (tty->TS_del_char)
  1123     {
  1124       del_startup_cost = (string_cost (tty->TS_delete_mode)
  1125                           + string_cost (tty->TS_end_delete_mode));
  1126       if (tty->delete_in_insert_mode)
  1127         del_startup_cost /= 2;
  1128       del_cost_per_char = string_cost_one_line (tty->TS_del_char);
  1129     }
  1130   else
  1131     {
  1132       del_startup_cost = 9999;
  1133       del_cost_per_char = 0;
  1134     }
  1135 
  1136   /* Delete costs are at negative offsets */
  1137   p = &char_ins_del_cost (f)[0];
  1138   for (i = FRAME_COLS (f); --i >= 0;)
  1139     *--p = (del_startup_cost += del_cost_per_char);
  1140 
  1141   /* Doing nothing is free */
  1142   p = &char_ins_del_cost (f)[0];
  1143   *p++ = 0;
  1144 
  1145   /* Insert costs are at positive offsets */
  1146   for (i = FRAME_COLS (f); --i >= 0;)
  1147     *p++ = (ins_startup_cost += ins_cost_per_char);
  1148 }
  1149 
  1150 void
  1151 calculate_costs (struct frame *frame)
  1152 {
  1153   FRAME_COST_BAUD_RATE (frame) = baud_rate;
  1154 
  1155   if (FRAME_TERMCAP_P (frame))
  1156     {
  1157       struct tty_display_info *tty = FRAME_TTY (frame);
  1158       register const char *f = (tty->TS_set_scroll_region
  1159                                 ? tty->TS_set_scroll_region
  1160                                 : tty->TS_set_scroll_region_1);
  1161 
  1162       FRAME_SCROLL_REGION_COST (frame) = string_cost (f);
  1163 
  1164       tty->costs_set = 1;
  1165 
  1166       /* These variables are only used for terminal stuff.  They are
  1167          allocated once for the terminal frame of X-windows emacs, but not
  1168          used afterwards.
  1169 
  1170          char_ins_del_vector (i.e., char_ins_del_cost) isn't used because
  1171          X turns off char_ins_del_ok. */
  1172 
  1173       max_frame_cols = max (max_frame_cols, FRAME_COLS (frame));
  1174       if ((min (PTRDIFF_MAX, SIZE_MAX) / sizeof (int) - 1) / 2
  1175           < max_frame_cols)
  1176         memory_full (SIZE_MAX);
  1177 
  1178       char_ins_del_vector =
  1179         xrealloc (char_ins_del_vector,
  1180                   (sizeof (int) + 2 * sizeof (int) * max_frame_cols));
  1181 
  1182       memset (char_ins_del_vector, 0,
  1183               (sizeof (int) + 2 * sizeof (int) * max_frame_cols));
  1184 
  1185 
  1186       if (f && (!tty->TS_ins_line && !tty->TS_del_line))
  1187         do_line_insertion_deletion_costs (frame,
  1188                                           tty->TS_rev_scroll, tty->TS_ins_multi_lines,
  1189                                           tty->TS_fwd_scroll, tty->TS_del_multi_lines,
  1190                                           f, f, 1);
  1191       else
  1192         do_line_insertion_deletion_costs (frame,
  1193                                           tty->TS_ins_line, tty->TS_ins_multi_lines,
  1194                                           tty->TS_del_line, tty->TS_del_multi_lines,
  1195                                           0, 0, 1);
  1196 
  1197       calculate_ins_del_char_costs (frame);
  1198 
  1199       /* Don't use TS_repeat if its padding is worse than sending the chars */
  1200       if (tty->TS_repeat
  1201           && (baud_rate <= 0
  1202               || per_line_cost (tty->TS_repeat) < 9000 / baud_rate))
  1203         tty->RPov = string_cost (tty->TS_repeat);
  1204       else
  1205         tty->RPov = FRAME_COLS (frame) * 2;
  1206 
  1207       cmcostinit (FRAME_TTY (frame)); /* set up cursor motion costs */
  1208     }
  1209 }
  1210 
  1211 struct fkey_table {
  1212   const char *cap, *name;
  1213 };
  1214 
  1215 #ifndef DOS_NT
  1216   /* Termcap capability names that correspond directly to X keysyms.
  1217      Some of these (marked "terminfo") aren't supplied by old-style
  1218      (Berkeley) termcap entries.  They're listed in X keysym order;
  1219      except we put the keypad keys first, so that if they clash with
  1220      other keys (as on the IBM PC keyboard) they get overridden.
  1221   */
  1222 
  1223 static const struct fkey_table keys[] =
  1224 {
  1225   {"kh", "home"},       /* termcap */
  1226   {"kl", "left"},       /* termcap */
  1227   {"ku", "up"},         /* termcap */
  1228   {"kr", "right"},      /* termcap */
  1229   {"kd", "down"},       /* termcap */
  1230   {"%8", "prior"},      /* terminfo */
  1231   {"%5", "next"},       /* terminfo */
  1232   {"@7", "end"},        /* terminfo */
  1233   {"@1", "begin"},      /* terminfo */
  1234   {"*6", "select"},     /* terminfo */
  1235   {"%9", "print"},      /* terminfo */
  1236   {"@4", "execute"},    /* terminfo --- actually the `command' key */
  1237   /*
  1238    * "insert" --- see below
  1239    */
  1240   {"&8", "undo"},       /* terminfo */
  1241   {"%0", "redo"},       /* terminfo */
  1242   {"%7", "menu"},       /* terminfo --- actually the `options' key */
  1243   {"@0", "find"},       /* terminfo */
  1244   {"@2", "cancel"},     /* terminfo */
  1245   {"%1", "help"},       /* terminfo */
  1246   /*
  1247    * "break" goes here, but can't be reliably intercepted with termcap
  1248    */
  1249   {"&4", "reset"},      /* terminfo --- actually `restart' */
  1250   /*
  1251    * "system" and "user" --- no termcaps
  1252    */
  1253   {"kE", "clearline"},  /* terminfo */
  1254   {"kA", "insertline"}, /* terminfo */
  1255   {"kL", "deleteline"}, /* terminfo */
  1256   {"kI", "insertchar"}, /* terminfo */
  1257   {"kD", "deletechar"}, /* terminfo */
  1258   {"kB", "backtab"},    /* terminfo */
  1259   /*
  1260    * "kp_backtab", "kp-space", "kp-tab" --- no termcaps
  1261    */
  1262   {"@8", "kp-enter"},   /* terminfo */
  1263   /*
  1264    * "kp-f1", "kp-f2", "kp-f3" "kp-f4",
  1265    * "kp-multiply", "kp-add", "kp-separator",
  1266    * "kp-subtract", "kp-decimal", "kp-divide", "kp-0";
  1267    * --- no termcaps for any of these.
  1268    */
  1269   {"K4", "kp-1"},       /* terminfo */
  1270   /*
  1271    * "kp-2" --- no termcap
  1272    */
  1273   {"K5", "kp-3"},       /* terminfo */
  1274   /*
  1275    * "kp-4" --- no termcap
  1276    */
  1277   {"K2", "kp-5"},       /* terminfo */
  1278   /*
  1279    * "kp-6" --- no termcap
  1280    */
  1281   {"K1", "kp-7"},       /* terminfo */
  1282   /*
  1283    * "kp-8" --- no termcap
  1284    */
  1285   {"K3", "kp-9"},       /* terminfo */
  1286   /*
  1287    * "kp-equal" --- no termcap
  1288    */
  1289   {"k1", "f1"},
  1290   {"k2", "f2"},
  1291   {"k3", "f3"},
  1292   {"k4", "f4"},
  1293   {"k5", "f5"},
  1294   {"k6", "f6"},
  1295   {"k7", "f7"},
  1296   {"k8", "f8"},
  1297   {"k9", "f9"},
  1298 
  1299   {"&0", "S-cancel"},    /*shifted cancel key*/
  1300   {"&9", "S-begin"},     /*shifted begin key*/
  1301   {"*0", "S-find"},      /*shifted find key*/
  1302   {"*1", "S-execute"},   /*shifted execute? actually shifted command key*/
  1303   {"*4", "S-delete"},    /*shifted delete-character key*/
  1304   {"*7", "S-end"},       /*shifted end key*/
  1305   {"*8", "S-clearline"}, /*shifted clear-to end-of-line key*/
  1306   {"#1", "S-help"},      /*shifted help key*/
  1307   {"#2", "S-home"},      /*shifted home key*/
  1308   {"#3", "S-insert"},    /*shifted insert-character key*/
  1309   {"#4", "S-left"},      /*shifted left-arrow key*/
  1310   {"%d", "S-menu"},      /*shifted menu? actually shifted options key*/
  1311   {"%c", "S-next"},      /*shifted next key*/
  1312   {"%e", "S-prior"},     /*shifted previous key*/
  1313   {"%f", "S-print"},     /*shifted print key*/
  1314   {"%g", "S-redo"},      /*shifted redo key*/
  1315   {"%i", "S-right"},     /*shifted right-arrow key*/
  1316   {"!3", "S-undo"}       /*shifted undo key*/
  1317   };
  1318 
  1319 static char **term_get_fkeys_address;
  1320 static KBOARD *term_get_fkeys_kboard;
  1321 static Lisp_Object term_get_fkeys_1 (void);
  1322 
  1323 /* Find the escape codes sent by the function keys for Vinput_decode_map.
  1324    This function scans the termcap function key sequence entries, and
  1325    adds entries to Vinput_decode_map for each function key it finds.  */
  1326 
  1327 static void
  1328 term_get_fkeys (char **address, KBOARD *kboard)
  1329 {
  1330   /* We run the body of the function (term_get_fkeys_1) and ignore all Lisp
  1331      errors during the call.  The only errors should be from Fdefine_key
  1332      when given a key sequence containing an invalid prefix key.  If the
  1333      termcap defines function keys which use a prefix that is already bound
  1334      to a command by the default bindings, we should silently ignore that
  1335      function key specification, rather than giving the user an error and
  1336      refusing to run at all on such a terminal.  */
  1337 
  1338   term_get_fkeys_address = address;
  1339   term_get_fkeys_kboard = kboard;
  1340   internal_condition_case (term_get_fkeys_1, Qerror, Fidentity);
  1341 }
  1342 
  1343 static Lisp_Object
  1344 term_get_fkeys_1 (void)
  1345 {
  1346   int i;
  1347 
  1348   char **address = term_get_fkeys_address;
  1349   KBOARD *kboard = term_get_fkeys_kboard;
  1350 
  1351   /* This can happen if Emacs is starting up from scratch, or with
  1352      strange options.  */
  1353   if (!KEYMAPP (KVAR (kboard, Vinput_decode_map)))
  1354     kset_input_decode_map (kboard, Fmake_sparse_keymap (Qnil));
  1355 
  1356   for (i = 0; i < ARRAYELTS (keys); i++)
  1357     {
  1358       char *sequence = tgetstr (keys[i].cap, address);
  1359       if (sequence)
  1360         Fdefine_key (KVAR (kboard, Vinput_decode_map), build_string (sequence),
  1361                      make_vector (1, intern (keys[i].name)), Qnil);
  1362     }
  1363 
  1364   /* The uses of the "k0" capability are inconsistent; sometimes it
  1365      describes F10, whereas othertimes it describes F0 and "k;" describes F10.
  1366      We will attempt to politely accommodate both systems by testing for
  1367      "k;", and if it is present, assuming that "k0" denotes F0, otherwise F10.
  1368      */
  1369   {
  1370     const char *k_semi  = tgetstr ("k;", address);
  1371     const char *k0      = tgetstr ("k0", address);
  1372     const char *k0_name = "f10";
  1373 
  1374     if (k_semi)
  1375       {
  1376         if (k0)
  1377           /* Define f0 first, so that f10 takes precedence in case the
  1378              key sequences happens to be the same.  */
  1379           Fdefine_key (KVAR (kboard, Vinput_decode_map), build_string (k0),
  1380                        make_vector (1, intern ("f0")), Qnil);
  1381         Fdefine_key (KVAR (kboard, Vinput_decode_map), build_string (k_semi),
  1382                      make_vector (1, intern ("f10")), Qnil);
  1383       }
  1384     else if (k0)
  1385       Fdefine_key (KVAR (kboard, Vinput_decode_map), build_string (k0),
  1386                    make_vector (1, intern (k0_name)), Qnil);
  1387   }
  1388 
  1389   /* Set up cookies for numbered function keys above f10. */
  1390   {
  1391     char fcap[3], fkey[4];
  1392 
  1393     fcap[0] = 'F'; fcap[2] = '\0';
  1394     for (i = 11; i < 64; i++)
  1395       {
  1396         if (i <= 19)
  1397           fcap[1] = '1' + i - 11;
  1398         else if (i <= 45)
  1399           fcap[1] = 'A' + i - 20;
  1400         else
  1401           fcap[1] = 'a' + i - 46;
  1402 
  1403         {
  1404           char *sequence = tgetstr (fcap, address);
  1405           if (sequence)
  1406             {
  1407               sprintf (fkey, "f%d", i);
  1408               Fdefine_key (KVAR (kboard, Vinput_decode_map),
  1409                            build_string (sequence),
  1410                            make_vector (1, intern (fkey)),
  1411                            Qnil);
  1412             }
  1413         }
  1414       }
  1415    }
  1416 
  1417   /*
  1418    * Various mappings to try and get a better fit.
  1419    */
  1420   {
  1421 #define CONDITIONAL_REASSIGN(cap1, cap2, sym)                           \
  1422       if (!tgetstr (cap1, address))                                     \
  1423         {                                                               \
  1424           char *sequence = tgetstr (cap2, address);                     \
  1425           if (sequence)                                                 \
  1426             Fdefine_key (KVAR (kboard, Vinput_decode_map), build_string (sequence), \
  1427                          make_vector (1, intern (sym)), Qnil);          \
  1428         }
  1429 
  1430       /* if there's no key_next keycap, map key_npage to `next' keysym */
  1431       CONDITIONAL_REASSIGN ("%5", "kN", "next");
  1432       /* if there's no key_prev keycap, map key_ppage to `previous' keysym */
  1433       CONDITIONAL_REASSIGN ("%8", "kP", "prior");
  1434       /* if there's no key_dc keycap, map key_ic to `insert' keysym */
  1435       CONDITIONAL_REASSIGN ("kD", "kI", "insert");
  1436       /* if there's no key_end keycap, map key_ll to 'end' keysym */
  1437       CONDITIONAL_REASSIGN ("@7", "kH", "end");
  1438 #undef CONDITIONAL_REASSIGN
  1439   }
  1440 
  1441   return Qnil;
  1442 }
  1443 #endif /* not DOS_NT */
  1444 
  1445 
  1446 /***********************************************************************
  1447                        Character Display Information
  1448  ***********************************************************************/
  1449 static void append_glyph (struct it *);
  1450 static void append_composite_glyph (struct it *);
  1451 static void produce_composite_glyph (struct it *);
  1452 static void append_glyphless_glyph (struct it *, int, const char *);
  1453 static void produce_glyphless_glyph (struct it *, Lisp_Object);
  1454 
  1455 /* Append glyphs to IT's glyph_row.  Called from produce_glyphs for
  1456    terminal frames if IT->glyph_row != NULL.  IT->char_to_display is
  1457    the character for which to produce glyphs; IT->face_id contains the
  1458    character's face.  Padding glyphs are appended if IT->c has a
  1459    IT->pixel_width > 1.  */
  1460 
  1461 static void
  1462 append_glyph (struct it *it)
  1463 {
  1464   struct glyph *glyph, *end;
  1465   int i;
  1466 
  1467   eassert (it->glyph_row);
  1468   glyph = (it->glyph_row->glyphs[it->area]
  1469            + it->glyph_row->used[it->area]);
  1470   end = it->glyph_row->glyphs[1 + it->area];
  1471 
  1472   /* If the glyph row is reversed, we need to prepend the glyph rather
  1473      than append it.  */
  1474   if (it->glyph_row->reversed_p && it->area == TEXT_AREA)
  1475     {
  1476       struct glyph *g;
  1477       int move_by = it->pixel_width;
  1478 
  1479       /* Make room for the new glyphs.  */
  1480       if (move_by > end - glyph) /* don't overstep end of this area */
  1481         move_by = end - glyph;
  1482       for (g = glyph - 1; g >= it->glyph_row->glyphs[it->area]; g--)
  1483         g[move_by] = *g;
  1484       glyph = it->glyph_row->glyphs[it->area];
  1485       end = glyph + move_by;
  1486     }
  1487 
  1488   /* BIDI Note: we put the glyphs of a "multi-pixel" character left to
  1489      right, even in the REVERSED_P case, since (a) all of its u.ch are
  1490      identical, and (b) the PADDING_P flag needs to be set for the
  1491      leftmost one, because we write to the terminal left-to-right.  */
  1492   for (i = 0;
  1493        i < it->pixel_width && glyph < end;
  1494        ++i)
  1495     {
  1496       glyph->type = CHAR_GLYPH;
  1497       glyph->pixel_width = 1;
  1498       glyph->u.ch = it->char_to_display;
  1499       glyph->face_id = it->face_id;
  1500       glyph->avoid_cursor_p = it->avoid_cursor_p;
  1501       glyph->multibyte_p = it->multibyte_p;
  1502       glyph->padding_p = i > 0;
  1503       glyph->charpos = CHARPOS (it->position);
  1504       glyph->object = it->object;
  1505       if (it->bidi_p)
  1506         {
  1507           glyph->resolved_level = it->bidi_it.resolved_level;
  1508           eassert ((it->bidi_it.type & 7) == it->bidi_it.type);
  1509           glyph->bidi_type = it->bidi_it.type;
  1510         }
  1511       else
  1512         {
  1513           glyph->resolved_level = 0;
  1514           glyph->bidi_type = UNKNOWN_BT;
  1515         }
  1516 
  1517       ++it->glyph_row->used[it->area];
  1518       ++glyph;
  1519     }
  1520 }
  1521 
  1522 /* For external use.  */
  1523 void
  1524 tty_append_glyph (struct it *it)
  1525 {
  1526   append_glyph (it);
  1527 }
  1528 
  1529 
  1530 /* Produce glyphs for the display element described by IT.  *IT
  1531    specifies what we want to produce a glyph for (character, image, ...),
  1532    and where in the glyph matrix we currently are (glyph row and hpos).
  1533    produce_glyphs fills in output fields of *IT with information such as the
  1534    pixel width and height of a character, and maybe output actual glyphs at
  1535    the same time if IT->glyph_row is non-null.  For an overview, see
  1536    the explanation in dispextern.h, before the definition of the
  1537    display_element_type enumeration.
  1538 
  1539    produce_glyphs also stores the result of glyph width, ascent
  1540    etc. computations in *IT.
  1541 
  1542    IT->glyph_row may be null, in which case produce_glyphs does not
  1543    actually fill in the glyphs.  This is used in the move_* functions
  1544    in xdisp.c for text width and height computations.
  1545 
  1546    Callers usually don't call produce_glyphs directly;
  1547    instead they use the macro PRODUCE_GLYPHS.  */
  1548 
  1549 void
  1550 produce_glyphs (struct it *it)
  1551 {
  1552   /* If a hook is installed, let it do the work.  */
  1553 
  1554   /* Nothing but characters are supported on terminal frames.  */
  1555   eassert (it->what == IT_CHARACTER
  1556            || it->what == IT_COMPOSITION
  1557            || it->what == IT_STRETCH
  1558            || it->what == IT_GLYPHLESS);
  1559 
  1560   if (it->what == IT_STRETCH)
  1561     {
  1562       produce_stretch_glyph (it);
  1563       goto done;
  1564     }
  1565 
  1566   if (it->what == IT_COMPOSITION)
  1567     {
  1568       produce_composite_glyph (it);
  1569       goto done;
  1570     }
  1571 
  1572   if (it->what == IT_GLYPHLESS)
  1573     {
  1574       produce_glyphless_glyph (it, Qnil);
  1575       goto done;
  1576     }
  1577 
  1578   if (it->char_to_display >= 040 && it->char_to_display < 0177)
  1579     {
  1580       it->pixel_width = it->nglyphs = 1;
  1581       if (it->glyph_row)
  1582         append_glyph (it);
  1583     }
  1584   else if (it->char_to_display == '\n')
  1585     it->pixel_width = it->nglyphs = 0;
  1586   else if (it->char_to_display == '\t')
  1587     {
  1588       int absolute_x = (it->current_x
  1589                         + it->continuation_lines_width);
  1590       int x0 = absolute_x;
  1591       /* Adjust for line numbers.  */
  1592       if (!NILP (Vdisplay_line_numbers) && it->line_number_produced_p)
  1593         absolute_x -= it->lnum_pixel_width;
  1594       int next_tab_x
  1595         = (((1 + absolute_x + it->tab_width - 1)
  1596             / it->tab_width)
  1597            * it->tab_width);
  1598       if (!NILP (Vdisplay_line_numbers) && it->line_number_produced_p)
  1599         next_tab_x += it->lnum_pixel_width;
  1600       int nspaces;
  1601 
  1602       /* If part of the TAB has been displayed on the previous line
  1603          which is continued now, continuation_lines_width will have
  1604          been incremented already by the part that fitted on the
  1605          continued line.  So, we will get the right number of spaces
  1606          here.  */
  1607       nspaces = next_tab_x - x0;
  1608 
  1609       if (it->glyph_row)
  1610         {
  1611           int n = nspaces;
  1612 
  1613           it->char_to_display = ' ';
  1614           it->pixel_width = it->len = 1;
  1615 
  1616           while (n--)
  1617             append_glyph (it);
  1618         }
  1619 
  1620       it->pixel_width = nspaces;
  1621       it->nglyphs = nspaces;
  1622     }
  1623   else if (CHAR_BYTE8_P (it->char_to_display))
  1624     {
  1625       /* Coming here means that we must send the raw 8-bit byte as is
  1626          to the terminal.  Although there's no way to know how many
  1627          columns it occupies on a screen, it is a good assumption that
  1628          a single byte code has 1-column width.  */
  1629       it->pixel_width = it->nglyphs = 1;
  1630       if (it->glyph_row)
  1631         append_glyph (it);
  1632     }
  1633   else
  1634     {
  1635       struct terminal *t = FRAME_TERMINAL (it->f);
  1636       Lisp_Object charset_list = t->charset_list, char_glyph;
  1637 
  1638       if (char_charset (it->char_to_display, charset_list, NULL)
  1639           && (char_glyph = terminal_glyph_code (t, it->char_to_display),
  1640               NILP (char_glyph)
  1641               || (FIXNUMP (char_glyph) && XFIXNUM (char_glyph) >= 0)))
  1642         {
  1643           it->pixel_width = CHARACTER_WIDTH (it->char_to_display);
  1644           it->nglyphs = it->pixel_width;
  1645           if (it->glyph_row)
  1646             append_glyph (it);
  1647         }
  1648       else
  1649         {
  1650           Lisp_Object acronym = lookup_glyphless_char_display (-1, it);
  1651 
  1652           eassert (it->what == IT_GLYPHLESS);
  1653           produce_glyphless_glyph (it, acronym);
  1654         }
  1655     }
  1656 
  1657  done:
  1658   /* Advance current_x by the pixel width as a convenience for
  1659      the caller.  */
  1660   if (it->area == TEXT_AREA)
  1661     it->current_x += it->pixel_width;
  1662   it->ascent = it->max_ascent = it->phys_ascent = it->max_phys_ascent = 0;
  1663   it->descent = it->max_descent = it->phys_descent = it->max_phys_descent = 1;
  1664 }
  1665 
  1666 /* Append glyphs to IT's glyph_row for the composition IT->cmp_id.
  1667    Called from produce_composite_glyph for terminal frames if
  1668    IT->glyph_row != NULL.  IT->face_id contains the character's
  1669    face.  */
  1670 
  1671 static void
  1672 append_composite_glyph (struct it *it)
  1673 {
  1674   struct glyph *glyph;
  1675 
  1676   eassert (it->glyph_row);
  1677   glyph = it->glyph_row->glyphs[it->area] + it->glyph_row->used[it->area];
  1678   if (glyph < it->glyph_row->glyphs[1 + it->area])
  1679     {
  1680       /* If the glyph row is reversed, we need to prepend the glyph
  1681          rather than append it.  */
  1682       if (it->glyph_row->reversed_p && it->area == TEXT_AREA)
  1683         {
  1684           struct glyph *g;
  1685 
  1686           /* Make room for the new glyph.  */
  1687           for (g = glyph - 1; g >= it->glyph_row->glyphs[it->area]; g--)
  1688             g[1] = *g;
  1689           glyph = it->glyph_row->glyphs[it->area];
  1690         }
  1691       glyph->type = COMPOSITE_GLYPH;
  1692       eassert (it->pixel_width <= SHRT_MAX);
  1693       glyph->pixel_width = it->pixel_width;
  1694       glyph->u.cmp.id = it->cmp_it.id;
  1695       if (it->cmp_it.ch < 0)
  1696         {
  1697           glyph->u.cmp.automatic = 0;
  1698           glyph->u.cmp.id = it->cmp_it.id;
  1699         }
  1700       else
  1701         {
  1702           glyph->u.cmp.automatic = 1;
  1703           glyph->u.cmp.id = it->cmp_it.id;
  1704           glyph->slice.cmp.from = it->cmp_it.from;
  1705           glyph->slice.cmp.to = it->cmp_it.to - 1;
  1706         }
  1707 
  1708       glyph->avoid_cursor_p = it->avoid_cursor_p;
  1709       glyph->multibyte_p = it->multibyte_p;
  1710       glyph->face_id = it->face_id;
  1711       glyph->padding_p = false;
  1712       glyph->charpos = CHARPOS (it->position);
  1713       glyph->object = it->object;
  1714       if (it->bidi_p)
  1715         {
  1716           glyph->resolved_level = it->bidi_it.resolved_level;
  1717           eassert ((it->bidi_it.type & 7) == it->bidi_it.type);
  1718           glyph->bidi_type = it->bidi_it.type;
  1719         }
  1720       else
  1721         {
  1722           glyph->resolved_level = 0;
  1723           glyph->bidi_type = UNKNOWN_BT;
  1724         }
  1725 
  1726       ++it->glyph_row->used[it->area];
  1727       ++glyph;
  1728     }
  1729 }
  1730 
  1731 
  1732 /* Produce a composite glyph for iterator IT.  IT->cmp_id is the ID of
  1733    the composition.  We simply produces components of the composition
  1734    assuming that the terminal has a capability to layout/render it
  1735    correctly.  */
  1736 
  1737 static void
  1738 produce_composite_glyph (struct it *it)
  1739 {
  1740   if (it->cmp_it.ch < 0)
  1741     {
  1742       struct composition *cmp = composition_table[it->cmp_it.id];
  1743 
  1744       it->pixel_width = cmp->width;
  1745     }
  1746   else
  1747     {
  1748       Lisp_Object gstring = composition_gstring_from_id (it->cmp_it.id);
  1749 
  1750       it->pixel_width = composition_gstring_width (gstring, it->cmp_it.from,
  1751                                                    it->cmp_it.to, NULL);
  1752     }
  1753   it->nglyphs = 1;
  1754   if (it->glyph_row)
  1755     append_composite_glyph (it);
  1756 }
  1757 
  1758 
  1759 /* Append a glyph for a glyphless character to IT->glyph_row.  FACE_ID
  1760    is a face ID to be used for the glyph.  What is actually appended
  1761    are glyphs of type CHAR_GLYPH whose characters are in STR (which
  1762    comes from it->nglyphs bytes).  */
  1763 
  1764 static void
  1765 append_glyphless_glyph (struct it *it, int face_id, const char *str)
  1766 {
  1767   struct glyph *glyph, *end;
  1768   int i;
  1769 
  1770   eassert (it->glyph_row);
  1771   glyph = it->glyph_row->glyphs[it->area] + it->glyph_row->used[it->area];
  1772   end = it->glyph_row->glyphs[1 + it->area];
  1773 
  1774   /* If the glyph row is reversed, we need to prepend the glyph rather
  1775      than append it.  */
  1776   if (it->glyph_row->reversed_p && it->area == TEXT_AREA)
  1777     {
  1778       struct glyph *g;
  1779       int move_by = it->pixel_width;
  1780 
  1781       /* Make room for the new glyphs.  */
  1782       if (move_by > end - glyph) /* don't overstep end of this area */
  1783         move_by = end - glyph;
  1784       for (g = glyph - 1; g >= it->glyph_row->glyphs[it->area]; g--)
  1785         g[move_by] = *g;
  1786       glyph = it->glyph_row->glyphs[it->area];
  1787       end = glyph + move_by;
  1788     }
  1789 
  1790   if (glyph >= end)
  1791     return;
  1792   glyph->type = CHAR_GLYPH;
  1793   glyph->pixel_width = 1;
  1794   glyph->avoid_cursor_p = it->avoid_cursor_p;
  1795   glyph->multibyte_p = it->multibyte_p;
  1796   glyph->face_id = face_id;
  1797   glyph->padding_p = false;
  1798   glyph->charpos = CHARPOS (it->position);
  1799   glyph->object = it->object;
  1800   if (it->bidi_p)
  1801     {
  1802       glyph->resolved_level = it->bidi_it.resolved_level;
  1803       eassert ((it->bidi_it.type & 7) == it->bidi_it.type);
  1804       glyph->bidi_type = it->bidi_it.type;
  1805     }
  1806   else
  1807     {
  1808       glyph->resolved_level = 0;
  1809       glyph->bidi_type = UNKNOWN_BT;
  1810     }
  1811 
  1812   /* BIDI Note: we put the glyphs of characters left to right, even in
  1813      the REVERSED_P case because we write to the terminal
  1814      left-to-right.  */
  1815   for (i = 0; i < it->nglyphs && glyph < end; ++i)
  1816     {
  1817       if (i > 0)
  1818         glyph[0] = glyph[-1];
  1819       glyph->u.ch = str[i];
  1820       ++it->glyph_row->used[it->area];
  1821       ++glyph;
  1822     }
  1823 }
  1824 
  1825 /* Produce glyphs for a glyphless character for iterator IT.
  1826    IT->glyphless_method specifies which method to use for displaying
  1827    the character.  See the description of enum
  1828    glyphless_display_method in dispextern.h for the details.
  1829 
  1830    ACRONYM, if non-nil, is an acronym string for the character.
  1831 
  1832    The glyphs actually produced are of type CHAR_GLYPH.  */
  1833 
  1834 static void
  1835 produce_glyphless_glyph (struct it *it, Lisp_Object acronym)
  1836 {
  1837   int len, face_id = merge_glyphless_glyph_face (it);
  1838   char buf[sizeof "\\x" + max (6, (INT_WIDTH + 3) / 4)];
  1839   char const *str = "    ";
  1840 
  1841   if (it->glyphless_method == GLYPHLESS_DISPLAY_THIN_SPACE)
  1842     {
  1843       /* As there's no way to produce a thin space, we produce a space
  1844          of canonical width.  */
  1845       len = 1;
  1846     }
  1847   else if (it->glyphless_method == GLYPHLESS_DISPLAY_EMPTY_BOX)
  1848     {
  1849       len = CHARACTER_WIDTH (it->c);
  1850       if (len == 0)
  1851         len = 1;
  1852       else if (len > 4)
  1853         len = 4;
  1854       len = sprintf (buf, "[%.*s]", len, str);
  1855       str = buf;
  1856     }
  1857   else
  1858     {
  1859       if (it->glyphless_method == GLYPHLESS_DISPLAY_ACRONYM)
  1860         {
  1861           if (! STRINGP (acronym) && CHAR_TABLE_P (Vglyphless_char_display))
  1862             acronym = CHAR_TABLE_REF (Vglyphless_char_display, it->c);
  1863           if (CONSP (acronym))
  1864             acronym = XCDR (acronym);
  1865           str = STRINGP (acronym) ? SSDATA (acronym) : "";
  1866           /* A special kludgey feature for single-character acronyms:
  1867              don't put them in a box, effectively treating them as a
  1868              replacement character.  */
  1869           if (STRINGP (acronym) && SCHARS (acronym) == 1)
  1870             {
  1871               buf[0] = str[0];
  1872               len = 1;
  1873             }
  1874           else
  1875             {
  1876               buf[0] = '[';
  1877               for (len = 0;
  1878                    len < 6 && str[len] && ASCII_CHAR_P (str[len]); len++)
  1879                 buf[1 + len] = str[len];
  1880               buf[1 + len] = ']';
  1881               len += 2;
  1882             }
  1883         }
  1884       else
  1885         {
  1886           eassert (it->glyphless_method == GLYPHLESS_DISPLAY_HEX_CODE);
  1887           len = sprintf (buf,
  1888                          (it->c < 0x10000 ? "\\u%04X"
  1889                           : it->c <= MAX_UNICODE_CHAR ? "\\U%06X"
  1890                           : "\\x%06X"),
  1891                          it->c + 0u);
  1892         }
  1893       str = buf;
  1894     }
  1895 
  1896   it->pixel_width = len;
  1897   it->nglyphs = len;
  1898   if (it->glyph_row)
  1899     append_glyphless_glyph (it, face_id, str);
  1900 }
  1901 
  1902 
  1903 /***********************************************************************
  1904                                 Faces
  1905  ***********************************************************************/
  1906 
  1907 /* Value is non-zero if attribute ATTR may be used.  ATTR should be
  1908    one of the enumerators from enum no_color_bit, or a bit set built
  1909    from them.  Some display attributes may not be used together with
  1910    color; the termcap capability `NC' specifies which ones.  */
  1911 
  1912 #define MAY_USE_WITH_COLORS_P(tty, ATTR)                \
  1913   (tty->TN_max_colors > 0                               \
  1914    ? (tty->TN_no_color_video & (ATTR)) == 0             \
  1915    : 1)
  1916 
  1917 /* Turn appearances of face FACE_ID on tty frame F on.
  1918    FACE_ID is a realized face ID number, in the face cache.  */
  1919 
  1920 static void
  1921 turn_on_face (struct frame *f, int face_id)
  1922 {
  1923   struct face *face = FACE_FROM_ID (f, face_id);
  1924   unsigned long fg = face->foreground;
  1925   unsigned long bg = face->background;
  1926   struct tty_display_info *tty = FRAME_TTY (f);
  1927 
  1928   /* Use reverse video if the face specifies that.
  1929      Do this first because TS_end_standout_mode may be the same
  1930      as TS_exit_attribute_mode, which turns all appearances off. */
  1931   if (MAY_USE_WITH_COLORS_P (tty, NC_REVERSE)
  1932       && (inverse_video
  1933           ? fg == FACE_TTY_DEFAULT_FG_COLOR || bg == FACE_TTY_DEFAULT_BG_COLOR
  1934           : fg == FACE_TTY_DEFAULT_BG_COLOR || bg == FACE_TTY_DEFAULT_FG_COLOR))
  1935     tty_toggle_highlight (tty);
  1936 
  1937   if (face->tty_bold_p && MAY_USE_WITH_COLORS_P (tty, NC_BOLD))
  1938     OUTPUT1_IF (tty, tty->TS_enter_bold_mode);
  1939 
  1940   if (face->tty_italic_p && MAY_USE_WITH_COLORS_P (tty, NC_ITALIC))
  1941     {
  1942       if (tty->TS_enter_italic_mode)
  1943         OUTPUT1 (tty, tty->TS_enter_italic_mode);
  1944       else
  1945         /* Italics mode is unavailable on many terminals.  In that
  1946            case, map slant to dimmed text; we want italic text to
  1947            appear different and dimming is not otherwise used.  */
  1948         OUTPUT1 (tty, tty->TS_enter_dim_mode);
  1949     }
  1950 
  1951   if (face->tty_underline_p && MAY_USE_WITH_COLORS_P (tty, NC_UNDERLINE))
  1952     OUTPUT1_IF (tty, tty->TS_enter_underline_mode);
  1953 
  1954   if (face->tty_strike_through_p
  1955       && MAY_USE_WITH_COLORS_P (tty, NC_STRIKE_THROUGH))
  1956     OUTPUT1_IF (tty, tty->TS_enter_strike_through_mode);
  1957 
  1958   if (tty->TN_max_colors > 0)
  1959     {
  1960       const char *ts;
  1961       char *p;
  1962 
  1963       ts = tty->standout_mode ? tty->TS_set_background : tty->TS_set_foreground;
  1964       if (face_tty_specified_color (fg) && ts)
  1965         {
  1966           p = tparam (ts, NULL, 0, fg, 0, 0, 0);
  1967           OUTPUT (tty, p);
  1968           xfree (p);
  1969         }
  1970 
  1971       ts = tty->standout_mode ? tty->TS_set_foreground : tty->TS_set_background;
  1972       if (face_tty_specified_color (bg) && ts)
  1973         {
  1974           p = tparam (ts, NULL, 0, bg, 0, 0, 0);
  1975           OUTPUT (tty, p);
  1976           xfree (p);
  1977         }
  1978     }
  1979 }
  1980 
  1981 
  1982 /* Turn off appearances of face FACE_ID on tty frame F.  */
  1983 
  1984 static void
  1985 turn_off_face (struct frame *f, int face_id)
  1986 {
  1987   struct face *face = FACE_FROM_ID (f, face_id);
  1988   struct tty_display_info *tty = FRAME_TTY (f);
  1989 
  1990   if (tty->TS_exit_attribute_mode)
  1991     {
  1992       /* Capability "me" will turn off appearance modes double-bright,
  1993          half-bright, reverse-video, standout, underline.  It may or
  1994          may not turn off alt-char-mode.  */
  1995       if (face->tty_bold_p
  1996           || face->tty_italic_p
  1997           || face->tty_reverse_p
  1998           || face->tty_underline_p
  1999           || face->tty_strike_through_p)
  2000         {
  2001           OUTPUT1_IF (tty, tty->TS_exit_attribute_mode);
  2002           if (strcmp (tty->TS_exit_attribute_mode, tty->TS_end_standout_mode) == 0)
  2003             tty->standout_mode = 0;
  2004         }
  2005     }
  2006   else
  2007     {
  2008       /* If we don't have "me" we can only have those appearances
  2009          that have exit sequences defined.  */
  2010       if (face->tty_underline_p)
  2011         OUTPUT_IF (tty, tty->TS_exit_underline_mode);
  2012     }
  2013 
  2014   /* Switch back to default colors.  */
  2015   if (tty->TN_max_colors > 0
  2016       && ((face->foreground != FACE_TTY_DEFAULT_COLOR
  2017            && face->foreground != FACE_TTY_DEFAULT_FG_COLOR)
  2018           || (face->background != FACE_TTY_DEFAULT_COLOR
  2019               && face->background != FACE_TTY_DEFAULT_BG_COLOR)))
  2020     OUTPUT1_IF (tty, tty->TS_orig_pair);
  2021 }
  2022 
  2023 
  2024 /* Return true if the terminal on frame F supports all of the
  2025    capabilities in CAPS simultaneously.  */
  2026 
  2027 bool
  2028 tty_capable_p (struct tty_display_info *tty, unsigned int caps)
  2029 {
  2030 #define TTY_CAPABLE_P_TRY(tty, cap, TS, NC_bit)                         \
  2031   if ((caps & (cap)) && (!(TS) || !MAY_USE_WITH_COLORS_P(tty, NC_bit))) \
  2032     return 0;
  2033 
  2034   TTY_CAPABLE_P_TRY (tty,
  2035                      TTY_CAP_INVERSE,     tty->TS_standout_mode, NC_REVERSE);
  2036   TTY_CAPABLE_P_TRY (tty,
  2037                      TTY_CAP_UNDERLINE,   tty->TS_enter_underline_mode,
  2038                      NC_UNDERLINE);
  2039   TTY_CAPABLE_P_TRY (tty,
  2040                      TTY_CAP_BOLD,        tty->TS_enter_bold_mode, NC_BOLD);
  2041   TTY_CAPABLE_P_TRY (tty,
  2042                      TTY_CAP_DIM,         tty->TS_enter_dim_mode, NC_DIM);
  2043   TTY_CAPABLE_P_TRY (tty,
  2044                      TTY_CAP_ITALIC,      tty->TS_enter_italic_mode, NC_ITALIC);
  2045   TTY_CAPABLE_P_TRY (tty,
  2046                      TTY_CAP_STRIKE_THROUGH, tty->TS_enter_strike_through_mode,
  2047                      NC_STRIKE_THROUGH);
  2048 
  2049   /* We can do it!  */
  2050   return 1;
  2051 }
  2052 
  2053 /* Return non-zero if the terminal is capable to display colors.  */
  2054 
  2055 DEFUN ("tty-display-color-p", Ftty_display_color_p, Stty_display_color_p,
  2056        0, 1, 0,
  2057        doc: /* Return non-nil if the tty device TERMINAL can display colors.
  2058 
  2059 TERMINAL can be a terminal object, a frame, or nil (meaning the
  2060 selected frame's terminal).  This function always returns nil if
  2061 TERMINAL does not refer to a text terminal.  */)
  2062   (Lisp_Object terminal)
  2063 {
  2064   struct terminal *t = decode_tty_terminal (terminal);
  2065 
  2066   return (t && t->display_info.tty->TN_max_colors > 0) ? Qt : Qnil;
  2067 }
  2068 
  2069 /* Return the number of supported colors.  */
  2070 DEFUN ("tty-display-color-cells", Ftty_display_color_cells,
  2071        Stty_display_color_cells, 0, 1, 0,
  2072        doc: /* Return the number of colors supported by the tty device TERMINAL.
  2073 
  2074 TERMINAL can be a terminal object, a frame, or nil (meaning the
  2075 selected frame's terminal).  This function always returns 0 if
  2076 TERMINAL does not refer to a text terminal.  */)
  2077   (Lisp_Object terminal)
  2078 {
  2079   struct terminal *t = decode_tty_terminal (terminal);
  2080 
  2081   return make_fixnum (t ? t->display_info.tty->TN_max_colors : 0);
  2082 }
  2083 
  2084 #ifndef DOS_NT
  2085 
  2086 /* Declare here rather than in the function, as in the rest of Emacs,
  2087    to work around an HPUX compiler bug (?). See
  2088    https://lists.gnu.org/r/emacs-devel/2007-08/msg00410.html  */
  2089 static int default_max_colors;
  2090 static int default_no_color_video;
  2091 static char *default_orig_pair;
  2092 static char *default_set_foreground;
  2093 static char *default_set_background;
  2094 
  2095 /* Save or restore the default color-related capabilities of this
  2096    terminal.  */
  2097 static void
  2098 tty_default_color_capabilities (struct tty_display_info *tty, bool save)
  2099 {
  2100 
  2101   if (save)
  2102     {
  2103       dupstring (&default_orig_pair, tty->TS_orig_pair);
  2104       dupstring (&default_set_foreground, tty->TS_set_foreground);
  2105       dupstring (&default_set_background, tty->TS_set_background);
  2106       default_max_colors = tty->TN_max_colors;
  2107       default_no_color_video = tty->TN_no_color_video;
  2108     }
  2109   else
  2110     {
  2111       tty->TS_orig_pair = default_orig_pair;
  2112       tty->TS_set_foreground = default_set_foreground;
  2113       tty->TS_set_background = default_set_background;
  2114       tty->TN_max_colors = default_max_colors;
  2115       tty->TN_no_color_video = default_no_color_video;
  2116     }
  2117 }
  2118 
  2119 /* Setup one of the standard tty color schemes according to MODE.
  2120    MODE's value is generally the number of colors which we want to
  2121    support; zero means set up for the default capabilities, the ones
  2122    we saw at init_tty time; -1 means turn off color support.  */
  2123 static void
  2124 tty_setup_colors (struct tty_display_info *tty, int mode)
  2125 {
  2126   /* Canonicalize all negative values of MODE.  */
  2127   if (mode < -1)
  2128     mode = -1;
  2129 
  2130   switch (mode)
  2131     {
  2132       case -1:   /* no colors at all */
  2133         tty->TN_max_colors = 0;
  2134         tty->TN_no_color_video = 0;
  2135         tty->TS_set_foreground = tty->TS_set_background = tty->TS_orig_pair = NULL;
  2136         break;
  2137       case 0:    /* default colors, if any */
  2138       default:
  2139         tty_default_color_capabilities (tty, 0);
  2140         break;
  2141       case 8:   /* 8 standard ANSI colors */
  2142         tty->TS_orig_pair = "\033[0m";
  2143 #ifdef TERMINFO
  2144         tty->TS_set_foreground = "\033[3%p1%dm";
  2145         tty->TS_set_background = "\033[4%p1%dm";
  2146 #else
  2147         tty->TS_set_foreground = "\033[3%dm";
  2148         tty->TS_set_background = "\033[4%dm";
  2149 #endif
  2150         tty->TN_max_colors = 8;
  2151         tty->TN_no_color_video = 0;
  2152         break;
  2153     }
  2154 }
  2155 
  2156 void
  2157 set_tty_color_mode (struct tty_display_info *tty, struct frame *f)
  2158 {
  2159   Lisp_Object tem, val;
  2160   Lisp_Object color_mode;
  2161   int mode;
  2162   Lisp_Object tty_color_mode_alist
  2163     = Fintern_soft (build_string ("tty-color-mode-alist"), Qnil);
  2164 
  2165   tem = assq_no_quit (Qtty_color_mode, f->param_alist);
  2166   val = CONSP (tem) ? XCDR (tem) : Qnil;
  2167 
  2168   if (FIXNUMP (val))
  2169     color_mode = val;
  2170   else if (SYMBOLP (tty_color_mode_alist))
  2171     {
  2172       tem = Fassq (val, Fsymbol_value (tty_color_mode_alist));
  2173       color_mode = CONSP (tem) ? XCDR (tem) : Qnil;
  2174     }
  2175   else
  2176     color_mode = Qnil;
  2177 
  2178   mode = TYPE_RANGED_FIXNUMP (int, color_mode) ? XFIXNUM (color_mode) : 0;
  2179 
  2180   if (mode != tty->previous_color_mode)
  2181     {
  2182       tty->previous_color_mode = mode;
  2183       tty_setup_colors (tty , mode);
  2184       /*  This recomputes all the faces given the new color definitions.  */
  2185       safe_call (1, intern ("tty-set-up-initial-frame-faces"));
  2186     }
  2187 }
  2188 
  2189 #endif /* !DOS_NT */
  2190 
  2191 char *
  2192 tty_type_name (Lisp_Object terminal)
  2193 {
  2194   struct terminal *t = decode_tty_terminal (terminal);
  2195 
  2196   return t? t->display_info.tty->type: NULL;
  2197 }
  2198 
  2199 DEFUN ("tty-type", Ftty_type, Stty_type, 0, 1, 0,
  2200        doc: /* Return the type of the tty device that TERMINAL uses.
  2201 Returns nil if TERMINAL is not on a tty device.
  2202 
  2203 TERMINAL can be a terminal object, a frame, or nil (meaning the
  2204 selected frame's terminal).  */)
  2205   (Lisp_Object terminal)
  2206 {
  2207   char *name = tty_type_name (terminal);
  2208 
  2209   return (name? build_string (name) : Qnil);
  2210 }
  2211 
  2212 DEFUN ("controlling-tty-p", Fcontrolling_tty_p, Scontrolling_tty_p, 0, 1, 0,
  2213        doc: /* Return non-nil if TERMINAL is the controlling tty of the Emacs process.
  2214 
  2215 TERMINAL can be a terminal object, a frame, or nil (meaning the
  2216 selected frame's terminal).  This function always returns nil if
  2217 TERMINAL is not on a tty device.  */)
  2218   (Lisp_Object terminal)
  2219 {
  2220   struct terminal *t = decode_tty_terminal (terminal);
  2221 
  2222   return (t && !strcmp (t->display_info.tty->name, DEV_TTY) ? Qt : Qnil);
  2223 }
  2224 
  2225 DEFUN ("tty-no-underline", Ftty_no_underline, Stty_no_underline, 0, 1, 0,
  2226        doc: /* Declare that the tty used by TERMINAL does not handle underlining.
  2227 This is used to override the terminfo data, for certain terminals that
  2228 do not really do underlining, but say that they do.  This function has
  2229 no effect if used on a non-tty terminal.
  2230 
  2231 TERMINAL can be a terminal object, a frame or nil (meaning the
  2232 selected frame's terminal).  This function always returns nil if
  2233 TERMINAL does not refer to a text terminal.  */)
  2234   (Lisp_Object terminal)
  2235 {
  2236   struct terminal *t = decode_live_terminal (terminal);
  2237 
  2238   if (t->type == output_termcap)
  2239     t->display_info.tty->TS_enter_underline_mode = 0;
  2240   return Qnil;
  2241 }
  2242 
  2243 DEFUN ("tty-top-frame", Ftty_top_frame, Stty_top_frame, 0, 1, 0,
  2244        doc: /* Return the topmost terminal frame on TERMINAL.
  2245 TERMINAL can be a terminal object, a frame or nil (meaning the
  2246 selected frame's terminal).  This function returns nil if TERMINAL
  2247 does not refer to a text terminal.  Otherwise, it returns the
  2248 top-most frame on the text terminal.  */)
  2249   (Lisp_Object terminal)
  2250 {
  2251   struct terminal *t = decode_live_terminal (terminal);
  2252 
  2253   if (t->type == output_termcap)
  2254     return t->display_info.tty->top_frame;
  2255   return Qnil;
  2256 }
  2257 
  2258 
  2259 
  2260 DEFUN ("suspend-tty", Fsuspend_tty, Ssuspend_tty, 0, 1, 0,
  2261        doc: /* Suspend the terminal device TTY.
  2262 
  2263 The device is restored to its default state, and Emacs ceases all
  2264 access to the tty device.  Frames that use the device are not deleted,
  2265 but input is not read from them and if they change, their display is
  2266 not updated.
  2267 
  2268 TTY may be a terminal object, a frame, or nil for the terminal device
  2269 of the currently selected frame.
  2270 
  2271 This function runs `suspend-tty-functions' after suspending the
  2272 device.  The functions are run with one arg, the id of the suspended
  2273 terminal device.
  2274 
  2275 `suspend-tty' does nothing if it is called on a device that is already
  2276 suspended.
  2277 
  2278 A suspended tty may be resumed by calling `resume-tty' on it.  */)
  2279   (Lisp_Object tty)
  2280 {
  2281   struct terminal *t = decode_tty_terminal (tty);
  2282   FILE *f;
  2283 
  2284   if (!t)
  2285     error ("Attempt to suspend a non-text terminal device");
  2286 
  2287   f = t->display_info.tty->input;
  2288 
  2289   if (f)
  2290     {
  2291       /* First run `suspend-tty-functions' and then clean up the tty
  2292          state because `suspend-tty-functions' might need to change
  2293          the tty state.  */
  2294       Lisp_Object term;
  2295       XSETTERMINAL (term, t);
  2296       CALLN (Frun_hook_with_args, intern ("suspend-tty-functions"), term);
  2297 
  2298       reset_sys_modes (t->display_info.tty);
  2299       delete_keyboard_wait_descriptor (fileno (f));
  2300 
  2301 #ifndef MSDOS
  2302       if (f != t->display_info.tty->output)
  2303         fclose (t->display_info.tty->output);
  2304       fclose (f);
  2305 #endif
  2306 
  2307       t->display_info.tty->input = 0;
  2308       t->display_info.tty->output = 0;
  2309 
  2310       if (FRAMEP (t->display_info.tty->top_frame))
  2311         SET_FRAME_VISIBLE (XFRAME (t->display_info.tty->top_frame), 0);
  2312 
  2313     }
  2314 
  2315   /* Clear display hooks to prevent further output.  */
  2316   clear_tty_hooks (t);
  2317 
  2318   return Qnil;
  2319 }
  2320 
  2321 DEFUN ("resume-tty", Fresume_tty, Sresume_tty, 0, 1, 0,
  2322        doc: /* Resume the previously suspended terminal device TTY.
  2323 The terminal is opened and reinitialized.  Frames that are on the
  2324 suspended terminal are revived.
  2325 
  2326 It is an error to resume a terminal while another terminal is active
  2327 on the same device.
  2328 
  2329 This function runs `resume-tty-functions' after resuming the terminal.
  2330 The functions are run with one arg, the id of the resumed terminal
  2331 device.
  2332 
  2333 `resume-tty' does nothing if it is called on a device that is not
  2334 suspended.
  2335 
  2336 TTY may be a terminal object, a frame, or nil (meaning the selected
  2337 frame's terminal). */)
  2338   (Lisp_Object tty)
  2339 {
  2340   struct terminal *t = decode_tty_terminal (tty);
  2341   int fd;
  2342 
  2343   if (!t)
  2344     error ("Attempt to resume a non-text terminal device");
  2345 
  2346   if (!t->display_info.tty->input)
  2347     {
  2348       if (get_named_terminal (t->display_info.tty->name))
  2349         error ("Cannot resume display while another display is active on the same device");
  2350 
  2351 #ifdef MSDOS
  2352       t->display_info.tty->output = stdout;
  2353       t->display_info.tty->input  = stdin;
  2354 #else  /* !MSDOS */
  2355       fd = emacs_open (t->display_info.tty->name, O_RDWR | O_NOCTTY, 0);
  2356       t->display_info.tty->input = t->display_info.tty->output
  2357         = fd < 0 ? 0 : fdopen (fd, "w+");
  2358 
  2359       if (! t->display_info.tty->input)
  2360         {
  2361           int open_errno = errno;
  2362           emacs_close (fd);
  2363           report_file_errno ("Cannot reopen tty device",
  2364                              build_string (t->display_info.tty->name),
  2365                              open_errno);
  2366         }
  2367 
  2368       if (!O_IGNORE_CTTY && strcmp (t->display_info.tty->name, DEV_TTY) != 0)
  2369         dissociate_if_controlling_tty (fd);
  2370 #endif
  2371 
  2372       add_keyboard_wait_descriptor (fd);
  2373 
  2374       if (FRAMEP (t->display_info.tty->top_frame))
  2375         {
  2376           struct frame *f = XFRAME (t->display_info.tty->top_frame);
  2377           int width, height;
  2378           int old_height = FRAME_COLS (f);
  2379           int old_width = FRAME_TOTAL_LINES (f);
  2380 
  2381           /* Check if terminal/window size has changed while the frame
  2382              was suspended.  */
  2383           get_tty_size (fileno (t->display_info.tty->input), &width, &height);
  2384           if (width != old_width || height != old_height)
  2385             change_frame_size (f, width, height, false, false, false);
  2386           SET_FRAME_VISIBLE (XFRAME (t->display_info.tty->top_frame), 1);
  2387         }
  2388 
  2389       set_tty_hooks (t);
  2390       init_sys_modes (t->display_info.tty);
  2391 
  2392       /* Run `resume-tty-functions'.  */
  2393       Lisp_Object term;
  2394       XSETTERMINAL (term, t);
  2395       CALLN (Frun_hook_with_args, intern ("resume-tty-functions"), term);
  2396     }
  2397 
  2398   set_tty_hooks (t);
  2399 
  2400   return Qnil;
  2401 }
  2402 
  2403 DEFUN ("tty--set-output-buffer-size", Ftty__set_output_buffer_size,
  2404        Stty__set_output_buffer_size, 1, 2, 0, doc:
  2405        /* Set the output buffer size for a TTY.
  2406 
  2407 SIZE zero means use the system's default value.  If SIZE is
  2408 non-zero, this also avoids flushing the output stream.
  2409 
  2410 TTY may be a terminal object, a frame, or nil (meaning the selected
  2411 frame's terminal).
  2412 
  2413 This function temporarily suspends and resumes the terminal
  2414 device.  */)
  2415   (Lisp_Object size, Lisp_Object tty)
  2416 {
  2417   if (!TYPE_RANGED_FIXNUMP (size_t, size))
  2418     error ("Invalid output buffer size");
  2419   Fsuspend_tty (tty);
  2420   struct terminal *terminal = decode_tty_terminal (tty);
  2421   terminal->display_info.tty->output_buffer_size = XFIXNUM (size);
  2422   return Fresume_tty (tty);
  2423 }
  2424 
  2425 DEFUN ("tty--output-buffer-size", Ftty__output_buffer_size,
  2426        Stty__output_buffer_size, 0, 1, 0, doc:
  2427        /* Return the output buffer size of TTY.
  2428 
  2429 TTY may be a terminal object, a frame, or nil (meaning the selected
  2430 frame's terminal).
  2431 
  2432 A value of zero means TTY uses the system's default value.  */)
  2433   (Lisp_Object tty)
  2434 {
  2435   struct terminal *terminal = decode_tty_terminal (tty);
  2436   if (terminal)
  2437     return make_fixnum (terminal->display_info.tty->output_buffer_size);
  2438   error ("Not a tty terminal");
  2439 }
  2440 
  2441 
  2442 /***********************************************************************
  2443                                Mouse
  2444  ***********************************************************************/
  2445 
  2446 #ifndef DOS_NT
  2447 
  2448 /* Implementation of draw_row_with_mouse_face for TTY/GPM and macOS.  */
  2449 void
  2450 tty_draw_row_with_mouse_face (struct window *w, struct glyph_row *row,
  2451                               int start_hpos, int end_hpos,
  2452                               enum draw_glyphs_face draw)
  2453 {
  2454   int nglyphs = end_hpos - start_hpos;
  2455   struct frame *f = XFRAME (WINDOW_FRAME (w));
  2456   struct tty_display_info *tty = FRAME_TTY (f);
  2457   int face_id = tty->mouse_highlight.mouse_face_face_id;
  2458   int save_x, save_y, pos_x, pos_y;
  2459 
  2460   if (end_hpos >= row->used[TEXT_AREA])
  2461     nglyphs = row->used[TEXT_AREA] - start_hpos;
  2462 
  2463   pos_y = row->y + WINDOW_TOP_EDGE_Y (w);
  2464   pos_x = row->used[LEFT_MARGIN_AREA] + start_hpos + WINDOW_LEFT_EDGE_X (w);
  2465 
  2466   /* Save current cursor coordinates.  */
  2467   save_y = curY (tty);
  2468   save_x = curX (tty);
  2469   cursor_to (f, pos_y, pos_x);
  2470 
  2471   if (draw == DRAW_MOUSE_FACE)
  2472     tty_write_glyphs_with_face (f, row->glyphs[TEXT_AREA] + start_hpos,
  2473                                 nglyphs, face_id);
  2474   else if (draw == DRAW_NORMAL_TEXT)
  2475     write_glyphs (f, row->glyphs[TEXT_AREA] + start_hpos, nglyphs);
  2476 
  2477   cursor_to (f, save_y, save_x);
  2478 }
  2479 
  2480 #endif
  2481 
  2482 #ifdef HAVE_GPM
  2483 
  2484 void
  2485 term_mouse_moveto (int x, int y)
  2486 {
  2487   /* TODO: how to set mouse position?
  2488   const char *name;
  2489   int fd;
  2490   name = (const char *) ttyname (0);
  2491   fd = emacs_open (name, O_WRONLY, 0);
  2492      SOME_FUNCTION (x, y, fd);
  2493   emacs_close (fd);
  2494   last_mouse_x = x;
  2495   last_mouse_y = y;  */
  2496 }
  2497 
  2498 /* Return the current time, as a Time value.  Wrap around on overflow.  */
  2499 static Time
  2500 current_Time (void)
  2501 {
  2502   struct timespec now = current_timespec ();
  2503   Time s_1000 = now.tv_sec;
  2504   s_1000 *= 1000;
  2505   Time ms = now.tv_nsec / 1000000;
  2506   return s_1000 + ms;
  2507 }
  2508 
  2509 /* Return the current position of the mouse.
  2510 
  2511    Set *f to the frame the mouse is in, or zero if the mouse is in no
  2512    Emacs frame.  If it is set to zero, all the other arguments are
  2513    garbage.
  2514 
  2515    Set *bar_window to Qnil, and *x and *y to the column and
  2516    row of the character cell the mouse is over.
  2517 
  2518    Set *timeptr to the time the mouse was at the returned position.
  2519 
  2520    This clears mouse_moved until the next motion
  2521    event arrives.  */
  2522 static void
  2523 term_mouse_position (struct frame **fp, int insist, Lisp_Object *bar_window,
  2524                      enum scroll_bar_part *part, Lisp_Object *x,
  2525                      Lisp_Object *y, Time *timeptr)
  2526 {
  2527   *fp = SELECTED_FRAME ();
  2528   (*fp)->mouse_moved = 0;
  2529 
  2530   *bar_window = Qnil;
  2531   *part = scroll_bar_above_handle;
  2532 
  2533   XSETINT (*x, last_mouse_x);
  2534   XSETINT (*y, last_mouse_y);
  2535   *timeptr = current_Time ();
  2536 }
  2537 
  2538 /* Prepare a mouse-event in *RESULT for placement in the input queue.
  2539 
  2540    If the event is a button press, then note that we have grabbed
  2541    the mouse.  */
  2542 
  2543 static Lisp_Object
  2544 term_mouse_click (struct input_event *result, Gpm_Event *event,
  2545                   struct frame *f)
  2546 {
  2547   int i, j;
  2548 
  2549   result->kind = MOUSE_CLICK_EVENT;
  2550   for (i = 0, j = GPM_B_LEFT; i < 3; i++, j >>= 1 )
  2551     {
  2552       if (event->buttons & j) {
  2553         result->code = i; /* button number */
  2554         break;
  2555       }
  2556     }
  2557   result->timestamp = current_Time ();
  2558 
  2559   if (event->type & GPM_UP)
  2560     result->modifiers = up_modifier;
  2561   else if (event->type & GPM_DOWN)
  2562     result->modifiers = down_modifier;
  2563   else
  2564     result->modifiers = 0;
  2565 
  2566   if (event->type & GPM_SINGLE)
  2567     result->modifiers |= click_modifier;
  2568 
  2569   if (event->type & GPM_DOUBLE)
  2570     result->modifiers |= double_modifier;
  2571 
  2572   if (event->type & GPM_TRIPLE)
  2573     result->modifiers |= triple_modifier;
  2574 
  2575   if (event->type & GPM_DRAG)
  2576     result->modifiers |= drag_modifier;
  2577 
  2578   if (!(event->type & (GPM_MOVE | GPM_DRAG))) {
  2579 
  2580     /* 1 << KG_SHIFT */
  2581     if (event->modifiers & (1 << 0))
  2582       result->modifiers |= shift_modifier;
  2583 
  2584     /* 1 << KG_CTRL */
  2585     if (event->modifiers & (1 << 2))
  2586       result->modifiers |= ctrl_modifier;
  2587 
  2588     /* 1 << KG_ALT || KG_ALTGR */
  2589     if (event->modifiers & (1 << 3)
  2590         || event->modifiers & (1 << 1))
  2591       result->modifiers |= meta_modifier;
  2592   }
  2593 
  2594   XSETINT (result->x, event->x);
  2595   XSETINT (result->y, event->y);
  2596   XSETFRAME (result->frame_or_window, f);
  2597   result->arg = Qnil;
  2598   return Qnil;
  2599 }
  2600 
  2601 int
  2602 handle_one_term_event (struct tty_display_info *tty, Gpm_Event *event)
  2603 {
  2604   struct frame *f = XFRAME (tty->top_frame);
  2605   struct input_event ie;
  2606   int count = 0;
  2607 
  2608   EVENT_INIT (ie);
  2609   ie.kind = NO_EVENT;
  2610   ie.arg = Qnil;
  2611 
  2612   if (event->type & (GPM_MOVE | GPM_DRAG))
  2613     {
  2614       Gpm_DrawPointer (event->x, event->y, fileno (tty->output));
  2615 
  2616       /* Has the mouse moved off the glyph it was on at the last
  2617          sighting?  */
  2618       if (event->x != last_mouse_x || event->y != last_mouse_y)
  2619         {
  2620           /* FIXME: These three lines can not be moved into
  2621              update_mouse_position unless xterm-mouse gets updated to
  2622              generate mouse events via C code.  See
  2623              https://lists.gnu.org/archive/html/emacs-devel/2020-11/msg00163.html */
  2624           last_mouse_x = event->x;
  2625           last_mouse_y = event->y;
  2626           f->mouse_moved = 1;
  2627 
  2628           count += update_mouse_position (f, event->x, event->y);
  2629         }
  2630     }
  2631   else
  2632     {
  2633       f->mouse_moved = 0;
  2634       term_mouse_click (&ie, event, f);
  2635       ie.arg = tty_handle_tab_bar_click (f, event->x, event->y,
  2636                                          (ie.modifiers & down_modifier) != 0, &ie);
  2637       kbd_buffer_store_event (&ie);
  2638       count++;
  2639     }
  2640 
  2641   return count;
  2642 }
  2643 
  2644 DEFUN ("gpm-mouse-start", Fgpm_mouse_start, Sgpm_mouse_start,
  2645        0, 0, 0,
  2646        doc: /* Open a connection to Gpm.
  2647 Gpm-mouse can only be activated for one tty at a time.  */)
  2648   (void)
  2649 {
  2650   struct frame *f = SELECTED_FRAME ();
  2651   struct tty_display_info *tty
  2652     = ((f)->output_method == output_termcap
  2653        ? (f)->terminal->display_info.tty : NULL);
  2654   Gpm_Connect connection;
  2655 
  2656   if (!tty)
  2657     error ("Gpm-mouse only works in the GNU/Linux console");
  2658   if (gpm_tty == tty)
  2659     return Qnil;                /* Already activated, nothing to do.  */
  2660   if (gpm_tty)
  2661     error ("Gpm-mouse can only be activated for one tty at a time");
  2662 
  2663   connection.eventMask = ~0;
  2664   connection.defaultMask = ~GPM_HARD;
  2665   connection.maxMod = ~0;
  2666   connection.minMod = 0;
  2667   gpm_zerobased = 1;
  2668 
  2669   if (Gpm_Open (&connection, 0) < 0)
  2670     error ("Gpm-mouse failed to connect to the gpm daemon");
  2671   else
  2672     {
  2673       gpm_tty = tty;
  2674       /* `init_sys_modes' arranges for mouse movements sent through gpm_fd
  2675          to generate SIGIOs.  Apparently we need to call reset_sys_modes
  2676          before calling init_sys_modes.  */
  2677       reset_sys_modes (tty);
  2678       init_sys_modes (tty);
  2679       add_gpm_wait_descriptor (gpm_fd);
  2680       return Qnil;
  2681     }
  2682 }
  2683 
  2684 void
  2685 close_gpm (int fd)
  2686 {
  2687   if (fd >= 0)
  2688     delete_gpm_wait_descriptor (fd);
  2689   while (Gpm_Close()); /* close all the stack */
  2690   gpm_tty = NULL;
  2691 }
  2692 
  2693 DEFUN ("gpm-mouse-stop", Fgpm_mouse_stop, Sgpm_mouse_stop,
  2694        0, 0, 0,
  2695        doc: /* Close a connection to Gpm.  */)
  2696   (void)
  2697 {
  2698   struct frame *f = SELECTED_FRAME ();
  2699   struct tty_display_info *tty
  2700     = ((f)->output_method == output_termcap
  2701        ? (f)->terminal->display_info.tty : NULL);
  2702 
  2703   if (!tty || gpm_tty != tty)
  2704     return Qnil;       /* Not activated on this terminal, nothing to do.  */
  2705 
  2706   close_gpm (gpm_fd);
  2707   return Qnil;
  2708 }
  2709 #endif /* HAVE_GPM */
  2710 
  2711 
  2712 /***********************************************************************
  2713                                Menus
  2714  ***********************************************************************/
  2715 
  2716 #if !defined (MSDOS)
  2717 
  2718 /* TTY menu implementation and main ideas are borrowed from msdos.c.
  2719 
  2720    However, unlike on MSDOS, where the menu text is drawn directly to
  2721    the display video memory, on a TTY we use display_string (see
  2722    display_tty_menu_item in xdisp.c) to put the glyphs produced from
  2723    the menu items into the frame's 'desired_matrix' glyph matrix, and
  2724    then call update_frame_with_menu to deliver the results to the
  2725    glass.  The previous contents of the screen, in the form of the
  2726    current_matrix, is stashed away, and used to restore screen
  2727    contents when the menu selection changes or when the final
  2728    selection is made and the menu should be popped down.
  2729 
  2730    The idea of this implementation was suggested by Gerd Moellmann.  */
  2731 
  2732 #define TTYM_FAILURE -1
  2733 #define TTYM_SUCCESS 1
  2734 #define TTYM_NO_SELECT 2
  2735 #define TTYM_IA_SELECT 3
  2736 #define TTYM_NEXT 4
  2737 #define TTYM_PREV 5
  2738 
  2739 /* These hold text of the current and the previous menu help messages.  */
  2740 static const char *menu_help_message, *prev_menu_help_message;
  2741 /* Pane number and item number of the menu item which generated the
  2742    last menu help message.  */
  2743 static int menu_help_paneno, menu_help_itemno;
  2744 
  2745 typedef struct tty_menu_struct
  2746 {
  2747   int count;
  2748   char **text;
  2749   struct tty_menu_struct **submenu;
  2750   int *panenumber; /* Also used as enabled flag.  */
  2751   ptrdiff_t allocated;
  2752   int panecount;
  2753   int width;
  2754   const char **help_text;
  2755 } tty_menu;
  2756 
  2757 /* Create a brand new menu structure.  */
  2758 
  2759 static tty_menu * ATTRIBUTE_MALLOC
  2760 tty_menu_create (void)
  2761 {
  2762   return xzalloc (sizeof *tty_menu_create ());
  2763 }
  2764 
  2765 /* Allocate some (more) memory for MENU ensuring that there is room for one
  2766    more item.  */
  2767 
  2768 static void
  2769 tty_menu_make_room (tty_menu *menu)
  2770 {
  2771   if (menu->allocated == menu->count)
  2772     {
  2773       ptrdiff_t allocated = menu->allocated;
  2774       menu->text = xpalloc (menu->text, &allocated, 1, -1, sizeof *menu->text);
  2775       menu->text = xrealloc (menu->text, allocated * sizeof *menu->text);
  2776       menu->submenu = xrealloc (menu->submenu,
  2777                                 allocated * sizeof *menu->submenu);
  2778       menu->panenumber = xrealloc (menu->panenumber,
  2779                                    allocated * sizeof *menu->panenumber);
  2780       menu->help_text = xrealloc (menu->help_text,
  2781                                   allocated * sizeof *menu->help_text);
  2782       menu->allocated = allocated;
  2783     }
  2784 }
  2785 
  2786 /* Search the given menu structure for a given pane number.  */
  2787 
  2788 static tty_menu *
  2789 tty_menu_search_pane (tty_menu *menu, int pane)
  2790 {
  2791   int i;
  2792   tty_menu *try;
  2793 
  2794   for (i = 0; i < menu->count; i++)
  2795     if (menu->submenu[i])
  2796       {
  2797         if (pane == menu->panenumber[i])
  2798           return menu->submenu[i];
  2799         try = tty_menu_search_pane (menu->submenu[i], pane);
  2800         if (try)
  2801           return try;
  2802       }
  2803   return (tty_menu *) 0;
  2804 }
  2805 
  2806 /* Determine how much screen space a given menu needs.  */
  2807 
  2808 static void
  2809 tty_menu_calc_size (tty_menu *menu, int *width, int *height)
  2810 {
  2811   int i, h2, w2, maxsubwidth, maxheight;
  2812 
  2813   maxsubwidth = menu->width;
  2814   maxheight = menu->count;
  2815   for (i = 0; i < menu->count; i++)
  2816     {
  2817       if (menu->submenu[i])
  2818         {
  2819           tty_menu_calc_size (menu->submenu[i], &w2, &h2);
  2820           if (w2 > maxsubwidth) maxsubwidth = w2;
  2821           if (i + h2 > maxheight) maxheight = i + h2;
  2822         }
  2823     }
  2824   *width = maxsubwidth;
  2825   *height = maxheight;
  2826 }
  2827 
  2828 static void
  2829 mouse_get_xy (int *x, int *y)
  2830 {
  2831   Lisp_Object lmx = Qnil, lmy = Qnil;
  2832   Lisp_Object mouse = mouse_position (tty_menu_calls_mouse_position_function);
  2833 
  2834   if (EQ (selected_frame, XCAR (mouse)))
  2835     {
  2836       lmx = XCAR (XCDR (mouse));
  2837       lmy = XCDR (XCDR (mouse));
  2838     }
  2839 
  2840   if (!NILP (lmx))
  2841     {
  2842       *x = XFIXNUM (lmx);
  2843       *y = XFIXNUM (lmy);
  2844     }
  2845 }
  2846 
  2847 /* Display MENU at (X,Y) using FACES, starting with FIRST_ITEM
  2848    (zero-based).  */
  2849 
  2850 static void
  2851 tty_menu_display (tty_menu *menu, int x, int y, int pn, int *faces,
  2852                   int mx, int my, int first_item, bool disp_help)
  2853 {
  2854   int i, face, width, enabled, mousehere, row, col;
  2855   struct frame *sf = SELECTED_FRAME ();
  2856   struct tty_display_info *tty = FRAME_TTY (sf);
  2857   /* Don't try to display more menu items than the console can display
  2858      using the available screen lines.  Exclude the echo area line, as
  2859      it will be overwritten by the help-echo anyway.  */
  2860   int max_items = min (menu->count - first_item, FRAME_TOTAL_LINES (sf) - 1 - y);
  2861 
  2862   menu_help_message = NULL;
  2863 
  2864   width = menu->width;
  2865   col = cursorX (tty);
  2866   row = cursorY (tty);
  2867   for (i = 0; i < max_items; i++)
  2868     {
  2869       int max_width = width + 2; /* +2 for padding blanks on each side */
  2870       int j = i + first_item;
  2871 
  2872       if (menu->submenu[j])
  2873         max_width += 2; /* for displaying " >" after the item */
  2874       enabled
  2875         = (!menu->submenu[j] && menu->panenumber[j]) || (menu->submenu[j]);
  2876       mousehere = (y + i == my && x <= mx && mx < x + max_width);
  2877       face = faces[enabled + mousehere * 2];
  2878       /* Display the menu help string for the i-th menu item even if
  2879          the menu item is currently disabled.  That's what the GUI
  2880          code does.  */
  2881       if (disp_help && enabled + mousehere * 2 >= 2)
  2882         {
  2883           menu_help_message = menu->help_text[j];
  2884           menu_help_paneno = pn - 1;
  2885           menu_help_itemno = j;
  2886         }
  2887       /* Take note of the coordinates of the active menu item, to
  2888          display the cursor there.  */
  2889       if (mousehere)
  2890         {
  2891           row = y + i;
  2892           col = x;
  2893         }
  2894       display_tty_menu_item (menu->text[j], max_width, face, x, y + i,
  2895                              menu->submenu[j] != NULL);
  2896     }
  2897   update_frame_with_menu (sf, row, col);
  2898 }
  2899 
  2900 /* --------------------------- X Menu emulation ---------------------- */
  2901 
  2902 /* Create a new pane and place it on the outer-most level.  */
  2903 
  2904 static int
  2905 tty_menu_add_pane (tty_menu *menu, const char *txt)
  2906 {
  2907   int len;
  2908 
  2909   tty_menu_make_room (menu);
  2910   menu->submenu[menu->count] = tty_menu_create ();
  2911   menu->text[menu->count] = (char *)txt;
  2912   menu->panenumber[menu->count] = ++menu->panecount;
  2913   menu->help_text[menu->count] = NULL;
  2914   menu->count++;
  2915 
  2916   /* Update the menu width, if necessary.  */
  2917   len = menu_item_width ((const unsigned char *) txt);
  2918   if (len > menu->width)
  2919     menu->width = len;
  2920 
  2921   return menu->panecount;
  2922 }
  2923 
  2924 /* Create a new item in a menu pane.  */
  2925 
  2926 static bool
  2927 tty_menu_add_selection (tty_menu *menu, int pane,
  2928                         char *txt, bool enable, char const *help_text)
  2929 {
  2930   int len;
  2931 
  2932   if (pane)
  2933     {
  2934       menu = tty_menu_search_pane (menu, pane);
  2935       if (! menu)
  2936         return 0;
  2937     }
  2938   tty_menu_make_room (menu);
  2939   menu->submenu[menu->count] = (tty_menu *) 0;
  2940   menu->text[menu->count] = txt;
  2941   menu->panenumber[menu->count] = enable;
  2942   menu->help_text[menu->count] = help_text;
  2943   menu->count++;
  2944 
  2945   /* Update the menu width, if necessary.  */
  2946   len = menu_item_width ((const unsigned char *) txt);
  2947   if (len > menu->width)
  2948     menu->width = len;
  2949 
  2950   return 1;
  2951 }
  2952 
  2953 /* Decide where the menu would be placed if requested at (X,Y).  */
  2954 
  2955 static void
  2956 tty_menu_locate (tty_menu *menu, int x, int y,
  2957                  int *ulx, int *uly, int *width, int *height)
  2958 {
  2959   tty_menu_calc_size (menu, width, height);
  2960   *ulx = x + 1;
  2961   *uly = y;
  2962   *width += 2;
  2963 }
  2964 
  2965 struct tty_menu_state
  2966 {
  2967   struct glyph_matrix *screen_behind;
  2968   tty_menu *menu;
  2969   int pane;
  2970   int x, y;
  2971 };
  2972 
  2973 /* Save away the contents of frame F's current frame matrix, and
  2974    enable all its rows.  Value is a glyph matrix holding the contents
  2975    of F's current frame matrix with all its glyph rows enabled.  */
  2976 
  2977 static struct glyph_matrix *
  2978 save_and_enable_current_matrix (struct frame *f)
  2979 {
  2980   int i;
  2981   struct glyph_matrix *saved = xzalloc (sizeof *saved);
  2982   saved->nrows = f->current_matrix->nrows;
  2983   saved->rows = xzalloc (saved->nrows * sizeof *saved->rows);
  2984 
  2985   for (i = 0; i < saved->nrows; ++i)
  2986     {
  2987       struct glyph_row *from = f->current_matrix->rows + i;
  2988       struct glyph_row *to = saved->rows + i;
  2989       ptrdiff_t nbytes = from->used[TEXT_AREA] * sizeof (struct glyph);
  2990 
  2991       to->glyphs[TEXT_AREA] = xmalloc (nbytes);
  2992       memcpy (to->glyphs[TEXT_AREA], from->glyphs[TEXT_AREA], nbytes);
  2993       to->used[TEXT_AREA] = from->used[TEXT_AREA];
  2994       /* Make sure every row is enabled, or else update_frame will not
  2995          redraw them.  (Rows that are identical to what is already on
  2996          screen will not be redrawn anyway.)  */
  2997       to->enabled_p = true;
  2998       to->hash = from->hash;
  2999     }
  3000 
  3001   return saved;
  3002 }
  3003 
  3004 /* Restore the contents of frame F's desired frame matrix from SAVED,
  3005    and free memory associated with SAVED.  */
  3006 
  3007 static void
  3008 restore_desired_matrix (struct frame *f, struct glyph_matrix *saved)
  3009 {
  3010   int i;
  3011 
  3012   for (i = 0; i < saved->nrows; ++i)
  3013     {
  3014       struct glyph_row *from = saved->rows + i;
  3015       struct glyph_row *to = f->desired_matrix->rows + i;
  3016       ptrdiff_t nbytes = from->used[TEXT_AREA] * sizeof (struct glyph);
  3017 
  3018       eassert (to->glyphs[TEXT_AREA] != from->glyphs[TEXT_AREA]);
  3019       memcpy (to->glyphs[TEXT_AREA], from->glyphs[TEXT_AREA], nbytes);
  3020       to->used[TEXT_AREA] = from->used[TEXT_AREA];
  3021       to->enabled_p = from->enabled_p;
  3022       to->hash = from->hash;
  3023     }
  3024 }
  3025 
  3026 static void
  3027 free_saved_screen (struct glyph_matrix *saved)
  3028 {
  3029   int i;
  3030 
  3031   if (!saved)
  3032     return;     /* Already freed!  */
  3033 
  3034   for (i = 0; i < saved->nrows; ++i)
  3035     {
  3036       struct glyph_row *from = saved->rows + i;
  3037 
  3038       xfree (from->glyphs[TEXT_AREA]);
  3039     }
  3040 
  3041   xfree (saved->rows);
  3042   xfree (saved);
  3043 }
  3044 
  3045 /* Update the display of frame F from its saved contents.  */
  3046 static void
  3047 screen_update (struct frame *f, struct glyph_matrix *mtx)
  3048 {
  3049   restore_desired_matrix (f, mtx);
  3050   update_frame_with_menu (f, -1, -1);
  3051 }
  3052 
  3053 typedef enum {
  3054   MI_QUIT_MENU      = -1,
  3055   MI_CONTINUE       = 0,
  3056   MI_ITEM_SELECTED  = 1,
  3057   MI_NEXT_ITEM      = 2,
  3058   MI_PREV_ITEM      = 3,
  3059   MI_SCROLL_FORWARD = 4,
  3060   MI_SCROLL_BACK    = 5
  3061 } mi_result;
  3062 
  3063 /* Read user input and return X and Y coordinates where that input
  3064    puts us.  We only consider mouse movement and click events, and
  3065    keyboard movement commands; the rest are ignored.  */
  3066 static mi_result
  3067 read_menu_input (struct frame *sf, int *x, int *y, int min_y, int max_y,
  3068                  bool *first_time)
  3069 {
  3070   if (*first_time)
  3071     {
  3072       *first_time = false;
  3073       sf->mouse_moved = 1;
  3074     }
  3075   else
  3076     {
  3077       Lisp_Object cmd;
  3078       bool usable_input = 1;
  3079       mi_result st = MI_CONTINUE;
  3080       struct tty_display_info *tty = FRAME_TTY (sf);
  3081       Lisp_Object old_track_mouse = track_mouse;
  3082 
  3083       /* Signal the keyboard reading routines we are displaying a menu
  3084          on this terminal.  */
  3085       tty->showing_menu = 1;
  3086       /* We want mouse movements be reported by read_menu_command.  */
  3087       track_mouse = Qt;
  3088       do {
  3089         cmd = read_menu_command ();
  3090       } while (NILP (cmd));
  3091       tty->showing_menu = 0;
  3092       track_mouse = old_track_mouse;
  3093 
  3094       if (EQ (cmd, Qt) || EQ (cmd, Qtty_menu_exit)
  3095           /* If some input switched frames under our feet, exit the
  3096              menu, since the menu faces are no longer valid, and the
  3097              menu is no longer relevant anyway.  */
  3098           || sf != SELECTED_FRAME ())
  3099         return MI_QUIT_MENU;
  3100       if (EQ (cmd, Qtty_menu_mouse_movement))
  3101         mouse_get_xy (x, y);
  3102       else if (EQ (cmd, Qtty_menu_next_menu))
  3103         {
  3104           usable_input = 0;
  3105           st = MI_NEXT_ITEM;
  3106         }
  3107       else if (EQ (cmd, Qtty_menu_prev_menu))
  3108         {
  3109           usable_input = 0;
  3110           st = MI_PREV_ITEM;
  3111         }
  3112       else if (EQ (cmd, Qtty_menu_next_item))
  3113         {
  3114           if (*y < max_y)
  3115             *y += 1;
  3116           else
  3117             st = MI_SCROLL_FORWARD;
  3118         }
  3119       else if (EQ (cmd, Qtty_menu_prev_item))
  3120         {
  3121           if (*y > min_y)
  3122             *y -= 1;
  3123           else
  3124             st = MI_SCROLL_BACK;
  3125         }
  3126       else if (EQ (cmd, Qtty_menu_select))
  3127         st = MI_ITEM_SELECTED;
  3128       else if (!EQ (cmd, Qtty_menu_ignore))
  3129         usable_input = 0;
  3130       if (usable_input)
  3131         sf->mouse_moved = 1;
  3132       return st;
  3133     }
  3134   return MI_CONTINUE;
  3135 }
  3136 
  3137 /* Display menu, wait for user's response, and return that response.  */
  3138 static int
  3139 tty_menu_activate (tty_menu *menu, int *pane, int *selidx,
  3140                    int x0, int y0, char **txt,
  3141                    void (*help_callback)(char const *, int, int),
  3142                    bool kbd_navigation)
  3143 {
  3144   struct tty_menu_state *state;
  3145   int statecount, x, y, i;
  3146   bool leave, onepane;
  3147   int result UNINIT;
  3148   int title_faces[4];           /* Face to display the menu title.  */
  3149   int faces[4], buffers_num_deleted = 0;
  3150   struct frame *sf = SELECTED_FRAME ();
  3151   struct tty_display_info *tty = FRAME_TTY (sf);
  3152   bool first_time;
  3153   Lisp_Object selectface;
  3154   int first_item = 0;
  3155   int col, row;
  3156   Lisp_Object prev_inhibit_redisplay = Vinhibit_redisplay;
  3157   USE_SAFE_ALLOCA;
  3158 
  3159   /* Don't allow non-positive x0 and y0, lest the menu will wrap
  3160      around the display.  */
  3161   if (x0 <= 0)
  3162     x0 = 1;
  3163   if (y0 <= 0)
  3164     y0 = 1;
  3165 
  3166   SAFE_NALLOCA (state, 1, menu->panecount);
  3167   memset (state, 0, sizeof (*state));
  3168   faces[0]
  3169     = lookup_derived_face (NULL, sf, intern ("tty-menu-disabled-face"),
  3170                            DEFAULT_FACE_ID, 1);
  3171   faces[1]
  3172     = lookup_derived_face (NULL, sf, intern ("tty-menu-enabled-face"),
  3173                            DEFAULT_FACE_ID, 1);
  3174   selectface = intern ("tty-menu-selected-face");
  3175   faces[2] = lookup_derived_face (NULL, sf, selectface,
  3176                                   faces[0], 1);
  3177   faces[3] = lookup_derived_face (NULL, sf, selectface,
  3178                                   faces[1], 1);
  3179 
  3180   /* Make sure the menu title is always displayed with
  3181      `tty-menu-selected-face', no matter where the mouse pointer is.  */
  3182   for (i = 0; i < 4; i++)
  3183     title_faces[i] = faces[3];
  3184 
  3185   statecount = 1;
  3186 
  3187   /* Don't let the title for the "Buffers" popup menu include a
  3188      digit (which is ugly).
  3189 
  3190      This is a terrible kludge, but I think the "Buffers" case is
  3191      the only one where the title includes a number, so it doesn't
  3192      seem to be necessary to make this more general.  */
  3193   if (strncmp (menu->text[0], "Buffers 1", 9) == 0)
  3194     {
  3195       menu->text[0][7] = '\0';
  3196       buffers_num_deleted = 1;
  3197     }
  3198 
  3199   /* Inhibit redisplay for as long as the menu is active, to avoid
  3200      messing the screen if some timer calls sit-for or a similar
  3201      function.  */
  3202   Vinhibit_redisplay = Qt;
  3203 
  3204   /* Force update of the current frame, so that the desired and the
  3205      current matrices are identical.  */
  3206   update_frame_with_menu (sf, -1, -1);
  3207   state[0].menu = menu;
  3208   state[0].screen_behind = save_and_enable_current_matrix (sf);
  3209 
  3210   /* Display the menu title.  We subtract 1 from x0 and y0 because we
  3211      want to interpret them as zero-based column and row coordinates,
  3212      and also because we want the first item of the menu, not its
  3213      title, to appear at x0,y0.  */
  3214   tty_menu_display (menu, x0 - 1, y0 - 1, 1, title_faces, x0 - 1, y0 - 1, 0, 0);
  3215 
  3216   /* Turn off the cursor.  Otherwise it shows through the menu
  3217      panes, which is ugly.  */
  3218   col = cursorX (tty);
  3219   row = cursorY (tty);
  3220   tty_hide_cursor (tty);
  3221 
  3222   if (buffers_num_deleted)
  3223     menu->text[0][7] = ' ';
  3224   onepane = menu->count == 1 && menu->submenu[0];
  3225   if (onepane)
  3226     {
  3227       menu->width = menu->submenu[0]->width;
  3228       state[0].menu = menu->submenu[0];
  3229     }
  3230   else
  3231     {
  3232       state[0].menu = menu;
  3233     }
  3234   state[0].x = x0 - 1;
  3235   state[0].y = y0;
  3236   state[0].pane = onepane;
  3237 
  3238   x = state[0].x;
  3239   y = state[0].y;
  3240   first_time = true;
  3241 
  3242   leave = 0;
  3243   while (!leave)
  3244     {
  3245       mi_result input_status;
  3246       int min_y = state[0].y;
  3247       int max_y = min (min_y + state[0].menu->count, FRAME_TOTAL_LINES (sf) - 1) - 1;
  3248 
  3249       input_status = read_menu_input (sf, &x, &y, min_y, max_y, &first_time);
  3250       if (input_status)
  3251         {
  3252           leave = 1;
  3253           switch (input_status)
  3254             {
  3255             case MI_QUIT_MENU:
  3256               /* Remove the last help-echo, so that it doesn't
  3257                  re-appear after "Quit".  */
  3258               show_help_echo (Qnil, Qnil, Qnil, Qnil);
  3259               result = TTYM_NO_SELECT;
  3260               break;
  3261             case MI_NEXT_ITEM:
  3262               if (kbd_navigation)
  3263                 result = TTYM_NEXT;
  3264               else
  3265                 leave = 0;
  3266               break;
  3267             case MI_PREV_ITEM:
  3268               if (kbd_navigation)
  3269                 result = TTYM_PREV;
  3270               else
  3271                 leave = 0;
  3272               break;
  3273             case MI_SCROLL_FORWARD:
  3274               if (y - min_y == state[0].menu->count - 1 - first_item)
  3275                 {
  3276                   y = min_y;
  3277                   first_item = 0;
  3278                 }
  3279               else
  3280                 first_item++;
  3281               leave = 0;
  3282               break;
  3283             case MI_SCROLL_BACK:
  3284               if (first_item == 0)
  3285                 {
  3286                   y = max_y;
  3287                   first_item = state[0].menu->count - 1 - (y - min_y);
  3288                 }
  3289               else
  3290                 first_item--;
  3291               leave = 0;
  3292               break;
  3293             default:
  3294               /* MI_ITEM_SELECTED is handled below, so nothing to do.  */
  3295               break;
  3296             }
  3297         }
  3298       if (sf->mouse_moved && input_status != MI_QUIT_MENU)
  3299         {
  3300           sf->mouse_moved = 0;
  3301           result = TTYM_IA_SELECT;
  3302           for (i = 0; i < statecount; i++)
  3303             if (state[i].x <= x && x < state[i].x + state[i].menu->width + 2)
  3304               {
  3305                 int dy = y - state[i].y + first_item;
  3306                 if (0 <= dy && dy < state[i].menu->count)
  3307                   {
  3308                     if (!state[i].menu->submenu[dy])
  3309                       {
  3310                         if (state[i].menu->panenumber[dy])
  3311                           result = TTYM_SUCCESS;
  3312                         else
  3313                           result = TTYM_IA_SELECT;
  3314                       }
  3315                     *pane = state[i].pane - 1;
  3316                     *selidx = dy;
  3317                     /* We hit some part of a menu, so drop extra menus that
  3318                        have been opened.  That does not include an open and
  3319                        active submenu.  */
  3320                     if (i != statecount - 2
  3321                         || state[i].menu->submenu[dy] != state[i + 1].menu)
  3322                       while (i != statecount - 1)
  3323                         {
  3324                           statecount--;
  3325                           screen_update (sf, state[statecount].screen_behind);
  3326                           state[statecount].screen_behind = NULL;
  3327                         }
  3328                     if (i == statecount - 1 && state[i].menu->submenu[dy])
  3329                       {
  3330                         tty_menu_display (state[i].menu,
  3331                                           state[i].x,
  3332                                           state[i].y,
  3333                                           state[i].pane,
  3334                                           faces, x, y, first_item, 1);
  3335                         state[statecount].menu = state[i].menu->submenu[dy];
  3336                         state[statecount].pane = state[i].menu->panenumber[dy];
  3337                         state[statecount].screen_behind
  3338                           = save_and_enable_current_matrix (sf);
  3339                         state[statecount].x
  3340                           = state[i].x + state[i].menu->width + 2;
  3341                         state[statecount].y = y;
  3342                         statecount++;
  3343                       }
  3344                   }
  3345               }
  3346           tty_menu_display (state[statecount - 1].menu,
  3347                             state[statecount - 1].x,
  3348                             state[statecount - 1].y,
  3349                             state[statecount - 1].pane,
  3350                             faces, x, y, first_item, 1);
  3351           /* The call to display help-echo below will move the cursor,
  3352              so remember its current position as computed by
  3353              tty_menu_display.  */
  3354           col = cursorX (tty);
  3355           row = cursorY (tty);
  3356         }
  3357 
  3358       /* Display the help-echo message for the currently-selected menu
  3359          item.  */
  3360       if ((menu_help_message || prev_menu_help_message)
  3361           && menu_help_message != prev_menu_help_message)
  3362         {
  3363           help_callback (menu_help_message,
  3364                          menu_help_paneno, menu_help_itemno);
  3365           /* Move the cursor to the beginning of the current menu
  3366              item, so that screen readers and other accessibility aids
  3367              know where the active region is.  */
  3368           cursor_to (sf, row, col);
  3369           prev_menu_help_message = menu_help_message;
  3370         }
  3371       /* Both tty_menu_display and help_callback invoke update_end,
  3372          which calls tty_show_cursor.  Re-hide it, so it doesn't show
  3373          through the menus.  */
  3374       tty_hide_cursor (tty);
  3375       fflush (tty->output);
  3376     }
  3377 
  3378   sf->mouse_moved = 0;
  3379   screen_update (sf, state[0].screen_behind);
  3380   while (statecount--)
  3381     free_saved_screen (state[statecount].screen_behind);
  3382   tty_show_cursor (tty);        /* Turn cursor back on.  */
  3383   fflush (tty->output);
  3384 
  3385 /* Clean up any mouse events that are waiting inside Emacs event queue.
  3386      These events are likely to be generated before the menu was even
  3387      displayed, probably because the user pressed and released the button
  3388      (which invoked the menu) too quickly.  If we don't remove these events,
  3389      Emacs will process them after we return and surprise the user.  */
  3390   discard_mouse_events ();
  3391   if (!kbd_buffer_events_waiting ())
  3392     clear_input_pending ();
  3393   SAFE_FREE ();
  3394   Vinhibit_redisplay = prev_inhibit_redisplay;
  3395   return result;
  3396 }
  3397 
  3398 /* Dispose of a menu.  */
  3399 
  3400 static void
  3401 tty_menu_destroy (tty_menu *menu)
  3402 {
  3403   int i;
  3404   if (menu->allocated)
  3405     {
  3406       for (i = 0; i < menu->count; i++)
  3407         if (menu->submenu[i])
  3408           tty_menu_destroy (menu->submenu[i]);
  3409       xfree (menu->text);
  3410       xfree (menu->submenu);
  3411       xfree (menu->panenumber);
  3412       xfree (menu->help_text);
  3413     }
  3414   xfree (menu);
  3415   menu_help_message = prev_menu_help_message = NULL;
  3416 }
  3417 
  3418 /* Show help HELP_STRING, or clear help if HELP_STRING is null.
  3419 
  3420    PANE is the pane number, and ITEM is the menu item number in
  3421    the menu (currently not used).  */
  3422 
  3423 static void
  3424 tty_menu_help_callback (char const *help_string, int pane, int item)
  3425 {
  3426   Lisp_Object *first_item;
  3427   Lisp_Object pane_name;
  3428   Lisp_Object menu_object;
  3429 
  3430   first_item = XVECTOR (menu_items)->contents;
  3431   if (EQ (first_item[0], Qt))
  3432     pane_name = first_item[MENU_ITEMS_PANE_NAME];
  3433   else if (EQ (first_item[0], Qquote))
  3434     /* This shouldn't happen, see xmenu_show.  */
  3435     pane_name = empty_unibyte_string;
  3436   else
  3437     pane_name = first_item[MENU_ITEMS_ITEM_NAME];
  3438 
  3439   /* (menu-item MENU-NAME PANE-NUMBER)  */
  3440   menu_object = list3 (Qmenu_item, pane_name, make_fixnum (pane));
  3441   show_help_echo (help_string ? build_string (help_string) : Qnil,
  3442                   Qnil, menu_object, make_fixnum (item));
  3443 }
  3444 
  3445 struct tty_pop_down_menu
  3446 {
  3447   tty_menu *menu;
  3448   struct buffer *buffer;
  3449 };
  3450 
  3451 static void
  3452 tty_pop_down_menu (void *arg)
  3453 {
  3454   struct tty_pop_down_menu *data = arg;
  3455 
  3456   block_input ();
  3457   tty_menu_destroy (data->menu);
  3458   set_buffer_internal (data->buffer);
  3459   unblock_input ();
  3460 }
  3461 
  3462 /* Return the zero-based index of the last menu-bar item on frame F.  */
  3463 static int
  3464 tty_menu_last_menubar_item (struct frame *f)
  3465 {
  3466   int i = 0;
  3467 
  3468   eassert (FRAME_TERMCAP_P (f) && FRAME_LIVE_P (f));
  3469   if (FRAME_TERMCAP_P (f) && FRAME_LIVE_P (f))
  3470     {
  3471       Lisp_Object items = FRAME_MENU_BAR_ITEMS (f);
  3472 
  3473       while (i < ASIZE (items))
  3474         {
  3475           Lisp_Object str;
  3476 
  3477           str = AREF (items, i + 1);
  3478           if (NILP (str))
  3479             break;
  3480           i += 4;
  3481         }
  3482       i -= 4;   /* Went one too far!  */
  3483     }
  3484   return i;
  3485 }
  3486 
  3487 /* Find in frame F's menu bar the menu item that is next or previous
  3488    to the item at X/Y, and return that item's position in X/Y.  WHICH
  3489    says which one--next or previous--item to look for.  X and Y are
  3490    measured in character cells.  This should only be called on TTY
  3491    frames.  */
  3492 static void
  3493 tty_menu_new_item_coords (struct frame *f, int which, int *x, int *y)
  3494 {
  3495   eassert (FRAME_TERMCAP_P (f) && FRAME_LIVE_P (f));
  3496   if (FRAME_TERMCAP_P (f) && FRAME_LIVE_P (f))
  3497     {
  3498       Lisp_Object items = FRAME_MENU_BAR_ITEMS (f);
  3499       int last_i = tty_menu_last_menubar_item (f);
  3500       int i, prev_x;
  3501 
  3502       /* This loop assumes a single menu-bar line, and will fail to
  3503          find an item if it is not in the first line.  Note that
  3504          make_lispy_event in keyboard.c makes the same assumption.  */
  3505       for (i = 0, prev_x = -1; i < ASIZE (items); i += 4)
  3506         {
  3507           Lisp_Object pos, str;
  3508           int ix;
  3509 
  3510           str = AREF (items, i + 1);
  3511           pos = AREF (items, i + 3);
  3512           if (NILP (str))
  3513             return;
  3514           ix = XFIXNUM (pos);
  3515           if (ix <= *x
  3516               /* We use <= so the blank between 2 items on a TTY is
  3517                  considered part of the previous item.  */
  3518               && *x <= ix + menu_item_width (SDATA (str)))
  3519             {
  3520               /* Found current item.  Now compute the X coordinate of
  3521                  the previous or next item.  */
  3522               if (which == TTYM_NEXT)
  3523                 {
  3524                   if (i < last_i)
  3525                     *x = XFIXNUM (AREF (items, i + 4 + 3));
  3526                   else
  3527                     *x = 0;     /* Wrap around to the first item.  */
  3528                 }
  3529               else if (prev_x < 0)
  3530                 {
  3531                   /* Wrap around to the last item.  */
  3532                   *x = XFIXNUM (AREF (items, last_i + 3));
  3533                 }
  3534               else
  3535                 *x = prev_x;
  3536               return;
  3537             }
  3538           prev_x = ix;
  3539         }
  3540     }
  3541 }
  3542 
  3543 /* WINDOWSNT uses this as menu_show_hook, see w32console.c.  */
  3544 Lisp_Object
  3545 tty_menu_show (struct frame *f, int x, int y, int menuflags,
  3546                Lisp_Object title, const char **error_name)
  3547 {
  3548   tty_menu *menu;
  3549   int pane, selidx, lpane, status;
  3550   Lisp_Object entry, pane_prefix;
  3551   char *datap;
  3552   int ulx, uly, width, height;
  3553   int item_x, item_y;
  3554   int dispwidth, dispheight;
  3555   int i, j, lines, maxlines;
  3556   int maxwidth;
  3557   specpdl_ref specpdl_count;
  3558 
  3559   eassert (FRAME_TERMCAP_P (f));
  3560 
  3561   *error_name = 0;
  3562   if (menu_items_n_panes == 0)
  3563     return Qnil;
  3564 
  3565   if (menu_items_used <= MENU_ITEMS_PANE_LENGTH)
  3566     {
  3567       *error_name = "Empty menu";
  3568       return Qnil;
  3569     }
  3570 
  3571   /* Make the menu on that window.  */
  3572   menu = tty_menu_create ();
  3573 
  3574   /* Don't GC while we prepare and show the menu, because we give the
  3575      menu functions pointers to the contents of strings.  */
  3576   specpdl_count = inhibit_garbage_collection ();
  3577 
  3578   /* Avoid crashes if, e.g., another client will connect while we
  3579      are in a menu.  */
  3580   temporarily_switch_to_single_kboard (f);
  3581 
  3582   /* Adjust coordinates to be root-window-relative.  */
  3583   item_x = x += f->left_pos;
  3584   item_y = y += f->top_pos;
  3585 
  3586   /* Create all the necessary panes and their items.  */
  3587   USE_SAFE_ALLOCA;
  3588   maxwidth = maxlines = lines = i = 0;
  3589   lpane = TTYM_FAILURE;
  3590   while (i < menu_items_used)
  3591     {
  3592       if (EQ (AREF (menu_items, i), Qt))
  3593         {
  3594           /* Create a new pane.  */
  3595           Lisp_Object pane_name, prefix;
  3596           const char *pane_string;
  3597 
  3598           maxlines = max (maxlines, lines);
  3599           lines = 0;
  3600           pane_name = AREF (menu_items, i + MENU_ITEMS_PANE_NAME);
  3601           prefix = AREF (menu_items, i + MENU_ITEMS_PANE_PREFIX);
  3602           pane_string = (NILP (pane_name)
  3603                          ? "" : SSDATA (pane_name));
  3604           if ((menuflags & MENU_KEYMAPS) && !NILP (prefix))
  3605             pane_string++;
  3606 
  3607           lpane = tty_menu_add_pane (menu, pane_string);
  3608           if (lpane == TTYM_FAILURE)
  3609             {
  3610               tty_menu_destroy (menu);
  3611               *error_name = "Can't create pane";
  3612               entry = Qnil;
  3613               goto tty_menu_end;
  3614             }
  3615           i += MENU_ITEMS_PANE_LENGTH;
  3616 
  3617           /* Find the width of the widest item in this pane.  */
  3618           j = i;
  3619           while (j < menu_items_used)
  3620             {
  3621               Lisp_Object item;
  3622               item = AREF (menu_items, j);
  3623               if (EQ (item, Qt))
  3624                 break;
  3625               if (NILP (item))
  3626                 {
  3627                   j++;
  3628                   continue;
  3629                 }
  3630               width = SBYTES (item);
  3631               if (width > maxwidth)
  3632                 maxwidth = width;
  3633 
  3634               j += MENU_ITEMS_ITEM_LENGTH;
  3635             }
  3636         }
  3637       /* Ignore a nil in the item list.
  3638          It's meaningful only for dialog boxes.  */
  3639       else if (EQ (AREF (menu_items, i), Qquote))
  3640         i += 1;
  3641       else
  3642         {
  3643           /* Create a new item within current pane.  */
  3644           Lisp_Object item_name, enable, descrip, help;
  3645           char *item_data;
  3646           char const *help_string;
  3647 
  3648           item_name = AREF (menu_items, i + MENU_ITEMS_ITEM_NAME);
  3649           enable = AREF (menu_items, i + MENU_ITEMS_ITEM_ENABLE);
  3650           descrip = AREF (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY);
  3651           help = AREF (menu_items, i + MENU_ITEMS_ITEM_HELP);
  3652           help_string = STRINGP (help) ? SSDATA (help) : NULL;
  3653 
  3654           if (!NILP (descrip))
  3655             {
  3656               item_data = SAFE_ALLOCA (maxwidth + SBYTES (descrip) + 1);
  3657               memcpy (item_data, SSDATA (item_name), SBYTES (item_name));
  3658               for (j = SCHARS (item_name); j < maxwidth; j++)
  3659                 item_data[j] = ' ';
  3660               memcpy (item_data + j, SSDATA (descrip), SBYTES (descrip));
  3661               item_data[j + SBYTES (descrip)] = 0;
  3662             }
  3663           else
  3664             item_data = SSDATA (item_name);
  3665 
  3666           if (lpane == TTYM_FAILURE
  3667               || (! tty_menu_add_selection (menu, lpane, item_data,
  3668                                             !NILP (enable), help_string)))
  3669             {
  3670               tty_menu_destroy (menu);
  3671               *error_name = "Can't add selection to menu";
  3672               entry = Qnil;
  3673               goto tty_menu_end;
  3674             }
  3675           i += MENU_ITEMS_ITEM_LENGTH;
  3676           lines++;
  3677         }
  3678     }
  3679 
  3680   maxlines = max (maxlines, lines);
  3681 
  3682   /* All set and ready to fly.  */
  3683   dispwidth = f->text_cols;
  3684   dispheight = f->text_lines;
  3685   x = min (x, dispwidth);
  3686   y = min (y, dispheight);
  3687   x = max (x, 1);
  3688   y = max (y, 1);
  3689   tty_menu_locate (menu, x, y, &ulx, &uly, &width, &height);
  3690   if (ulx + width > dispwidth)
  3691     {
  3692       x -= (ulx + width) - dispwidth;
  3693       ulx = dispwidth - width;
  3694     }
  3695   if (uly + height > dispheight)
  3696     {
  3697       y -= (uly + height) - dispheight;
  3698       uly = dispheight - height;
  3699     }
  3700 
  3701   if (FRAME_HAS_MINIBUF_P (f) && uly + height > dispheight - 2)
  3702     {
  3703       /* Move the menu away of the echo area, to avoid overwriting the
  3704          menu with help echo messages or vice versa.  */
  3705       if (BUFFERP (echo_area_buffer[0]) && WINDOWP (echo_area_window))
  3706         {
  3707           y -= WINDOW_TOTAL_LINES (XWINDOW (echo_area_window)) + 1;
  3708           uly -= WINDOW_TOTAL_LINES (XWINDOW (echo_area_window)) + 1;
  3709         }
  3710       else
  3711         {
  3712           y -= 2;
  3713           uly -= 2;
  3714         }
  3715     }
  3716 
  3717   if (ulx < 0) x -= ulx;
  3718   if (uly < 0) y -= uly;
  3719 
  3720 #if 0
  3721   /* This code doesn't make sense on a TTY, since it can easily annul
  3722      the adjustments above that carefully avoid truncation of the menu
  3723      items.  I think it was written to fix some problem that only
  3724      happens on X11.  */
  3725   if (! for_click)
  3726     {
  3727       /* If position was not given by a mouse click, adjust so upper left
  3728          corner of the menu as a whole ends up at given coordinates.  This
  3729          is what x-popup-menu says in its documentation.  */
  3730       x += width / 2;
  3731       y += 1.5 * height / (maxlines + 2);
  3732     }
  3733 #endif
  3734 
  3735   pane = selidx = 0;
  3736 
  3737   /* We save and restore the current buffer because tty_menu_activate
  3738      triggers redisplay, which switches buffers at will.  */
  3739   record_unwind_protect_ptr (tty_pop_down_menu,
  3740                              &((struct tty_pop_down_menu)
  3741                                {menu, current_buffer}));
  3742 
  3743   specbind (Qoverriding_terminal_local_map,
  3744             Fsymbol_value (Qtty_menu_navigation_map));
  3745   status = tty_menu_activate (menu, &pane, &selidx, x, y, &datap,
  3746                               tty_menu_help_callback,
  3747                               menuflags & MENU_KBD_NAVIGATION);
  3748   entry = pane_prefix = Qnil;
  3749 
  3750   switch (status)
  3751     {
  3752     case TTYM_SUCCESS:
  3753       /* Find the item number SELIDX in pane number PANE.  */
  3754       i = 0;
  3755       while (i < menu_items_used)
  3756         {
  3757           if (EQ (AREF (menu_items, i), Qt))
  3758             {
  3759               if (pane == 0)
  3760                 pane_prefix
  3761                   = AREF (menu_items, i + MENU_ITEMS_PANE_PREFIX);
  3762               pane--;
  3763               i += MENU_ITEMS_PANE_LENGTH;
  3764             }
  3765           else
  3766             {
  3767               if (pane == -1)
  3768                 {
  3769                   if (selidx == 0)
  3770                     {
  3771                       entry
  3772                         = AREF (menu_items, i + MENU_ITEMS_ITEM_VALUE);
  3773                       if (menuflags & MENU_KEYMAPS)
  3774                         {
  3775                           entry = Fcons (entry, Qnil);
  3776                           if (!NILP (pane_prefix))
  3777                             entry = Fcons (pane_prefix, entry);
  3778                         }
  3779                       break;
  3780                     }
  3781                   selidx--;
  3782                 }
  3783               i += MENU_ITEMS_ITEM_LENGTH;
  3784             }
  3785         }
  3786       break;
  3787 
  3788     case TTYM_NEXT:
  3789     case TTYM_PREV:
  3790       tty_menu_new_item_coords (f, status, &item_x, &item_y);
  3791       entry = Fcons (make_fixnum (item_x), make_fixnum (item_y));
  3792       break;
  3793 
  3794     case TTYM_FAILURE:
  3795       *error_name = "Can't activate menu";
  3796     case TTYM_IA_SELECT:
  3797       break;
  3798     case TTYM_NO_SELECT:
  3799       /* If the selected frame was changed while we displayed a menu,
  3800          throw to top level in order to undo any temporary settings
  3801          made by TTY menu code.  */
  3802       if (f != SELECTED_FRAME ())
  3803         Ftop_level ();
  3804       /* Make "Cancel" equivalent to C-g unless FOR_CLICK (which means
  3805          the menu was invoked with a mouse event as POSITION).  */
  3806       if (!(menuflags & MENU_FOR_CLICK))
  3807         quit ();
  3808       break;
  3809     }
  3810 
  3811  tty_menu_end:
  3812 
  3813   return SAFE_FREE_UNBIND_TO (specpdl_count, entry);
  3814 }
  3815 
  3816 #endif  /* !MSDOS */
  3817 
  3818 
  3819 #ifndef MSDOS
  3820 /***********************************************************************
  3821                             Initialization
  3822  ***********************************************************************/
  3823 
  3824 /* Initialize the tty-dependent part of frame F.  The frame must
  3825    already have its device initialized.  */
  3826 
  3827 void
  3828 create_tty_output (struct frame *f)
  3829 {
  3830   struct tty_output *t = xzalloc (sizeof *t);
  3831 
  3832   eassert (FRAME_TERMCAP_P (f));
  3833 
  3834   t->display_info = FRAME_TERMINAL (f)->display_info.tty;
  3835 
  3836   f->output_data.tty = t;
  3837 }
  3838 
  3839 /* Delete frame F's face cache, and its tty-dependent part.  */
  3840 
  3841 static void
  3842 tty_free_frame_resources (struct frame *f)
  3843 {
  3844   eassert (FRAME_TERMCAP_P (f));
  3845   free_frame_faces (f);
  3846   xfree (f->output_data.tty);
  3847 }
  3848 
  3849 #else  /* MSDOS */
  3850 
  3851 /* Delete frame F's face cache.  */
  3852 
  3853 static void
  3854 tty_free_frame_resources (struct frame *f)
  3855 {
  3856   eassert (FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f));
  3857   free_frame_faces (f);
  3858 }
  3859 #endif  /* MSDOS */
  3860 
  3861 /* Reset the hooks in TERMINAL.  */
  3862 
  3863 static void
  3864 clear_tty_hooks (struct terminal *terminal)
  3865 {
  3866   terminal->rif = 0;
  3867   terminal->cursor_to_hook = 0;
  3868   terminal->raw_cursor_to_hook = 0;
  3869   terminal->clear_to_end_hook = 0;
  3870   terminal->clear_frame_hook = 0;
  3871   terminal->clear_end_of_line_hook = 0;
  3872   terminal->ins_del_lines_hook = 0;
  3873   terminal->insert_glyphs_hook = 0;
  3874   terminal->write_glyphs_hook = 0;
  3875   terminal->delete_glyphs_hook = 0;
  3876   terminal->ring_bell_hook = 0;
  3877   terminal->reset_terminal_modes_hook = 0;
  3878   terminal->set_terminal_modes_hook = 0;
  3879   terminal->update_begin_hook = 0;
  3880   terminal->update_end_hook = 0;
  3881   terminal->set_terminal_window_hook = 0;
  3882   /* Don't clear the defined_color_hook, as that makes it impossible
  3883      to unload or load a theme when some TTY frame is suspended.  */
  3884   /* terminal->defined_color_hook = 0; */
  3885   terminal->mouse_position_hook = 0;
  3886   terminal->frame_rehighlight_hook = 0;
  3887   terminal->frame_raise_lower_hook = 0;
  3888   terminal->fullscreen_hook = 0;
  3889   terminal->menu_show_hook = 0;
  3890   terminal->set_vertical_scroll_bar_hook = 0;
  3891   terminal->set_horizontal_scroll_bar_hook = 0;
  3892   terminal->condemn_scroll_bars_hook = 0;
  3893   terminal->redeem_scroll_bar_hook = 0;
  3894   terminal->judge_scroll_bars_hook = 0;
  3895   terminal->read_socket_hook = 0;
  3896   terminal->frame_up_to_date_hook = 0;
  3897 
  3898   /* Leave these two set, or suspended frames are not deleted
  3899      correctly.  */
  3900   terminal->delete_frame_hook = &tty_free_frame_resources;
  3901   terminal->delete_terminal_hook = &delete_tty;
  3902 }
  3903 
  3904 /* Initialize hooks in TERMINAL with the values needed for a tty.  */
  3905 
  3906 static void
  3907 set_tty_hooks (struct terminal *terminal)
  3908 {
  3909   terminal->cursor_to_hook = &tty_cursor_to;
  3910   terminal->raw_cursor_to_hook = &tty_raw_cursor_to;
  3911   terminal->clear_to_end_hook = &tty_clear_to_end;
  3912   terminal->clear_frame_hook = &tty_clear_frame;
  3913   terminal->clear_end_of_line_hook = &tty_clear_end_of_line;
  3914   terminal->ins_del_lines_hook = &tty_ins_del_lines;
  3915   terminal->insert_glyphs_hook = &tty_insert_glyphs;
  3916   terminal->write_glyphs_hook = &tty_write_glyphs;
  3917   terminal->delete_glyphs_hook = &tty_delete_glyphs;
  3918   terminal->ring_bell_hook = &tty_ring_bell;
  3919   terminal->reset_terminal_modes_hook = &tty_reset_terminal_modes;
  3920   terminal->set_terminal_modes_hook = &tty_set_terminal_modes;
  3921   terminal->update_end_hook = &tty_update_end;
  3922 #ifdef MSDOS
  3923   terminal->menu_show_hook = &x_menu_show;
  3924 #else
  3925   terminal->menu_show_hook = &tty_menu_show;
  3926 #endif
  3927   terminal->set_terminal_window_hook = &tty_set_terminal_window;
  3928   terminal->defined_color_hook = &tty_defined_color; /* xfaces.c */
  3929   terminal->read_socket_hook = &tty_read_avail_input; /* keyboard.c */
  3930   terminal->delete_frame_hook = &tty_free_frame_resources;
  3931   terminal->delete_terminal_hook = &delete_tty;
  3932   /* Other hooks are NULL by default.  */
  3933 }
  3934 
  3935 /* If FD is the controlling terminal, drop it.  */
  3936 static void
  3937 dissociate_if_controlling_tty (int fd)
  3938 {
  3939   /* If tcgetpgrp succeeds, fd is the controlling terminal,
  3940      so dissociate it by invoking setsid.  */
  3941   if (tcgetpgrp (fd) >= 0 && setsid () < 0)
  3942     {
  3943 #ifdef TIOCNOTTY
  3944       /* setsid failed, presumably because Emacs is already a process
  3945          group leader.  Fall back on the obsolescent way to dissociate
  3946          a controlling tty.  */
  3947       sigset_t oldset;
  3948       block_tty_out_signal (&oldset);
  3949       ioctl (fd, TIOCNOTTY, 0);
  3950       unblock_tty_out_signal (&oldset);
  3951 #endif
  3952     }
  3953 }
  3954 
  3955 /* Create a termcap display on the tty device with the given name and
  3956    type.
  3957 
  3958    If NAME is NULL, then use the controlling tty, i.e., DEV_TTY.
  3959    Otherwise NAME should be a path to the tty device file,
  3960    e.g. "/dev/pts/7".
  3961 
  3962    TERMINAL_TYPE is the termcap type of the device, e.g. "vt100".
  3963 
  3964    If MUST_SUCCEED is true, then all errors are fatal.  */
  3965 
  3966 struct terminal *
  3967 init_tty (const char *name, const char *terminal_type, bool must_succeed)
  3968 {
  3969   struct tty_display_info *tty = NULL;
  3970   struct terminal *terminal = NULL;
  3971 #ifndef DOS_NT
  3972   char *area;
  3973   char **address = &area;
  3974   int status;
  3975   sigset_t oldset;
  3976   bool ctty = false;  /* True if asked to open controlling tty.  */
  3977 #endif
  3978 
  3979   if (!terminal_type)
  3980     maybe_fatal (must_succeed, 0,
  3981                  "Unknown terminal type",
  3982                  "Unknown terminal type");
  3983 
  3984   if (name == NULL)
  3985     name = DEV_TTY;
  3986 #ifndef DOS_NT
  3987   if (!strcmp (name, DEV_TTY))
  3988     ctty = 1;
  3989 #endif
  3990 
  3991   /* If we already have a terminal on the given device, use that.  If
  3992      all such terminals are suspended, create a new one instead.  */
  3993   /* XXX Perhaps this should be made explicit by having init_tty
  3994      always create a new terminal and separating terminal and frame
  3995      creation on Lisp level.  */
  3996   terminal = get_named_terminal (name);
  3997   if (terminal)
  3998     return terminal;
  3999 
  4000   terminal = create_terminal (output_termcap, NULL);
  4001 #ifdef MSDOS
  4002   if (been_here > 0)
  4003     maybe_fatal (0, 0, "Attempt to create another terminal %s", "",
  4004                  name, "");
  4005   been_here = 1;
  4006   tty = &the_only_display_info;
  4007 #else
  4008   tty = xzalloc (sizeof *tty);
  4009 #endif
  4010   tty->top_frame = Qnil;
  4011   tty->next = tty_list;
  4012   tty_list = tty;
  4013 
  4014   terminal->display_info.tty = tty;
  4015   tty->terminal = terminal;
  4016 
  4017   tty->Wcm = xmalloc (sizeof *tty->Wcm);
  4018   Wcm_clear (tty);
  4019 
  4020   encode_terminal_src_size = 0;
  4021   encode_terminal_dst_size = 0;
  4022 
  4023 
  4024 #ifndef DOS_NT
  4025   set_tty_hooks (terminal);
  4026 
  4027   {
  4028     /* Open the terminal device.  */
  4029 
  4030     /* If !ctty, don't recognize it as our controlling terminal, and
  4031        don't make it the controlling tty if we don't have one now.
  4032 
  4033        Alas, O_IGNORE_CTTY is a GNU extension that seems to be only
  4034        defined on Hurd.  On other systems, we need to explicitly
  4035        dissociate ourselves from the controlling tty when we want to
  4036        open a frame on the same terminal.  */
  4037     int flags = O_RDWR | O_NOCTTY | (ctty ? 0 : O_IGNORE_CTTY);
  4038     int fd = emacs_open (name, flags, 0);
  4039     tty->input = tty->output
  4040       = ((fd < 0 || ! isatty (fd))
  4041          ? NULL
  4042          : fdopen (fd, "w+"));
  4043 
  4044     if (! tty->input)
  4045       {
  4046         char const *diagnostic
  4047           = (fd < 0) ? "Could not open file: %s" : "Not a tty device: %s";
  4048         emacs_close (fd);
  4049         delete_terminal_internal (terminal);
  4050         maybe_fatal (must_succeed, terminal, diagnostic, diagnostic, name);
  4051       }
  4052 
  4053     tty->name = xstrdup (name);
  4054     terminal->name = xstrdup (name);
  4055 
  4056     if (!O_IGNORE_CTTY && !ctty)
  4057       dissociate_if_controlling_tty (fd);
  4058   }
  4059 
  4060   tty->type = xstrdup (terminal_type);
  4061 
  4062   add_keyboard_wait_descriptor (fileno (tty->input));
  4063 
  4064   Wcm_clear (tty);
  4065 
  4066   /* On some systems, tgetent tries to access the controlling
  4067      terminal.  */
  4068   block_tty_out_signal (&oldset);
  4069   status = tgetent (tty->termcap_term_buffer, terminal_type);
  4070   if (tty->termcap_term_buffer[TERMCAP_BUFFER_SIZE - 1])
  4071     emacs_abort ();
  4072   unblock_tty_out_signal (&oldset);
  4073 
  4074   if (status < 0)
  4075     {
  4076 #ifdef TERMINFO
  4077       maybe_fatal (must_succeed, terminal,
  4078                    "Cannot open terminfo database file",
  4079                    "Cannot open terminfo database file");
  4080 #else
  4081       maybe_fatal (must_succeed, terminal,
  4082                    "Cannot open termcap database file",
  4083                    "Cannot open termcap database file");
  4084 #endif
  4085     }
  4086   if (status == 0)
  4087     {
  4088       maybe_fatal (must_succeed, terminal,
  4089                    "Terminal type %s is not defined",
  4090                    "Terminal type %s is not defined.\n\
  4091 If that is not the actual type of terminal you have,\n\
  4092 use the Bourne shell command 'TERM=...; export TERM' (C-shell:\n\
  4093 'setenv TERM ...') to specify the correct type.  It may be necessary\n"
  4094 #ifdef TERMINFO
  4095 "to do 'unset TERMINFO' (C-shell: 'unsetenv TERMINFO') as well.",
  4096 #else
  4097 "to do 'unset TERMCAP' (C-shell: 'unsetenv TERMCAP') as well.",
  4098 #endif
  4099                    terminal_type);
  4100     }
  4101 
  4102   area = tty->termcap_strings_buffer;
  4103   tty->TS_ins_line = tgetstr ("al", address);
  4104   tty->TS_ins_multi_lines = tgetstr ("AL", address);
  4105   tty->TS_bell = tgetstr ("bl", address);
  4106   BackTab (tty) = tgetstr ("bt", address);
  4107   tty->TS_clr_to_bottom = tgetstr ("cd", address);
  4108   tty->TS_clr_line = tgetstr ("ce", address);
  4109   tty->TS_clr_frame = tgetstr ("cl", address);
  4110   ColPosition (tty) = NULL; /* tgetstr ("ch", address); */
  4111   AbsPosition (tty) = tgetstr ("cm", address);
  4112   CR (tty) = tgetstr ("cr", address);
  4113   tty->TS_set_scroll_region = tgetstr ("cs", address);
  4114   tty->TS_set_scroll_region_1 = tgetstr ("cS", address);
  4115   RowPosition (tty) = tgetstr ("cv", address);
  4116   tty->TS_del_char = tgetstr ("dc", address);
  4117   tty->TS_del_multi_chars = tgetstr ("DC", address);
  4118   tty->TS_del_line = tgetstr ("dl", address);
  4119   tty->TS_del_multi_lines = tgetstr ("DL", address);
  4120   tty->TS_delete_mode = tgetstr ("dm", address);
  4121   tty->TS_end_delete_mode = tgetstr ("ed", address);
  4122   tty->TS_end_insert_mode = tgetstr ("ei", address);
  4123   Home (tty) = tgetstr ("ho", address);
  4124   tty->TS_ins_char = tgetstr ("ic", address);
  4125   tty->TS_ins_multi_chars = tgetstr ("IC", address);
  4126   tty->TS_insert_mode = tgetstr ("im", address);
  4127   tty->TS_pad_inserted_char = tgetstr ("ip", address);
  4128   tty->TS_end_keypad_mode = tgetstr ("ke", address);
  4129   tty->TS_keypad_mode = tgetstr ("ks", address);
  4130   LastLine (tty) = tgetstr ("ll", address);
  4131   Right (tty) = tgetstr ("nd", address);
  4132   Down (tty) = tgetstr ("do", address);
  4133   if (!Down (tty))
  4134     Down (tty) = tgetstr ("nl", address); /* Obsolete name for "do".  */
  4135   if (tgetflag ("bs"))
  4136     Left (tty) = "\b";            /* Can't possibly be longer!  */
  4137   else                            /* (Actually, "bs" is obsolete...)  */
  4138     Left (tty) = tgetstr ("le", address);
  4139   if (!Left (tty))
  4140     Left (tty) = tgetstr ("bc", address); /* Obsolete name for "le".  */
  4141   tty->TS_pad_char = tgetstr ("pc", address);
  4142   tty->TS_repeat = tgetstr ("rp", address);
  4143   tty->TS_end_standout_mode = tgetstr ("se", address);
  4144   tty->TS_fwd_scroll = tgetstr ("sf", address);
  4145   tty->TS_standout_mode = tgetstr ("so", address);
  4146   tty->TS_rev_scroll = tgetstr ("sr", address);
  4147   tty->Wcm->cm_tab = tgetstr ("ta", address);
  4148   tty->TS_end_termcap_modes = tgetstr ("te", address);
  4149   tty->TS_termcap_modes = tgetstr ("ti", address);
  4150   Up (tty) = tgetstr ("up", address);
  4151   tty->TS_visible_bell = tgetstr ("vb", address);
  4152   tty->TS_cursor_normal = tgetstr ("ve", address);
  4153   tty->TS_cursor_visible = tgetstr ("vs", address);
  4154   tty->TS_cursor_invisible = tgetstr ("vi", address);
  4155   tty->TS_set_window = tgetstr ("wi", address);
  4156 
  4157   tty->TS_enter_underline_mode = tgetstr ("us", address);
  4158   tty->TS_exit_underline_mode = tgetstr ("ue", address);
  4159   tty->TS_enter_bold_mode = tgetstr ("md", address);
  4160   tty->TS_enter_italic_mode = tgetstr ("ZH", address);
  4161   tty->TS_enter_dim_mode = tgetstr ("mh", address);
  4162   tty->TS_enter_reverse_mode = tgetstr ("mr", address);
  4163   tty->TS_enter_alt_charset_mode = tgetstr ("as", address);
  4164   tty->TS_exit_alt_charset_mode = tgetstr ("ae", address);
  4165   tty->TS_exit_attribute_mode = tgetstr ("me", address);
  4166 #ifdef TERMINFO
  4167   tty->TS_enter_strike_through_mode = tigetstr ("smxx");
  4168   if (tty->TS_enter_strike_through_mode == (char *) (intptr_t) -1)
  4169     tty->TS_enter_strike_through_mode = NULL;
  4170 #else
  4171   /* FIXME: Is calling tgetstr here for non-terminfo case correct,
  4172      even though "smxx" is more than 2 characters?  */
  4173   tty->TS_enter_strike_through_mode = tgetstr ("smxx", address);
  4174 #endif
  4175 
  4176   MultiUp (tty) = tgetstr ("UP", address);
  4177   MultiDown (tty) = tgetstr ("DO", address);
  4178   MultiLeft (tty) = tgetstr ("LE", address);
  4179   MultiRight (tty) = tgetstr ("RI", address);
  4180 
  4181   /* SVr4/ANSI color support.  If "op" isn't available, don't support
  4182      color because we can't switch back to the default foreground and
  4183      background.  */
  4184   tty->TS_orig_pair = tgetstr ("op", address);
  4185   if (tty->TS_orig_pair)
  4186     {
  4187       tty->TS_set_foreground = tgetstr ("AF", address);
  4188       tty->TS_set_background = tgetstr ("AB", address);
  4189       if (!tty->TS_set_foreground)
  4190         {
  4191           /* SVr4.  */
  4192           tty->TS_set_foreground = tgetstr ("Sf", address);
  4193           tty->TS_set_background = tgetstr ("Sb", address);
  4194         }
  4195 
  4196       tty->TN_max_colors = tgetnum ("Co");
  4197 
  4198 #ifdef TERMINFO
  4199       {
  4200         const char *fg = tigetstr ("setf24");
  4201         const char *bg = tigetstr ("setb24");
  4202         /* Non-standard support for 24-bit colors. */
  4203         if (fg && bg
  4204             && fg != (char *) (intptr_t) -1
  4205             && bg != (char *) (intptr_t) -1)
  4206           {
  4207             tty->TS_set_foreground = fg;
  4208             tty->TS_set_background = bg;
  4209             tty->TN_max_colors = 16777216;
  4210           }
  4211         /* Standard support for 24-bit colors.  */
  4212         else if (tigetflag ("RGB") > 0)
  4213           {
  4214             /* If the used Terminfo library supports only 16-bit
  4215                signed values, tgetnum("Co") and tigetnum("colors")
  4216                could return 32767.  */
  4217             tty->TN_max_colors = 16777216;
  4218           }
  4219         /* Fall back to xterm+direct (semicolon version) if Tc is set
  4220            (de-facto standard introduced by tmux) or if requested by
  4221            the COLORTERM environment variable.  */
  4222         else if ((tigetflag ("Tc") > 0)
  4223                  || ((bg = getenv ("COLORTERM")) != NULL
  4224                      && strcasecmp (bg, "truecolor") == 0))
  4225           {
  4226             tty->TS_set_foreground = "\033[%?%p1%{8}%<%t3%p1%d%e38;2;%p1%{65536}%/%d;%p1%{256}%/%{255}%&%d;%p1%{255}%&%d%;m";
  4227             tty->TS_set_background = "\033[%?%p1%{8}%<%t4%p1%d%e48;2;%p1%{65536}%/%d;%p1%{256}%/%{255}%&%d;%p1%{255}%&%d%;m";
  4228             tty->TN_max_colors = 16777216;
  4229           }
  4230       }
  4231 #endif
  4232 
  4233       tty->TN_no_color_video = tgetnum ("NC");
  4234       if (tty->TN_no_color_video == -1)
  4235         tty->TN_no_color_video = 0;
  4236     }
  4237 
  4238   tty_default_color_capabilities (tty, 1);
  4239 
  4240   MagicWrap (tty) = tgetflag ("xn");
  4241   /* Since we make MagicWrap terminals look like AutoWrap, we need to have
  4242      the former flag imply the latter.  */
  4243   AutoWrap (tty) = MagicWrap (tty) || tgetflag ("am");
  4244   tty->memory_below_frame = tgetflag ("db");
  4245   tty->TF_hazeltine = tgetflag ("hz");
  4246   tty->must_write_spaces = tgetflag ("in");
  4247   tty->meta_key = tgetflag ("km") || tgetflag ("MT");
  4248   tty->TF_insmode_motion = tgetflag ("mi");
  4249   tty->TF_standout_motion = tgetflag ("ms");
  4250   tty->TF_underscore = tgetflag ("ul");
  4251   tty->TF_teleray = tgetflag ("xt");
  4252 
  4253 #else /* DOS_NT */
  4254 #ifdef WINDOWSNT
  4255   {
  4256     struct frame *f = XFRAME (selected_frame);
  4257     int height, width;
  4258 
  4259     initialize_w32_display (terminal, &width, &height);
  4260 
  4261     FrameRows (tty) = height;
  4262     FrameCols (tty) = width;
  4263     tty->specified_window = height;
  4264 
  4265     FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_none;
  4266     FRAME_HAS_HORIZONTAL_SCROLL_BARS (f) = 0;
  4267     tty->char_ins_del_ok = 1;
  4268     baud_rate = 19200;
  4269   }
  4270 #else  /* MSDOS */
  4271   {
  4272     int height, width;
  4273     if (strcmp (terminal_type, "internal") == 0)
  4274       terminal->type = output_msdos_raw;
  4275     initialize_msdos_display (terminal);
  4276 
  4277     get_tty_size (fileno (tty->input), &width, &height);
  4278     FrameCols (tty) = width;
  4279     FrameRows (tty) = height;
  4280     tty->char_ins_del_ok = 0;
  4281     init_baud_rate (fileno (tty->input));
  4282   }
  4283 #endif  /* MSDOS */
  4284   tty->output = stdout;
  4285   tty->input = stdin;
  4286   /* The following two are inaccessible from w32console.c.  */
  4287   terminal->delete_frame_hook = &tty_free_frame_resources;
  4288   terminal->delete_terminal_hook = &delete_tty;
  4289 
  4290   tty->name = xstrdup (name);
  4291   terminal->name = xstrdup (name);
  4292   tty->type = xstrdup (terminal_type);
  4293 
  4294   add_keyboard_wait_descriptor (0);
  4295 
  4296   tty->delete_in_insert_mode = 1;
  4297 
  4298   UseTabs (tty) = 0;
  4299   tty->scroll_region_ok = 0;
  4300 
  4301   /* Seems to insert lines when it's not supposed to, messing up the
  4302      display.  In doing a trace, it didn't seem to be called much, so I
  4303      don't think we're losing anything by turning it off.  */
  4304   tty->line_ins_del_ok = 0;
  4305 
  4306   tty->TN_max_colors = 16;  /* Must be non-zero for tty-display-color-p.  */
  4307 #endif  /* DOS_NT */
  4308 
  4309 #ifdef HAVE_GPM
  4310   terminal->mouse_position_hook = term_mouse_position;
  4311 #endif
  4312   tty->mouse_highlight.mouse_face_window = Qnil;
  4313 
  4314   terminal->kboard = allocate_kboard (Qnil);
  4315   terminal->kboard->reference_count++;
  4316   /* Don't let the initial kboard remain current longer than necessary.
  4317      That would cause problems if a file loaded on startup tries to
  4318      prompt in the mini-buffer.  */
  4319   if (current_kboard == initial_kboard)
  4320     current_kboard = terminal->kboard;
  4321 #ifndef DOS_NT
  4322   term_get_fkeys (address, terminal->kboard);
  4323 
  4324   /* Get frame size from system, or else from termcap.  */
  4325   {
  4326     int height, width;
  4327     get_tty_size (fileno (tty->input), &width, &height);
  4328     FrameCols (tty) = width;
  4329     FrameRows (tty) = height;
  4330   }
  4331 
  4332   if (FrameCols (tty) <= 0)
  4333     FrameCols (tty) = tgetnum ("co");
  4334   if (FrameRows (tty) <= 0)
  4335     FrameRows (tty) = tgetnum ("li");
  4336 
  4337   if (FrameRows (tty) < 3 || FrameCols (tty) < 3)
  4338     maybe_fatal (must_succeed, terminal,
  4339                  "Screen size %dx%d is too small",
  4340                  "Screen size %dx%d is too small",
  4341                  FrameCols (tty), FrameRows (tty));
  4342 
  4343   TabWidth (tty) = tgetnum ("tw");
  4344 
  4345   if (!tty->TS_bell)
  4346     tty->TS_bell = "\07";
  4347 
  4348   if (!tty->TS_fwd_scroll)
  4349     tty->TS_fwd_scroll = Down (tty);
  4350 
  4351   PC = tty->TS_pad_char ? *tty->TS_pad_char : 0;
  4352 
  4353   if (TabWidth (tty) < 0)
  4354     TabWidth (tty) = 8;
  4355 
  4356 /* Turned off since /etc/termcap seems to have :ta= for most terminals
  4357    and newer termcap doc does not seem to say there is a default.
  4358   if (!tty->Wcm->cm_tab)
  4359     tty->Wcm->cm_tab = "\t";
  4360 */
  4361 
  4362   /* We don't support standout modes that use `magic cookies', so
  4363      turn off any that do.  */
  4364   if (tty->TS_standout_mode && tgetnum ("sg") >= 0)
  4365     {
  4366       tty->TS_standout_mode = 0;
  4367       tty->TS_end_standout_mode = 0;
  4368     }
  4369   if (tty->TS_enter_underline_mode && tgetnum ("ug") >= 0)
  4370     {
  4371       tty->TS_enter_underline_mode = 0;
  4372       tty->TS_exit_underline_mode = 0;
  4373     }
  4374 
  4375   /* If there's no standout mode, try to use underlining instead.  */
  4376   if (tty->TS_standout_mode == 0)
  4377     {
  4378       tty->TS_standout_mode = tty->TS_enter_underline_mode;
  4379       tty->TS_end_standout_mode = tty->TS_exit_underline_mode;
  4380     }
  4381 
  4382   /* If no `se' string, try using a `me' string instead.
  4383      If that fails, we can't use standout mode at all.  */
  4384   if (tty->TS_end_standout_mode == 0)
  4385     {
  4386       char *s = tgetstr ("me", address);
  4387       if (s != 0)
  4388         tty->TS_end_standout_mode = s;
  4389       else
  4390         tty->TS_standout_mode = 0;
  4391     }
  4392 
  4393   if (tty->TF_teleray)
  4394     {
  4395       tty->Wcm->cm_tab = 0;
  4396       /* We can't support standout mode, because it uses magic cookies.  */
  4397       tty->TS_standout_mode = 0;
  4398       /* But that means we cannot rely on ^M to go to column zero!  */
  4399       CR (tty) = 0;
  4400       /* LF can't be trusted either -- can alter hpos.  */
  4401       /* If move at column 0 thru a line with TS_standout_mode.  */
  4402       Down (tty) = 0;
  4403     }
  4404 
  4405   tty->specified_window = FrameRows (tty);
  4406 
  4407   if (Wcm_init (tty) == -1)     /* Can't do cursor motion.  */
  4408     {
  4409       maybe_fatal (must_succeed, terminal,
  4410                    "Terminal type \"%s\" is not powerful enough to run Emacs",
  4411                    "Terminal type \"%s\" is not powerful enough to run Emacs.\n\
  4412 It lacks the ability to position the cursor.\n\
  4413 If that is not the actual type of terminal you have,\n\
  4414 use the Bourne shell command 'TERM=...; export TERM' (C-shell:\n\
  4415 'setenv TERM ...') to specify the correct type.  It may be necessary\n"
  4416 # ifdef TERMINFO
  4417 "to do 'unset TERMINFO' (C-shell: 'unsetenv TERMINFO') as well.",
  4418 # else /* TERMCAP */
  4419 "to do 'unset TERMCAP' (C-shell: 'unsetenv TERMCAP') as well.",
  4420 # endif /* TERMINFO */
  4421                    terminal_type);
  4422     }
  4423 
  4424   if (FrameRows (tty) <= 0 || FrameCols (tty) <= 0)
  4425     maybe_fatal (must_succeed, terminal,
  4426                  "Could not determine the frame size",
  4427                  "Could not determine the frame size");
  4428 
  4429   tty->delete_in_insert_mode
  4430     = tty->TS_delete_mode && tty->TS_insert_mode
  4431     && !strcmp (tty->TS_delete_mode, tty->TS_insert_mode);
  4432 
  4433   UseTabs (tty) = tabs_safe_p (fileno (tty->input)) && TabWidth (tty) == 8;
  4434 
  4435   tty->scroll_region_ok
  4436     = (tty->Wcm->cm_abs
  4437        && (tty->TS_set_window || tty->TS_set_scroll_region || tty->TS_set_scroll_region_1));
  4438 
  4439   tty->line_ins_del_ok
  4440     = (((tty->TS_ins_line || tty->TS_ins_multi_lines)
  4441         && (tty->TS_del_line || tty->TS_del_multi_lines))
  4442        || (tty->scroll_region_ok
  4443            && tty->TS_fwd_scroll && tty->TS_rev_scroll));
  4444 
  4445   tty->char_ins_del_ok
  4446     = ((tty->TS_ins_char || tty->TS_insert_mode
  4447         || tty->TS_pad_inserted_char || tty->TS_ins_multi_chars)
  4448        && (tty->TS_del_char || tty->TS_del_multi_chars));
  4449 
  4450   init_baud_rate (fileno (tty->input));
  4451 
  4452 #endif /* not DOS_NT */
  4453 
  4454   /* Init system terminal modes (RAW or CBREAK, etc.).  */
  4455   init_sys_modes (tty);
  4456 
  4457   return terminal;
  4458 }
  4459 
  4460 
  4461 static void
  4462 vfatal (const char *str, va_list ap)
  4463 {
  4464   fputs ("emacs: ", stderr);
  4465   vfprintf (stderr, str, ap);
  4466   if (! (str[0] && str[strlen (str) - 1] == '\n'))
  4467     putc ('\n', stderr);
  4468   exit (1);
  4469 }
  4470 
  4471 
  4472 /* Auxiliary error-handling function for init_tty.
  4473    Delete TERMINAL, then call error or fatal with str1 or str2,
  4474    respectively, according to whether MUST_SUCCEED is true.  */
  4475 
  4476 static void
  4477 maybe_fatal (bool must_succeed, struct terminal *terminal,
  4478              const char *str1, const char *str2, ...)
  4479 {
  4480   va_list ap;
  4481   va_start (ap, str2);
  4482   if (terminal)
  4483     delete_tty (terminal);
  4484 
  4485   if (must_succeed)
  4486     vfatal (str2, ap);
  4487   else
  4488     verror (str1, ap);
  4489 }
  4490 
  4491 void
  4492 fatal (const char *str, ...)
  4493 {
  4494   va_list ap;
  4495   va_start (ap, str);
  4496   vfatal (str, ap);
  4497 }
  4498 
  4499 
  4500 
  4501 /* Delete the given tty terminal, closing all frames on it.  */
  4502 
  4503 static void
  4504 delete_tty (struct terminal *terminal)
  4505 {
  4506   struct tty_display_info *tty;
  4507 
  4508   /* Protect against recursive calls.  delete_frame in
  4509      delete_terminal calls us back when it deletes our last frame.  */
  4510   if (!terminal->name)
  4511     return;
  4512 
  4513   eassert (terminal->type == output_termcap);
  4514 
  4515   tty = terminal->display_info.tty;
  4516 
  4517   if (tty == tty_list)
  4518     tty_list = tty->next;
  4519   else
  4520     {
  4521       struct tty_display_info *p;
  4522       for (p = tty_list; p && p->next != tty; p = p->next)
  4523         ;
  4524 
  4525       if (! p)
  4526         /* This should not happen.  */
  4527         emacs_abort ();
  4528 
  4529       p->next = tty->next;
  4530       tty->next = 0;
  4531     }
  4532 
  4533   /* reset_sys_modes needs a valid device, so this call needs to be
  4534      before delete_terminal.  */
  4535   reset_sys_modes (tty);
  4536 
  4537   delete_terminal (terminal);
  4538 
  4539   xfree (tty->name);
  4540   xfree (tty->type);
  4541 
  4542   if (tty->input)
  4543     {
  4544       delete_keyboard_wait_descriptor (fileno (tty->input));
  4545       if (tty->input != stdin)
  4546         fclose (tty->input);
  4547     }
  4548   if (tty->output && tty->output != stdout && tty->output != tty->input)
  4549     fclose (tty->output);
  4550   if (tty->termscript)
  4551     fclose (tty->termscript);
  4552 
  4553   xfree (tty->old_tty);
  4554   xfree (tty->Wcm);
  4555   xfree (tty);
  4556 }
  4557 
  4558 void
  4559 syms_of_term (void)
  4560 {
  4561   DEFVAR_BOOL ("system-uses-terminfo", system_uses_terminfo,
  4562     doc: /* Non-nil means the system uses terminfo rather than termcap.
  4563 This variable can be used by terminal emulator packages.  */);
  4564 #ifdef TERMINFO
  4565   system_uses_terminfo = 1;
  4566 #else
  4567   system_uses_terminfo = 0;
  4568 #endif
  4569 
  4570   DEFVAR_LISP ("suspend-tty-functions", Vsuspend_tty_functions,
  4571     doc: /* Functions run after suspending a tty.
  4572 The functions are run with one argument, the terminal object to be suspended.
  4573 See `suspend-tty'.  */);
  4574   Vsuspend_tty_functions = Qnil;
  4575 
  4576 
  4577   DEFVAR_LISP ("resume-tty-functions", Vresume_tty_functions,
  4578     doc: /* Functions run after resuming a tty.
  4579 The functions are run with one argument, the terminal object that was revived.
  4580 See `resume-tty'.  */);
  4581   Vresume_tty_functions = Qnil;
  4582 
  4583   DEFVAR_BOOL ("visible-cursor", visible_cursor,
  4584                doc: /* Non-nil means to make the cursor very visible.
  4585 This only has an effect when running in a text terminal.
  4586 What means \"very visible\" is up to your terminal.  It may make the cursor
  4587 bigger, or it may make it blink, or it may do nothing at all.  */);
  4588   visible_cursor = 1;
  4589 
  4590   DEFVAR_BOOL ("tty-menu-calls-mouse-position-function",
  4591                tty_menu_calls_mouse_position_function,
  4592     doc: /* Non-nil means TTY menu code will call `mouse-position-function'.
  4593 This should be set if the function in `mouse-position-function' does not
  4594 trigger redisplay.  */);
  4595   tty_menu_calls_mouse_position_function = 0;
  4596 
  4597   defsubr (&Stty_display_color_p);
  4598   defsubr (&Stty_display_color_cells);
  4599   defsubr (&Stty_no_underline);
  4600   defsubr (&Stty_type);
  4601   defsubr (&Scontrolling_tty_p);
  4602   defsubr (&Stty_top_frame);
  4603   defsubr (&Ssuspend_tty);
  4604   defsubr (&Sresume_tty);
  4605   defsubr (&Stty__set_output_buffer_size);
  4606   defsubr (&Stty__output_buffer_size);
  4607 #ifdef HAVE_GPM
  4608   defsubr (&Sgpm_mouse_start);
  4609   defsubr (&Sgpm_mouse_stop);
  4610 #endif /* HAVE_GPM */
  4611 
  4612 #ifndef DOS_NT
  4613   default_orig_pair = NULL;
  4614   default_set_foreground = NULL;
  4615   default_set_background = NULL;
  4616 #endif /* !DOS_NT */
  4617 
  4618   encode_terminal_src = NULL;
  4619   encode_terminal_dst = NULL;
  4620 
  4621   DEFSYM (Qtty_mode_set_strings, "tty-mode-set-strings");
  4622   DEFSYM (Qtty_mode_reset_strings, "tty-mode-reset-strings");
  4623 
  4624 #ifndef MSDOS
  4625   DEFSYM (Qtty_menu_next_item, "tty-menu-next-item");
  4626   DEFSYM (Qtty_menu_prev_item, "tty-menu-prev-item");
  4627   DEFSYM (Qtty_menu_next_menu, "tty-menu-next-menu");
  4628   DEFSYM (Qtty_menu_prev_menu, "tty-menu-prev-menu");
  4629   DEFSYM (Qtty_menu_select, "tty-menu-select");
  4630   DEFSYM (Qtty_menu_ignore, "tty-menu-ignore");
  4631   DEFSYM (Qtty_menu_exit, "tty-menu-exit");
  4632   DEFSYM (Qtty_menu_mouse_movement, "tty-menu-mouse-movement");
  4633   DEFSYM (Qtty_menu_navigation_map, "tty-menu-navigation-map");
  4634 #endif
  4635 }

/* [<][>][^][v][top][bottom][index][help] */