/* GDB hooks for TUI.
- Copyright (C) 2001-2015 Free Software Foundation, Inc.
+ Copyright (C) 2001-2019 Free Software Foundation, Inc.
This file is part of GDB.
#include "breakpoint.h"
#include "ui-out.h"
#include "top.h"
-#include "observer.h"
+#include "observable.h"
+#include "source.h"
#include <unistd.h>
#include <fcntl.h>
#include "tui/tui-regs.h"
#include "tui/tui-win.h"
#include "tui/tui-stack.h"
-#include "tui/tui-windata.h"
#include "tui/tui-winsource.h"
#include "gdb_curses.h"
-/* 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"
-
-int tui_target_has_run = 0;
-
static void
tui_new_objfile_hook (struct objfile* objfile)
{
/* Prevent recursion of deprecated_register_changed_hook(). */
static int tui_refreshing_registers = 0;
+/* Observer for the register_changed notification. */
+
static void
-tui_register_changed_hook (int regno)
+tui_register_changed (struct frame_info *frame, int regno)
{
struct frame_info *fi;
+ if (!tui_is_window_visible (DATA_WIN))
+ return;
+
+ /* The frame of the register that was changed may differ from the selected
+ frame, but we only want to show the register values of the selected frame.
+ And even if the frames differ a register change made in one can still show
+ up in the other. So we always use the selected frame here, and ignore
+ FRAME. */
fi = get_selected_frame (NULL);
if (tui_refreshing_registers == 0)
{
tui_refreshing_registers = 1;
- tui_check_data_values (fi);
+ TUI_DATA_WIN->check_register_values (fi);
tui_refreshing_registers = 0;
}
}
static void
tui_event_create_breakpoint (struct breakpoint *b)
{
- tui_update_all_breakpoint_info ();
+ tui_update_all_breakpoint_info (nullptr);
}
/* Breakpoint deletion hook.
static void
tui_event_delete_breakpoint (struct breakpoint *b)
{
- tui_update_all_breakpoint_info ();
+ tui_update_all_breakpoint_info (b);
}
static void
tui_event_modify_breakpoint (struct breakpoint *b)
{
- tui_update_all_breakpoint_info ();
-}
-
-/* Called when a command is about to proceed the inferior. */
-
-static void
-tui_about_to_proceed (void)
-{
- /* Leave tui mode (optional). */
-#if 0
- if (tui_active)
- {
- target_terminal_ours ();
- endwin ();
- target_terminal_inferior ();
- }
-#endif
- tui_target_has_run = 1;
+ tui_update_all_breakpoint_info (nullptr);
}
/* Refresh TUI's frame and register information. This is a hook intended to be
used to update the screen after potential frame and register changes.
- REGISTERS_TOO_P controls whether to refresh our register information. */
+ REGISTERS_TOO_P controls whether to refresh our register information even
+ if frame information hasn't changed. */
static void
-tui_refresh_frame_and_register_information (int registers_too_p)
+tui_refresh_frame_and_register_information (bool registers_too_p)
{
struct frame_info *fi;
CORE_ADDR pc;
- struct cleanup *old_chain;
+ int frame_info_changed_p;
if (!has_stack_frames ())
return;
- old_chain = make_cleanup_restore_target_terminal ();
- target_terminal_ours_for_output ();
+ target_terminal::scoped_restore_terminal_state term_state;
+ target_terminal::ours_for_output ();
fi = get_selected_frame (NULL);
/* Ensure that symbols for this frame are read in. Also, determine
/* Display the frame position (even if there is no symbols or the PC
is not known). */
- tui_show_frame_info (fi);
+ frame_info_changed_p = tui_show_frame_info (fi);
/* Refresh the register window if it's visible. */
- if (tui_is_window_visible (DATA_WIN) && registers_too_p)
+ if (tui_is_window_visible (DATA_WIN)
+ && (frame_info_changed_p || registers_too_p))
{
tui_refreshing_registers = 1;
- tui_check_data_values (fi);
+ TUI_DATA_WIN->check_register_values (fi);
tui_refreshing_registers = 0;
}
-
- do_cleanups (old_chain);
}
/* Dummy callback for deprecated_print_frame_info_listing_hook which is called
{
/* This refresh is intended to catch changes to the selected frame following
a call to "up", "down" or "frame". As such we don't necessarily want to
- refresh registers here as they could not have changed. Registers will be
- refreshed after a normal stop or by our tui_register_changed_hook. */
- tui_refresh_frame_and_register_information (/*registers_too_p=*/0);
+ refresh registers here unless the frame actually changed by one of these
+ commands. Registers will otherwise be refreshed after a normal stop or by
+ our tui_register_changed_hook. */
+ tui_refresh_frame_and_register_information (/*registers_too_p=*/false);
}
/* Observer for the normal_stop notification. */
{
/* This refresh is intended to catch changes to the selected frame and to
registers following a normal stop. */
- tui_refresh_frame_and_register_information (/*registers_too_p=*/1);
+ tui_refresh_frame_and_register_information (/*registers_too_p=*/true);
+}
+
+/* Token associated with observers registered while TUI hooks are
+ installed. */
+static const gdb::observers::token tui_observers_token {};
+
+/* Attach or detach a single observer, according to ATTACH. */
+
+template<typename T>
+static void
+attach_or_detach (T &observable, typename T::func_type func, bool attach)
+{
+ if (attach)
+ observable.attach (func, tui_observers_token);
+ else
+ observable.detach (tui_observers_token);
}
-/* Observers created when installing TUI hooks. */
-static struct observer *tui_bp_created_observer;
-static struct observer *tui_bp_deleted_observer;
-static struct observer *tui_bp_modified_observer;
-static struct observer *tui_inferior_exit_observer;
-static struct observer *tui_about_to_proceed_observer;
-static struct observer *tui_before_prompt_observer;
-static struct observer *tui_normal_stop_observer;
+/* Attach or detach TUI observers, according to ATTACH. */
+
+static void
+tui_attach_detach_observers (bool attach)
+{
+ attach_or_detach (gdb::observers::breakpoint_created,
+ tui_event_create_breakpoint, attach);
+ attach_or_detach (gdb::observers::breakpoint_deleted,
+ tui_event_delete_breakpoint, attach);
+ attach_or_detach (gdb::observers::breakpoint_modified,
+ tui_event_modify_breakpoint, attach);
+ attach_or_detach (gdb::observers::inferior_exit,
+ tui_inferior_exit, attach);
+ attach_or_detach (gdb::observers::before_prompt,
+ tui_before_prompt, attach);
+ attach_or_detach (gdb::observers::normal_stop,
+ tui_normal_stop, attach);
+ attach_or_detach (gdb::observers::register_changed,
+ tui_register_changed, attach);
+}
/* Install the TUI specific hooks. */
void
= tui_dummy_print_frame_info_listing_hook;
/* Install the event hooks. */
- tui_bp_created_observer
- = observer_attach_breakpoint_created (tui_event_create_breakpoint);
- tui_bp_deleted_observer
- = observer_attach_breakpoint_deleted (tui_event_delete_breakpoint);
- tui_bp_modified_observer
- = observer_attach_breakpoint_modified (tui_event_modify_breakpoint);
- tui_inferior_exit_observer
- = observer_attach_inferior_exit (tui_inferior_exit);
- tui_about_to_proceed_observer
- = observer_attach_about_to_proceed (tui_about_to_proceed);
- tui_before_prompt_observer
- = observer_attach_before_prompt (tui_before_prompt);
- tui_normal_stop_observer
- = observer_attach_normal_stop (tui_normal_stop);
-
- deprecated_register_changed_hook = tui_register_changed_hook;
+ tui_attach_detach_observers (true);
}
/* Remove the TUI specific hooks. */
tui_remove_hooks (void)
{
deprecated_print_frame_info_listing_hook = 0;
- deprecated_query_hook = 0;
- deprecated_register_changed_hook = 0;
/* Remove our observers. */
- observer_detach_breakpoint_created (tui_bp_created_observer);
- tui_bp_created_observer = NULL;
- observer_detach_breakpoint_deleted (tui_bp_deleted_observer);
- tui_bp_deleted_observer = NULL;
- observer_detach_breakpoint_modified (tui_bp_modified_observer);
- tui_bp_modified_observer = NULL;
- observer_detach_inferior_exit (tui_inferior_exit_observer);
- tui_inferior_exit_observer = NULL;
- observer_detach_about_to_proceed (tui_about_to_proceed_observer);
- tui_about_to_proceed_observer = NULL;
- observer_detach_before_prompt (tui_before_prompt_observer);
- tui_before_prompt_observer = NULL;
- observer_detach_normal_stop (tui_normal_stop_observer);
- tui_normal_stop_observer = NULL;
+ tui_attach_detach_observers (false);
}
-void _initialize_tui_hooks (void);
-
void
_initialize_tui_hooks (void)
{
/* Install the permanent hooks. */
- observer_attach_new_objfile (tui_new_objfile_hook);
+ gdb::observers::new_objfile.attach (tui_new_objfile_hook);
}