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_curses.h"
44 /* Function to display the "main" routine. */
46 tui_display_main (void)
48 if ((tui_source_windows ())->count
> 0)
52 addr
= tui_get_begin_asm_address ();
53 if (addr
!= (CORE_ADDR
) 0)
55 struct symtab_and_line sal
;
57 tui_update_source_windows_with_addr (addr
);
58 sal
= find_pc_line (addr
, 0);
60 tui_update_locator_filename (sal
.symtab
->filename
);
62 tui_update_locator_filename ("??");
69 /* Function to display source in the source window. This function
70 initializes the horizontal scroll to 0. */
72 tui_update_source_window (struct tui_win_info
* win_info
, struct symtab
*s
,
73 union tui_line_or_address line_or_addr
, int noerror
)
75 win_info
->detail
.source_info
.horizontal_offset
= 0;
76 tui_update_source_window_as_is (win_info
, s
, line_or_addr
, noerror
);
82 /* Function to display source in the source/asm window. This function
83 shows the source as specified by the horizontal offset. */
85 tui_update_source_window_as_is (struct tui_win_info
* win_info
, struct symtab
*s
,
86 union tui_line_or_address line_or_addr
, int noerror
)
90 if (win_info
->generic
.type
== SRC_WIN
)
91 ret
= tui_set_source_content (s
, line_or_addr
.line_no
, noerror
);
93 ret
= tui_set_disassem_content (line_or_addr
.addr
);
95 if (ret
== TUI_FAILURE
)
97 tui_clear_source_content (win_info
, EMPTY_SOURCE_PROMPT
);
98 tui_clear_exec_info_content (win_info
);
102 tui_update_breakpoint_info (win_info
, 0);
103 tui_show_source_content (win_info
);
104 tui_update_exec_info (win_info
);
105 if (win_info
->generic
.type
== SRC_WIN
)
107 struct symtab_and_line sal
;
109 sal
.line
= line_or_addr
.line_no
+
110 (win_info
->generic
.content_size
- 2);
112 set_current_source_symtab_and_line (&sal
);
114 ** If the focus was in the asm win, put it in the src
115 ** win if we don't have a split layout
117 if (tui_win_with_focus () == TUI_DISASM_WIN
&&
118 tui_current_layout () != SRC_DISASSEM_COMMAND
)
119 tui_set_win_focus_to (TUI_SRC_WIN
);
128 /* Function to ensure that the source and/or disassemly windows
129 reflect the input address. */
131 tui_update_source_windows_with_addr (CORE_ADDR addr
)
135 struct symtab_and_line sal
;
136 union tui_line_or_address l
;
138 switch (tui_current_layout ())
140 case DISASSEM_COMMAND
:
141 case DISASSEM_DATA_COMMAND
:
142 tui_show_disassem (addr
);
144 case SRC_DISASSEM_COMMAND
:
145 tui_show_disassem_and_update_source (addr
);
148 sal
= find_pc_line (addr
, 0);
149 l
.line_no
= sal
.line
;
150 tui_show_symtab_source (sal
.symtab
, l
, FALSE
);
158 for (i
= 0; i
< (tui_source_windows ())->count
; i
++)
160 struct tui_win_info
* win_info
= (struct tui_win_info
*) (tui_source_windows ())->list
[i
];
162 tui_clear_source_content (win_info
, EMPTY_SOURCE_PROMPT
);
163 tui_clear_exec_info_content (win_info
);
168 /* Function to ensure that the source and/or disassemly windows
169 reflect the input address. */
171 tui_update_source_windows_with_line (struct symtab
*s
, int line
)
174 union tui_line_or_address l
;
176 switch (tui_current_layout ())
178 case DISASSEM_COMMAND
:
179 case DISASSEM_DATA_COMMAND
:
180 find_line_pc (s
, line
, &pc
);
181 tui_update_source_windows_with_addr (pc
);
185 tui_show_symtab_source (s
, l
, FALSE
);
186 if (tui_current_layout () == SRC_DISASSEM_COMMAND
)
188 find_line_pc (s
, line
, &pc
);
189 tui_show_disassem (pc
);
198 tui_clear_source_content (struct tui_win_info
* win_info
, int display_prompt
)
200 if (win_info
!= NULL
)
204 win_info
->generic
.content_in_use
= FALSE
;
205 tui_erase_source_content (win_info
, display_prompt
);
206 for (i
= 0; i
< win_info
->generic
.content_size
; i
++)
208 struct tui_win_element
* element
=
209 (struct tui_win_element
*) win_info
->generic
.content
[i
];
210 element
->which_element
.source
.has_break
= FALSE
;
211 element
->which_element
.source
.is_exec_point
= FALSE
;
218 tui_erase_source_content (struct tui_win_info
* win_info
, int display_prompt
)
221 int half_width
= (win_info
->generic
.width
- 2) / 2;
223 if (win_info
->generic
.handle
!= (WINDOW
*) NULL
)
225 werase (win_info
->generic
.handle
);
226 tui_check_and_display_highlight_if_needed (win_info
);
227 if (display_prompt
== EMPTY_SOURCE_PROMPT
)
231 if (win_info
->generic
.type
== SRC_WIN
)
232 no_src_str
= NO_SRC_STRING
;
234 no_src_str
= NO_DISASSEM_STRING
;
235 if (strlen (no_src_str
) >= half_width
)
238 x_pos
= half_width
- strlen (no_src_str
);
239 mvwaddstr (win_info
->generic
.handle
,
240 (win_info
->generic
.height
/ 2),
244 /* elz: added this function call to set the real contents of
245 the window to what is on the screen, so that later calls
246 to refresh, do display
247 the correct stuff, and not the old image */
249 tui_set_source_content_nil (win_info
, no_src_str
);
251 tui_refresh_win (&win_info
->generic
);
256 /* Redraw the complete line of a source or disassembly window. */
258 tui_show_source_line (struct tui_win_info
* win_info
, int lineno
)
260 struct tui_win_element
* line
;
263 line
= (struct tui_win_element
*) win_info
->generic
.content
[lineno
- 1];
264 if (line
->which_element
.source
.is_exec_point
)
265 wattron (win_info
->generic
.handle
, A_STANDOUT
);
267 mvwaddstr (win_info
->generic
.handle
, lineno
, 1,
268 line
->which_element
.source
.line
);
269 if (line
->which_element
.source
.is_exec_point
)
270 wattroff (win_info
->generic
.handle
, A_STANDOUT
);
272 /* Clear to end of line but stop before the border. */
273 getyx (win_info
->generic
.handle
, y
, x
);
274 while (x
+ 1 < win_info
->generic
.width
)
276 waddch (win_info
->generic
.handle
, ' ');
277 getyx (win_info
->generic
.handle
, y
, x
);
282 tui_show_source_content (struct tui_win_info
* win_info
)
284 if (win_info
->generic
.content_size
> 0)
288 for (lineno
= 1; lineno
<= win_info
->generic
.content_size
; lineno
++)
289 tui_show_source_line (win_info
, lineno
);
292 tui_erase_source_content (win_info
, TRUE
);
294 tui_check_and_display_highlight_if_needed (win_info
);
295 tui_refresh_win (&win_info
->generic
);
296 win_info
->generic
.content_in_use
= TRUE
;
300 /* Scroll the source forward or backward horizontally. */
302 tui_horizontal_source_scroll (struct tui_win_info
* win_info
,
303 enum tui_scroll_direction direction
,
306 if (win_info
->generic
.content
!= NULL
)
310 struct symtab_and_line cursal
= get_current_source_symtab_and_line ();
312 if (cursal
.symtab
== (struct symtab
*) NULL
)
313 s
= find_pc_symtab (get_frame_pc (deprecated_selected_frame
));
317 if (direction
== LEFT_SCROLL
)
318 offset
= win_info
->detail
.source_info
.horizontal_offset
+ num_to_scroll
;
322 win_info
->detail
.source_info
.horizontal_offset
- num_to_scroll
) < 0)
325 win_info
->detail
.source_info
.horizontal_offset
= offset
;
326 tui_update_source_window_as_is (win_info
, s
,
327 ((struct tui_win_element
*)
328 win_info
->generic
.content
[0])->which_element
.source
.line_or_addr
,
336 /* Set or clear the has_break flag in the line whose line is line_no. */
338 tui_set_is_exec_point_at (union tui_line_or_address l
, struct tui_win_info
* win_info
)
342 tui_win_content content
= (tui_win_content
) win_info
->generic
.content
;
345 while (i
< win_info
->generic
.content_size
)
349 if (content
[i
]->which_element
.source
.line_or_addr
.addr
== l
.addr
)
353 if (new_state
!= content
[i
]->which_element
.source
.is_exec_point
)
356 content
[i
]->which_element
.source
.is_exec_point
= new_state
;
357 tui_show_source_line (win_info
, i
+ 1);
362 tui_refresh_win (&win_info
->generic
);
365 /* Update the execution windows to show the active breakpoints.
366 This is called whenever a breakpoint is inserted, removed or
367 has its state changed. */
369 tui_update_all_breakpoint_info (void)
371 struct tui_list
*list
= tui_source_windows ();
374 for (i
= 0; i
< list
->count
; i
++)
376 struct tui_win_info
* win
= (struct tui_win_info
*) list
->list
[i
];
378 if (tui_update_breakpoint_info (win
, FALSE
))
380 tui_update_exec_info (win
);
386 /* Scan the source window and the breakpoints to update the
387 has_break information for each line.
388 Returns 1 if something changed and the execution window
389 must be refreshed. */
391 tui_update_breakpoint_info (struct tui_win_info
* win
, int current_only
)
394 int need_refresh
= 0;
395 struct tui_source_info
* src
= &win
->detail
.source_info
;
397 for (i
= 0; i
< win
->generic
.content_size
; i
++)
399 struct breakpoint
*bp
;
400 extern struct breakpoint
*breakpoint_chain
;
402 struct tui_source_element
* line
;
404 line
= &((struct tui_win_element
*) win
->generic
.content
[i
])->which_element
.source
;
405 if (current_only
&& !line
->is_exec_point
)
408 /* Scan each breakpoint to see if the current line has something to
409 do with it. Identify enable/disabled breakpoints as well as
410 those that we already hit. */
412 for (bp
= breakpoint_chain
;
413 bp
!= (struct breakpoint
*) NULL
;
416 if ((win
== TUI_SRC_WIN
418 && (strcmp (src
->filename
, bp
->source_file
) == 0)
419 && bp
->line_number
== line
->line_or_addr
.line_no
)
420 || (win
== TUI_DISASM_WIN
421 && bp
->loc
->address
== line
->line_or_addr
.addr
))
423 if (bp
->enable_state
== bp_disabled
)
424 mode
|= TUI_BP_DISABLED
;
426 mode
|= TUI_BP_ENABLED
;
430 mode
|= TUI_BP_CONDITIONAL
;
431 if (bp
->type
== bp_hardware_breakpoint
)
432 mode
|= TUI_BP_HARDWARE
;
435 if (line
->has_break
!= mode
)
437 line
->has_break
= mode
;
445 /* Function to initialize the content of the execution info window,
446 based upon the input window which is either the source or
447 disassembly window. */
449 tui_set_exec_info_content (struct tui_win_info
* win_info
)
451 enum tui_status ret
= TUI_SUCCESS
;
453 if (win_info
->detail
.source_info
.execution_info
!= (struct tui_gen_win_info
*) NULL
)
455 struct tui_gen_win_info
* exec_info_ptr
= win_info
->detail
.source_info
.execution_info
;
457 if (exec_info_ptr
->content
== NULL
)
458 exec_info_ptr
->content
=
459 (void **) tui_alloc_content (win_info
->generic
.height
,
460 exec_info_ptr
->type
);
461 if (exec_info_ptr
->content
!= NULL
)
465 tui_update_breakpoint_info (win_info
, 1);
466 for (i
= 0; i
< win_info
->generic
.content_size
; i
++)
468 struct tui_win_element
* element
;
469 struct tui_win_element
* src_element
;
472 element
= (struct tui_win_element
*) exec_info_ptr
->content
[i
];
473 src_element
= (struct tui_win_element
*) win_info
->generic
.content
[i
];
475 memset(element
->which_element
.simple_string
, ' ',
476 sizeof(element
->which_element
.simple_string
));
477 element
->which_element
.simple_string
[TUI_EXECINFO_SIZE
- 1] = 0;
479 /* Now update the exec info content based upon the state
480 of each line as indicated by the source content. */
481 mode
= src_element
->which_element
.source
.has_break
;
482 if (mode
& TUI_BP_HIT
)
483 element
->which_element
.simple_string
[TUI_BP_HIT_POS
] =
484 (mode
& TUI_BP_HARDWARE
) ? 'H' : 'B';
485 else if (mode
& (TUI_BP_ENABLED
| TUI_BP_DISABLED
))
486 element
->which_element
.simple_string
[TUI_BP_HIT_POS
] =
487 (mode
& TUI_BP_HARDWARE
) ? 'h' : 'b';
489 if (mode
& TUI_BP_ENABLED
)
490 element
->which_element
.simple_string
[TUI_BP_BREAK_POS
] = '+';
491 else if (mode
& TUI_BP_DISABLED
)
492 element
->which_element
.simple_string
[TUI_BP_BREAK_POS
] = '-';
494 if (src_element
->which_element
.source
.is_exec_point
)
495 element
->which_element
.simple_string
[TUI_EXEC_POS
] = '>';
497 exec_info_ptr
->content_size
= win_info
->generic
.content_size
;
508 tui_show_exec_info_content (struct tui_win_info
* win_info
)
510 struct tui_gen_win_info
* exec_info
= win_info
->detail
.source_info
.execution_info
;
513 werase (exec_info
->handle
);
514 tui_refresh_win (exec_info
);
515 for (cur_line
= 1; (cur_line
<= exec_info
->content_size
); cur_line
++)
516 mvwaddstr (exec_info
->handle
,
519 ((struct tui_win_element
*)
520 exec_info
->content
[cur_line
- 1])->which_element
.simple_string
);
521 tui_refresh_win (exec_info
);
522 exec_info
->content_in_use
= TRUE
;
527 tui_erase_exec_info_content (struct tui_win_info
* win_info
)
529 struct tui_gen_win_info
* exec_info
= win_info
->detail
.source_info
.execution_info
;
531 werase (exec_info
->handle
);
532 tui_refresh_win (exec_info
);
536 tui_clear_exec_info_content (struct tui_win_info
* win_info
)
538 win_info
->detail
.source_info
.execution_info
->content_in_use
= FALSE
;
539 tui_erase_exec_info_content (win_info
);
544 /* Function to update the execution info window. */
546 tui_update_exec_info (struct tui_win_info
* win_info
)
548 tui_set_exec_info_content (win_info
);
549 tui_show_exec_info_content (win_info
);
553 tui_alloc_source_buffer (struct tui_win_info
*win_info
)
556 int i
, line_width
, max_lines
;
557 enum tui_status ret
= TUI_FAILURE
;
559 max_lines
= win_info
->generic
.height
; /* less the highlight box */
560 line_width
= win_info
->generic
.width
- 1;
562 ** Allocate the buffer for the source lines. Do this only once since they
563 ** will be re-used for all source displays. The only other time this will
564 ** be done is when a window's size changes.
566 if (win_info
->generic
.content
== NULL
)
568 src_line_buf
= (char *) xmalloc ((max_lines
* line_width
) * sizeof (char));
569 if (src_line_buf
== (char *) NULL
)
571 "Unable to Allocate Memory for Source or Disassembly Display.\n",
575 /* allocate the content list */
576 if ((win_info
->generic
.content
=
577 (void **) tui_alloc_content (max_lines
, SRC_WIN
)) == NULL
)
579 xfree (src_line_buf
);
580 src_line_buf
= (char *) NULL
;
582 "Unable to Allocate Memory for Source or Disassembly Display.\n",
586 for (i
= 0; i
< max_lines
; i
++)
587 ((struct tui_win_element
*)
588 win_info
->generic
.content
[i
])->which_element
.source
.line
=
589 src_line_buf
+ (line_width
* i
);
599 /* Answer whether the a particular line number or address is displayed
600 in the current source window. */
602 tui_line_is_displayed (int line
, struct tui_win_info
* win_info
,
605 int is_displayed
= FALSE
;
609 threshold
= SCROLL_THRESHOLD
;
613 while (i
< win_info
->generic
.content_size
- threshold
&& !is_displayed
)
615 is_displayed
= (((struct tui_win_element
*)
616 win_info
->generic
.content
[i
])->which_element
.source
.line_or_addr
.line_no
625 /* Answer whether the a particular line number or address is displayed
626 in the current source window. */
628 tui_addr_is_displayed (CORE_ADDR addr
, struct tui_win_info
* win_info
,
631 int is_displayed
= FALSE
;
635 threshold
= SCROLL_THRESHOLD
;
639 while (i
< win_info
->generic
.content_size
- threshold
&& !is_displayed
)
641 is_displayed
= (((struct tui_win_element
*)
642 win_info
->generic
.content
[i
])->which_element
.source
.line_or_addr
.addr
651 /*****************************************
652 ** STATIC LOCAL FUNCTIONS **
653 ******************************************/