/* General functions for the WDB TUI.
- Copyright 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+
+ Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software
+ Foundation, Inc.
+
Contributed by Hewlett-Packard Company.
This file is part of GDB.
Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-/* If we need <curses.h>, we must include it before we get "bfd.h". */
-#include "config.h"
-#ifdef HAVE_NCURSES_H
-#include <ncurses.h>
-#else
-#ifdef HAVE_CURSES_H
-#include <curses.h>
-#endif
-#endif
-
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#endif
#include <signal.h>
#include <fcntl.h>
+#if 0
#include <termio.h>
+#endif
#include <setjmp.h>
#include "defs.h"
#include "gdbcmd.h"
-#include "tui.h"
-#include "tuiData.h"
-#include "tuiLayout.h"
-#include "tuiIO.h"
-#include "tuiRegs.h"
-#include "tuiStack.h"
-#include "tuiWin.h"
-#include "tuiSourceWin.h"
+#include "tui/tui.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 "readline/readline.h"
#include "target.h"
#include "frame.h"
#include "breakpoint.h"
#include "inferior.h"
+#include "symtab.h"
+#include "source.h"
+
+#ifdef HAVE_NCURSES_H
+#include <ncurses.h>
+#else
+#ifdef HAVE_CURSES_H
+#include <curses.h>
+#endif
+#endif
/* Tells whether the TUI is active or not. */
int tui_active = 0;
static int tui_finish_init = 1;
-/* Switch the output mode between TUI/standard gdb. */
+enum tui_key_mode tui_current_key_mode = TUI_COMMAND_MODE;
+
+struct tui_char_command
+{
+ unsigned char key;
+ const char* cmd;
+};
+
+/* Key mapping to gdb commands when the TUI is using the single key mode. */
+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;
+
+/* TUI readline command.
+ Switch the output mode between TUI/standard gdb. */
static int
-tui_switch_mode (void)
+tui_rl_switch_mode (int notused1, int notused2)
{
if (tui_active)
{
tui_disable ();
rl_prep_terminal (0);
-
- printf_filtered ("Left the TUI mode\n");
}
else
{
rl_deprep_terminal ();
tui_enable ();
- printf_filtered ("Entered the TUI mode\n");
}
/* Clear the readline in case switching occurred in middle of something. */
return 0;
}
-/* Change the TUI layout to show a next layout.
+/* TUI readline command.
+ Change the TUI layout to show a next layout.
This function is bound to CTRL-X 2. It is intended to provide
a functionality close to the Emacs split-window command. We always
show two windows (src+asm), (src+regs) or (asm+regs). */
static int
-tui_change_windows (void)
+tui_rl_change_windows (int notused1, int notused2)
{
if (!tui_active)
- tui_switch_mode ();
+ tui_rl_switch_mode (0/*notused*/, 0/*notused*/);
if (tui_active)
{
- TuiLayoutType new_layout;
- TuiRegisterDisplayType regs_type = TUI_UNDEFINED_REGS;
+ enum tui_layout_type new_layout;
+ enum tui_register_display_type regs_type = TUI_UNDEFINED_REGS;
- new_layout = currentLayout ();
+ new_layout = tui_current_layout ();
/* Select a new layout to have a rolling layout behavior
with always two windows (except when undefined). */
new_layout = SRC_COMMAND;
break;
}
- tuiSetLayout (new_layout, regs_type);
+ tui_set_layout (new_layout, regs_type);
}
return 0;
}
-
-/* Delete the second TUI window to only show one. */
+/* TUI readline command.
+ Delete the second TUI window to only show one. */
static int
-tui_delete_other_windows (void)
+tui_rl_delete_other_windows (int notused1, int notused2)
{
if (!tui_active)
- tui_switch_mode ();
+ tui_rl_switch_mode (0/*notused*/, 0/*notused*/);
if (tui_active)
{
- TuiLayoutType new_layout;
- TuiRegisterDisplayType regs_type = TUI_UNDEFINED_REGS;
+ enum tui_layout_type new_layout;
+ enum tui_register_display_type regs_type = TUI_UNDEFINED_REGS;
- new_layout = currentLayout ();
+ new_layout = tui_current_layout ();
/* Kill one window. */
switch (new_layout)
new_layout = DISASSEM_COMMAND;
break;
}
- tuiSetLayout (new_layout, regs_type);
+ tui_set_layout (new_layout, regs_type);
+ }
+ return 0;
+}
+
+/* TUI readline command.
+ Switch the active window to give the focus to a next window. */
+static int
+tui_rl_other_window (int count, int key)
+{
+ struct tui_win_info * win_info;
+
+ if (!tui_active)
+ tui_rl_switch_mode (0/*notused*/, 0/*notused*/);
+
+ 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;
}
+/* TUI readline command.
+ Execute the gdb command bound to the specified key. */
+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)
+ {
+ /* Must save the command because it can be modified
+ by execute_command. */
+ char* cmd = alloca (strlen (tui_commands[i].cmd) + 1);
+ strcpy (cmd, tui_commands[i].cmd);
+ execute_command (cmd, TRUE);
+ return 0;
+ }
+ }
+ return 0;
+}
+
+/* TUI readline command.
+ Temporarily leave the TUI SingleKey mode to allow editing
+ a gdb command with the normal readline. Once the command
+ is executed, the TUI SingleKey mode is installed back. */
+static int
+tui_rl_command_mode (int count, int key)
+{
+ tui_set_key_mode (TUI_ONE_COMMAND_MODE);
+ return rl_insert (count, key);
+}
+
+/* TUI readline command.
+ Switch between TUI SingleKey mode and gdb readline editing. */
+static int
+tui_rl_next_keymap (int notused1, int notused2)
+{
+ if (!tui_active)
+ tui_rl_switch_mode (0/*notused*/, 0/*notused*/);
+
+ tui_set_key_mode (tui_current_key_mode == TUI_COMMAND_MODE
+ ? TUI_SINGLE_KEY_MODE : TUI_COMMAND_MODE);
+ return 0;
+}
+
+/* Readline hook to redisplay ourself the gdb prompt.
+ In the SingleKey mode, the prompt is not printed so that
+ the command window is cleaner. It will be displayed if
+ we temporarily leave the SingleKey mode. */
+static int
+tui_rl_startup_hook (void)
+{
+ rl_already_prompted = 1;
+ if (tui_current_key_mode != TUI_COMMAND_MODE)
+ tui_set_key_mode (TUI_SINGLE_KEY_MODE);
+ tui_redisplay_readline ();
+ return 0;
+}
+
+/* Change the TUI key mode by installing the appropriate readline keymap. */
+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 ();
+}
+
/* Initialize readline and configure the keymap for the switching
key shortcut. */
void
-tui_initialize_readline ()
+tui_initialize_readline (void)
{
+ int i;
+ Keymap tui_ctlx_keymap;
+
rl_initialize ();
- rl_add_defun ("tui-switch-mode", tui_switch_mode, -1);
- rl_bind_key_in_map ('a', tui_switch_mode, emacs_ctlx_keymap);
- rl_bind_key_in_map ('A', tui_switch_mode, emacs_ctlx_keymap);
- rl_bind_key_in_map (CTRL ('A'), tui_switch_mode, emacs_ctlx_keymap);
- rl_bind_key_in_map ('1', tui_delete_other_windows, emacs_ctlx_keymap);
- rl_bind_key_in_map ('2', tui_change_windows, emacs_ctlx_keymap);
+ 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);
+
+ /* Bind all other keys to tui_rl_command_mode so that we switch
+ temporarily from SingleKey mode and can enter a gdb command. */
+ 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);
}
/* Enter in the tui mode (curses).
nl();
keypad (w, TRUE);
rl_initialize ();
- setTermHeightTo (LINES);
- setTermWidthTo (COLS);
+ tui_set_term_height_to (LINES);
+ tui_set_term_width_to (COLS);
def_prog_mode ();
- tuiSetLocatorContent (0);
- showLayout (SRC_COMMAND);
- tuiSetWinFocusTo (srcWin);
- keypad (cmdWin->generic.handle, TRUE);
- wrefresh (cmdWin->generic.handle);
+ 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
/* Install the TUI specific hooks. */
tui_install_hooks ();
+ rl_startup_hook = tui_rl_startup_hook;
tui_update_variables ();
tui_setup_io (1);
- tui_version = 1;
tui_active = 1;
- refresh ();
+ if (deprecated_selected_frame)
+ tui_show_frame_info (deprecated_selected_frame);
+
+ /* Restore TUI keymap. */
+ tui_set_key_mode (tui_current_key_mode);
+ tui_refresh_all_win ();
+
+ /* Update gdb's knowledge of its terminal. */
+ target_terminal_save_ours ();
+ tui_update_gdb_sizes ();
}
/* Leave the tui mode.
if (!tui_active)
return;
+ /* Restore initial readline keymap. */
+ rl_set_keymap (tui_readline_standard_keymap);
+
/* Remove TUI hooks. */
tui_remove_hooks ();
+ rl_startup_hook = 0;
+ rl_already_prompted = 0;
/* Leave curses and restore previous gdb terminal setting. */
endwin ();
so that terminal management with the inferior works. */
tui_setup_io (0);
- tui_version = 0;
- tui_active = 0;
-}
-
-/* Wrapper on top of free() to ensure that input address
- is greater than 0x0. */
-void
-tuiFree (char *ptr)
-{
- if (ptr != (char *) NULL)
- {
- xfree (ptr);
- }
-}
-
-/* Determine what the low address will be to display in the TUI's
- disassembly window. This may or may not be the same as the
- low address input. */
-CORE_ADDR
-tuiGetLowDisassemblyAddress (CORE_ADDR low, CORE_ADDR pc)
-{
- int line;
- CORE_ADDR newLow;
-
- /* Determine where to start the disassembly so that the pc is about in the
- middle of the viewport. */
- for (line = 0, newLow = pc;
- (newLow > low &&
- line < (tuiDefaultWinViewportHeight (DISASSEM_WIN,
- DISASSEM_COMMAND) / 2));)
- {
- bfd_byte buffer[4];
-
- newLow -= sizeof (bfd_getb32 (buffer));
- line++;
- }
+ /* Update gdb's knowledge of its terminal. */
+ target_terminal_save_ours ();
- return newLow;
+ tui_active = 0;
+ tui_update_gdb_sizes ();
}
void
-strcat_to_buf (char *buf, int buflen, char *itemToAdd)
+strcat_to_buf (char *buf, int buflen, const char *item_to_add)
{
- if (itemToAdd != (char *) NULL && buf != (char *) NULL)
+ if (item_to_add != (char *) NULL && buf != (char *) NULL)
{
- if ((strlen (buf) + strlen (itemToAdd)) <= buflen)
- strcat (buf, itemToAdd);
+ if ((strlen (buf) + strlen (item_to_add)) <= buflen)
+ strcat (buf, item_to_add);
else
- strncat (buf, itemToAdd, (buflen - strlen (buf)));
+ strncat (buf, item_to_add, (buflen - strlen (buf)));
}
}
#define CHK(val, dft) (val<=0 ? dft : val)
static void
-_tuiReset (void)
+tui_reset (void)
{
struct termio mode;
#endif /* USG */
return;
-} /* _tuiReset */
+}
#endif
void
tui_show_source (const char *file, int line)
{
+ struct symtab_and_line cursal = get_current_source_symtab_and_line ();
/* make sure that the source window is displayed */
- tuiAddWinToLayout (SRC_WIN);
+ tui_add_win_to_layout (SRC_WIN);
- tuiUpdateSourceWindowsWithLine (current_source_symtab, line);
- tuiUpdateLocatorFilename (file);
+ tui_update_source_windows_with_line (cursal.symtab, line);
+ tui_update_locator_filename (file);
}
void
tui_show_assembly (CORE_ADDR addr)
{
- tuiAddWinToLayout (DISASSEM_WIN);
- tuiUpdateSourceWindowsWithAddr (addr);
+ tui_add_win_to_layout (DISASSEM_WIN);
+ tui_update_source_windows_with_addr (addr);
}
int
-tui_is_window_visible (TuiWinType type)
+tui_is_window_visible (enum tui_win_type type)
{
- if (tui_version == 0)
+ if (tui_active == 0)
return 0;
- if (winList[type] == 0)
+ if (tui_win_list[type] == 0)
return 0;
- return winList[type]->generic.isVisible;
+ return tui_win_list[type]->generic.is_visible;
}
int
tui_get_command_dimension (int *width, int *height)
{
- if (!tui_version || !m_winPtrNotNull (cmdWin))
+ if (!tui_active || (TUI_CMD_WIN == NULL))
{
return 0;
}
- *width = cmdWin->generic.width;
- *height = cmdWin->generic.height;
+ *width = TUI_CMD_WIN->generic.width;
+ *height = TUI_CMD_WIN->generic.height;
return 1;
}