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

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