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
,
76 struct tui_line_or_address line_or_addr
,
79 win_info
->detail
.source_info
.horizontal_offset
= 0;
80 tui_update_source_window_as_is (win_info
, s
, line_or_addr
, noerror
);
86 /* Function to display source in the source/asm window. This function
87 shows the source as specified by the horizontal offset. */
89 tui_update_source_window_as_is (struct tui_win_info
*win_info
,
91 struct tui_line_or_address line_or_addr
,
96 if (win_info
->generic
.type
== SRC_WIN
)
97 ret
= tui_set_source_content (s
, line_or_addr
.u
.line_no
, noerror
);
99 ret
= tui_set_disassem_content (line_or_addr
.u
.addr
);
101 if (ret
== TUI_FAILURE
)
103 tui_clear_source_content (win_info
, EMPTY_SOURCE_PROMPT
);
104 tui_clear_exec_info_content (win_info
);
108 tui_update_breakpoint_info (win_info
, 0);
109 tui_show_source_content (win_info
);
110 tui_update_exec_info (win_info
);
111 if (win_info
->generic
.type
== SRC_WIN
)
113 struct symtab_and_line sal
;
115 sal
.line
= line_or_addr
.u
.line_no
+
116 (win_info
->generic
.content_size
- 2);
118 set_current_source_symtab_and_line (&sal
);
119 /* If the focus was in the asm win, put it in the src win if
120 we don't have a split layout. */
121 if (tui_win_with_focus () == TUI_DISASM_WIN
122 && tui_current_layout () != SRC_DISASSEM_COMMAND
)
123 tui_set_win_focus_to (TUI_SRC_WIN
);
132 /* Function to ensure that the source and/or disassemly windows
133 reflect the input address. */
135 tui_update_source_windows_with_addr (CORE_ADDR addr
)
139 struct symtab_and_line sal
;
140 struct tui_line_or_address l
;
142 switch (tui_current_layout ())
144 case DISASSEM_COMMAND
:
145 case DISASSEM_DATA_COMMAND
:
146 tui_show_disassem (addr
);
148 case SRC_DISASSEM_COMMAND
:
149 tui_show_disassem_and_update_source (addr
);
152 sal
= find_pc_line (addr
, 0);
154 l
.u
.line_no
= sal
.line
;
155 tui_show_symtab_source (sal
.symtab
, l
, FALSE
);
163 for (i
= 0; i
< (tui_source_windows ())->count
; i
++)
165 struct tui_win_info
*win_info
= (tui_source_windows ())->list
[i
];
167 tui_clear_source_content (win_info
, EMPTY_SOURCE_PROMPT
);
168 tui_clear_exec_info_content (win_info
);
173 /* Function to ensure that the source and/or disassemly windows
174 reflect the input address. */
176 tui_update_source_windows_with_line (struct symtab
*s
, int line
)
179 struct tui_line_or_address l
;
181 switch (tui_current_layout ())
183 case DISASSEM_COMMAND
:
184 case DISASSEM_DATA_COMMAND
:
185 find_line_pc (s
, line
, &pc
);
186 tui_update_source_windows_with_addr (pc
);
191 tui_show_symtab_source (s
, l
, FALSE
);
192 if (tui_current_layout () == SRC_DISASSEM_COMMAND
)
194 find_line_pc (s
, line
, &pc
);
195 tui_show_disassem (pc
);
204 tui_clear_source_content (struct tui_win_info
*win_info
,
207 if (win_info
!= NULL
)
211 win_info
->generic
.content_in_use
= FALSE
;
212 tui_erase_source_content (win_info
, display_prompt
);
213 for (i
= 0; i
< win_info
->generic
.content_size
; i
++)
215 struct tui_win_element
*element
=
216 (struct tui_win_element
*) win_info
->generic
.content
[i
];
217 element
->which_element
.source
.has_break
= FALSE
;
218 element
->which_element
.source
.is_exec_point
= FALSE
;
225 tui_erase_source_content (struct tui_win_info
*win_info
,
229 int half_width
= (win_info
->generic
.width
- 2) / 2;
231 if (win_info
->generic
.handle
!= (WINDOW
*) NULL
)
233 werase (win_info
->generic
.handle
);
234 tui_check_and_display_highlight_if_needed (win_info
);
235 if (display_prompt
== EMPTY_SOURCE_PROMPT
)
239 if (win_info
->generic
.type
== SRC_WIN
)
240 no_src_str
= NO_SRC_STRING
;
242 no_src_str
= NO_DISASSEM_STRING
;
243 if (strlen (no_src_str
) >= half_width
)
246 x_pos
= half_width
- strlen (no_src_str
);
247 mvwaddstr (win_info
->generic
.handle
,
248 (win_info
->generic
.height
/ 2),
252 /* elz: Added this function call to set the real contents of
253 the window to what is on the screen, so that later calls
254 to refresh, do display the correct stuff, and not the old
257 tui_set_source_content_nil (win_info
, no_src_str
);
259 tui_refresh_win (&win_info
->generic
);
264 /* Redraw the complete line of a source or disassembly window. */
266 tui_show_source_line (struct tui_win_info
*win_info
, int lineno
)
268 struct tui_win_element
*line
;
271 line
= (struct tui_win_element
*) win_info
->generic
.content
[lineno
- 1];
272 if (line
->which_element
.source
.is_exec_point
)
273 wattron (win_info
->generic
.handle
, A_STANDOUT
);
275 mvwaddstr (win_info
->generic
.handle
, lineno
, 1,
276 line
->which_element
.source
.line
);
277 if (line
->which_element
.source
.is_exec_point
)
278 wattroff (win_info
->generic
.handle
, A_STANDOUT
);
280 /* Clear to end of line but stop before the border. */
281 getyx (win_info
->generic
.handle
, y
, x
);
282 while (x
+ 1 < win_info
->generic
.width
)
284 waddch (win_info
->generic
.handle
, ' ');
285 getyx (win_info
->generic
.handle
, y
, x
);
290 tui_show_source_content (struct tui_win_info
*win_info
)
292 if (win_info
->generic
.content_size
> 0)
296 for (lineno
= 1; lineno
<= win_info
->generic
.content_size
; lineno
++)
297 tui_show_source_line (win_info
, lineno
);
300 tui_erase_source_content (win_info
, TRUE
);
302 tui_check_and_display_highlight_if_needed (win_info
);
303 tui_refresh_win (&win_info
->generic
);
304 win_info
->generic
.content_in_use
= TRUE
;
308 /* Scroll the source forward or backward horizontally. */
310 tui_horizontal_source_scroll (struct tui_win_info
*win_info
,
311 enum tui_scroll_direction direction
,
314 if (win_info
->generic
.content
!= NULL
)
318 struct symtab_and_line cursal
= get_current_source_symtab_and_line ();
320 if (cursal
.symtab
== (struct symtab
*) NULL
)
321 s
= find_pc_symtab (get_frame_pc (get_selected_frame (NULL
)));
325 if (direction
== LEFT_SCROLL
)
326 offset
= win_info
->detail
.source_info
.horizontal_offset
+ num_to_scroll
;
330 win_info
->detail
.source_info
.horizontal_offset
- num_to_scroll
) < 0)
333 win_info
->detail
.source_info
.horizontal_offset
= offset
;
334 tui_update_source_window_as_is (win_info
, s
,
335 ((struct tui_win_element
*)
336 win_info
->generic
.content
[0])->which_element
.source
.line_or_addr
,
344 /* Set or clear the has_break flag in the line whose line is
348 tui_set_is_exec_point_at (struct tui_line_or_address l
,
349 struct tui_win_info
*win_info
)
353 tui_win_content content
= (tui_win_content
) win_info
->generic
.content
;
356 while (i
< win_info
->generic
.content_size
)
359 struct tui_line_or_address content_loa
=
360 content
[i
]->which_element
.source
.line_or_addr
;
362 gdb_assert (l
.loa
== LOA_ADDRESS
|| l
.loa
== LOA_LINE
);
363 gdb_assert (content_loa
.loa
== LOA_LINE
364 || content_loa
.loa
== LOA_ADDRESS
);
365 if (content_loa
.loa
== l
.loa
366 && ((l
.loa
== LOA_LINE
&& content_loa
.u
.line_no
== l
.u
.line_no
)
367 || (content_loa
.u
.addr
== l
.u
.addr
)))
371 if (new_state
!= content
[i
]->which_element
.source
.is_exec_point
)
374 content
[i
]->which_element
.source
.is_exec_point
= new_state
;
375 tui_show_source_line (win_info
, i
+ 1);
380 tui_refresh_win (&win_info
->generic
);
383 /* Update the execution windows to show the active breakpoints.
384 This is called whenever a breakpoint is inserted, removed or
385 has its state changed. */
387 tui_update_all_breakpoint_info (void)
389 struct tui_list
*list
= tui_source_windows ();
392 for (i
= 0; i
< list
->count
; i
++)
394 struct tui_win_info
*win
= list
->list
[i
];
396 if (tui_update_breakpoint_info (win
, FALSE
))
398 tui_update_exec_info (win
);
404 /* Scan the source window and the breakpoints to update the has_break
405 information for each line.
407 Returns 1 if something changed and the execution window must be
411 tui_update_breakpoint_info (struct tui_win_info
*win
,
415 int need_refresh
= 0;
416 struct tui_source_info
*src
= &win
->detail
.source_info
;
418 for (i
= 0; i
< win
->generic
.content_size
; i
++)
420 struct breakpoint
*bp
;
421 extern struct breakpoint
*breakpoint_chain
;
423 struct tui_source_element
*line
;
425 line
= &((struct tui_win_element
*) win
->generic
.content
[i
])->which_element
.source
;
426 if (current_only
&& !line
->is_exec_point
)
429 /* Scan each breakpoint to see if the current line has something to
430 do with it. Identify enable/disabled breakpoints as well as
431 those that we already hit. */
433 for (bp
= breakpoint_chain
;
434 bp
!= (struct breakpoint
*) NULL
;
437 gdb_assert (line
->line_or_addr
.loa
== LOA_LINE
438 || line
->line_or_addr
.loa
== LOA_ADDRESS
);
439 if ((win
== TUI_SRC_WIN
441 && (strcmp (src
->filename
, bp
->source_file
) == 0)
442 && line
->line_or_addr
.loa
== LOA_LINE
443 && bp
->line_number
== line
->line_or_addr
.u
.line_no
)
444 || (win
== TUI_DISASM_WIN
445 && line
->line_or_addr
.loa
== LOA_ADDRESS
446 && bp
->loc
->address
== line
->line_or_addr
.u
.addr
))
448 if (bp
->enable_state
== bp_disabled
)
449 mode
|= TUI_BP_DISABLED
;
451 mode
|= TUI_BP_ENABLED
;
455 mode
|= TUI_BP_CONDITIONAL
;
456 if (bp
->type
== bp_hardware_breakpoint
)
457 mode
|= TUI_BP_HARDWARE
;
460 if (line
->has_break
!= mode
)
462 line
->has_break
= mode
;
470 /* Function to initialize the content of the execution info window,
471 based upon the input window which is either the source or
472 disassembly window. */
474 tui_set_exec_info_content (struct tui_win_info
*win_info
)
476 enum tui_status ret
= TUI_SUCCESS
;
478 if (win_info
->detail
.source_info
.execution_info
!= (struct tui_gen_win_info
*) NULL
)
480 struct tui_gen_win_info
*exec_info_ptr
= win_info
->detail
.source_info
.execution_info
;
482 if (exec_info_ptr
->content
== NULL
)
483 exec_info_ptr
->content
=
484 (void **) tui_alloc_content (win_info
->generic
.height
,
485 exec_info_ptr
->type
);
486 if (exec_info_ptr
->content
!= NULL
)
490 tui_update_breakpoint_info (win_info
, 1);
491 for (i
= 0; i
< win_info
->generic
.content_size
; i
++)
493 struct tui_win_element
*element
;
494 struct tui_win_element
*src_element
;
497 element
= (struct tui_win_element
*) exec_info_ptr
->content
[i
];
498 src_element
= (struct tui_win_element
*) win_info
->generic
.content
[i
];
500 memset(element
->which_element
.simple_string
, ' ',
501 sizeof(element
->which_element
.simple_string
));
502 element
->which_element
.simple_string
[TUI_EXECINFO_SIZE
- 1] = 0;
504 /* Now update the exec info content based upon the state
505 of each line as indicated by the source content. */
506 mode
= src_element
->which_element
.source
.has_break
;
507 if (mode
& TUI_BP_HIT
)
508 element
->which_element
.simple_string
[TUI_BP_HIT_POS
] =
509 (mode
& TUI_BP_HARDWARE
) ? 'H' : 'B';
510 else if (mode
& (TUI_BP_ENABLED
| TUI_BP_DISABLED
))
511 element
->which_element
.simple_string
[TUI_BP_HIT_POS
] =
512 (mode
& TUI_BP_HARDWARE
) ? 'h' : 'b';
514 if (mode
& TUI_BP_ENABLED
)
515 element
->which_element
.simple_string
[TUI_BP_BREAK_POS
] = '+';
516 else if (mode
& TUI_BP_DISABLED
)
517 element
->which_element
.simple_string
[TUI_BP_BREAK_POS
] = '-';
519 if (src_element
->which_element
.source
.is_exec_point
)
520 element
->which_element
.simple_string
[TUI_EXEC_POS
] = '>';
522 exec_info_ptr
->content_size
= win_info
->generic
.content_size
;
533 tui_show_exec_info_content (struct tui_win_info
*win_info
)
535 struct tui_gen_win_info
*exec_info
= win_info
->detail
.source_info
.execution_info
;
538 werase (exec_info
->handle
);
539 tui_refresh_win (exec_info
);
540 for (cur_line
= 1; (cur_line
<= exec_info
->content_size
); cur_line
++)
541 mvwaddstr (exec_info
->handle
,
544 ((struct tui_win_element
*)
545 exec_info
->content
[cur_line
- 1])->which_element
.simple_string
);
546 tui_refresh_win (exec_info
);
547 exec_info
->content_in_use
= TRUE
;
552 tui_erase_exec_info_content (struct tui_win_info
*win_info
)
554 struct tui_gen_win_info
*exec_info
= win_info
->detail
.source_info
.execution_info
;
556 werase (exec_info
->handle
);
557 tui_refresh_win (exec_info
);
561 tui_clear_exec_info_content (struct tui_win_info
*win_info
)
563 win_info
->detail
.source_info
.execution_info
->content_in_use
= FALSE
;
564 tui_erase_exec_info_content (win_info
);
569 /* Function to update the execution info window. */
571 tui_update_exec_info (struct tui_win_info
*win_info
)
573 tui_set_exec_info_content (win_info
);
574 tui_show_exec_info_content (win_info
);
578 tui_alloc_source_buffer (struct tui_win_info
*win_info
)
581 int i
, line_width
, max_lines
;
583 max_lines
= win_info
->generic
.height
; /* Less the highlight box. */
584 line_width
= win_info
->generic
.width
- 1;
586 * Allocate the buffer for the source lines. Do this only once
587 * since they will be re-used for all source displays. The only
588 * other time this will be done is when a window's size changes.
590 if (win_info
->generic
.content
== NULL
)
592 src_line_buf
= (char *)
593 xmalloc ((max_lines
* line_width
) * sizeof (char));
594 if (src_line_buf
== (char *) NULL
)
596 fputs_unfiltered ("Unable to Allocate Memory for Source or Disassembly Display.\n",
600 /* Allocate the content list. */
601 if ((win_info
->generic
.content
=
602 (void **) tui_alloc_content (max_lines
, SRC_WIN
)) == NULL
)
604 xfree (src_line_buf
);
605 fputs_unfiltered ("Unable to Allocate Memory for Source or Disassembly Display.\n",
609 for (i
= 0; i
< max_lines
; i
++)
610 ((struct tui_win_element
*)
611 win_info
->generic
.content
[i
])->which_element
.source
.line
=
612 src_line_buf
+ (line_width
* i
);
619 /* Answer whether the a particular line number or address is displayed
620 in the current source window. */
622 tui_line_is_displayed (int line
,
623 struct tui_win_info
*win_info
,
626 int is_displayed
= FALSE
;
630 threshold
= SCROLL_THRESHOLD
;
634 while (i
< win_info
->generic
.content_size
- threshold
637 is_displayed
= (((struct tui_win_element
*)
638 win_info
->generic
.content
[i
])->which_element
.source
.line_or_addr
.loa
640 && (((struct tui_win_element
*)
641 win_info
->generic
.content
[i
])->which_element
.source
.line_or_addr
.u
.line_no
650 /* Answer whether the a particular line number or address is displayed
651 in the current source window. */
653 tui_addr_is_displayed (CORE_ADDR addr
,
654 struct tui_win_info
*win_info
,
657 int is_displayed
= FALSE
;
661 threshold
= SCROLL_THRESHOLD
;
665 while (i
< win_info
->generic
.content_size
- threshold
668 is_displayed
= (((struct tui_win_element
*)
669 win_info
->generic
.content
[i
])->which_element
.source
.line_or_addr
.loa
671 && (((struct tui_win_element
*)
672 win_info
->generic
.content
[i
])->which_element
.source
.line_or_addr
.u
.addr
681 /*****************************************
682 ** STATIC LOCAL FUNCTIONS **
683 ******************************************/