+/* Observer for the before_prompt notification. */
+
+static void
+tui_before_prompt (const char *current_gdb_prompt)
+{
+ /* 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 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=*/0);
+}
+
+/* Observer for the normal_stop notification. */
+
+static void
+tui_normal_stop (struct bpstats *bs, int print_frame)
+{
+ /* 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);
+}
+
+/* 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);
+}
+
+/* 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);
+}