1130803Smarcel/* GDB hooks for TUI.
2130803Smarcel
3130803Smarcel   Copyright 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
4130803Smarcel
5130803Smarcel   This file is part of GDB.
6130803Smarcel
7130803Smarcel   This program is free software; you can redistribute it and/or modify
8130803Smarcel   it under the terms of the GNU General Public License as published by
9130803Smarcel   the Free Software Foundation; either version 2 of the License, or
10130803Smarcel   (at your option) any later version.
11130803Smarcel
12130803Smarcel   This program is distributed in the hope that it will be useful,
13130803Smarcel   but WITHOUT ANY WARRANTY; without even the implied warranty of
14130803Smarcel   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15130803Smarcel   GNU General Public License for more details.
16130803Smarcel
17130803Smarcel   You should have received a copy of the GNU General Public License
18130803Smarcel   along with this program; if not, write to the Free Software
19130803Smarcel   Foundation, Inc., 59 Temple Place - Suite 330,
20130803Smarcel   Boston, MA 02111-1307, USA.  */
21130803Smarcel
22130803Smarcel#include "defs.h"
23130803Smarcel#include "symtab.h"
24130803Smarcel#include "inferior.h"
25130803Smarcel#include "command.h"
26130803Smarcel#include "bfd.h"
27130803Smarcel#include "symfile.h"
28130803Smarcel#include "objfiles.h"
29130803Smarcel#include "target.h"
30130803Smarcel#include "gdbcore.h"
31130803Smarcel#include "event-loop.h"
32130803Smarcel#include "event-top.h"
33130803Smarcel#include "frame.h"
34130803Smarcel#include "breakpoint.h"
35130803Smarcel#include "gdb-events.h"
36130803Smarcel#include "ui-out.h"
37130803Smarcel#include "top.h"
38130803Smarcel#include "readline/readline.h"
39130803Smarcel#include <unistd.h>
40130803Smarcel#include <fcntl.h>
41130803Smarcel
42130803Smarcel#include "tui/tui.h"
43130803Smarcel#include "tui/tui-hooks.h"
44130803Smarcel#include "tui/tui-data.h"
45130803Smarcel#include "tui/tui-layout.h"
46130803Smarcel#include "tui/tui-io.h"
47130803Smarcel#include "tui/tui-regs.h"
48130803Smarcel#include "tui/tui-win.h"
49130803Smarcel#include "tui/tui-stack.h"
50130803Smarcel#include "tui/tui-windata.h"
51130803Smarcel#include "tui/tui-winsource.h"
52130803Smarcel
53130803Smarcel#include "gdb_curses.h"
54130803Smarcel
55130803Smarcelint tui_target_has_run = 0;
56130803Smarcel
57130803Smarcelstatic void (* tui_target_new_objfile_chain) (struct objfile*);
58130803Smarcel
59130803Smarcelstatic void
60130803Smarceltui_new_objfile_hook (struct objfile* objfile)
61130803Smarcel{
62130803Smarcel  if (tui_active)
63130803Smarcel    tui_display_main ();
64130803Smarcel
65130803Smarcel  if (tui_target_new_objfile_chain)
66130803Smarcel    tui_target_new_objfile_chain (objfile);
67130803Smarcel}
68130803Smarcel
69130803Smarcelstatic int
70130803Smarceltui_query_hook (const char * msg, va_list argp)
71130803Smarcel{
72130803Smarcel  int retval;
73130803Smarcel  int ans2;
74130803Smarcel  int answer;
75130803Smarcel
76130803Smarcel  /* Automatically answer "yes" if input is not from a terminal.  */
77130803Smarcel  if (!input_from_terminal_p ())
78130803Smarcel    return 1;
79130803Smarcel
80130803Smarcel  echo ();
81130803Smarcel  while (1)
82130803Smarcel    {
83130803Smarcel      wrap_here ("");		/* Flush any buffered output */
84130803Smarcel      gdb_flush (gdb_stdout);
85130803Smarcel
86130803Smarcel      vfprintf_filtered (gdb_stdout, msg, argp);
87130803Smarcel      printf_filtered ("(y or n) ");
88130803Smarcel
89130803Smarcel      wrap_here ("");
90130803Smarcel      gdb_flush (gdb_stdout);
91130803Smarcel
92130803Smarcel      answer = tui_getc (stdin);
93130803Smarcel      clearerr (stdin);		/* in case of C-d */
94130803Smarcel      if (answer == EOF)	/* C-d */
95130803Smarcel	{
96130803Smarcel	  retval = 1;
97130803Smarcel	  break;
98130803Smarcel	}
99130803Smarcel      /* Eat rest of input line, to EOF or newline */
100130803Smarcel      if (answer != '\n')
101130803Smarcel	do
102130803Smarcel	  {
103130803Smarcel            ans2 = tui_getc (stdin);
104130803Smarcel	    clearerr (stdin);
105130803Smarcel	  }
106130803Smarcel	while (ans2 != EOF && ans2 != '\n' && ans2 != '\r');
107130803Smarcel
108130803Smarcel      if (answer >= 'a')
109130803Smarcel	answer -= 040;
110130803Smarcel      if (answer == 'Y')
111130803Smarcel	{
112130803Smarcel	  retval = 1;
113130803Smarcel	  break;
114130803Smarcel	}
115130803Smarcel      if (answer == 'N')
116130803Smarcel	{
117130803Smarcel	  retval = 0;
118130803Smarcel	  break;
119130803Smarcel	}
120130803Smarcel      printf_filtered ("Please answer y or n.\n");
121130803Smarcel    }
122130803Smarcel  noecho ();
123130803Smarcel  return retval;
124130803Smarcel}
125130803Smarcel
126130803Smarcel/* Prevent recursion of registers_changed_hook().  */
127130803Smarcelstatic int tui_refreshing_registers = 0;
128130803Smarcel
129130803Smarcelstatic void
130130803Smarceltui_registers_changed_hook (void)
131130803Smarcel{
132130803Smarcel  struct frame_info *fi;
133130803Smarcel
134130803Smarcel  fi = deprecated_selected_frame;
135130803Smarcel  if (fi && tui_refreshing_registers == 0)
136130803Smarcel    {
137130803Smarcel      tui_refreshing_registers = 1;
138130803Smarcel#if 0
139130803Smarcel      tui_check_data_values (fi);
140130803Smarcel#endif
141130803Smarcel      tui_refreshing_registers = 0;
142130803Smarcel    }
143130803Smarcel}
144130803Smarcel
145130803Smarcelstatic void
146130803Smarceltui_register_changed_hook (int regno)
147130803Smarcel{
148130803Smarcel  struct frame_info *fi;
149130803Smarcel
150130803Smarcel  fi = deprecated_selected_frame;
151130803Smarcel  if (fi && tui_refreshing_registers == 0)
152130803Smarcel    {
153130803Smarcel      tui_refreshing_registers = 1;
154130803Smarcel      tui_check_data_values (fi);
155130803Smarcel      tui_refreshing_registers = 0;
156130803Smarcel    }
157130803Smarcel}
158130803Smarcel
159130803Smarcel/* Breakpoint creation hook.
160130803Smarcel   Update the screen to show the new breakpoint.  */
161130803Smarcelstatic void
162130803Smarceltui_event_create_breakpoint (int number)
163130803Smarcel{
164130803Smarcel  tui_update_all_breakpoint_info ();
165130803Smarcel}
166130803Smarcel
167130803Smarcel/* Breakpoint deletion hook.
168130803Smarcel   Refresh the screen to update the breakpoint marks.  */
169130803Smarcelstatic void
170130803Smarceltui_event_delete_breakpoint (int number)
171130803Smarcel{
172130803Smarcel  tui_update_all_breakpoint_info ();
173130803Smarcel}
174130803Smarcel
175130803Smarcelstatic void
176130803Smarceltui_event_modify_breakpoint (int number)
177130803Smarcel{
178130803Smarcel  tui_update_all_breakpoint_info ();
179130803Smarcel}
180130803Smarcel
181130803Smarcelstatic void
182130803Smarceltui_event_default (int number)
183130803Smarcel{
184130803Smarcel  ;
185130803Smarcel}
186130803Smarcel
187130803Smarcelstatic struct gdb_events *tui_old_event_hooks;
188130803Smarcel
189130803Smarcelstatic struct gdb_events tui_event_hooks =
190130803Smarcel{
191130803Smarcel  tui_event_create_breakpoint,
192130803Smarcel  tui_event_delete_breakpoint,
193130803Smarcel  tui_event_modify_breakpoint,
194130803Smarcel  tui_event_default,
195130803Smarcel  tui_event_default,
196130803Smarcel  tui_event_default
197130803Smarcel};
198130803Smarcel
199130803Smarcel/* Called when going to wait for the target.
200130803Smarcel   Leave curses mode and setup program mode.  */
201130803Smarcelstatic ptid_t
202130803Smarceltui_target_wait_hook (ptid_t pid, struct target_waitstatus *status)
203130803Smarcel{
204130803Smarcel  ptid_t res;
205130803Smarcel
206130803Smarcel  /* Leave tui mode (optional).  */
207130803Smarcel#if 0
208130803Smarcel  if (tui_active)
209130803Smarcel    {
210130803Smarcel      target_terminal_ours ();
211130803Smarcel      endwin ();
212130803Smarcel      target_terminal_inferior ();
213130803Smarcel    }
214130803Smarcel#endif
215130803Smarcel  tui_target_has_run = 1;
216130803Smarcel  res = target_wait (pid, status);
217130803Smarcel
218130803Smarcel  if (tui_active)
219130803Smarcel    {
220130803Smarcel      /* TODO: need to refresh (optional).  */
221130803Smarcel    }
222130803Smarcel  return res;
223130803Smarcel}
224130803Smarcel
225130803Smarcel/* The selected frame has changed.  This is happens after a target
226130803Smarcel   stop or when the user explicitly changes the frame (up/down/thread/...).  */
227130803Smarcelstatic void
228130803Smarceltui_selected_frame_level_changed_hook (int level)
229130803Smarcel{
230130803Smarcel  struct frame_info *fi;
231130803Smarcel
232130803Smarcel  fi = deprecated_selected_frame;
233130803Smarcel  /* Ensure that symbols for this frame are read in.  Also, determine the
234130803Smarcel     source language of this frame, and switch to it if desired.  */
235130803Smarcel  if (fi)
236130803Smarcel    {
237130803Smarcel      struct symtab *s;
238130803Smarcel
239130803Smarcel      s = find_pc_symtab (get_frame_pc (fi));
240130803Smarcel      /* elz: this if here fixes the problem with the pc not being displayed
241130803Smarcel         in the tui asm layout, with no debug symbols. The value of s
242130803Smarcel         would be 0 here, and select_source_symtab would abort the
243130803Smarcel         command by calling the 'error' function */
244130803Smarcel      if (s)
245130803Smarcel        select_source_symtab (s);
246130803Smarcel
247130803Smarcel      /* Display the frame position (even if there is no symbols).  */
248130803Smarcel      tui_show_frame_info (fi);
249130803Smarcel
250130803Smarcel      /* Refresh the register window if it's visible.  */
251130803Smarcel      if (tui_is_window_visible (DATA_WIN))
252130803Smarcel        {
253130803Smarcel          tui_refreshing_registers = 1;
254130803Smarcel          tui_check_data_values (fi);
255130803Smarcel          tui_refreshing_registers = 0;
256130803Smarcel        }
257130803Smarcel    }
258130803Smarcel}
259130803Smarcel
260130803Smarcel/* Called from print_frame_info to list the line we stopped in.  */
261130803Smarcelstatic void
262130803Smarceltui_print_frame_info_listing_hook (struct symtab *s, int line,
263130803Smarcel                                   int stopline, int noerror)
264130803Smarcel{
265130803Smarcel  select_source_symtab (s);
266130803Smarcel  tui_show_frame_info (deprecated_selected_frame);
267130803Smarcel}
268130803Smarcel
269130803Smarcel/* Called when the target process died or is detached.
270130803Smarcel   Update the status line.  */
271130803Smarcelstatic void
272130803Smarceltui_detach_hook (void)
273130803Smarcel{
274130803Smarcel  tui_show_frame_info (0);
275130803Smarcel  tui_display_main ();
276130803Smarcel}
277130803Smarcel
278130803Smarcel/* Install the TUI specific hooks.  */
279130803Smarcelvoid
280130803Smarceltui_install_hooks (void)
281130803Smarcel{
282130803Smarcel  target_wait_hook = tui_target_wait_hook;
283130803Smarcel  selected_frame_level_changed_hook = tui_selected_frame_level_changed_hook;
284130803Smarcel  print_frame_info_listing_hook = tui_print_frame_info_listing_hook;
285130803Smarcel
286130803Smarcel  query_hook = tui_query_hook;
287130803Smarcel
288130803Smarcel  /* Install the event hooks.  */
289130803Smarcel  tui_old_event_hooks = set_gdb_event_hooks (&tui_event_hooks);
290130803Smarcel
291130803Smarcel  registers_changed_hook = tui_registers_changed_hook;
292130803Smarcel  register_changed_hook = tui_register_changed_hook;
293130803Smarcel  detach_hook = tui_detach_hook;
294130803Smarcel}
295130803Smarcel
296130803Smarcel/* Remove the TUI specific hooks.  */
297130803Smarcelvoid
298130803Smarceltui_remove_hooks (void)
299130803Smarcel{
300130803Smarcel  target_wait_hook = 0;
301130803Smarcel  selected_frame_level_changed_hook = 0;
302130803Smarcel  print_frame_info_listing_hook = 0;
303130803Smarcel  query_hook = 0;
304130803Smarcel  registers_changed_hook = 0;
305130803Smarcel  register_changed_hook = 0;
306130803Smarcel  detach_hook = 0;
307130803Smarcel
308130803Smarcel  /* Restore the previous event hooks.  */
309130803Smarcel  set_gdb_event_hooks (tui_old_event_hooks);
310130803Smarcel}
311130803Smarcel
312130803Smarcelvoid _initialize_tui_hooks (void);
313130803Smarcel
314130803Smarcelvoid
315130803Smarcel_initialize_tui_hooks (void)
316130803Smarcel{
317130803Smarcel  /* Install the permanent hooks.  */
318130803Smarcel  tui_target_new_objfile_chain = target_new_objfile_hook;
319130803Smarcel  target_new_objfile_hook = tui_new_objfile_hook;
320130803Smarcel}
321