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"
50 /* Function to display the "main" routine. */
52 tui_display_main (void)
54 if ((tui_source_windows ())->count
> 0)
58 addr
= tui_get_begin_asm_address ();
59 if (addr
!= (CORE_ADDR
) 0)
61 struct symtab_and_line sal
;
63 tui_update_source_windows_with_addr (addr
);
64 sal
= find_pc_line (addr
, 0);
66 tui_update_locator_filename (sal
.symtab
->filename
);
68 tui_update_locator_filename ("??");
75 /* Function to display source in the source window. This function
76 initializes the horizontal scroll to 0. */
78 tui_update_source_window (struct tui_win_info
* win_info
, struct symtab
*s
,
79 union tui_line_or_address line_or_addr
, int noerror
)
81 win_info
->detail
.source_info
.horizontal_offset
= 0;
82 tui_update_source_window_as_is (win_info
, s
, line_or_addr
, noerror
);
88 /* Function to display source in the source/asm window. This function
89 shows the source as specified by the horizontal offset. */
91 tui_update_source_window_as_is (struct tui_win_info
* win_info
, struct symtab
*s
,
92 union tui_line_or_address line_or_addr
, int noerror
)
96 if (win_info
->generic
.type
== SRC_WIN
)
97 ret
= tui_set_source_content (s
, line_or_addr
.line_no
, noerror
);
99 ret
= tui_set_disassem_content (line_or_addr
.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
.line_no
+
116 (win_info
->generic
.content_size
- 2);
118 set_current_source_symtab_and_line (&sal
);
120 ** If the focus was in the asm win, put it in the src
121 ** win if we don't have a split layout
123 if (tui_win_with_focus () == TUI_DISASM_WIN
&&
124 tui_current_layout () != SRC_DISASSEM_COMMAND
)
125 tui_set_win_focus_to (TUI_SRC_WIN
);
134 /* Function to ensure that the source and/or disassemly windows
135 reflect the input address. */
137 tui_update_source_windows_with_addr (CORE_ADDR addr
)
141 struct symtab_and_line sal
;
142 union tui_line_or_address l
;
144 switch (tui_current_layout ())
146 case DISASSEM_COMMAND
:
147 case DISASSEM_DATA_COMMAND
:
148 tui_show_disassem (addr
);
150 case SRC_DISASSEM_COMMAND
:
151 tui_show_disassem_and_update_source (addr
);
154 sal
= find_pc_line (addr
, 0);
155 l
.line_no
= sal
.line
;
156 tui_show_symtab_source (sal
.symtab
, l
, FALSE
);
164 for (i
= 0; i
< (tui_source_windows ())->count
; i
++)
166 struct tui_win_info
* win_info
= (struct tui_win_info
*) (tui_source_windows ())->list
[i
];
168 tui_clear_source_content (win_info
, EMPTY_SOURCE_PROMPT
);
169 tui_clear_exec_info_content (win_info
);
174 /* Function to ensure that the source and/or disassemly windows
175 reflect the input address. */
177 tui_update_source_windows_with_line (struct symtab
*s
, int line
)
180 union tui_line_or_address l
;
182 switch (tui_current_layout ())
184 case DISASSEM_COMMAND
:
185 case DISASSEM_DATA_COMMAND
:
186 find_line_pc (s
, line
, &pc
);
187 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
, int display_prompt
)
206 if (win_info
!= NULL
)
210 win_info
->generic
.content_in_use
= FALSE
;
211 tui_erase_source_content (win_info
, display_prompt
);
212 for (i
= 0; i
< win_info
->generic
.content_size
; i
++)
214 struct tui_win_element
* element
=
215 (struct tui_win_element
*) win_info
->generic
.content
[i
];
216 element
->which_element
.source
.has_break
= FALSE
;
217 element
->which_element
.source
.is_exec_point
= FALSE
;
224 tui_erase_source_content (struct tui_win_info
* win_info
, int display_prompt
)
227 int half_width
= (win_info
->generic
.width
- 2) / 2;
229 if (win_info
->generic
.handle
!= (WINDOW
*) NULL
)
231 werase (win_info
->generic
.handle
);
232 tui_check_and_display_highlight_if_needed (win_info
);
233 if (display_prompt
== EMPTY_SOURCE_PROMPT
)
237 if (win_info
->generic
.type
== SRC_WIN
)
238 no_src_str
= NO_SRC_STRING
;
240 no_src_str
= NO_DISASSEM_STRING
;
241 if (strlen (no_src_str
) >= half_width
)
244 x_pos
= half_width
- strlen (no_src_str
);
245 mvwaddstr (win_info
->generic
.handle
,
246 (win_info
->generic
.height
/ 2),
250 /* elz: added this function call to set the real contents of
251 the window to what is on the screen, so that later calls
252 to refresh, do display
253 the correct stuff, and not the old image */
255 tui_set_source_content_nil (win_info
, no_src_str
);
257 tui_refresh_win (&win_info
->generic
);
262 /* Redraw the complete line of a source or disassembly window. */
264 tui_show_source_line (struct tui_win_info
* win_info
, int lineno
)
266 struct tui_win_element
* line
;
269 line
= (struct tui_win_element
*) win_info
->generic
.content
[lineno
- 1];
270 if (line
->which_element
.source
.is_exec_point
)
271 wattron (win_info
->generic
.handle
, A_STANDOUT
);
273 mvwaddstr (win_info
->generic
.handle
, lineno
, 1,
274 line
->which_element
.source
.line
);
275 if (line
->which_element
.source
.is_exec_point
)
276 wattroff (win_info
->generic
.handle
, A_STANDOUT
);
278 /* Clear to end of line but stop before the border. */
279 getyx (win_info
->generic
.handle
, y
, x
);
280 while (x
+ 1 < win_info
->generic
.width
)
282 waddch (win_info
->generic
.handle
, ' ');
283 getyx (win_info
->generic
.handle
, y
, x
);
288 tui_show_source_content (struct tui_win_info
* win_info
)
290 if (win_info
->generic
.content_size
> 0)
294 for (lineno
= 1; lineno
<= win_info
->generic
.content_size
; lineno
++)
295 tui_show_source_line (win_info
, lineno
);
298 tui_erase_source_content (win_info
, TRUE
);
300 tui_check_and_display_highlight_if_needed (win_info
);
301 tui_refresh_win (&win_info
->generic
);
302 win_info
->generic
.content_in_use
= TRUE
;
306 /* Scroll the source forward or backward horizontally. */
308 tui_horizontal_source_scroll (struct tui_win_info
* win_info
,
309 enum tui_scroll_direction direction
,
312 if (win_info
->generic
.content
!= NULL
)
316 struct symtab_and_line cursal
= get_current_source_symtab_and_line ();
318 if (cursal
.symtab
== (struct symtab
*) NULL
)
319 s
= find_pc_symtab (get_frame_pc (deprecated_selected_frame
));
323 if (direction
== LEFT_SCROLL
)
324 offset
= win_info
->detail
.source_info
.horizontal_offset
+ num_to_scroll
;
328 win_info
->detail
.source_info
.horizontal_offset
- num_to_scroll
) < 0)
331 win_info
->detail
.source_info
.horizontal_offset
= offset
;
332 tui_update_source_window_as_is (win_info
, s
,
333 ((struct tui_win_element
*)
334 win_info
->generic
.content
[0])->which_element
.source
.line_or_addr
,
342 /* Set or clear the has_break flag in the line whose line is line_no. */
344 tui_set_is_exec_point_at (union 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
)
355 if (content
[i
]->which_element
.source
.line_or_addr
.addr
== l
.addr
)
359 if (new_state
!= content
[i
]->which_element
.source
.is_exec_point
)
362 content
[i
]->which_element
.source
.is_exec_point
= new_state
;
363 tui_show_source_line (win_info
, i
+ 1);
368 tui_refresh_win (&win_info
->generic
);
371 /* Update the execution windows to show the active breakpoints.
372 This is called whenever a breakpoint is inserted, removed or
373 has its state changed. */
375 tui_update_all_breakpoint_info ()
377 struct tui_list
*list
= tui_source_windows ();
380 for (i
= 0; i
< list
->count
; i
++)
382 struct tui_win_info
* win
= (struct tui_win_info
*) list
->list
[i
];
384 if (tui_update_breakpoint_info (win
, FALSE
))
386 tui_update_exec_info (win
);
392 /* Scan the source window and the breakpoints to update the
393 has_break information for each line.
394 Returns 1 if something changed and the execution window
395 must be refreshed. */
397 tui_update_breakpoint_info (struct tui_win_info
* win
, int current_only
)
400 int need_refresh
= 0;
401 struct tui_source_info
* src
= &win
->detail
.source_info
;
403 for (i
= 0; i
< win
->generic
.content_size
; i
++)
405 struct breakpoint
*bp
;
406 extern struct breakpoint
*breakpoint_chain
;
408 struct tui_source_element
* line
;
410 line
= &((struct tui_win_element
*) win
->generic
.content
[i
])->which_element
.source
;
411 if (current_only
&& !line
->is_exec_point
)
414 /* Scan each breakpoint to see if the current line has something to
415 do with it. Identify enable/disabled breakpoints as well as
416 those that we already hit. */
418 for (bp
= breakpoint_chain
;
419 bp
!= (struct breakpoint
*) NULL
;
422 if ((win
== TUI_SRC_WIN
424 && (strcmp (src
->filename
, bp
->source_file
) == 0)
425 && bp
->line_number
== line
->line_or_addr
.line_no
)
426 || (win
== TUI_DISASM_WIN
427 && bp
->loc
->address
== line
->line_or_addr
.addr
))
429 if (bp
->enable_state
== bp_disabled
)
430 mode
|= TUI_BP_DISABLED
;
432 mode
|= TUI_BP_ENABLED
;
436 mode
|= TUI_BP_CONDITIONAL
;
437 if (bp
->type
== bp_hardware_breakpoint
)
438 mode
|= TUI_BP_HARDWARE
;
441 if (line
->has_break
!= mode
)
443 line
->has_break
= mode
;
451 /* Function to initialize the content of the execution info window,
452 based upon the input window which is either the source or
453 disassembly window. */
455 tui_set_exec_info_content (struct tui_win_info
* win_info
)
457 enum tui_status ret
= TUI_SUCCESS
;
459 if (win_info
->detail
.source_info
.execution_info
!= (struct tui_gen_win_info
*) NULL
)
461 struct tui_gen_win_info
* exec_info_ptr
= win_info
->detail
.source_info
.execution_info
;
463 if (exec_info_ptr
->content
== NULL
)
464 exec_info_ptr
->content
=
465 (void **) tui_alloc_content (win_info
->generic
.height
,
466 exec_info_ptr
->type
);
467 if (exec_info_ptr
->content
!= NULL
)
471 tui_update_breakpoint_info (win_info
, 1);
472 for (i
= 0; i
< win_info
->generic
.content_size
; i
++)
474 struct tui_win_element
* element
;
475 struct tui_win_element
* src_element
;
478 element
= (struct tui_win_element
*) exec_info_ptr
->content
[i
];
479 src_element
= (struct tui_win_element
*) win_info
->generic
.content
[i
];
481 memset(element
->which_element
.simple_string
, ' ',
482 sizeof(element
->which_element
.simple_string
));
483 element
->which_element
.simple_string
[TUI_EXECINFO_SIZE
- 1] = 0;
485 /* Now update the exec info content based upon the state
486 of each line as indicated by the source content. */
487 mode
= src_element
->which_element
.source
.has_break
;
488 if (mode
& TUI_BP_HIT
)
489 element
->which_element
.simple_string
[TUI_BP_HIT_POS
] =
490 (mode
& TUI_BP_HARDWARE
) ? 'H' : 'B';
491 else if (mode
& (TUI_BP_ENABLED
| TUI_BP_DISABLED
))
492 element
->which_element
.simple_string
[TUI_BP_HIT_POS
] =
493 (mode
& TUI_BP_HARDWARE
) ? 'h' : 'b';
495 if (mode
& TUI_BP_ENABLED
)
496 element
->which_element
.simple_string
[TUI_BP_BREAK_POS
] = '+';
497 else if (mode
& TUI_BP_DISABLED
)
498 element
->which_element
.simple_string
[TUI_BP_BREAK_POS
] = '-';
500 if (src_element
->which_element
.source
.is_exec_point
)
501 element
->which_element
.simple_string
[TUI_EXEC_POS
] = '>';
503 exec_info_ptr
->content_size
= win_info
->generic
.content_size
;
514 tui_show_exec_info_content (struct tui_win_info
* win_info
)
516 struct tui_gen_win_info
* exec_info
= win_info
->detail
.source_info
.execution_info
;
519 werase (exec_info
->handle
);
520 tui_refresh_win (exec_info
);
521 for (cur_line
= 1; (cur_line
<= exec_info
->content_size
); cur_line
++)
522 mvwaddstr (exec_info
->handle
,
525 ((struct tui_win_element
*)
526 exec_info
->content
[cur_line
- 1])->which_element
.simple_string
);
527 tui_refresh_win (exec_info
);
528 exec_info
->content_in_use
= TRUE
;
533 tui_erase_exec_info_content (struct tui_win_info
* win_info
)
535 struct tui_gen_win_info
* exec_info
= win_info
->detail
.source_info
.execution_info
;
537 werase (exec_info
->handle
);
538 tui_refresh_win (exec_info
);
542 tui_clear_exec_info_content (struct tui_win_info
* win_info
)
544 win_info
->detail
.source_info
.execution_info
->content_in_use
= FALSE
;
545 tui_erase_exec_info_content (win_info
);
550 /* Function to update the execution info window. */
552 tui_update_exec_info (struct tui_win_info
* win_info
)
554 tui_set_exec_info_content (win_info
);
555 tui_show_exec_info_content (win_info
);
559 tui_alloc_source_buffer (struct tui_win_info
*win_info
)
561 register char *src_line_buf
;
562 register int i
, line_width
, max_lines
;
563 enum tui_status ret
= TUI_FAILURE
;
565 max_lines
= win_info
->generic
.height
; /* less the highlight box */
566 line_width
= win_info
->generic
.width
- 1;
568 ** Allocate the buffer for the source lines. Do this only once since they
569 ** will be re-used for all source displays. The only other time this will
570 ** be done is when a window's size changes.
572 if (win_info
->generic
.content
== NULL
)
574 src_line_buf
= (char *) xmalloc ((max_lines
* line_width
) * sizeof (char));
575 if (src_line_buf
== (char *) NULL
)
577 "Unable to Allocate Memory for Source or Disassembly Display.\n",
581 /* allocate the content list */
582 if ((win_info
->generic
.content
=
583 (void **) tui_alloc_content (max_lines
, SRC_WIN
)) == NULL
)
585 xfree (src_line_buf
);
586 src_line_buf
= (char *) NULL
;
588 "Unable to Allocate Memory for Source or Disassembly Display.\n",
592 for (i
= 0; i
< max_lines
; i
++)
593 ((struct tui_win_element
*)
594 win_info
->generic
.content
[i
])->which_element
.source
.line
=
595 src_line_buf
+ (line_width
* i
);
605 /* Answer whether the a particular line number or address is displayed
606 in the current source window. */
608 tui_line_is_displayed (int line
, struct tui_win_info
* win_info
,
611 int is_displayed
= FALSE
;
615 threshold
= SCROLL_THRESHOLD
;
619 while (i
< win_info
->generic
.content_size
- threshold
&& !is_displayed
)
621 is_displayed
= (((struct tui_win_element
*)
622 win_info
->generic
.content
[i
])->which_element
.source
.line_or_addr
.line_no
631 /* Answer whether the a particular line number or address is displayed
632 in the current source window. */
634 tui_addr_is_displayed (CORE_ADDR addr
, struct tui_win_info
* win_info
,
637 int is_displayed
= FALSE
;
641 threshold
= SCROLL_THRESHOLD
;
645 while (i
< win_info
->generic
.content_size
- threshold
&& !is_displayed
)
647 is_displayed
= (((struct tui_win_element
*)
648 win_info
->generic
.content
[i
])->which_element
.source
.line_or_addr
.addr
657 /*****************************************
658 ** STATIC LOCAL FUNCTIONS **
659 ******************************************/