-/*
- ** tui.c
- ** General functions for the WDB TUI
- */
+/* General functions for the WDB TUI.
+
+ Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software
+ Foundation, Inc.
+
+ Contributed by Hewlett-Packard Company.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#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 <stdio.h>
#include <stdlib.h>
#include <ctype.h>
-#include <malloc.h>
-#ifdef HAVE_TERM_H
-#include <term.h>
-#endif
#include <signal.h>
#include <fcntl.h>
+#if 0
#include <termio.h>
-#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 "tuiWin.h"
-
-/* The Solaris header files seem to provide no declaration for this at
- all when __STDC__ is defined. This shouldn't conflict with
- anything. */
-extern char *tgoto ();
-
-/***********************
-** Local Definitions
-************************/
-#define FILEDES 2
-/* Solaris <sys/termios.h> defines CTRL. */
-#ifndef CTRL
-#define CTRL(x) (x & ~0140)
#endif
-#define CHK(val, dft) (val<=0 ? dft : val)
-
-#define TOGGLE_USAGE "Usage:toggle breakpoints"
-#define TUI_TOGGLE_USAGE "Usage:\ttoggle $fregs\n\ttoggle breakpoints"
-
-/*****************************
-** Local static forward decls
-******************************/
-static void _tuiReset PARAMS ((void));
-static void _toggle_command PARAMS ((char *, int));
-static void _tui_vToggle_command PARAMS ((va_list));
-static Opaque _tui_vDo PARAMS ((TuiOpaqueFuncPtr, va_list));
-
-
+#include <setjmp.h>
-/***********************
-** Public Functions
-************************/
+#include "gdb_curses.h"
-/*
- ** tuiInit().
- */
-void
-#ifdef __STDC__
-tuiInit (char *argv0)
-#else
-tuiInit (argv0)
- char *argv0;
-#endif
-{
- extern void init_page_info ();
- extern void initialize_tui_files PARAMS ((void));
-
- initialize_tui_files ();
- initializeStaticData ();
- initscr ();
- refresh ();
- setTermHeightTo (LINES);
- setTermWidthTo (COLS);
- tuiInitWindows ();
- wrefresh (cmdWin->generic.handle);
- init_page_info ();
- /* Don't hook debugger output if doing command-window
- * the XDB way. However, one thing we do want to do in
- * XDB style is set up the scrolling region to be
- * the bottom of the screen (tuiTermUnsetup()).
- */
- fputs_unfiltered_hook = NULL;
- rl_initialize (); /* need readline initialization to
- * create termcap sequences
- */
- tuiTermUnsetup (1, cmdWin->detail.commandInfo.curch);
+/* This redefines CTRL if it is not already defined, so it must come
+ after terminal state releated include files like <term.h> and
+ "gdb_curses.h". */
+#include "readline/readline.h"
- return;
-} /* tuiInit */
+/* Tells whether the TUI is active or not. */
+int tui_active = 0;
+static int tui_finish_init = 1;
+enum tui_key_mode tui_current_key_mode = TUI_COMMAND_MODE;
-/*
- ** tuiInitWindows().
- */
-void
-#ifdef __STDC__
-tuiInitWindows (void)
-#else
-tuiInitWindows ()
-#endif
+struct tui_char_command
{
- TuiWinType type;
-
- tuiSetLocatorContent (0);
- showLayout (SRC_COMMAND);
- keypad (cmdWin->generic.handle, TRUE);
- echo ();
- crmode ();
- nl ();
- tuiSetWinFocusTo (srcWin);
-
- return;
-} /* tuiInitWindows */
-
-
-/*
- ** tuiCleanUp().
- ** Kill signal handler and cleanup termination method
- */
-void
-#ifdef __STDC__
-tuiResetScreen (void)
-#else
-tuiResetScreen ()
-#endif
+ 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_rl_switch_mode (int notused1, int notused2)
{
- TuiWinType type = SRC_WIN;
-
- keypad (cmdWin->generic.handle, FALSE);
- for (; type < MAX_MAJOR_WINDOWS; type++)
+ if (tui_active)
{
- if (m_winPtrNotNull (winList[type]) &&
- winList[type]->generic.type != UNDEFINED_WIN &&
- !winList[type]->generic.isVisible)
- tuiDelWindow (winList[type]);
+ tui_disable ();
+ rl_prep_terminal (0);
}
- endwin ();
- initscr ();
- refresh ();
- echo ();
- crmode ();
- nl ();
-
- return;
-} /* tuiResetScreen */
-
-
-/*
- ** tuiCleanUp().
- ** Kill signal handler and cleanup termination method
- */
-void
-#ifdef __STDC__
-tuiCleanUp (void)
-#else
-tuiCleanUp ()
-#endif
-{
- char *buffer;
- extern char *term_cursor_move;
-
- signal (SIGINT, SIG_IGN);
- tuiTermSetup (0); /* Restore scrolling region to whole screen */
- keypad (cmdWin->generic.handle, FALSE);
- freeAllWindows ();
- endwin ();
- buffer = tgoto (term_cursor_move, 0, termHeight ());
- tputs (buffer, 1, putchar);
- _tuiReset ();
-
- return;
-} /* tuiCleanUp */
-
-
-/*
- ** tuiError().
- */
-void
-#ifdef __STDC__
-tuiError (
- char *string,
- int exitGdb)
-#else
-tuiError (string, exitGdb)
- char *string;
- int exitGdb;
-#endif
-{
- puts_unfiltered (string);
- if (exitGdb)
+ else
{
- tuiCleanUp ();
- exit (-1);
+ rl_deprep_terminal ();
+ tui_enable ();
}
- return;
-} /* tuiError */
-
+ /* Clear the readline in case switching occurred in middle of something. */
+ if (rl_end)
+ rl_kill_text (0, rl_end);
+
+ /* Since we left the curses mode, the terminal mode is restored to
+ some previous state. That state may not be suitable for readline
+ to work correctly (it may be restored in line mode). We force an
+ exit of the current readline so that readline is re-entered and it
+ will be able to setup the terminal for its needs. By re-entering
+ in readline, we also redisplay its prompt in the non-curses mode. */
+ rl_newline (1, '\n');
+
+ /* Make sure the \n we are returning does not repeat the last command. */
+ dont_repeat ();
+ return 0;
+}
-/*
- ** tui_vError()
- ** tuiError with args in a va_list.
- */
-void
-#ifdef __STDC__
-tui_vError (
- va_list args)
-#else
-tui_vError (args)
- va_list args;
-#endif
+/* 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_rl_change_windows (int notused1, int notused2)
{
- char *string;
- int exitGdb;
-
- string = va_arg (args, char *);
- exitGdb = va_arg (args, int);
-
- tuiError (string, exitGdb);
-
- return;
-} /* tui_vError */
+ if (!tui_active)
+ tui_rl_switch_mode (0/*notused*/, 0/*notused*/);
-
-/*
- ** tuiFree()
- ** Wrapper on top of free() to ensure that input address is greater than 0x0
- */
-void
-#ifdef __STDC__
-tuiFree (
- char *ptr)
-#else
-tuiFree (ptr)
- char *ptr;
-#endif
-{
- if (ptr != (char *) NULL)
+ if (tui_active)
{
- free (ptr);
+ enum tui_layout_type new_layout;
+ enum tui_register_display_type regs_type = TUI_UNDEFINED_REGS;
+
+ new_layout = tui_current_layout ();
+
+ /* Select a new layout to have a rolling layout behavior
+ with always two windows (except when undefined). */
+ 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;
+}
- return;
-} /* tuiFree */
-
-
-/* tuiGetLowDisassemblyAddress().
- ** 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.
- */
-Opaque
-#ifdef __STDC__
-tuiGetLowDisassemblyAddress (
- Opaque low,
- Opaque pc)
-#else
-tuiGetLowDisassemblyAddress (low, pc)
- Opaque low;
- Opaque pc;
-#endif
+/* TUI readline command.
+ Delete the second TUI window to only show one. */
+static int
+tui_rl_delete_other_windows (int notused1, int notused2)
{
- int line;
- Opaque newLow;
+ if (!tui_active)
+ tui_rl_switch_mode (0/*notused*/, 0/*notused*/);
- /*
- ** 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));)
+ if (tui_active)
{
- bfd_byte buffer[4];
-
- newLow -= sizeof (bfd_getb32 (buffer));
- line++;
+ enum tui_layout_type new_layout;
+ enum tui_register_display_type regs_type = TUI_UNDEFINED_REGS;
+
+ new_layout = tui_current_layout ();
+
+ /* Kill one window. */
+ 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;
+}
- return newLow;
-} /* tuiGetLowDisassemblyAddress */
-
-
-/* tui_vGetLowDisassemblyAddress().
- ** Determine what the low address will be to display in the TUI's
- ** disassembly window with args in a va_list.
- */
-Opaque
-#ifdef __STDC__
-tui_vGetLowDisassemblyAddress (
- va_list args)
-#else
-tui_vGetLowDisassemblyAddress (args)
- va_list args;
-#endif
+/* 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)
{
- int line;
- Opaque newLow;
- Opaque low;
- Opaque pc;
-
- low = va_arg (args, Opaque);
- pc = va_arg (args, Opaque);
-
- return (tuiGetLowDisassemblyAddress (low, pc));
-
-} /* tui_vGetLowDisassemblyAddress */
-
-
-/*
- ** tuiDo().
- ** General purpose function to execute a tui function. Transitions
- ** between curses and the are handled here. This function is called
- ** by non-tui gdb functions.
- **
- ** Errors are caught here.
- ** If there is no error, the value returned by 'func' is returned.
- ** If there is an error, then zero is returned.
- **
- ** Must not be called with immediate_quit in effect (bad things might
- ** happen, say we got a signal in the middle of a memcpy to quit_return).
- ** This is an OK restriction; with very few exceptions immediate_quit can
- ** be replaced by judicious use of QUIT.
- */
-Opaque
-#ifdef __STDC__
-tuiDo (
- TuiOpaqueFuncPtr func,...)
-#else
-tuiDo (func, va_alist)
- TuiOpaqueFuncPtr func;
- va_dcl
-#endif
-{
- extern int terminal_is_ours;
-
- Opaque ret = (Opaque) NULL;
+ struct tui_win_info * win_info;
- /* It is an error to be tuiDo'ing if we
- * don't own the terminal.
- */
- if (!terminal_is_ours)
- return ret;
+ if (!tui_active)
+ tui_rl_switch_mode (0/*notused*/, 0/*notused*/);
- if (tui_version)
+ win_info = tui_next_win (tui_win_with_focus ());
+ if (win_info)
{
- va_list args;
-
-#ifdef __STDC__
- va_start (args, func);
-#else
- va_start (args);
-#endif
- ret = _tui_vDo (func, args);
- va_end (args);
+ 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;
+}
- return ret;
-} /* tuiDo */
-
-
-/*
- ** tuiDoAndReturnToTop().
- ** General purpose function to execute a tui function. Transitions
- ** between curses and the are handled here. This function is called
- ** by non-tui gdb functions who wish to reset gdb to the top level.
- ** After the tuiDo is performed, a return to the top level occurs.
- **
- ** Errors are caught here.
- ** If there is no error, the value returned by 'func' is returned.
- ** If there is an error, then zero is returned.
- **
- ** Must not be called with immediate_quit in effect (bad things might
- ** happen, say we got a signal in the middle of a memcpy to quit_return).
- ** This is an OK restriction; with very few exceptions immediate_quit can
- ** be replaced by judicious use of QUIT.
- **
- */
-Opaque
-#ifdef __STDC__
-tuiDoAndReturnToTop (
- TuiOpaqueFuncPtr func,...)
-#else
-tuiDoAndReturnToTop (func, va_alist)
- TuiOpaqueFuncPtr func;
- va_dcl
-#endif
+/* TUI readline command.
+ Execute the gdb command bound to the specified key. */
+static int
+tui_rl_command_key (int count, int key)
{
- extern int terminal_is_ours;
-
- Opaque ret = (Opaque) NULL;
+ int i;
- /* It is an error to be tuiDo'ing if we
- * don't own the terminal.
- */
- if (!terminal_is_ours)
- return ret;
-
- if (tui_version)
+ reinitialize_more_filter ();
+ for (i = 0; tui_commands[i].cmd; i++)
{
- va_list args;
-
-#ifdef __STDC__
- va_start (args, func);
-#else
- va_start (args);
-#endif
- ret = _tui_vDo (func, args);
-
- /* force a return to the top level */
- return_to_top_level (RETURN_ERROR);
+ 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;
+}
- return ret;
-} /* tuiDoAndReturnToTop */
-
-
-void
-#ifdef __STDC__
-tui_vSelectSourceSymtab (
- va_list args)
-#else
-tui_vSelectSourceSymtab (args)
- va_list args;
-#endif
-{
- struct symtab *s = va_arg (args, struct symtab *);
-
- select_source_symtab (s);
- return;
-} /* tui_vSelectSourceSymtab */
-
-
-/*
- ** _initialize_tui().
- ** Function to initialize gdb commands, for tui window manipulation.
- */
-void
-_initialize_tui ()
+/* 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)
{
-#if 0
- if (tui_version)
- {
- add_com ("toggle", class_tui, _toggle_command,
- "Toggle Terminal UI Features\n\
-Usage: Toggle $fregs\n\
-\tToggles between single and double precision floating point registers.\n");
- }
-#endif
- char *helpStr;
+ tui_set_key_mode (TUI_ONE_COMMAND_MODE);
+ return rl_insert (count, key);
+}
- if (tui_version)
- helpStr = "Toggle Specified Features\n\
-Usage:\ttoggle $fregs\n\ttoggle breakpoints";
- else
- helpStr = "Toggle Specified Features\nUsage:toggle breakpoints";
- add_abbrev_prefix_cmd ("toggle",
- class_tui,
- _toggle_command,
- helpStr,
- &togglelist,
- "toggle ",
- 1,
- &cmdlist);
-} /* _initialize_tui */
-
-
-/*
- ** va_catch_errors().
- ** General purpose function to execute a function, catching errors.
- ** If there is no error, the value returned by 'func' is returned.
- ** If there is error, then zero is returned.
- ** Note that 'func' must take a variable argument list as well.
- **
- ** Must not be called with immediate_quit in effect (bad things might
- ** happen, say we got a signal in the middle of a memcpy to quit_return).
- ** This is an OK restriction; with very few exceptions immediate_quit can
- ** be replaced by judicious use of QUIT.
- */
-Opaque
-#ifdef __STDC__
-va_catch_errors (
- TuiOpaqueFuncPtr func,
- va_list args)
-#else
-va_catch_errors (func, args)
- TuiOpaqueFuncPtr func;
- va_list args;
-#endif
+/* TUI readline command.
+ Switch between TUI SingleKey mode and gdb readline editing. */
+static int
+tui_rl_next_keymap (int notused1, int notused2)
{
- Opaque ret = (Opaque) NULL;
-
- /*
- ** We could have used catch_errors(), but it doesn't handle variable args.
- ** Also, for the tui, we always want to catch all errors, so we don't
- ** need to pass a mask, or an error string.
- */
- jmp_buf saved_error;
- jmp_buf saved_quit;
- jmp_buf tmp_jmp;
- struct cleanup *saved_cleanup_chain;
- char *saved_error_pre_print;
- char *saved_quit_pre_print;
- extern jmp_buf error_return;
- extern jmp_buf quit_return;
-
- saved_cleanup_chain = save_cleanups ();
- saved_error_pre_print = error_pre_print;
- saved_quit_pre_print = quit_pre_print;
-
- memcpy ((char *) saved_error, (char *) error_return, sizeof (jmp_buf));
- error_pre_print = "";
- memcpy (saved_quit, quit_return, sizeof (jmp_buf));
- quit_pre_print = "";
-
- if (setjmp (tmp_jmp) == 0)
- {
- va_list argList = args;
- memcpy (error_return, tmp_jmp, sizeof (jmp_buf));
- memcpy (quit_return, tmp_jmp, sizeof (jmp_buf));
- ret = func (argList);
- }
- restore_cleanups (saved_cleanup_chain);
- memcpy (error_return, saved_error, sizeof (jmp_buf));
- error_pre_print = saved_error_pre_print;
- memcpy (quit_return, saved_quit, sizeof (jmp_buf));
- quit_pre_print = saved_quit_pre_print;
+ if (!tui_active)
+ tui_rl_switch_mode (0/*notused*/, 0/*notused*/);
- return ret;
+ tui_set_key_mode (tui_current_key_mode == TUI_COMMAND_MODE
+ ? TUI_SINGLE_KEY_MODE : TUI_COMMAND_MODE);
+ return 0;
}
-/*
- ** vcatch_errors().
- ** Catch errors occurring in tui or non tui function, handling
- ** variable param lists. Note that 'func' must take a variable
- ** argument list as well.
- */
-Opaque
-#ifdef __STDC__
-vcatch_errors (
- OpaqueFuncPtr func,...)
-#else
-vcatch_errors (va_alist)
- va_dcl
-/*
- vcatch_errors(func, va_alist)
- OpaqueFuncPtr func;
- va_dcl
- */
-#endif
+/* 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)
{
- Opaque ret = (Opaque) NULL;
- va_list args;
-#ifdef __STDC__
- va_start (args, func);
-/*
- va_arg(args, OpaqueFuncPtr);
- */
-#else
- OpaqueFuncPtr func;
-
- va_start (args);
- func = va_arg (args, OpaqueFuncPtr);
-#endif
- ret = va_catch_errors (func, args);
- va_end (args);
-
- return ret;
+ 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
-#ifdef __STDC__
-strcat_to_buf (
- char *buf,
- int buflen,
- char *itemToAdd)
-#else
-strcat_to_buf (buf, buflen, itemToAdd)
- char *buf;
- int buflen;
- char *itemToAdd;
-#endif
+tui_set_key_mode (enum tui_key_mode mode)
{
- if (itemToAdd != (char *) NULL && buf != (char *) NULL)
- {
- if ((strlen (buf) + strlen (itemToAdd)) <= buflen)
- strcat (buf, itemToAdd);
- else
- strncat (buf, itemToAdd, (buflen - strlen (buf)));
- }
-
- return;
-} /* strcat_to_buf */
+ tui_current_key_mode = mode;
+ rl_set_keymap (mode == TUI_SINGLE_KEY_MODE
+ ? tui_keymap : tui_readline_standard_keymap);
+ tui_show_locator_content ();
+}
-/* VARARGS */
+/* Initialize readline and configure the keymap for the switching
+ key shortcut. */
void
-#ifdef ANSI_PROTOTYPES
-strcat_to_buf_with_fmt (
- char *buf,
- int bufLen,
- char *format,...)
-#else
-strcat_to_buf_with_fmt (va_alist)
- va_dcl
-#endif
+tui_initialize_readline (void)
{
- char *linebuffer;
- struct cleanup *old_cleanups;
- va_list args;
-#ifdef ANSI_PROTOTYPES
- va_start (args, format);
-#else
- char *buf;
- int bufLen;
- char *format;
-
- va_start (args);
- buf = va_arg (args, char *);
- bufLen = va_arg (args, int);
- format = va_arg (args, char *);
-#endif
- vasprintf (&linebuffer, format, args);
- old_cleanups = make_cleanup (free, linebuffer);
- strcat_to_buf (buf, bufLen, linebuffer);
- do_cleanups (old_cleanups);
- va_end (args);
-}
+ 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);
-/***********************
-** Static Functions
-************************/
-
-
-/*
- ** _tui_vDo().
- ** General purpose function to execute a tui function. Transitions
- ** between curses and the are handled here. This function is called
- ** by non-tui gdb functions.
- **
- ** Errors are caught here.
- ** If there is no error, the value returned by 'func' is returned.
- ** If there is an error, then zero is returned.
- **
- ** Must not be called with immediate_quit in effect (bad things might
- ** happen, say we got a signal in the middle of a memcpy to quit_return).
- ** This is an OK restriction; with very few exceptions immediate_quit can
- ** be replaced by judicious use of QUIT.
- */
-static Opaque
-#ifdef __STDC__
-_tui_vDo (
- TuiOpaqueFuncPtr func,
- va_list args)
-#else
-_tui_vDo (func, args)
- TuiOpaqueFuncPtr func;
- va_list args;
-#endif
-{
- extern int terminal_is_ours;
+ rl_generic_bind (ISKMAP, "\\C-x", (char*) tui_ctlx_keymap, tui_keymap);
- Opaque ret = (Opaque) NULL;
-
- /* It is an error to be tuiDo'ing if we
- * don't own the terminal.
- */
- if (!terminal_is_ours)
- return ret;
-
- if (tui_version)
+ /* 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++)
{
- /* If doing command window the "XDB way" (command window
- * is unmanaged by curses...
- */
- /* Set up terminal for TUI */
- tuiTermSetup (1);
+ int j;
- ret = va_catch_errors (func, args);
+ for (j = 0; tui_commands[j].cmd; j++)
+ if (tui_commands[j].key == i)
+ break;
- /* Set up terminal for command window */
- tuiTermUnsetup (1, cmdWin->detail.commandInfo.curch);
- }
+ if (tui_commands[j].cmd)
+ continue;
- return ret;
-} /* _tui_vDo */
+ 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 void
-#ifdef __STDC__
-_toggle_command (
- char *arg,
- int fromTTY)
-#else
-_toggle_command (arg, fromTTY)
- char *arg;
- int fromTTY;
-#endif
+/* Enter in the tui mode (curses).
+ When in normal mode, it installs the tui hooks in gdb, redirects
+ the gdb output, configures the readline to work in tui mode.
+ When in curses mode, it does nothing. */
+void
+tui_enable (void)
{
- printf_filtered ("Specify feature to toggle.\n%s\n",
- (tui_version) ? TUI_TOGGLE_USAGE : TOGGLE_USAGE);
-/*
- tuiDo((TuiOpaqueFuncPtr)_Toggle_command, arg, fromTTY);
- */
+ if (tui_active)
+ return;
+
+ /* To avoid to initialize curses when gdb starts, there is a defered
+ curses initialization. This initialization is made only once
+ and the first time the curses mode is entered. */
+ if (tui_finish_init)
+ {
+ WINDOW *w;
+
+ w = initscr ();
+
+ cbreak ();
+ noecho ();
+ /*timeout (1);*/
+ 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
+ {
+ /* Save the current gdb setting of the terminal.
+ Curses will restore this state when endwin() is called. */
+ def_shell_mode ();
+ clearok (stdscr, TRUE);
+ }
+
+ /* Install the TUI specific hooks. */
+ tui_install_hooks ();
+ rl_startup_hook = tui_rl_startup_hook;
+
+ tui_update_variables ();
+
+ tui_setup_io (1);
+
+ tui_active = 1;
+ 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 ();
}
-/*
- ** _tui_vToggle_command().
- */
-static void
-#ifdef __STDC__
-_tui_vToggle_command (
- va_list args)
-#else
-_tui_vToggle_command (args)
- va_list args;
-#endif
+/* Leave the tui mode.
+ Remove the tui hooks and configure the gdb output and readline
+ back to their original state. The curses mode is left so that
+ the terminal setting is restored to the point when we entered. */
+void
+tui_disable (void)
{
- char *arg;
- int fromTTY;
+ if (!tui_active)
+ return;
- arg = va_arg (args, char *);
+ /* Restore initial readline keymap. */
+ rl_set_keymap (tui_readline_standard_keymap);
- if (arg == (char *) NULL)
- printf_filtered (TOGGLE_USAGE);
- else
- {
- char *ptr = (char *) tuiStrDup (arg);
- int i;
+ /* Remove TUI hooks. */
+ tui_remove_hooks ();
+ rl_startup_hook = 0;
+ rl_already_prompted = 0;
+
+ /* Leave curses and restore previous gdb terminal setting. */
+ endwin ();
+
+ /* gdb terminal has changed, update gdb internal copy of it
+ so that terminal management with the inferior works. */
+ tui_setup_io (0);
+
+ /* Update gdb's knowledge of its terminal. */
+ target_terminal_save_ours ();
- for (i = 0; (ptr[i]); i++)
- ptr[i] = toupper (arg[i]);
+ tui_active = 0;
+ tui_update_gdb_sizes ();
+}
- if (subsetCompare (ptr, TUI_FLOAT_REGS_NAME))
- tuiToggleFloatRegs ();
-/* else if (subsetCompare(ptr, "ANOTHER TOGGLE OPTION"))
- ...
- */
+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
- printf_filtered (TOGGLE_USAGE);
- tuiFree (ptr);
+ strncat (buf, item_to_add, (buflen - strlen (buf)));
}
+}
- return;
-} /* _tuiToggle_command */
+#if 0
+/* Solaris <sys/termios.h> defines CTRL. */
+#ifndef CTRL
+#define CTRL(x) (x & ~0140)
+#endif
+#define FILEDES 2
+#define CHK(val, dft) (val<=0 ? dft : val)
static void
-#ifdef __STDC__
-_tuiReset (void)
-#else
-_tuiReset ()
-#endif
+tui_reset (void)
{
struct termio mode;
** reset the teletype mode bits to a sensible state.
** Copied tset.c
*/
-#if ! defined (USG) && defined (TIOCGETC)
+#if defined (TIOCGETC)
struct tchars tbuf;
-#endif /* !USG && TIOCGETC */
+#endif /* TIOCGETC */
#ifdef UCB_NTTY
struct ltchars ltc;
ioctl (FILEDES, TIOCSLTC, <c);
}
#endif /* UCB_NTTY */
-#ifndef USG
#ifdef TIOCGETC
ioctl (FILEDES, TIOCGETC, &tbuf);
tbuf.t_intrc = CHK (tbuf.t_intrc, CTRL ('?'));
#endif /* CBREAK */
| VTDELAY | ALLDELAY);
mode.sg_flags |= XTABS | ECHO | CRMOD | ANYP;
-#else /*USG */
- ioctl (FILEDES, TCGETA, &mode);
- mode.c_cc[VINTR] = CHK (mode.c_cc[VINTR], CTRL ('?'));
- mode.c_cc[VQUIT] = CHK (mode.c_cc[VQUIT], CTRL ('\\'));
- mode.c_cc[VEOF] = CHK (mode.c_cc[VEOF], CTRL ('D'));
-
- mode.c_iflag &= ~(IGNBRK | PARMRK | INPCK | INLCR | IGNCR | IUCLC | IXOFF);
- mode.c_iflag |= (BRKINT | ISTRIP | ICRNL | IXON);
- mode.c_oflag &= ~(OLCUC | OCRNL | ONOCR | ONLRET | OFILL | OFDEL |
- NLDLY | CRDLY | TABDLY | BSDLY | VTDLY | FFDLY);
- mode.c_oflag |= (OPOST | ONLCR);
- mode.c_cflag &= ~(CSIZE | PARODD | CLOCAL);
-#ifndef hp9000s800
- mode.c_cflag |= (CS8 | CREAD);
-#else /*hp9000s800 */
- mode.c_cflag |= (CS8 | CSTOPB | CREAD);
-#endif /* hp9000s800 */
- mode.c_lflag &= ~(XCASE | ECHONL | NOFLSH);
- mode.c_lflag |= (ISIG | ICANON | ECHO | ECHOK);
- ioctl (FILEDES, TCSETAW, &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 */
+ tui_add_win_to_layout (SRC_WIN);
+
+ tui_update_source_windows_with_line (cursal.symtab, line);
+ tui_update_locator_filename (file);
+}
+
+void
+tui_show_assembly (CORE_ADDR addr)
+{
+ tui_add_win_to_layout (DISASSEM_WIN);
+ tui_update_source_windows_with_addr (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;
+}