1 /* TUI display source/assembly window.
3 Copyright 1998, 1999, 2000, 2001, 2002 Free Software Foundation,
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. */
25 /* FIXME: cagney/2002-02-28: The GDB coding standard indicates that
26 "defs.h" should be included first. Unfortunatly some systems
27 (currently Debian GNU/Linux) include the <stdbool.h> via <curses.h>
28 and they clash with "bfd.h"'s definiton of true/false. The correct
29 fix is to remove true/false from "bfd.h", however, until that
30 happens, hack around it by including "config.h" and <curses.h>
46 #include "breakpoint.h"
54 #include "tuiGeneralWin.h"
55 #include "tuiSourceWin.h"
56 #include "tuiSource.h"
57 #include "tuiDisassem.h"
60 /* Function to display the "main" routine. */
62 tui_display_main (void)
64 if ((sourceWindows ())->count
> 0)
68 addr
= tuiGetBeginAsmAddress ();
69 if (addr
!= (CORE_ADDR
) 0)
71 struct symtab_and_line sal
;
73 tuiUpdateSourceWindowsWithAddr (addr
);
74 sal
= find_pc_line (addr
, 0);
76 tuiUpdateLocatorFilename (sal
.symtab
->filename
);
78 tuiUpdateLocatorFilename ("??");
86 ** tuiUpdateSourceWindow().
87 ** Function to display source in the source window. This function
88 ** initializes the horizontal scroll to 0.
91 tuiUpdateSourceWindow (TuiWinInfoPtr winInfo
, struct symtab
*s
,
92 TuiLineOrAddress lineOrAddr
, int noerror
)
94 winInfo
->detail
.sourceInfo
.horizontalOffset
= 0;
95 tuiUpdateSourceWindowAsIs (winInfo
, s
, lineOrAddr
, noerror
);
98 } /* tuiUpdateSourceWindow */
102 ** tuiUpdateSourceWindowAsIs().
103 ** Function to display source in the source/asm window. This
104 ** function shows the source as specified by the horizontal offset.
107 tuiUpdateSourceWindowAsIs (TuiWinInfoPtr winInfo
, struct symtab
*s
,
108 TuiLineOrAddress lineOrAddr
, int noerror
)
112 if (winInfo
->generic
.type
== SRC_WIN
)
113 ret
= tuiSetSourceContent (s
, lineOrAddr
.lineNo
, noerror
);
115 ret
= tuiSetDisassemContent (lineOrAddr
.addr
);
117 if (ret
== TUI_FAILURE
)
119 tuiClearSourceContent (winInfo
, EMPTY_SOURCE_PROMPT
);
120 tuiClearExecInfoContent (winInfo
);
124 tui_update_breakpoint_info (winInfo
, 0);
125 tuiShowSourceContent (winInfo
);
126 tuiUpdateExecInfo (winInfo
);
127 if (winInfo
->generic
.type
== SRC_WIN
)
129 struct symtab_and_line sal
;
131 sal
.line
= lineOrAddr
.lineNo
+
132 (winInfo
->generic
.contentSize
- 2);
134 set_current_source_symtab_and_line (&sal
);
136 ** If the focus was in the asm win, put it in the src
137 ** win if we don't have a split layout
139 if (tuiWinWithFocus () == disassemWin
&&
140 currentLayout () != SRC_DISASSEM_COMMAND
)
141 tuiSetWinFocusTo (srcWin
);
147 } /* tuiUpdateSourceWindowAsIs */
151 ** tuiUpdateSourceWindowsWithAddr().
152 ** Function to ensure that the source and/or disassemly windows
153 ** reflect the input address.
156 tuiUpdateSourceWindowsWithAddr (CORE_ADDR addr
)
160 struct symtab_and_line sal
;
163 switch (currentLayout ())
165 case DISASSEM_COMMAND
:
166 case DISASSEM_DATA_COMMAND
:
167 tuiShowDisassem (addr
);
169 case SRC_DISASSEM_COMMAND
:
170 tuiShowDisassemAndUpdateSource (addr
);
173 sal
= find_pc_line (addr
, 0);
175 tuiShowSource (sal
.symtab
, l
, FALSE
);
183 for (i
= 0; i
< (sourceWindows ())->count
; i
++)
185 TuiWinInfoPtr winInfo
= (TuiWinInfoPtr
) (sourceWindows ())->list
[i
];
187 tuiClearSourceContent (winInfo
, EMPTY_SOURCE_PROMPT
);
188 tuiClearExecInfoContent (winInfo
);
193 } /* tuiUpdateSourceWindowsWithAddr */
196 ** tuiUpdateSourceWindowsWithLine().
197 ** Function to ensure that the source and/or disassemly windows
198 ** reflect the input address.
201 tuiUpdateSourceWindowsWithLine (struct symtab
*s
, int line
)
206 switch (currentLayout ())
208 case DISASSEM_COMMAND
:
209 case DISASSEM_DATA_COMMAND
:
210 find_line_pc (s
, line
, &pc
);
211 tuiUpdateSourceWindowsWithAddr (pc
);
215 tuiShowSource (s
, l
, FALSE
);
216 if (currentLayout () == SRC_DISASSEM_COMMAND
)
218 find_line_pc (s
, line
, &pc
);
219 tuiShowDisassem (pc
);
225 } /* tuiUpdateSourceWindowsWithLine */
228 ** tuiClearSourceContent().
231 tuiClearSourceContent (TuiWinInfoPtr winInfo
, int displayPrompt
)
233 if (m_winPtrNotNull (winInfo
))
237 winInfo
->generic
.contentInUse
= FALSE
;
238 tuiEraseSourceContent (winInfo
, displayPrompt
);
239 for (i
= 0; i
< winInfo
->generic
.contentSize
; i
++)
241 TuiWinElementPtr element
=
242 (TuiWinElementPtr
) winInfo
->generic
.content
[i
];
243 element
->whichElement
.source
.hasBreak
= FALSE
;
244 element
->whichElement
.source
.isExecPoint
= FALSE
;
249 } /* tuiClearSourceContent */
253 ** tuiEraseSourceContent().
256 tuiEraseSourceContent (TuiWinInfoPtr winInfo
, int displayPrompt
)
259 int halfWidth
= (winInfo
->generic
.width
- 2) / 2;
261 if (winInfo
->generic
.handle
!= (WINDOW
*) NULL
)
263 werase (winInfo
->generic
.handle
);
264 checkAndDisplayHighlightIfNeeded (winInfo
);
265 if (displayPrompt
== EMPTY_SOURCE_PROMPT
)
269 if (winInfo
->generic
.type
== SRC_WIN
)
270 noSrcStr
= NO_SRC_STRING
;
272 noSrcStr
= NO_DISASSEM_STRING
;
273 if (strlen (noSrcStr
) >= halfWidth
)
276 xPos
= halfWidth
- strlen (noSrcStr
);
277 mvwaddstr (winInfo
->generic
.handle
,
278 (winInfo
->generic
.height
/ 2),
282 /* elz: added this function call to set the real contents of
283 the window to what is on the screen, so that later calls
284 to refresh, do display
285 the correct stuff, and not the old image */
287 tuiSetSourceContentNil (winInfo
, noSrcStr
);
289 tuiRefreshWin (&winInfo
->generic
);
292 } /* tuiEraseSourceContent */
295 /* Redraw the complete line of a source or disassembly window. */
297 tui_show_source_line (TuiWinInfoPtr winInfo
, int lineno
)
299 TuiWinElementPtr line
;
302 line
= (TuiWinElementPtr
) winInfo
->generic
.content
[lineno
- 1];
303 if (line
->whichElement
.source
.isExecPoint
)
304 wattron (winInfo
->generic
.handle
, A_STANDOUT
);
306 mvwaddstr (winInfo
->generic
.handle
, lineno
, 1,
307 line
->whichElement
.source
.line
);
308 if (line
->whichElement
.source
.isExecPoint
)
309 wattroff (winInfo
->generic
.handle
, A_STANDOUT
);
311 /* Clear to end of line but stop before the border. */
312 getyx (winInfo
->generic
.handle
, y
, x
);
313 while (x
+ 1 < winInfo
->generic
.width
)
315 waddch (winInfo
->generic
.handle
, ' ');
316 getyx (winInfo
->generic
.handle
, y
, x
);
321 ** tuiShowSourceContent().
324 tuiShowSourceContent (TuiWinInfoPtr winInfo
)
326 if (winInfo
->generic
.contentSize
> 0)
330 for (lineno
= 1; lineno
<= winInfo
->generic
.contentSize
; lineno
++)
331 tui_show_source_line (winInfo
, lineno
);
334 tuiEraseSourceContent (winInfo
, TRUE
);
336 checkAndDisplayHighlightIfNeeded (winInfo
);
337 tuiRefreshWin (&winInfo
->generic
);
338 winInfo
->generic
.contentInUse
= TRUE
;
343 ** tuiHorizontalSourceScroll().
344 ** Scroll the source forward or backward horizontally
347 tuiHorizontalSourceScroll (TuiWinInfoPtr winInfo
,
348 TuiScrollDirection direction
,
351 if (winInfo
->generic
.content
!= (OpaquePtr
) NULL
)
355 struct symtab_and_line cursal
= get_current_source_symtab_and_line ();
357 if (cursal
.symtab
== (struct symtab
*) NULL
)
358 s
= find_pc_symtab (get_frame_pc (deprecated_selected_frame
));
362 if (direction
== LEFT_SCROLL
)
363 offset
= winInfo
->detail
.sourceInfo
.horizontalOffset
+ numToScroll
;
367 winInfo
->detail
.sourceInfo
.horizontalOffset
- numToScroll
) < 0)
370 winInfo
->detail
.sourceInfo
.horizontalOffset
= offset
;
371 tuiUpdateSourceWindowAsIs (
375 winInfo
->generic
.content
[0])->whichElement
.source
.lineOrAddr
,
380 } /* tuiHorizontalSourceScroll */
383 /* Set or clear the hasBreak flag in the line whose line is lineNo. */
385 tuiSetIsExecPointAt (TuiLineOrAddress l
, TuiWinInfoPtr winInfo
)
389 TuiWinContent content
= (TuiWinContent
) winInfo
->generic
.content
;
392 while (i
< winInfo
->generic
.contentSize
)
396 if (content
[i
]->whichElement
.source
.lineOrAddr
.addr
== l
.addr
)
400 if (newState
!= content
[i
]->whichElement
.source
.isExecPoint
)
403 content
[i
]->whichElement
.source
.isExecPoint
= newState
;
404 tui_show_source_line (winInfo
, i
+ 1);
409 tuiRefreshWin (&winInfo
->generic
);
412 /* Update the execution windows to show the active breakpoints.
413 This is called whenever a breakpoint is inserted, removed or
414 has its state changed. */
416 tui_update_all_breakpoint_info ()
418 TuiList
* list
= sourceWindows ();
421 for (i
= 0; i
< list
->count
; i
++)
423 TuiWinInfoPtr win
= (TuiWinInfoPtr
) list
->list
[i
];
425 if (tui_update_breakpoint_info (win
, FALSE
))
427 tuiUpdateExecInfo (win
);
433 /* Scan the source window and the breakpoints to update the
434 hasBreak information for each line.
435 Returns 1 if something changed and the execution window
436 must be refreshed. */
438 tui_update_breakpoint_info (TuiWinInfoPtr win
, int current_only
)
441 int need_refresh
= 0;
442 TuiSourceInfoPtr src
= &win
->detail
.sourceInfo
;
444 for (i
= 0; i
< win
->generic
.contentSize
; i
++)
446 struct breakpoint
*bp
;
447 extern struct breakpoint
*breakpoint_chain
;
449 TuiSourceElement
* line
;
451 line
= &((TuiWinElementPtr
) win
->generic
.content
[i
])->whichElement
.source
;
452 if (current_only
&& !line
->isExecPoint
)
455 /* Scan each breakpoint to see if the current line has something to
456 do with it. Identify enable/disabled breakpoints as well as
457 those that we already hit. */
459 for (bp
= breakpoint_chain
;
460 bp
!= (struct breakpoint
*) NULL
;
465 && (strcmp (src
->filename
, bp
->source_file
) == 0)
466 && bp
->line_number
== line
->lineOrAddr
.lineNo
)
467 || (win
== disassemWin
468 && bp
->address
== line
->lineOrAddr
.addr
))
470 if (bp
->enable_state
== bp_disabled
)
471 mode
|= TUI_BP_DISABLED
;
473 mode
|= TUI_BP_ENABLED
;
477 mode
|= TUI_BP_CONDITIONAL
;
478 if (bp
->type
== bp_hardware_breakpoint
)
479 mode
|= TUI_BP_HARDWARE
;
482 if (line
->hasBreak
!= mode
)
484 line
->hasBreak
= mode
;
493 ** tuiSetExecInfoContent().
494 ** Function to initialize the content of the execution info window,
495 ** based upon the input window which is either the source or
496 ** disassembly window.
499 tuiSetExecInfoContent (TuiWinInfoPtr winInfo
)
501 TuiStatus ret
= TUI_SUCCESS
;
503 if (winInfo
->detail
.sourceInfo
.executionInfo
!= (TuiGenWinInfoPtr
) NULL
)
505 TuiGenWinInfoPtr execInfoPtr
= winInfo
->detail
.sourceInfo
.executionInfo
;
507 if (execInfoPtr
->content
== (OpaquePtr
) NULL
)
508 execInfoPtr
->content
=
509 (OpaquePtr
) allocContent (winInfo
->generic
.height
,
511 if (execInfoPtr
->content
!= (OpaquePtr
) NULL
)
515 tui_update_breakpoint_info (winInfo
, 1);
516 for (i
= 0; i
< winInfo
->generic
.contentSize
; i
++)
518 TuiWinElementPtr element
;
519 TuiWinElementPtr srcElement
;
522 element
= (TuiWinElementPtr
) execInfoPtr
->content
[i
];
523 srcElement
= (TuiWinElementPtr
) winInfo
->generic
.content
[i
];
525 memset(element
->whichElement
.simpleString
, ' ',
526 sizeof(element
->whichElement
.simpleString
));
527 element
->whichElement
.simpleString
[TUI_EXECINFO_SIZE
- 1] = 0;
529 /* Now update the exec info content based upon the state
530 of each line as indicated by the source content. */
531 mode
= srcElement
->whichElement
.source
.hasBreak
;
532 if (mode
& TUI_BP_HIT
)
533 element
->whichElement
.simpleString
[TUI_BP_HIT_POS
] =
534 (mode
& TUI_BP_HARDWARE
) ? 'H' : 'B';
535 else if (mode
& (TUI_BP_ENABLED
| TUI_BP_DISABLED
))
536 element
->whichElement
.simpleString
[TUI_BP_HIT_POS
] =
537 (mode
& TUI_BP_HARDWARE
) ? 'h' : 'b';
539 if (mode
& TUI_BP_ENABLED
)
540 element
->whichElement
.simpleString
[TUI_BP_BREAK_POS
] = '+';
541 else if (mode
& TUI_BP_DISABLED
)
542 element
->whichElement
.simpleString
[TUI_BP_BREAK_POS
] = '-';
544 if (srcElement
->whichElement
.source
.isExecPoint
)
545 element
->whichElement
.simpleString
[TUI_EXEC_POS
] = '>';
547 execInfoPtr
->contentSize
= winInfo
->generic
.contentSize
;
558 ** tuiShowExecInfoContent().
561 tuiShowExecInfoContent (TuiWinInfoPtr winInfo
)
563 TuiGenWinInfoPtr execInfo
= winInfo
->detail
.sourceInfo
.executionInfo
;
566 werase (execInfo
->handle
);
567 tuiRefreshWin (execInfo
);
568 for (curLine
= 1; (curLine
<= execInfo
->contentSize
); curLine
++)
569 mvwaddstr (execInfo
->handle
,
573 execInfo
->content
[curLine
- 1])->whichElement
.simpleString
);
574 tuiRefreshWin (execInfo
);
575 execInfo
->contentInUse
= TRUE
;
578 } /* tuiShowExecInfoContent */
582 ** tuiEraseExecInfoContent().
585 tuiEraseExecInfoContent (TuiWinInfoPtr winInfo
)
587 TuiGenWinInfoPtr execInfo
= winInfo
->detail
.sourceInfo
.executionInfo
;
589 werase (execInfo
->handle
);
590 tuiRefreshWin (execInfo
);
593 } /* tuiEraseExecInfoContent */
596 ** tuiClearExecInfoContent().
599 tuiClearExecInfoContent (TuiWinInfoPtr winInfo
)
601 winInfo
->detail
.sourceInfo
.executionInfo
->contentInUse
= FALSE
;
602 tuiEraseExecInfoContent (winInfo
);
605 } /* tuiClearExecInfoContent */
608 ** tuiUpdateExecInfo().
609 ** Function to update the execution info window
612 tuiUpdateExecInfo (TuiWinInfoPtr winInfo
)
614 tuiSetExecInfoContent (winInfo
);
615 tuiShowExecInfoContent (winInfo
);
616 } /* tuiUpdateExecInfo */
619 tuiAllocSourceBuffer (TuiWinInfoPtr winInfo
)
621 register char *srcLineBuf
;
622 register int i
, lineWidth
, maxLines
;
623 TuiStatus ret
= TUI_FAILURE
;
625 maxLines
= winInfo
->generic
.height
; /* less the highlight box */
626 lineWidth
= winInfo
->generic
.width
- 1;
628 ** Allocate the buffer for the source lines. Do this only once since they
629 ** will be re-used for all source displays. The only other time this will
630 ** be done is when a window's size changes.
632 if (winInfo
->generic
.content
== (OpaquePtr
) NULL
)
634 srcLineBuf
= (char *) xmalloc ((maxLines
* lineWidth
) * sizeof (char));
635 if (srcLineBuf
== (char *) NULL
)
637 "Unable to Allocate Memory for Source or Disassembly Display.\n",
641 /* allocate the content list */
642 if ((winInfo
->generic
.content
=
643 (OpaquePtr
) allocContent (maxLines
, SRC_WIN
)) == (OpaquePtr
) NULL
)
645 tuiFree (srcLineBuf
);
646 srcLineBuf
= (char *) NULL
;
648 "Unable to Allocate Memory for Source or Disassembly Display.\n",
652 for (i
= 0; i
< maxLines
; i
++)
654 winInfo
->generic
.content
[i
])->whichElement
.source
.line
=
655 srcLineBuf
+ (lineWidth
* i
);
662 } /* tuiAllocSourceBuffer */
666 ** tuiLineIsDisplayed().
667 ** Answer whether the a particular line number or address is displayed
668 ** in the current source window.
671 tuiLineIsDisplayed (int line
, TuiWinInfoPtr winInfo
,
674 int isDisplayed
= FALSE
;
678 threshold
= SCROLL_THRESHOLD
;
682 while (i
< winInfo
->generic
.contentSize
- threshold
&& !isDisplayed
)
684 isDisplayed
= (((TuiWinElementPtr
)
685 winInfo
->generic
.content
[i
])->whichElement
.source
.lineOrAddr
.lineNo
691 } /* tuiLineIsDisplayed */
695 ** tuiLineIsDisplayed().
696 ** Answer whether the a particular line number or address is displayed
697 ** in the current source window.
700 tuiAddrIsDisplayed (CORE_ADDR addr
, TuiWinInfoPtr winInfo
,
703 int isDisplayed
= FALSE
;
707 threshold
= SCROLL_THRESHOLD
;
711 while (i
< winInfo
->generic
.contentSize
- threshold
&& !isDisplayed
)
713 isDisplayed
= (((TuiWinElementPtr
)
714 winInfo
->generic
.content
[i
])->whichElement
.source
.lineOrAddr
.addr
723 /*****************************************
724 ** STATIC LOCAL FUNCTIONS **
725 ******************************************/