1 /* TUI display source/assembly window.
3 Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software
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., 59 Temple Place - Suite 330,
23 Boston, MA 02111-1307, 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"
45 /* Function to display the "main" routine. */
47 tui_display_main (void)
49 if ((tui_source_windows ())->count
> 0)
53 addr
= tui_get_begin_asm_address ();
54 if (addr
!= (CORE_ADDR
) 0)
56 struct symtab_and_line sal
;
58 tui_update_source_windows_with_addr (addr
);
59 sal
= find_pc_line (addr
, 0);
61 tui_update_locator_filename (sal
.symtab
->filename
);
63 tui_update_locator_filename ("??");
70 /* Function to display source in the source window. This function
71 initializes the horizontal scroll to 0. */
73 tui_update_source_window (struct tui_win_info
* win_info
, struct symtab
*s
,
74 union tui_line_or_address line_or_addr
, int noerror
)
76 win_info
->detail
.source_info
.horizontal_offset
= 0;
77 tui_update_source_window_as_is (win_info
, s
, line_or_addr
, noerror
);
83 /* Function to display source in the source/asm window. This function
84 shows the source as specified by the horizontal offset. */
86 tui_update_source_window_as_is (struct tui_win_info
* win_info
, struct symtab
*s
,
87 union tui_line_or_address line_or_addr
, int noerror
)
91 if (win_info
->generic
.type
== SRC_WIN
)
92 ret
= tui_set_source_content (s
, line_or_addr
.line_no
, noerror
);
94 ret
= tui_set_disassem_content (line_or_addr
.addr
);
96 if (ret
== TUI_FAILURE
)
98 tui_clear_source_content (win_info
, EMPTY_SOURCE_PROMPT
);
99 tui_clear_exec_info_content (win_info
);
103 tui_update_breakpoint_info (win_info
, 0);
104 tui_show_source_content (win_info
);
105 tui_update_exec_info (win_info
);
106 if (win_info
->generic
.type
== SRC_WIN
)
108 struct symtab_and_line sal
;
110 sal
.line
= line_or_addr
.line_no
+
111 (win_info
->generic
.content_size
- 2);
113 set_current_source_symtab_and_line (&sal
);
115 ** If the focus was in the asm win, put it in the src
116 ** win if we don't have a split layout
118 if (tui_win_with_focus () == TUI_DISASM_WIN
&&
119 tui_current_layout () != SRC_DISASSEM_COMMAND
)
120 tui_set_win_focus_to (TUI_SRC_WIN
);
129 /* Function to ensure that the source and/or disassemly windows
130 reflect the input address. */
132 tui_update_source_windows_with_addr (CORE_ADDR addr
)
136 struct symtab_and_line sal
;
137 union tui_line_or_address l
;
139 switch (tui_current_layout ())
141 case DISASSEM_COMMAND
:
142 case DISASSEM_DATA_COMMAND
:
143 tui_show_disassem (addr
);
145 case SRC_DISASSEM_COMMAND
:
146 tui_show_disassem_and_update_source (addr
);
149 sal
= find_pc_line (addr
, 0);
150 l
.line_no
= sal
.line
;
151 tui_show_symtab_source (sal
.symtab
, l
, FALSE
);
159 for (i
= 0; i
< (tui_source_windows ())->count
; i
++)
161 struct tui_win_info
* win_info
= (struct tui_win_info
*) (tui_source_windows ())->list
[i
];
163 tui_clear_source_content (win_info
, EMPTY_SOURCE_PROMPT
);
164 tui_clear_exec_info_content (win_info
);
169 /* Function to ensure that the source and/or disassemly windows
170 reflect the input address. */
172 tui_update_source_windows_with_line (struct symtab
*s
, int line
)
175 union tui_line_or_address l
;
177 switch (tui_current_layout ())
179 case DISASSEM_COMMAND
:
180 case DISASSEM_DATA_COMMAND
:
181 find_line_pc (s
, line
, &pc
);
182 tui_update_source_windows_with_addr (pc
);
186 tui_show_symtab_source (s
, l
, FALSE
);
187 if (tui_current_layout () == SRC_DISASSEM_COMMAND
)
189 find_line_pc (s
, line
, &pc
);
190 tui_show_disassem (pc
);
199 tui_clear_source_content (struct tui_win_info
* win_info
, int display_prompt
)
201 if (win_info
!= NULL
)
205 win_info
->generic
.content_in_use
= FALSE
;
206 tui_erase_source_content (win_info
, display_prompt
);
207 for (i
= 0; i
< win_info
->generic
.content_size
; i
++)
209 struct tui_win_element
* element
=
210 (struct tui_win_element
*) win_info
->generic
.content
[i
];
211 element
->which_element
.source
.has_break
= FALSE
;
212 element
->which_element
.source
.is_exec_point
= FALSE
;
219 tui_erase_source_content (struct tui_win_info
* win_info
, int display_prompt
)
222 int half_width
= (win_info
->generic
.width
- 2) / 2;
224 if (win_info
->generic
.handle
!= (WINDOW
*) NULL
)
226 werase (win_info
->generic
.handle
);
227 tui_check_and_display_highlight_if_needed (win_info
);
228 if (display_prompt
== EMPTY_SOURCE_PROMPT
)
232 if (win_info
->generic
.type
== SRC_WIN
)
233 no_src_str
= NO_SRC_STRING
;
235 no_src_str
= NO_DISASSEM_STRING
;
236 if (strlen (no_src_str
) >= half_width
)
239 x_pos
= half_width
- strlen (no_src_str
);
240 mvwaddstr (win_info
->generic
.handle
,
241 (win_info
->generic
.height
/ 2),
245 /* elz: added this function call to set the real contents of
246 the window to what is on the screen, so that later calls
247 to refresh, do display
248 the correct stuff, and not the old image */
250 tui_set_source_content_nil (win_info
, no_src_str
);
252 tui_refresh_win (&win_info
->generic
);
257 /* Redraw the complete line of a source or disassembly window. */
259 tui_show_source_line (struct tui_win_info
* win_info
, int lineno
)
261 struct tui_win_element
* line
;
264 line
= (struct tui_win_element
*) win_info
->generic
.content
[lineno
- 1];
265 if (line
->which_element
.source
.is_exec_point
)
266 wattron (win_info
->generic
.handle
, A_STANDOUT
);
268 mvwaddstr (win_info
->generic
.handle
, lineno
, 1,
269 line
->which_element
.source
.line
);
270 if (line
->which_element
.source
.is_exec_point
)
271 wattroff (win_info
->generic
.handle
, A_STANDOUT
);
273 /* Clear to end of line but stop before the border. */
274 getyx (win_info
->generic
.handle
, y
, x
);
275 while (x
+ 1 < win_info
->generic
.width
)
277 waddch (win_info
->generic
.handle
, ' ');
278 getyx (win_info
->generic
.handle
, y
, x
);
283 tui_show_source_content (struct tui_win_info
* win_info
)
285 if (win_info
->generic
.content_size
> 0)
289 for (lineno
= 1; lineno
<= win_info
->generic
.content_size
; lineno
++)
290 tui_show_source_line (win_info
, lineno
);
293 tui_erase_source_content (win_info
, TRUE
);
295 tui_check_and_display_highlight_if_needed (win_info
);
296 tui_refresh_win (&win_info
->generic
);
297 win_info
->generic
.content_in_use
= TRUE
;
301 /* Scroll the source forward or backward horizontally. */
303 tui_horizontal_source_scroll (struct tui_win_info
* win_info
,
304 enum tui_scroll_direction direction
,
307 if (win_info
->generic
.content
!= NULL
)
311 struct symtab_and_line cursal
= get_current_source_symtab_and_line ();
313 if (cursal
.symtab
== (struct symtab
*) NULL
)
314 s
= find_pc_symtab (get_frame_pc (deprecated_selected_frame
));
318 if (direction
== LEFT_SCROLL
)
319 offset
= win_info
->detail
.source_info
.horizontal_offset
+ num_to_scroll
;
323 win_info
->detail
.source_info
.horizontal_offset
- num_to_scroll
) < 0)
326 win_info
->detail
.source_info
.horizontal_offset
= offset
;
327 tui_update_source_window_as_is (win_info
, s
,
328 ((struct tui_win_element
*)
329 win_info
->generic
.content
[0])->which_element
.source
.line_or_addr
,
337 /* Set or clear the has_break flag in the line whose line is line_no. */
339 tui_set_is_exec_point_at (union tui_line_or_address l
, struct tui_win_info
* win_info
)
343 tui_win_content content
= (tui_win_content
) win_info
->generic
.content
;
346 while (i
< win_info
->generic
.content_size
)
350 if (content
[i
]->which_element
.source
.line_or_addr
.addr
== l
.addr
)
354 if (new_state
!= content
[i
]->which_element
.source
.is_exec_point
)
357 content
[i
]->which_element
.source
.is_exec_point
= new_state
;
358 tui_show_source_line (win_info
, i
+ 1);
363 tui_refresh_win (&win_info
->generic
);
366 /* Update the execution windows to show the active breakpoints.
367 This is called whenever a breakpoint is inserted, removed or
368 has its state changed. */
370 tui_update_all_breakpoint_info (void)
372 struct tui_list
*list
= tui_source_windows ();
375 for (i
= 0; i
< list
->count
; i
++)
377 struct tui_win_info
* win
= (struct tui_win_info
*) list
->list
[i
];
379 if (tui_update_breakpoint_info (win
, FALSE
))
381 tui_update_exec_info (win
);
387 /* Scan the source window and the breakpoints to update the
388 has_break information for each line.
389 Returns 1 if something changed and the execution window
390 must be refreshed. */
392 tui_update_breakpoint_info (struct tui_win_info
* win
, int current_only
)
395 int need_refresh
= 0;
396 struct tui_source_info
* src
= &win
->detail
.source_info
;
398 for (i
= 0; i
< win
->generic
.content_size
; i
++)
400 struct breakpoint
*bp
;
401 extern struct breakpoint
*breakpoint_chain
;
403 struct tui_source_element
* line
;
405 line
= &((struct tui_win_element
*) win
->generic
.content
[i
])->which_element
.source
;
406 if (current_only
&& !line
->is_exec_point
)
409 /* Scan each breakpoint to see if the current line has something to
410 do with it. Identify enable/disabled breakpoints as well as
411 those that we already hit. */
413 for (bp
= breakpoint_chain
;
414 bp
!= (struct breakpoint
*) NULL
;
417 if ((win
== TUI_SRC_WIN
419 && (strcmp (src
->filename
, bp
->source_file
) == 0)
420 && bp
->line_number
== line
->line_or_addr
.line_no
)
421 || (win
== TUI_DISASM_WIN
422 && bp
->loc
->address
== line
->line_or_addr
.addr
))
424 if (bp
->enable_state
== bp_disabled
)
425 mode
|= TUI_BP_DISABLED
;
427 mode
|= TUI_BP_ENABLED
;
431 mode
|= TUI_BP_CONDITIONAL
;
432 if (bp
->type
== bp_hardware_breakpoint
)
433 mode
|= TUI_BP_HARDWARE
;
436 if (line
->has_break
!= mode
)
438 line
->has_break
= mode
;
446 /* Function to initialize the content of the execution info window,
447 based upon the input window which is either the source or
448 disassembly window. */
450 tui_set_exec_info_content (struct tui_win_info
* win_info
)
452 enum tui_status ret
= TUI_SUCCESS
;
454 if (win_info
->detail
.source_info
.execution_info
!= (struct tui_gen_win_info
*) NULL
)
456 struct tui_gen_win_info
* exec_info_ptr
= win_info
->detail
.source_info
.execution_info
;
458 if (exec_info_ptr
->content
== NULL
)
459 exec_info_ptr
->content
=
460 (void **) tui_alloc_content (win_info
->generic
.height
,
461 exec_info_ptr
->type
);
462 if (exec_info_ptr
->content
!= NULL
)
466 tui_update_breakpoint_info (win_info
, 1);
467 for (i
= 0; i
< win_info
->generic
.content_size
; i
++)
469 struct tui_win_element
* element
;
470 struct tui_win_element
* src_element
;
473 element
= (struct tui_win_element
*) exec_info_ptr
->content
[i
];
474 src_element
= (struct tui_win_element
*) win_info
->generic
.content
[i
];
476 memset(element
->which_element
.simple_string
, ' ',
477 sizeof(element
->which_element
.simple_string
));
478 element
->which_element
.simple_string
[TUI_EXECINFO_SIZE
- 1] = 0;
480 /* Now update the exec info content based upon the state
481 of each line as indicated by the source content. */
482 mode
= src_element
->which_element
.source
.has_break
;
483 if (mode
& TUI_BP_HIT
)
484 element
->which_element
.simple_string
[TUI_BP_HIT_POS
] =
485 (mode
& TUI_BP_HARDWARE
) ? 'H' : 'B';
486 else if (mode
& (TUI_BP_ENABLED
| TUI_BP_DISABLED
))
487 element
->which_element
.simple_string
[TUI_BP_HIT_POS
] =
488 (mode
& TUI_BP_HARDWARE
) ? 'h' : 'b';
490 if (mode
& TUI_BP_ENABLED
)
491 element
->which_element
.simple_string
[TUI_BP_BREAK_POS
] = '+';
492 else if (mode
& TUI_BP_DISABLED
)
493 element
->which_element
.simple_string
[TUI_BP_BREAK_POS
] = '-';
495 if (src_element
->which_element
.source
.is_exec_point
)
496 element
->which_element
.simple_string
[TUI_EXEC_POS
] = '>';
498 exec_info_ptr
->content_size
= win_info
->generic
.content_size
;
509 tui_show_exec_info_content (struct tui_win_info
* win_info
)
511 struct tui_gen_win_info
* exec_info
= win_info
->detail
.source_info
.execution_info
;
514 werase (exec_info
->handle
);
515 tui_refresh_win (exec_info
);
516 for (cur_line
= 1; (cur_line
<= exec_info
->content_size
); cur_line
++)
517 mvwaddstr (exec_info
->handle
,
520 ((struct tui_win_element
*)
521 exec_info
->content
[cur_line
- 1])->which_element
.simple_string
);
522 tui_refresh_win (exec_info
);
523 exec_info
->content_in_use
= TRUE
;
528 tui_erase_exec_info_content (struct tui_win_info
* win_info
)
530 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
);
537 tui_clear_exec_info_content (struct tui_win_info
* win_info
)
539 win_info
->detail
.source_info
.execution_info
->content_in_use
= FALSE
;
540 tui_erase_exec_info_content (win_info
);
545 /* Function to update the execution info window. */
547 tui_update_exec_info (struct tui_win_info
* win_info
)
549 tui_set_exec_info_content (win_info
);
550 tui_show_exec_info_content (win_info
);
554 tui_alloc_source_buffer (struct tui_win_info
*win_info
)
557 int i
, line_width
, max_lines
;
558 enum tui_status ret
= TUI_FAILURE
;
560 max_lines
= win_info
->generic
.height
; /* less the highlight box */
561 line_width
= win_info
->generic
.width
- 1;
563 ** Allocate the buffer for the source lines. Do this only once since they
564 ** will be re-used for all source displays. The only other time this will
565 ** be done is when a window's size changes.
567 if (win_info
->generic
.content
== NULL
)
569 src_line_buf
= (char *) xmalloc ((max_lines
* line_width
) * sizeof (char));
570 if (src_line_buf
== (char *) NULL
)
572 "Unable to Allocate Memory for Source or Disassembly Display.\n",
576 /* allocate the content list */
577 if ((win_info
->generic
.content
=
578 (void **) tui_alloc_content (max_lines
, SRC_WIN
)) == NULL
)
580 xfree (src_line_buf
);
581 src_line_buf
= (char *) NULL
;
583 "Unable to Allocate Memory for Source or Disassembly Display.\n",
587 for (i
= 0; i
< max_lines
; i
++)
588 ((struct tui_win_element
*)
589 win_info
->generic
.content
[i
])->which_element
.source
.line
=
590 src_line_buf
+ (line_width
* i
);
600 /* Answer whether the a particular line number or address is displayed
601 in the current source window. */
603 tui_line_is_displayed (int line
, struct tui_win_info
* win_info
,
606 int is_displayed
= FALSE
;
610 threshold
= SCROLL_THRESHOLD
;
614 while (i
< win_info
->generic
.content_size
- threshold
&& !is_displayed
)
616 is_displayed
= (((struct tui_win_element
*)
617 win_info
->generic
.content
[i
])->which_element
.source
.line_or_addr
.line_no
626 /* Answer whether the a particular line number or address is displayed
627 in the current source window. */
629 tui_addr_is_displayed (CORE_ADDR addr
, struct tui_win_info
* win_info
,
632 int is_displayed
= FALSE
;
636 threshold
= SCROLL_THRESHOLD
;
640 while (i
< win_info
->generic
.content_size
- threshold
&& !is_displayed
)
642 is_displayed
= (((struct tui_win_element
*)
643 win_info
->generic
.content
[i
])->which_element
.source
.line_or_addr
.addr
652 /*****************************************
653 ** STATIC LOCAL FUNCTIONS **
654 ******************************************/