/* GDB hooks for TUI.

   Copyright (C) 2001-2021 Free Software Foundation, Inc.

   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 3 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, see <http://www.gnu.org/licenses/>.  */

#include "defs.h"
#include "symtab.h"
#include "inferior.h"
#include "command.h"
#include "bfd.h"
#include "symfile.h"
#include "objfiles.h"
#include "target.h"
#include "gdbcore.h"
#include "gdbsupport/event-loop.h"
#include "event-top.h"
#include "frame.h"
#include "breakpoint.h"
#include "ui-out.h"
#include "top.h"
#include "observable.h"
#include "source.h"
#include <unistd.h>
#include <fcntl.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-win.h"
#include "tui/tui-stack.h"
#include "tui/tui-winsource.h"

#include "gdb_curses.h"

static void
tui_new_objfile_hook (struct objfile* objfile)
{
  if (tui_active)
    tui_display_main ();
}

/* Prevent recursion of deprecated_register_changed_hook().  */
static bool tui_refreshing_registers = false;

/* Observer for the register_changed notification.  */

static void
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)
    {
      tui_refreshing_registers = true;
      TUI_DATA_WIN->check_register_values (fi);
      tui_refreshing_registers = false;
    }
}

/* Breakpoint creation hook.
   Update the screen to show the new breakpoint.  */
static void
tui_event_create_breakpoint (struct breakpoint *b)
{
  tui_update_all_breakpoint_info (nullptr);
}

/* Breakpoint deletion hook.
   Refresh the screen to update the breakpoint marks.  */
static void
tui_event_delete_breakpoint (struct breakpoint *b)
{
  tui_update_all_breakpoint_info (b);
}

static void
tui_event_modify_breakpoint (struct breakpoint *b)
{
  tui_update_all_breakpoint_info (nullptr);
}

/* This is set to true if the next window refresh should come from the
   current stack frame.  */

static bool from_stack;

/* This is set to true if the next window refresh should come from the
   current source symtab.  */

static bool from_source_symtab;

/* 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.  */

static void
tui_refresh_frame_and_register_information ()
{
  if (!from_stack && !from_source_symtab)
    return;

  target_terminal::scoped_restore_terminal_state term_state;
  target_terminal::ours_for_output ();

  if (from_stack && has_stack_frames ())
    {
      struct frame_info *fi = get_selected_frame (NULL);

      /* Display the frame position (even if there is no symbols or
	 the PC is not known).  */
      bool frame_info_changed_p = tui_show_frame_info (fi);

      /* Refresh the register window if it's visible.  */
      if (tui_is_window_visible (DATA_WIN)
	  && (frame_info_changed_p || from_stack))
	{
	  tui_refreshing_registers = true;
	  TUI_DATA_WIN->check_register_values (fi);
	  tui_refreshing_registers = false;
	}
    }
  else if (!from_stack)
    {
      /* Make sure that the source window is displayed.  */
      tui_add_win_to_layout (SRC_WIN);

      struct symtab_and_line sal = get_current_source_symtab_and_line ();
      tui_update_source_windows_with_line (sal);
    }
}

/* Dummy callback for deprecated_print_frame_info_listing_hook which is called
   from print_frame_info.  */

static void
tui_dummy_print_frame_info_listing_hook (struct symtab *s,
					 int line,
					 int stopline, 
					 int noerror)
{
}

/* Perform all necessary cleanups regarding our module's inferior data
   that is required after the inferior INF just exited.  */

static void
tui_inferior_exit (struct inferior *inf)
{
  /* Leave the SingleKey mode to make sure the gdb prompt is visible.  */
  tui_set_key_mode (TUI_COMMAND_MODE);
  tui_show_frame_info (0);
  tui_display_main ();
}

/* Observer for the before_prompt notification.  */

static void
tui_before_prompt (const char *current_gdb_prompt)
{
  tui_refresh_frame_and_register_information ();
  from_stack = false;
  from_source_symtab = false;
}

/* Observer for the normal_stop notification.  */

static void
tui_normal_stop (struct bpstats *bs, int print_frame)
{
  from_stack = true;
}

/* Observer for user_selected_context_changed.  */

static void
tui_context_changed (user_selected_what ignore)
{
  from_stack = true;
}

/* Observer for current_source_symtab_and_line_changed.  */

static void
tui_symtab_changed ()
{
  from_source_symtab = 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, "tui-hooks");
  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);
  attach_or_detach (gdb::observers::user_selected_context_changed,
		    tui_context_changed, attach);
  attach_or_detach (gdb::observers::current_source_symtab_and_line_changed,
		    tui_symtab_changed, attach);
}

/* Install the TUI specific hooks.  */
void
tui_install_hooks (void)
{
  /* If this hook is not set to something then print_frame_info will
     assume that the CLI, not the TUI, is active, and will print the frame info
     for us in such a way that we are not prepared to handle.  This hook is
     otherwise effectively obsolete.  */
  deprecated_print_frame_info_listing_hook
    = tui_dummy_print_frame_info_listing_hook;

  /* Install the event hooks.  */
  tui_attach_detach_observers (true);
}

/* Remove the TUI specific hooks.  */
void
tui_remove_hooks (void)
{
  deprecated_print_frame_info_listing_hook = 0;

  /* Remove our observers.  */
  tui_attach_detach_observers (false);
}

void _initialize_tui_hooks ();
void
_initialize_tui_hooks ()
{
  /* Install the permanent hooks.  */
  gdb::observers::new_objfile.attach (tui_new_objfile_hook, "tui-hooks");
}
