Home | History | Annotate | Line # | Download | only in tui
      1   1.1  christos /* General functions for the WDB TUI.
      2   1.1  christos 
      3  1.11  christos    Copyright (C) 1998-2024 Free Software Foundation, Inc.
      4   1.1  christos 
      5   1.1  christos    Contributed by Hewlett-Packard Company.
      6   1.1  christos 
      7   1.1  christos    This file is part of GDB.
      8   1.1  christos 
      9   1.1  christos    This program is free software; you can redistribute it and/or modify
     10   1.1  christos    it under the terms of the GNU General Public License as published by
     11   1.1  christos    the Free Software Foundation; either version 3 of the License, or
     12   1.1  christos    (at your option) any later version.
     13   1.1  christos 
     14   1.1  christos    This program is distributed in the hope that it will be useful,
     15   1.1  christos    but WITHOUT ANY WARRANTY; without even the implied warranty of
     16   1.1  christos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     17   1.1  christos    GNU General Public License for more details.
     18   1.1  christos 
     19   1.1  christos    You should have received a copy of the GNU General Public License
     20   1.1  christos    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
     21   1.1  christos 
     22  1.11  christos #include "event-top.h"
     23  1.11  christos #include "cli/cli-cmds.h"
     24  1.12  christos #include "exceptions.h"
     25   1.1  christos #include "tui/tui.h"
     26   1.1  christos #include "tui/tui-hooks.h"
     27   1.9  christos #include "tui/tui-command.h"
     28   1.1  christos #include "tui/tui-data.h"
     29   1.1  christos #include "tui/tui-layout.h"
     30   1.1  christos #include "tui/tui-io.h"
     31  1.11  christos #include "tui/tui-status.h"
     32   1.1  christos #include "tui/tui-win.h"
     33   1.9  christos #include "tui/tui-wingeneral.h"
     34   1.1  christos #include "tui/tui-winsource.h"
     35   1.9  christos #include "tui/tui-source.h"
     36   1.1  christos #include "target.h"
     37   1.1  christos #include "frame.h"
     38   1.1  christos #include "inferior.h"
     39   1.1  christos #include "symtab.h"
     40   1.3  christos #include "terminal.h"
     41   1.6  christos #include "top.h"
     42  1.11  christos #include "ui.h"
     43  1.12  christos #include "observable.h"
     44   1.1  christos 
     45   1.1  christos #include <fcntl.h>
     46   1.1  christos 
     47   1.1  christos #include "gdb_curses.h"
     48   1.3  christos #include "interps.h"
     49   1.1  christos 
     50  1.10  christos /* See tui.h.  */
     51  1.10  christos 
     52  1.10  christos bool debug_tui = false;
     53  1.10  christos 
     54  1.10  christos /* Implement 'show debug tui'.  */
     55  1.10  christos 
     56  1.10  christos static void
     57  1.10  christos show_tui_debug (struct ui_file *file, int from_tty,
     58  1.10  christos 		struct cmd_list_element *c, const char *value)
     59  1.10  christos {
     60  1.10  christos   gdb_printf (file, _("TUI debugging is \"%s\".\n"), value);
     61  1.10  christos }
     62  1.10  christos 
     63   1.1  christos /* This redefines CTRL if it is not already defined, so it must come
     64   1.1  christos    after terminal state releated include files like <term.h> and
     65   1.1  christos    "gdb_curses.h".  */
     66   1.1  christos #include "readline/readline.h"
     67   1.1  christos 
     68   1.1  christos /* Tells whether the TUI is active or not.  */
     69   1.9  christos bool tui_active = false;
     70   1.9  christos static bool tui_finish_init = true;
     71   1.1  christos 
     72   1.1  christos enum tui_key_mode tui_current_key_mode = TUI_COMMAND_MODE;
     73   1.1  christos 
     74   1.1  christos struct tui_char_command
     75   1.1  christos {
     76   1.1  christos   unsigned char key;
     77   1.1  christos   const char *cmd;
     78   1.1  christos };
     79   1.1  christos 
     80   1.1  christos /* Key mapping to gdb commands when the TUI is using the single key
     81   1.1  christos    mode.  */
     82   1.1  christos static const struct tui_char_command tui_commands[] = {
     83   1.1  christos   { 'c', "continue" },
     84  1.11  christos   { 'C', "reverse-continue" },
     85   1.1  christos   { 'd', "down" },
     86   1.1  christos   { 'f', "finish" },
     87  1.11  christos   { 'F', "reverse-finish" },
     88   1.1  christos   { 'n', "next" },
     89  1.11  christos   { 'N', "reverse-next" },
     90   1.8  christos   { 'o', "nexti" },
     91  1.11  christos   { 'O', "reverse-nexti" },
     92   1.1  christos   { 'r', "run" },
     93   1.1  christos   { 's', "step" },
     94  1.11  christos   { 'S', "reverse-step" },
     95   1.8  christos   { 'i', "stepi" },
     96  1.11  christos   { 'I', "reverse-stepi" },
     97   1.1  christos   { 'u', "up" },
     98   1.1  christos   { 'v', "info locals" },
     99   1.1  christos   { 'w', "where" },
    100   1.1  christos   { 0, 0 },
    101   1.1  christos };
    102   1.1  christos 
    103   1.1  christos static Keymap tui_keymap;
    104   1.1  christos static Keymap tui_readline_standard_keymap;
    105   1.1  christos 
    106   1.1  christos /* TUI readline command.
    107   1.1  christos    Switch the output mode between TUI/standard gdb.  */
    108   1.1  christos static int
    109   1.1  christos tui_rl_switch_mode (int notused1, int notused2)
    110   1.1  christos {
    111   1.3  christos 
    112   1.3  christos   /* Don't let exceptions escape.  We're in the middle of a readline
    113   1.3  christos      callback that isn't prepared for that.  */
    114   1.9  christos   try
    115   1.1  christos     {
    116   1.3  christos       if (tui_active)
    117   1.3  christos 	{
    118   1.3  christos 	  tui_disable ();
    119   1.3  christos 	  rl_prep_terminal (0);
    120   1.3  christos 	}
    121   1.3  christos       else
    122   1.3  christos 	{
    123   1.3  christos 	  /* If tui_enable throws, we'll re-prep below.  */
    124   1.3  christos 	  rl_deprep_terminal ();
    125   1.3  christos 	  tui_enable ();
    126   1.3  christos 	}
    127   1.1  christos     }
    128  1.11  christos   catch (const gdb_exception_forced_quit &ex)
    129  1.11  christos     {
    130  1.11  christos       /* Ideally, we'd do a 'throw' here, but as noted above, we can't
    131  1.11  christos 	 do that, so, instead, we'll set the necessary flags so that
    132  1.11  christos 	 a later QUIT check will restart the forced quit.  */
    133  1.11  christos       set_force_quit_flag ();
    134  1.11  christos     }
    135   1.9  christos   catch (const gdb_exception &ex)
    136   1.1  christos     {
    137   1.3  christos       exception_print (gdb_stderr, ex);
    138   1.3  christos 
    139   1.3  christos       if (!tui_active)
    140   1.3  christos 	rl_prep_terminal (0);
    141   1.1  christos     }
    142   1.1  christos 
    143   1.1  christos   /* Clear the readline in case switching occurred in middle of
    144   1.1  christos      something.  */
    145   1.1  christos   if (rl_end)
    146   1.1  christos     rl_kill_text (0, rl_end);
    147   1.1  christos 
    148   1.1  christos   /* Since we left the curses mode, the terminal mode is restored to
    149   1.1  christos      some previous state.  That state may not be suitable for readline
    150   1.1  christos      to work correctly (it may be restored in line mode).  We force an
    151   1.1  christos      exit of the current readline so that readline is re-entered and
    152   1.1  christos      it will be able to setup the terminal for its needs.  By
    153   1.1  christos      re-entering in readline, we also redisplay its prompt in the
    154   1.1  christos      non-curses mode.  */
    155   1.1  christos   rl_newline (1, '\n');
    156   1.1  christos 
    157   1.1  christos   /* Make sure the \n we are returning does not repeat the last
    158   1.1  christos      command.  */
    159   1.1  christos   dont_repeat ();
    160   1.1  christos   return 0;
    161   1.1  christos }
    162   1.1  christos 
    163   1.1  christos /* TUI readline command.
    164   1.1  christos    Change the TUI layout to show a next layout.
    165   1.1  christos    This function is bound to CTRL-X 2.  It is intended to provide
    166   1.9  christos    a functionality close to the Emacs split-window command.  */
    167   1.1  christos static int
    168   1.1  christos tui_rl_change_windows (int notused1, int notused2)
    169   1.1  christos {
    170   1.1  christos   if (!tui_active)
    171   1.1  christos     tui_rl_switch_mode (0 /* notused */, 0 /* notused */);
    172   1.1  christos 
    173   1.1  christos   if (tui_active)
    174   1.9  christos     tui_next_layout ();
    175   1.1  christos 
    176   1.1  christos   return 0;
    177   1.1  christos }
    178   1.1  christos 
    179   1.1  christos /* TUI readline command.
    180   1.1  christos    Delete the second TUI window to only show one.  */
    181   1.1  christos static int
    182   1.1  christos tui_rl_delete_other_windows (int notused1, int notused2)
    183   1.1  christos {
    184   1.1  christos   if (!tui_active)
    185   1.1  christos     tui_rl_switch_mode (0 /* notused */, 0 /* notused */);
    186   1.1  christos 
    187   1.1  christos   if (tui_active)
    188   1.9  christos     tui_remove_some_windows ();
    189   1.1  christos 
    190   1.1  christos   return 0;
    191   1.1  christos }
    192   1.1  christos 
    193   1.1  christos /* TUI readline command.
    194   1.1  christos    Switch the active window to give the focus to a next window.  */
    195   1.1  christos static int
    196   1.1  christos tui_rl_other_window (int count, int key)
    197   1.1  christos {
    198   1.1  christos   struct tui_win_info *win_info;
    199   1.1  christos 
    200   1.1  christos   if (!tui_active)
    201   1.1  christos     tui_rl_switch_mode (0 /* notused */, 0 /* notused */);
    202   1.1  christos 
    203   1.1  christos   win_info = tui_next_win (tui_win_with_focus ());
    204   1.1  christos   if (win_info)
    205  1.10  christos     tui_set_win_focus_to (win_info);
    206   1.1  christos   return 0;
    207   1.1  christos }
    208   1.1  christos 
    209   1.1  christos /* TUI readline command.
    210   1.1  christos    Execute the gdb command bound to the specified key.  */
    211   1.1  christos static int
    212   1.1  christos tui_rl_command_key (int count, int key)
    213   1.1  christos {
    214   1.1  christos   int i;
    215   1.1  christos 
    216   1.1  christos   reinitialize_more_filter ();
    217   1.1  christos   for (i = 0; tui_commands[i].cmd; i++)
    218   1.1  christos     {
    219   1.1  christos       if (tui_commands[i].key == key)
    220  1.10  christos 	{
    221  1.10  christos 	  /* Insert the command in the readline buffer.
    222  1.10  christos 	     Avoid calling the gdb command here since it creates
    223  1.10  christos 	     a possible recursion on readline if prompt_for_continue
    224  1.10  christos 	     is called (See PR 9584).  The command will also appear
    225  1.10  christos 	     in the readline history which turns out to be better.  */
    226  1.10  christos 	  rl_insert_text (tui_commands[i].cmd);
    227  1.10  christos 	  rl_newline (1, '\n');
    228  1.10  christos 
    229  1.10  christos 	  /* Switch to gdb command mode while executing the command.
    230  1.11  christos 	     This way the gdb's continue prompt will be displayed.  */
    231  1.10  christos 	  tui_set_key_mode (TUI_ONE_COMMAND_MODE);
    232  1.10  christos 	  return 0;
    233  1.10  christos 	}
    234   1.1  christos     }
    235   1.1  christos   return 0;
    236   1.1  christos }
    237   1.1  christos 
    238   1.1  christos /* TUI readline command.
    239   1.1  christos    Temporarily leave the TUI SingleKey mode to allow editing
    240   1.1  christos    a gdb command with the normal readline.  Once the command
    241   1.1  christos    is executed, the TUI SingleKey mode is installed back.  */
    242   1.1  christos static int
    243   1.1  christos tui_rl_command_mode (int count, int key)
    244   1.1  christos {
    245   1.1  christos   tui_set_key_mode (TUI_ONE_COMMAND_MODE);
    246   1.1  christos   return rl_insert (count, key);
    247   1.1  christos }
    248   1.1  christos 
    249   1.1  christos /* TUI readline command.
    250   1.1  christos    Switch between TUI SingleKey mode and gdb readline editing.  */
    251   1.1  christos static int
    252   1.1  christos tui_rl_next_keymap (int notused1, int notused2)
    253   1.1  christos {
    254   1.1  christos   if (!tui_active)
    255   1.1  christos     tui_rl_switch_mode (0 /* notused */, 0 /* notused */);
    256   1.1  christos 
    257  1.11  christos   if (rl_end)
    258  1.11  christos     {
    259  1.11  christos       rl_end = 0;
    260  1.11  christos       rl_point = 0;
    261  1.11  christos       rl_mark = 0;
    262  1.11  christos     }
    263  1.11  christos 
    264   1.1  christos   tui_set_key_mode (tui_current_key_mode == TUI_COMMAND_MODE
    265  1.10  christos 		    ? TUI_SINGLE_KEY_MODE : TUI_COMMAND_MODE);
    266   1.1  christos   return 0;
    267   1.1  christos }
    268   1.1  christos 
    269   1.1  christos /* Readline hook to redisplay ourself the gdb prompt.
    270   1.1  christos    In the SingleKey mode, the prompt is not printed so that
    271   1.1  christos    the command window is cleaner.  It will be displayed if
    272   1.1  christos    we temporarily leave the SingleKey mode.  */
    273   1.1  christos static int
    274   1.1  christos tui_rl_startup_hook (void)
    275   1.1  christos {
    276   1.6  christos   if (tui_current_key_mode != TUI_COMMAND_MODE
    277   1.6  christos       && !gdb_in_secondary_prompt_p (current_ui))
    278   1.1  christos     tui_set_key_mode (TUI_SINGLE_KEY_MODE);
    279   1.1  christos   return 0;
    280   1.1  christos }
    281   1.1  christos 
    282   1.1  christos /* Change the TUI key mode by installing the appropriate readline
    283   1.1  christos    keymap.  */
    284   1.1  christos void
    285   1.1  christos tui_set_key_mode (enum tui_key_mode mode)
    286   1.1  christos {
    287   1.1  christos   tui_current_key_mode = mode;
    288   1.1  christos   rl_set_keymap (mode == TUI_SINGLE_KEY_MODE
    289  1.10  christos 		 ? tui_keymap : tui_readline_standard_keymap);
    290  1.11  christos   tui_show_status_content ();
    291   1.1  christos }
    292   1.1  christos 
    293   1.1  christos /* Initialize readline and configure the keymap for the switching
    294   1.1  christos    key shortcut.  */
    295   1.1  christos void
    296   1.9  christos tui_ensure_readline_initialized ()
    297   1.1  christos {
    298   1.9  christos   static bool initialized;
    299   1.9  christos 
    300   1.9  christos   if (initialized)
    301   1.9  christos     return;
    302   1.9  christos   initialized = true;
    303   1.9  christos 
    304   1.1  christos   int i;
    305   1.1  christos   Keymap tui_ctlx_keymap;
    306   1.1  christos 
    307   1.1  christos   rl_add_defun ("tui-switch-mode", tui_rl_switch_mode, -1);
    308   1.1  christos   rl_add_defun ("next-keymap", tui_rl_next_keymap, -1);
    309   1.9  christos   rl_add_defun ("tui-delete-other-windows", tui_rl_delete_other_windows, -1);
    310   1.9  christos   rl_add_defun ("tui-change-windows", tui_rl_change_windows, -1);
    311   1.9  christos   rl_add_defun ("tui-other-window", tui_rl_other_window, -1);
    312   1.1  christos 
    313   1.1  christos   tui_keymap = rl_make_bare_keymap ();
    314   1.9  christos 
    315   1.9  christos   /* The named keymap feature was added in Readline 8.0.  */
    316   1.9  christos #if RL_READLINE_VERSION >= 0x800
    317   1.9  christos   rl_set_keymap_name ("SingleKey", tui_keymap);
    318   1.9  christos #endif
    319   1.9  christos 
    320   1.1  christos   tui_ctlx_keymap = rl_make_bare_keymap ();
    321   1.1  christos   tui_readline_standard_keymap = rl_get_keymap ();
    322   1.1  christos 
    323   1.1  christos   for (i = 0; tui_commands[i].cmd; i++)
    324   1.1  christos     rl_bind_key_in_map (tui_commands[i].key, tui_rl_command_key, tui_keymap);
    325   1.1  christos 
    326   1.1  christos   rl_generic_bind (ISKMAP, "\\C-x", (char*) tui_ctlx_keymap, tui_keymap);
    327   1.1  christos 
    328   1.1  christos   /* Bind all other keys to tui_rl_command_mode so that we switch
    329   1.1  christos      temporarily from SingleKey mode and can enter a gdb command.  */
    330   1.1  christos   for (i = ' '; i < 0x7f; i++)
    331   1.1  christos     {
    332   1.1  christos       int j;
    333   1.1  christos 
    334   1.1  christos       for (j = 0; tui_commands[j].cmd; j++)
    335  1.10  christos 	if (tui_commands[j].key == i)
    336  1.10  christos 	  break;
    337   1.1  christos 
    338   1.1  christos       if (tui_commands[j].cmd)
    339  1.10  christos 	continue;
    340   1.1  christos 
    341   1.1  christos       rl_bind_key_in_map (i, tui_rl_command_mode, tui_keymap);
    342   1.1  christos     }
    343   1.1  christos 
    344   1.1  christos   rl_bind_key_in_map ('a', tui_rl_switch_mode, emacs_ctlx_keymap);
    345   1.1  christos   rl_bind_key_in_map ('a', tui_rl_switch_mode, tui_ctlx_keymap);
    346   1.1  christos   rl_bind_key_in_map ('A', tui_rl_switch_mode, emacs_ctlx_keymap);
    347   1.1  christos   rl_bind_key_in_map ('A', tui_rl_switch_mode, tui_ctlx_keymap);
    348   1.1  christos   rl_bind_key_in_map (CTRL ('A'), tui_rl_switch_mode, emacs_ctlx_keymap);
    349   1.1  christos   rl_bind_key_in_map (CTRL ('A'), tui_rl_switch_mode, tui_ctlx_keymap);
    350   1.1  christos   rl_bind_key_in_map ('1', tui_rl_delete_other_windows, emacs_ctlx_keymap);
    351   1.1  christos   rl_bind_key_in_map ('1', tui_rl_delete_other_windows, tui_ctlx_keymap);
    352   1.1  christos   rl_bind_key_in_map ('2', tui_rl_change_windows, emacs_ctlx_keymap);
    353   1.1  christos   rl_bind_key_in_map ('2', tui_rl_change_windows, tui_ctlx_keymap);
    354   1.1  christos   rl_bind_key_in_map ('o', tui_rl_other_window, emacs_ctlx_keymap);
    355   1.1  christos   rl_bind_key_in_map ('o', tui_rl_other_window, tui_ctlx_keymap);
    356   1.1  christos   rl_bind_key_in_map ('q', tui_rl_next_keymap, tui_keymap);
    357   1.1  christos   rl_bind_key_in_map ('s', tui_rl_next_keymap, emacs_ctlx_keymap);
    358   1.1  christos   rl_bind_key_in_map ('s', tui_rl_next_keymap, tui_ctlx_keymap);
    359   1.9  christos 
    360   1.9  christos   /* Initialize readline after the above.  */
    361   1.9  christos   rl_initialize ();
    362   1.1  christos }
    363   1.1  christos 
    364   1.3  christos /* Return the TERM variable from the environment, or "<unset>"
    365   1.3  christos    if not set.  */
    366   1.3  christos 
    367   1.3  christos static const char *
    368   1.3  christos gdb_getenv_term (void)
    369   1.3  christos {
    370   1.3  christos   const char *term;
    371   1.3  christos 
    372   1.3  christos   term = getenv ("TERM");
    373   1.3  christos   if (term != NULL)
    374   1.3  christos     return term;
    375   1.3  christos   return "<unset>";
    376   1.3  christos }
    377   1.3  christos 
    378   1.1  christos /* Enter in the tui mode (curses).
    379   1.1  christos    When in normal mode, it installs the tui hooks in gdb, redirects
    380   1.1  christos    the gdb output, configures the readline to work in tui mode.
    381   1.1  christos    When in curses mode, it does nothing.  */
    382   1.1  christos void
    383   1.1  christos tui_enable (void)
    384   1.1  christos {
    385  1.10  christos   TUI_SCOPED_DEBUG_ENTER_EXIT;
    386  1.10  christos 
    387   1.1  christos   if (tui_active)
    388   1.1  christos     return;
    389   1.1  christos 
    390   1.9  christos   /* To avoid to initialize curses when gdb starts, there is a deferred
    391   1.1  christos      curses initialization.  This initialization is made only once
    392   1.1  christos      and the first time the curses mode is entered.  */
    393   1.1  christos   if (tui_finish_init)
    394   1.1  christos     {
    395   1.1  christos       WINDOW *w;
    396   1.3  christos       SCREEN *s;
    397   1.8  christos #ifndef __MINGW32__
    398   1.8  christos        const char *cap;
    399   1.8  christos #endif
    400   1.3  christos       const char *interp;
    401   1.3  christos 
    402   1.3  christos       /* If the top level interpreter is not the console/tui (e.g.,
    403   1.3  christos 	 MI), enabling curses will certainly lose.  */
    404   1.8  christos       interp = top_level_interpreter ()->name ();
    405   1.3  christos       if (strcmp (interp, INTERP_TUI) != 0)
    406   1.3  christos 	error (_("Cannot enable the TUI when the interpreter is '%s'"), interp);
    407   1.3  christos 
    408   1.3  christos       /* Don't try to setup curses (and print funny control
    409   1.3  christos 	 characters) if we're not outputting to a terminal.  */
    410   1.9  christos       if (!gdb_stderr->isatty ())
    411   1.3  christos 	error (_("Cannot enable the TUI when output is not a terminal"));
    412   1.3  christos 
    413   1.3  christos       s = newterm (NULL, stdout, stdin);
    414   1.3  christos #ifdef __MINGW32__
    415   1.3  christos       /* The MinGW port of ncurses requires $TERM to be unset in order
    416   1.3  christos 	 to activate the Windows console driver.  */
    417   1.3  christos       if (s == NULL)
    418   1.7  christos 	s = newterm ((char *) "unknown", stdout, stdin);
    419   1.3  christos #endif
    420   1.3  christos       if (s == NULL)
    421   1.3  christos 	{
    422   1.3  christos 	  error (_("Cannot enable the TUI: error opening terminal [TERM=%s]"),
    423   1.3  christos 		 gdb_getenv_term ());
    424   1.3  christos 	}
    425   1.3  christos       w = stdscr;
    426   1.8  christos       if (has_colors ())
    427   1.8  christos 	{
    428   1.8  christos #ifdef HAVE_USE_DEFAULT_COLORS
    429   1.8  christos 	  /* Ncurses extension to help with resetting to the default
    430   1.8  christos 	     color.  */
    431   1.8  christos 	  use_default_colors ();
    432   1.8  christos #endif
    433   1.8  christos 	  start_color ();
    434   1.8  christos 	}
    435   1.3  christos 
    436   1.3  christos       /* Check required terminal capabilities.  The MinGW port of
    437   1.3  christos 	 ncurses does have them, but doesn't expose them through "cup".  */
    438   1.3  christos #ifndef __MINGW32__
    439   1.7  christos       cap = tigetstr ((char *) "cup");
    440   1.3  christos       if (cap == NULL || cap == (char *) -1 || *cap == '\0')
    441   1.3  christos 	{
    442   1.3  christos 	  endwin ();
    443   1.3  christos 	  delscreen (s);
    444   1.3  christos 	  error (_("Cannot enable the TUI: "
    445   1.3  christos 		   "terminal doesn't support cursor addressing [TERM=%s]"),
    446   1.3  christos 		 gdb_getenv_term ());
    447   1.3  christos 	}
    448   1.3  christos #endif
    449   1.1  christos 
    450  1.10  christos       /* We must mark the tui sub-system active before trying to setup the
    451  1.10  christos 	 current layout as tui windows defined by an extension language
    452  1.10  christos 	 rely on this flag being true in order to know that the window
    453  1.10  christos 	 they are creating is currently valid.  */
    454  1.10  christos       tui_active = true;
    455  1.10  christos 
    456   1.1  christos       cbreak ();
    457   1.1  christos       noecho ();
    458   1.1  christos       /* timeout (1); */
    459   1.1  christos       nodelay(w, FALSE);
    460   1.1  christos       nl();
    461   1.1  christos       keypad (w, TRUE);
    462   1.1  christos       tui_set_term_height_to (LINES);
    463   1.1  christos       tui_set_term_width_to (COLS);
    464   1.1  christos       def_prog_mode ();
    465   1.1  christos 
    466  1.11  christos       tui_show_frame_info (deprecated_safe_get_selected_frame ());
    467   1.9  christos       tui_set_initial_layout ();
    468  1.12  christos       tui_set_win_focus_to (tui_src_win ());
    469  1.12  christos       keypad (tui_cmd_win ()->handle.get (), TRUE);
    470  1.12  christos       wrefresh (tui_cmd_win ()->handle.get ());
    471   1.9  christos       tui_finish_init = false;
    472   1.1  christos     }
    473   1.1  christos   else
    474   1.1  christos     {
    475  1.10  christos       /* Save the current gdb setting of the terminal.
    476  1.10  christos 	 Curses will restore this state when endwin() is called.  */
    477  1.10  christos       def_shell_mode ();
    478  1.10  christos       clearok (stdscr, TRUE);
    479  1.10  christos 
    480  1.10  christos       tui_active = true;
    481  1.10  christos     }
    482  1.10  christos 
    483  1.10  christos   gdb_assert (tui_active);
    484   1.1  christos 
    485   1.9  christos   if (tui_update_variables ())
    486   1.9  christos     tui_rehighlight_all ();
    487   1.1  christos 
    488   1.1  christos   tui_setup_io (1);
    489   1.1  christos 
    490   1.5  christos   /* Resize windows before anything might display/refresh a
    491   1.5  christos      window.  */
    492   1.5  christos   if (tui_win_resized ())
    493   1.5  christos     {
    494   1.9  christos       tui_set_win_resized_to (false);
    495   1.5  christos       tui_resize_all ();
    496   1.5  christos     }
    497   1.5  christos 
    498   1.9  christos   /* Install the TUI specific hooks.  This must be done after the call to
    499   1.9  christos      tui_display_main so that we don't detect the symtab changed event it
    500   1.9  christos      can cause.  */
    501   1.9  christos   tui_install_hooks ();
    502   1.9  christos   rl_startup_hook = tui_rl_startup_hook;
    503   1.1  christos 
    504   1.1  christos   /* Restore TUI keymap.  */
    505   1.1  christos   tui_set_key_mode (tui_current_key_mode);
    506   1.5  christos 
    507   1.5  christos   /* Refresh the screen.  */
    508   1.1  christos   tui_refresh_all_win ();
    509   1.1  christos 
    510   1.1  christos   /* Update gdb's knowledge of its terminal.  */
    511   1.3  christos   gdb_save_tty_state ();
    512   1.1  christos   tui_update_gdb_sizes ();
    513  1.12  christos 
    514  1.12  christos   gdb::observers::tui_enabled.notify (true);
    515   1.1  christos }
    516   1.1  christos 
    517   1.1  christos /* Leave the tui mode.
    518   1.1  christos    Remove the tui hooks and configure the gdb output and readline
    519   1.1  christos    back to their original state.  The curses mode is left so that
    520   1.1  christos    the terminal setting is restored to the point when we entered.  */
    521   1.1  christos void
    522   1.1  christos tui_disable (void)
    523   1.1  christos {
    524  1.10  christos   TUI_SCOPED_DEBUG_ENTER_EXIT;
    525  1.10  christos 
    526   1.1  christos   if (!tui_active)
    527   1.1  christos     return;
    528   1.1  christos 
    529   1.1  christos   /* Restore initial readline keymap.  */
    530   1.1  christos   rl_set_keymap (tui_readline_standard_keymap);
    531   1.1  christos 
    532   1.1  christos   /* Remove TUI hooks.  */
    533   1.1  christos   tui_remove_hooks ();
    534   1.1  christos   rl_startup_hook = 0;
    535   1.1  christos   rl_already_prompted = 0;
    536   1.1  christos 
    537  1.10  christos #ifdef NCURSES_MOUSE_VERSION
    538  1.10  christos   mousemask (0, NULL);
    539  1.10  christos #endif
    540  1.10  christos 
    541   1.1  christos   /* Leave curses and restore previous gdb terminal setting.  */
    542   1.1  christos   endwin ();
    543   1.1  christos 
    544   1.1  christos   /* gdb terminal has changed, update gdb internal copy of it
    545   1.1  christos      so that terminal management with the inferior works.  */
    546   1.1  christos   tui_setup_io (0);
    547   1.1  christos 
    548   1.1  christos   /* Update gdb's knowledge of its terminal.  */
    549   1.3  christos   gdb_save_tty_state ();
    550   1.1  christos 
    551   1.9  christos   tui_active = false;
    552   1.1  christos   tui_update_gdb_sizes ();
    553  1.12  christos 
    554  1.12  christos   gdb::observers::tui_enabled.notify (false);
    555   1.1  christos }
    556   1.1  christos 
    557   1.5  christos /* Command wrapper for enabling tui mode.  */
    558   1.5  christos 
    559   1.5  christos static void
    560   1.8  christos tui_enable_command (const char *args, int from_tty)
    561   1.5  christos {
    562   1.5  christos   tui_enable ();
    563   1.5  christos }
    564   1.5  christos 
    565   1.5  christos /* Command wrapper for leaving tui mode.  */
    566   1.5  christos 
    567   1.5  christos static void
    568   1.8  christos tui_disable_command (const char *args, int from_tty)
    569   1.5  christos {
    570   1.5  christos   tui_disable ();
    571   1.5  christos }
    572   1.5  christos 
    573   1.1  christos void
    574   1.1  christos tui_show_assembly (struct gdbarch *gdbarch, CORE_ADDR addr)
    575   1.1  christos {
    576  1.12  christos   tui_batch_rendering suppress;
    577   1.1  christos   tui_add_win_to_layout (DISASSEM_WIN);
    578   1.1  christos   tui_update_source_windows_with_addr (gdbarch, addr);
    579   1.1  christos }
    580   1.1  christos 
    581   1.9  christos bool
    582   1.1  christos tui_is_window_visible (enum tui_win_type type)
    583   1.1  christos {
    584   1.9  christos   if (!tui_active)
    585   1.9  christos     return false;
    586   1.1  christos 
    587  1.10  christos   if (tui_win_list[type] == nullptr)
    588   1.9  christos     return false;
    589  1.10  christos 
    590   1.9  christos   return tui_win_list[type]->is_visible ();
    591   1.1  christos }
    592   1.1  christos 
    593   1.9  christos bool
    594   1.1  christos tui_get_command_dimension (unsigned int *width,
    595   1.1  christos 			   unsigned int *height)
    596   1.1  christos {
    597  1.12  christos   if (!tui_active || (tui_cmd_win () == NULL))
    598   1.9  christos     return false;
    599   1.1  christos 
    600  1.12  christos   *width = tui_cmd_win ()->width;
    601  1.12  christos   *height = tui_cmd_win ()->height;
    602   1.9  christos   return true;
    603   1.1  christos }
    604   1.5  christos 
    605   1.9  christos void _initialize_tui ();
    606   1.5  christos void
    607   1.9  christos _initialize_tui ()
    608   1.5  christos {
    609   1.5  christos   struct cmd_list_element **tuicmd;
    610   1.5  christos 
    611   1.5  christos   tuicmd = tui_get_cmd_list ();
    612   1.5  christos 
    613   1.5  christos   add_cmd ("enable", class_tui, tui_enable_command,
    614   1.9  christos 	   _("Enable TUI display mode.\n\
    615   1.9  christos Usage: tui enable"),
    616   1.5  christos 	   tuicmd);
    617   1.5  christos   add_cmd ("disable", class_tui, tui_disable_command,
    618   1.9  christos 	   _("Disable TUI display mode.\n\
    619   1.9  christos Usage: tui disable"),
    620   1.5  christos 	   tuicmd);
    621  1.10  christos 
    622  1.10  christos   /* Debug this tui internals.  */
    623  1.10  christos   add_setshow_boolean_cmd ("tui", class_maintenance, &debug_tui,  _("\
    624  1.10  christos Set tui debugging."), _("\
    625  1.10  christos Show tui debugging."), _("\
    626  1.10  christos When true, tui specific internal debugging is enabled."),
    627  1.10  christos 			   NULL,
    628  1.10  christos 			   show_tui_debug,
    629  1.10  christos 			   &setdebuglist, &showdebuglist);
    630   1.5  christos }
    631