gdb/tui/tui.c - gdb
Global variables defined
Data types defined
Functions defined
Source code
#include "defs.h"
#include "gdbcmd.h"
#include "tui/tui.h"
#include "tui/tui-hooks.h"
#include "tui/tui-data.h"
#include "tui/tui-layout.h"
#include "tui/tui-io.h"
#include "tui/tui-regs.h"
#include "tui/tui-stack.h"
#include "tui/tui-win.h"
#include "tui/tui-winsource.h"
#include "tui/tui-windata.h"
#include "target.h"
#include "frame.h"
#include "breakpoint.h"
#include "inferior.h"
#include "symtab.h"
#include "source.h"
#include "terminal.h"
#include <ctype.h>
#include <signal.h>
#include <fcntl.h>
#if 0
#endif
#include <setjmp.h>
#include "gdb_curses.h"
#include "interps.h"
#include "readline/readline.h"
int tui_active = 0;
static int tui_finish_init = 1;
enum tui_key_mode tui_current_key_mode = TUI_COMMAND_MODE;
struct tui_char_command
{
unsigned char key;
const char *cmd;
};
static const struct tui_char_command tui_commands[] = {
{ 'c', "continue" },
{ 'd', "down" },
{ 'f', "finish" },
{ 'n', "next" },
{ 'r', "run" },
{ 's', "step" },
{ 'u', "up" },
{ 'v', "info locals" },
{ 'w', "where" },
{ 0, 0 },
};
static Keymap tui_keymap;
static Keymap tui_readline_standard_keymap;
static int
tui_rl_switch_mode (int notused1, int notused2)
{
volatile struct gdb_exception ex;
TRY_CATCH (ex, RETURN_MASK_ALL)
{
if (tui_active)
{
tui_disable ();
rl_prep_terminal (0);
}
else
{
rl_deprep_terminal ();
tui_enable ();
}
}
if (ex.reason < 0)
{
exception_print (gdb_stderr, ex);
if (!tui_active)
rl_prep_terminal (0);
}
if (rl_end)
rl_kill_text (0, rl_end);
rl_newline (1, '\n');
dont_repeat ();
return 0;
}
static int
tui_rl_change_windows (int notused1, int notused2)
{
if (!tui_active)
tui_rl_switch_mode (0 , 0 );
if (tui_active)
{
enum tui_layout_type new_layout;
enum tui_register_display_type regs_type = TUI_UNDEFINED_REGS;
new_layout = tui_current_layout ();
switch (new_layout)
{
case SRC_COMMAND:
new_layout = SRC_DISASSEM_COMMAND;
break;
case DISASSEM_COMMAND:
new_layout = SRC_DISASSEM_COMMAND;
break;
case SRC_DATA_COMMAND:
new_layout = SRC_DISASSEM_COMMAND;
break;
case SRC_DISASSEM_COMMAND:
new_layout = DISASSEM_DATA_COMMAND;
break;
case DISASSEM_DATA_COMMAND:
new_layout = SRC_DATA_COMMAND;
break;
default:
new_layout = SRC_COMMAND;
break;
}
tui_set_layout (new_layout, regs_type);
}
return 0;
}
static int
tui_rl_delete_other_windows (int notused1, int notused2)
{
if (!tui_active)
tui_rl_switch_mode (0 , 0 );
if (tui_active)
{
enum tui_layout_type new_layout;
enum tui_register_display_type regs_type = TUI_UNDEFINED_REGS;
new_layout = tui_current_layout ();
switch (new_layout)
{
case SRC_COMMAND:
case SRC_DATA_COMMAND:
case SRC_DISASSEM_COMMAND:
default:
new_layout = SRC_COMMAND;
break;
case DISASSEM_COMMAND:
case DISASSEM_DATA_COMMAND:
new_layout = DISASSEM_COMMAND;
break;
}
tui_set_layout (new_layout, regs_type);
}
return 0;
}
static int
tui_rl_other_window (int count, int key)
{
struct tui_win_info *win_info;
if (!tui_active)
tui_rl_switch_mode (0 , 0 );
win_info = tui_next_win (tui_win_with_focus ());
if (win_info)
{
tui_set_win_focus_to (win_info);
if (TUI_DATA_WIN && TUI_DATA_WIN->generic.is_visible)
tui_refresh_data_win ();
keypad (TUI_CMD_WIN->generic.handle, (win_info != TUI_CMD_WIN));
}
return 0;
}
static int
tui_rl_command_key (int count, int key)
{
int i;
reinitialize_more_filter ();
for (i = 0; tui_commands[i].cmd; i++)
{
if (tui_commands[i].key == key)
{
rl_insert_text (tui_commands[i].cmd);
rl_newline (1, '\n');
tui_set_key_mode (TUI_ONE_COMMAND_MODE);
return 0;
}
}
return 0;
}
static int
tui_rl_command_mode (int count, int key)
{
tui_set_key_mode (TUI_ONE_COMMAND_MODE);
return rl_insert (count, key);
}
static int
tui_rl_next_keymap (int notused1, int notused2)
{
if (!tui_active)
tui_rl_switch_mode (0 , 0 );
tui_set_key_mode (tui_current_key_mode == TUI_COMMAND_MODE
? TUI_SINGLE_KEY_MODE : TUI_COMMAND_MODE);
return 0;
}
static int
tui_rl_startup_hook (void)
{
rl_already_prompted = 1;
if (tui_current_key_mode != TUI_COMMAND_MODE && immediate_quit == 0)
tui_set_key_mode (TUI_SINGLE_KEY_MODE);
tui_redisplay_readline ();
return 0;
}
void
tui_set_key_mode (enum tui_key_mode mode)
{
tui_current_key_mode = mode;
rl_set_keymap (mode == TUI_SINGLE_KEY_MODE
? tui_keymap : tui_readline_standard_keymap);
tui_show_locator_content ();
}
void
tui_initialize_readline (void)
{
int i;
Keymap tui_ctlx_keymap;
rl_initialize ();
rl_add_defun ("tui-switch-mode", tui_rl_switch_mode, -1);
rl_add_defun ("gdb-command", tui_rl_command_key, -1);
rl_add_defun ("next-keymap", tui_rl_next_keymap, -1);
tui_keymap = rl_make_bare_keymap ();
tui_ctlx_keymap = rl_make_bare_keymap ();
tui_readline_standard_keymap = rl_get_keymap ();
for (i = 0; tui_commands[i].cmd; i++)
rl_bind_key_in_map (tui_commands[i].key, tui_rl_command_key, tui_keymap);
rl_generic_bind (ISKMAP, "\\C-x", (char*) tui_ctlx_keymap, tui_keymap);
for (i = ' '; i < 0x7f; i++)
{
int j;
for (j = 0; tui_commands[j].cmd; j++)
if (tui_commands[j].key == i)
break;
if (tui_commands[j].cmd)
continue;
rl_bind_key_in_map (i, tui_rl_command_mode, tui_keymap);
}
rl_bind_key_in_map ('a', tui_rl_switch_mode, emacs_ctlx_keymap);
rl_bind_key_in_map ('a', tui_rl_switch_mode, tui_ctlx_keymap);
rl_bind_key_in_map ('A', tui_rl_switch_mode, emacs_ctlx_keymap);
rl_bind_key_in_map ('A', tui_rl_switch_mode, tui_ctlx_keymap);
rl_bind_key_in_map (CTRL ('A'), tui_rl_switch_mode, emacs_ctlx_keymap);
rl_bind_key_in_map (CTRL ('A'), tui_rl_switch_mode, tui_ctlx_keymap);
rl_bind_key_in_map ('1', tui_rl_delete_other_windows, emacs_ctlx_keymap);
rl_bind_key_in_map ('1', tui_rl_delete_other_windows, tui_ctlx_keymap);
rl_bind_key_in_map ('2', tui_rl_change_windows, emacs_ctlx_keymap);
rl_bind_key_in_map ('2', tui_rl_change_windows, tui_ctlx_keymap);
rl_bind_key_in_map ('o', tui_rl_other_window, emacs_ctlx_keymap);
rl_bind_key_in_map ('o', tui_rl_other_window, tui_ctlx_keymap);
rl_bind_key_in_map ('q', tui_rl_next_keymap, tui_keymap);
rl_bind_key_in_map ('s', tui_rl_next_keymap, emacs_ctlx_keymap);
rl_bind_key_in_map ('s', tui_rl_next_keymap, tui_ctlx_keymap);
}
static const char *
gdb_getenv_term (void)
{
const char *term;
term = getenv ("TERM");
if (term != NULL)
return term;
return "<unset>";
}
void
tui_enable (void)
{
struct interp *interp;
if (tui_active)
return;
if (tui_finish_init)
{
WINDOW *w;
SCREEN *s;
const char *cap;
const char *interp;
interp = interp_name (top_level_interpreter ());
if (strcmp (interp, INTERP_TUI) != 0)
error (_("Cannot enable the TUI when the interpreter is '%s'"), interp);
if (!ui_file_isatty (gdb_stdout))
error (_("Cannot enable the TUI when output is not a terminal"));
s = newterm (NULL, stdout, stdin);
if (s == NULL)
{
error (_("Cannot enable the TUI: error opening terminal [TERM=%s]"),
gdb_getenv_term ());
}
w = stdscr;
cap = tigetstr ("cup");
if (cap == NULL || cap == (char *) -1 || *cap == '\0')
{
endwin ();
delscreen (s);
error (_("Cannot enable the TUI: "
"terminal doesn't support cursor addressing [TERM=%s]"),
gdb_getenv_term ());
}
cbreak ();
noecho ();
nodelay(w, FALSE);
nl();
keypad (w, TRUE);
rl_initialize ();
tui_set_term_height_to (LINES);
tui_set_term_width_to (COLS);
def_prog_mode ();
tui_show_frame_info (0);
tui_set_layout (SRC_COMMAND, TUI_UNDEFINED_REGS);
tui_set_win_focus_to (TUI_SRC_WIN);
keypad (TUI_CMD_WIN->generic.handle, TRUE);
wrefresh (TUI_CMD_WIN->generic.handle);
tui_finish_init = 0;
}
else
{
def_shell_mode ();
clearok (stdscr, TRUE);
}
tui_install_hooks ();
rl_startup_hook = tui_rl_startup_hook;
tui_update_variables ();
tui_setup_io (1);
tui_active = 1;
if (deprecated_safe_get_selected_frame ())
tui_show_frame_info (deprecated_safe_get_selected_frame ());
tui_set_key_mode (tui_current_key_mode);
tui_refresh_all_win ();
gdb_save_tty_state ();
tui_update_gdb_sizes ();
}
void
tui_disable (void)
{
if (!tui_active)
return;
rl_set_keymap (tui_readline_standard_keymap);
tui_remove_hooks ();
rl_startup_hook = 0;
rl_already_prompted = 0;
endwin ();
tui_setup_io (0);
gdb_save_tty_state ();
tui_active = 0;
tui_update_gdb_sizes ();
}
void
strcat_to_buf (char *buf, int buflen,
const char *item_to_add)
{
if (item_to_add != (char *) NULL && buf != (char *) NULL)
{
if ((strlen (buf) + strlen (item_to_add)) <= buflen)
strcat (buf, item_to_add);
else
strncat (buf, item_to_add, (buflen - strlen (buf)));
}
}
#if 0
#endif
void
tui_show_source (const char *fullname, int line)
{
struct symtab_and_line cursal = get_current_source_symtab_and_line ();
tui_add_win_to_layout (SRC_WIN);
tui_update_source_windows_with_line (cursal.symtab, line);
tui_update_locator_fullname (fullname);
}
void
tui_show_assembly (struct gdbarch *gdbarch, CORE_ADDR addr)
{
tui_add_win_to_layout (DISASSEM_WIN);
tui_update_source_windows_with_addr (gdbarch, addr);
}
int
tui_is_window_visible (enum tui_win_type type)
{
if (tui_active == 0)
return 0;
if (tui_win_list[type] == 0)
return 0;
return tui_win_list[type]->generic.is_visible;
}
int
tui_get_command_dimension (unsigned int *width,
unsigned int *height)
{
if (!tui_active || (TUI_CMD_WIN == NULL))
{
return 0;
}
*width = TUI_CMD_WIN->generic.width;
*height = TUI_CMD_WIN->generic.height;
return 1;
}