1 /* TUI display source/assembly window.
3 Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2006, 2007
4 Free Software Foundation, Inc.
6 Contributed by Hewlett-Packard Company.
8 This file is part of GDB.
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin Street, Fifth Floor,
23 Boston, MA 02110-1301, USA. */
29 #include "breakpoint.h"
34 #include "tui/tui-data.h"
35 #include "tui/tui-stack.h"
36 #include "tui/tui-win.h"
37 #include "tui/tui-wingeneral.h"
38 #include "tui/tui-winsource.h"
39 #include "tui/tui-source.h"
40 #include "tui/tui-disasm.h"
42 #include "gdb_string.h"
43 #include "gdb_curses.h"
44 #include "gdb_assert.h"
46 /* Function to display the "main" routine. */
48 tui_display_main (void)
50 if ((tui_source_windows ())->count > 0)
54 addr = tui_get_begin_asm_address ();
55 if (addr != (CORE_ADDR) 0)
57 struct symtab_and_line sal;
59 tui_update_source_windows_with_addr (addr);
60 sal = find_pc_line (addr, 0);
62 tui_update_locator_filename (sal.symtab->filename);
64 tui_update_locator_filename ("??");
71 /* Function to display source in the source window. This function
72 initializes the horizontal scroll to 0. */
74 tui_update_source_window (struct tui_win_info *win_info, struct symtab *s,
75 struct tui_line_or_address line_or_addr, int noerror)
77 win_info->detail.source_info.horizontal_offset = 0;
78 tui_update_source_window_as_is (win_info, s, line_or_addr, noerror);
84 /* Function to display source in the source/asm window. This function
85 shows the source as specified by the horizontal offset. */
87 tui_update_source_window_as_is (struct tui_win_info *win_info, struct symtab *s,
88 struct tui_line_or_address line_or_addr, int noerror)
92 if (win_info->generic.type == SRC_WIN)
93 ret = tui_set_source_content (s, line_or_addr.u.line_no, noerror);
95 ret = tui_set_disassem_content (line_or_addr.u.addr);
97 if (ret == TUI_FAILURE)
99 tui_clear_source_content (win_info, EMPTY_SOURCE_PROMPT);
100 tui_clear_exec_info_content (win_info);
104 tui_update_breakpoint_info (win_info, 0);
105 tui_show_source_content (win_info);
106 tui_update_exec_info (win_info);
107 if (win_info->generic.type == SRC_WIN)
109 struct symtab_and_line sal;
111 sal.line = line_or_addr.u.line_no +
112 (win_info->generic.content_size - 2);
114 set_current_source_symtab_and_line (&sal);
116 ** If the focus was in the asm win, put it in the src
117 ** win if we don't have a split layout.
119 if (tui_win_with_focus () == TUI_DISASM_WIN &&
120 tui_current_layout () != SRC_DISASSEM_COMMAND)
121 tui_set_win_focus_to (TUI_SRC_WIN);
130 /* Function to ensure that the source and/or disassemly windows
131 reflect the input address. */
133 tui_update_source_windows_with_addr (CORE_ADDR addr)
137 struct symtab_and_line sal;
138 struct tui_line_or_address l;
140 switch (tui_current_layout ())
142 case DISASSEM_COMMAND:
143 case DISASSEM_DATA_COMMAND:
144 tui_show_disassem (addr);
146 case SRC_DISASSEM_COMMAND:
147 tui_show_disassem_and_update_source (addr);
150 sal = find_pc_line (addr, 0);
152 l.u.line_no = sal.line;
153 tui_show_symtab_source (sal.symtab, l, FALSE);
161 for (i = 0; i < (tui_source_windows ())->count; i++)
163 struct tui_win_info *win_info = (tui_source_windows ())->list[i];
165 tui_clear_source_content (win_info, EMPTY_SOURCE_PROMPT);
166 tui_clear_exec_info_content (win_info);
171 /* Function to ensure that the source and/or disassemly windows
172 reflect the input address. */
174 tui_update_source_windows_with_line (struct symtab *s, int line)
177 struct tui_line_or_address l;
179 switch (tui_current_layout ())
181 case DISASSEM_COMMAND:
182 case DISASSEM_DATA_COMMAND:
183 find_line_pc (s, line, &pc);
184 tui_update_source_windows_with_addr (pc);
189 tui_show_symtab_source (s, l, FALSE);
190 if (tui_current_layout () == SRC_DISASSEM_COMMAND)
192 find_line_pc (s, line, &pc);
193 tui_show_disassem (pc);
202 tui_clear_source_content (struct tui_win_info *win_info, int display_prompt)
204 if (win_info != NULL)
208 win_info->generic.content_in_use = FALSE;
209 tui_erase_source_content (win_info, display_prompt);
210 for (i = 0; i < win_info->generic.content_size; i++)
212 struct tui_win_element *element =
213 (struct tui_win_element *) win_info->generic.content[i];
214 element->which_element.source.has_break = FALSE;
215 element->which_element.source.is_exec_point = FALSE;
222 tui_erase_source_content (struct tui_win_info *win_info, int display_prompt)
225 int half_width = (win_info->generic.width - 2) / 2;
227 if (win_info->generic.handle != (WINDOW *) NULL)
229 werase (win_info->generic.handle);
230 tui_check_and_display_highlight_if_needed (win_info);
231 if (display_prompt == EMPTY_SOURCE_PROMPT)
235 if (win_info->generic.type == SRC_WIN)
236 no_src_str = NO_SRC_STRING;
238 no_src_str = NO_DISASSEM_STRING;
239 if (strlen (no_src_str) >= half_width)
242 x_pos = half_width - strlen (no_src_str);
243 mvwaddstr (win_info->generic.handle,
244 (win_info->generic.height / 2),
248 /* elz: Added this function call to set the real contents of
249 the window to what is on the screen, so that later calls
250 to refresh, do display the correct stuff, and not the old
253 tui_set_source_content_nil (win_info, no_src_str);
255 tui_refresh_win (&win_info->generic);
260 /* Redraw the complete line of a source or disassembly window. */
262 tui_show_source_line (struct tui_win_info *win_info, int lineno)
264 struct tui_win_element *line;
267 line = (struct tui_win_element *) win_info->generic.content[lineno - 1];
268 if (line->which_element.source.is_exec_point)
269 wattron (win_info->generic.handle, A_STANDOUT);
271 mvwaddstr (win_info->generic.handle, lineno, 1,
272 line->which_element.source.line);
273 if (line->which_element.source.is_exec_point)
274 wattroff (win_info->generic.handle, A_STANDOUT);
276 /* Clear to end of line but stop before the border. */
277 getyx (win_info->generic.handle, y, x);
278 while (x + 1 < win_info->generic.width)
280 waddch (win_info->generic.handle, ' ');
281 getyx (win_info->generic.handle, y, x);
286 tui_show_source_content (struct tui_win_info *win_info)
288 if (win_info->generic.content_size > 0)
292 for (lineno = 1; lineno <= win_info->generic.content_size; lineno++)
293 tui_show_source_line (win_info, lineno);
296 tui_erase_source_content (win_info, TRUE);
298 tui_check_and_display_highlight_if_needed (win_info);
299 tui_refresh_win (&win_info->generic);
300 win_info->generic.content_in_use = TRUE;
304 /* Scroll the source forward or backward horizontally. */
306 tui_horizontal_source_scroll (struct tui_win_info *win_info,
307 enum tui_scroll_direction direction,
310 if (win_info->generic.content != NULL)
314 struct symtab_and_line cursal = get_current_source_symtab_and_line ();
316 if (cursal.symtab == (struct symtab *) NULL)
317 s = find_pc_symtab (get_frame_pc (get_selected_frame (NULL)));
321 if (direction == LEFT_SCROLL)
322 offset = win_info->detail.source_info.horizontal_offset + num_to_scroll;
326 win_info->detail.source_info.horizontal_offset - num_to_scroll) < 0)
329 win_info->detail.source_info.horizontal_offset = offset;
330 tui_update_source_window_as_is (win_info, s,
331 ((struct tui_win_element *)
332 win_info->generic.content[0])->which_element.source.line_or_addr,
340 /* Set or clear the has_break flag in the line whose line is
344 tui_set_is_exec_point_at (struct tui_line_or_address l, struct tui_win_info *win_info)
348 tui_win_content content = (tui_win_content) win_info->generic.content;
351 while (i < win_info->generic.content_size)
354 struct tui_line_or_address content_loa =
355 content[i]->which_element.source.line_or_addr;
357 gdb_assert (l.loa == LOA_ADDRESS || l.loa == LOA_LINE);
358 gdb_assert (content_loa.loa == LOA_LINE
359 || content_loa.loa == LOA_ADDRESS);
360 if (content_loa.loa == l.loa
361 && ((l.loa == LOA_LINE && content_loa.u.line_no == l.u.line_no)
362 || (content_loa.u.addr == l.u.addr)))
366 if (new_state != content[i]->which_element.source.is_exec_point)
369 content[i]->which_element.source.is_exec_point = new_state;
370 tui_show_source_line (win_info, i + 1);
375 tui_refresh_win (&win_info->generic);
378 /* Update the execution windows to show the active breakpoints.
379 This is called whenever a breakpoint is inserted, removed or
380 has its state changed. */
382 tui_update_all_breakpoint_info (void)
384 struct tui_list *list = tui_source_windows ();
387 for (i = 0; i < list->count; i++)
389 struct tui_win_info *win = list->list[i];
391 if (tui_update_breakpoint_info (win, FALSE))
393 tui_update_exec_info (win);
399 /* Scan the source window and the breakpoints to update the has_break
400 information for each line.
402 Returns 1 if something changed and the execution window must be
406 tui_update_breakpoint_info (struct tui_win_info *win, int current_only)
409 int need_refresh = 0;
410 struct tui_source_info *src = &win->detail.source_info;
412 for (i = 0; i < win->generic.content_size; i++)
414 struct breakpoint *bp;
415 extern struct breakpoint *breakpoint_chain;
417 struct tui_source_element *line;
419 line = &((struct tui_win_element *) win->generic.content[i])->which_element.source;
420 if (current_only && !line->is_exec_point)
423 /* Scan each breakpoint to see if the current line has something to
424 do with it. Identify enable/disabled breakpoints as well as
425 those that we already hit. */
427 for (bp = breakpoint_chain;
428 bp != (struct breakpoint *) NULL;
431 gdb_assert (line->line_or_addr.loa == LOA_LINE
432 || line->line_or_addr.loa == LOA_ADDRESS);
433 if ((win == TUI_SRC_WIN
435 && (strcmp (src->filename, bp->source_file) == 0)
436 && line->line_or_addr.loa == LOA_LINE
437 && bp->line_number == line->line_or_addr.u.line_no)
438 || (win == TUI_DISASM_WIN
439 && line->line_or_addr.loa == LOA_ADDRESS
440 && bp->loc->address == line->line_or_addr.u.addr))
442 if (bp->enable_state == bp_disabled)
443 mode |= TUI_BP_DISABLED;
445 mode |= TUI_BP_ENABLED;
449 mode |= TUI_BP_CONDITIONAL;
450 if (bp->type == bp_hardware_breakpoint)
451 mode |= TUI_BP_HARDWARE;
454 if (line->has_break != mode)
456 line->has_break = mode;
464 /* Function to initialize the content of the execution info window,
465 based upon the input window which is either the source or
466 disassembly window. */
468 tui_set_exec_info_content (struct tui_win_info *win_info)
470 enum tui_status ret = TUI_SUCCESS;
472 if (win_info->detail.source_info.execution_info != (struct tui_gen_win_info *) NULL)
474 struct tui_gen_win_info *exec_info_ptr = win_info->detail.source_info.execution_info;
476 if (exec_info_ptr->content == NULL)
477 exec_info_ptr->content =
478 (void **) tui_alloc_content (win_info->generic.height,
479 exec_info_ptr->type);
480 if (exec_info_ptr->content != NULL)
484 tui_update_breakpoint_info (win_info, 1);
485 for (i = 0; i < win_info->generic.content_size; i++)
487 struct tui_win_element *element;
488 struct tui_win_element *src_element;
491 element = (struct tui_win_element *) exec_info_ptr->content[i];
492 src_element = (struct tui_win_element *) win_info->generic.content[i];
494 memset(element->which_element.simple_string, ' ',
495 sizeof(element->which_element.simple_string));
496 element->which_element.simple_string[TUI_EXECINFO_SIZE - 1] = 0;
498 /* Now update the exec info content based upon the state
499 of each line as indicated by the source content. */
500 mode = src_element->which_element.source.has_break;
501 if (mode & TUI_BP_HIT)
502 element->which_element.simple_string[TUI_BP_HIT_POS] =
503 (mode & TUI_BP_HARDWARE) ? 'H' : 'B';
504 else if (mode & (TUI_BP_ENABLED | TUI_BP_DISABLED))
505 element->which_element.simple_string[TUI_BP_HIT_POS] =
506 (mode & TUI_BP_HARDWARE) ? 'h' : 'b';
508 if (mode & TUI_BP_ENABLED)
509 element->which_element.simple_string[TUI_BP_BREAK_POS] = '+';
510 else if (mode & TUI_BP_DISABLED)
511 element->which_element.simple_string[TUI_BP_BREAK_POS] = '-';
513 if (src_element->which_element.source.is_exec_point)
514 element->which_element.simple_string[TUI_EXEC_POS] = '>';
516 exec_info_ptr->content_size = win_info->generic.content_size;
527 tui_show_exec_info_content (struct tui_win_info *win_info)
529 struct tui_gen_win_info *exec_info = win_info->detail.source_info.execution_info;
532 werase (exec_info->handle);
533 tui_refresh_win (exec_info);
534 for (cur_line = 1; (cur_line <= exec_info->content_size); cur_line++)
535 mvwaddstr (exec_info->handle,
538 ((struct tui_win_element *)
539 exec_info->content[cur_line - 1])->which_element.simple_string);
540 tui_refresh_win (exec_info);
541 exec_info->content_in_use = TRUE;
546 tui_erase_exec_info_content (struct tui_win_info *win_info)
548 struct tui_gen_win_info *exec_info = win_info->detail.source_info.execution_info;
550 werase (exec_info->handle);
551 tui_refresh_win (exec_info);
555 tui_clear_exec_info_content (struct tui_win_info *win_info)
557 win_info->detail.source_info.execution_info->content_in_use = FALSE;
558 tui_erase_exec_info_content (win_info);
563 /* Function to update the execution info window. */
565 tui_update_exec_info (struct tui_win_info *win_info)
567 tui_set_exec_info_content (win_info);
568 tui_show_exec_info_content (win_info);
572 tui_alloc_source_buffer (struct tui_win_info *win_info)
575 int i, line_width, max_lines;
577 max_lines = win_info->generic.height; /* Less the highlight box. */
578 line_width = win_info->generic.width - 1;
580 * Allocate the buffer for the source lines. Do this only once
581 * since they will be re-used for all source displays. The only
582 * other time this will be done is when a window's size changes.
584 if (win_info->generic.content == NULL)
586 src_line_buf = (char *)
587 xmalloc ((max_lines * line_width) * sizeof (char));
588 if (src_line_buf == (char *) NULL)
590 fputs_unfiltered ("Unable to Allocate Memory for Source or Disassembly Display.\n",
594 /* Allocate the content list. */
595 if ((win_info->generic.content =
596 (void **) tui_alloc_content (max_lines, SRC_WIN)) == NULL)
598 xfree (src_line_buf);
599 fputs_unfiltered ("Unable to Allocate Memory for Source or Disassembly Display.\n",
603 for (i = 0; i < max_lines; i++)
604 ((struct tui_win_element *)
605 win_info->generic.content[i])->which_element.source.line =
606 src_line_buf + (line_width * i);
613 /* Answer whether the a particular line number or address is displayed
614 in the current source window. */
616 tui_line_is_displayed (int line, struct tui_win_info *win_info,
619 int is_displayed = FALSE;
623 threshold = SCROLL_THRESHOLD;
627 while (i < win_info->generic.content_size - threshold && !is_displayed)
629 is_displayed = (((struct tui_win_element *)
630 win_info->generic.content[i])->which_element.source.line_or_addr.loa
632 && (((struct tui_win_element *)
633 win_info->generic.content[i])->which_element.source.line_or_addr.u.line_no
642 /* Answer whether the a particular line number or address is displayed
643 in the current source window. */
645 tui_addr_is_displayed (CORE_ADDR addr, struct tui_win_info *win_info,
648 int is_displayed = FALSE;
652 threshold = SCROLL_THRESHOLD;
656 while (i < win_info->generic.content_size - threshold && !is_displayed)
658 is_displayed = (((struct tui_win_element *)
659 win_info->generic.content[i])->which_element.source.line_or_addr.loa
661 && (((struct tui_win_element *)
662 win_info->generic.content[i])->which_element.source.line_or_addr.u.addr
671 /*****************************************
672 ** STATIC LOCAL FUNCTIONS **
673 ******************************************/