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"
53 #include "tuiGeneralWin.h"
54 #include "tuiSourceWin.h"
55 #include "tuiSource.h"
56 #include "tuiDisassem.h"
59 /* Function to display the "main" routine. */
61 tui_display_main (void)
63 if ((sourceWindows ())->count
> 0)
67 addr
= tuiGetBeginAsmAddress ();
68 if (addr
!= (CORE_ADDR
) 0)
70 struct symtab_and_line sal
;
72 tuiUpdateSourceWindowsWithAddr (addr
);
73 sal
= find_pc_line (addr
, 0);
75 tuiUpdateLocatorFilename (sal
.symtab
->filename
);
77 tuiUpdateLocatorFilename ("??");
85 ** tuiUpdateSourceWindow().
86 ** Function to display source in the source window. This function
87 ** initializes the horizontal scroll to 0.
90 tuiUpdateSourceWindow (TuiWinInfoPtr winInfo
, struct symtab
*s
,
91 TuiLineOrAddress lineOrAddr
, int noerror
)
93 winInfo
->detail
.sourceInfo
.horizontalOffset
= 0;
94 tuiUpdateSourceWindowAsIs (winInfo
, s
, lineOrAddr
, noerror
);
97 } /* tuiUpdateSourceWindow */
101 ** tuiUpdateSourceWindowAsIs().
102 ** Function to display source in the source/asm window. This
103 ** function shows the source as specified by the horizontal offset.
106 tuiUpdateSourceWindowAsIs (TuiWinInfoPtr winInfo
, struct symtab
*s
,
107 TuiLineOrAddress lineOrAddr
, int noerror
)
111 if (winInfo
->generic
.type
== SRC_WIN
)
112 ret
= tuiSetSourceContent (s
, lineOrAddr
.lineNo
, noerror
);
114 ret
= tuiSetDisassemContent (lineOrAddr
.addr
);
116 if (ret
== TUI_FAILURE
)
118 tuiClearSourceContent (winInfo
, EMPTY_SOURCE_PROMPT
);
119 tuiClearExecInfoContent (winInfo
);
123 tui_update_breakpoint_info (winInfo
, 0);
124 tuiShowSourceContent (winInfo
);
125 tuiUpdateExecInfo (winInfo
);
126 if (winInfo
->generic
.type
== SRC_WIN
)
128 current_source_line
= lineOrAddr
.lineNo
+
129 (winInfo
->generic
.contentSize
- 2);
130 current_source_symtab
= s
;
132 ** If the focus was in the asm win, put it in the src
133 ** win if we don't have a split layout
135 if (tuiWinWithFocus () == disassemWin
&&
136 currentLayout () != SRC_DISASSEM_COMMAND
)
137 tuiSetWinFocusTo (srcWin
);
143 } /* tuiUpdateSourceWindowAsIs */
147 ** tuiUpdateSourceWindowsWithAddr().
148 ** Function to ensure that the source and/or disassemly windows
149 ** reflect the input address.
152 tuiUpdateSourceWindowsWithAddr (CORE_ADDR addr
)
156 struct symtab_and_line sal
;
159 switch (currentLayout ())
161 case DISASSEM_COMMAND
:
162 case DISASSEM_DATA_COMMAND
:
163 tuiShowDisassem (addr
);
165 case SRC_DISASSEM_COMMAND
:
166 tuiShowDisassemAndUpdateSource (addr
);
169 sal
= find_pc_line (addr
, 0);
171 tuiShowSource (sal
.symtab
, l
, FALSE
);
179 for (i
= 0; i
< (sourceWindows ())->count
; i
++)
181 TuiWinInfoPtr winInfo
= (TuiWinInfoPtr
) (sourceWindows ())->list
[i
];
183 tuiClearSourceContent (winInfo
, EMPTY_SOURCE_PROMPT
);
184 tuiClearExecInfoContent (winInfo
);
189 } /* tuiUpdateSourceWindowsWithAddr */
192 ** tuiUpdateSourceWindowsWithLine().
193 ** Function to ensure that the source and/or disassemly windows
194 ** reflect the input address.
197 tuiUpdateSourceWindowsWithLine (struct symtab
*s
, int line
)
202 switch (currentLayout ())
204 case DISASSEM_COMMAND
:
205 case DISASSEM_DATA_COMMAND
:
206 find_line_pc (s
, line
, &pc
);
207 tuiUpdateSourceWindowsWithAddr (pc
);
211 tuiShowSource (s
, l
, FALSE
);
212 if (currentLayout () == SRC_DISASSEM_COMMAND
)
214 find_line_pc (s
, line
, &pc
);
215 tuiShowDisassem (pc
);
221 } /* tuiUpdateSourceWindowsWithLine */
224 ** tuiClearSourceContent().
227 tuiClearSourceContent (TuiWinInfoPtr winInfo
, int displayPrompt
)
229 if (m_winPtrNotNull (winInfo
))
233 winInfo
->generic
.contentInUse
= FALSE
;
234 tuiEraseSourceContent (winInfo
, displayPrompt
);
235 for (i
= 0; i
< winInfo
->generic
.contentSize
; i
++)
237 TuiWinElementPtr element
=
238 (TuiWinElementPtr
) winInfo
->generic
.content
[i
];
239 element
->whichElement
.source
.hasBreak
= FALSE
;
240 element
->whichElement
.source
.isExecPoint
= FALSE
;
245 } /* tuiClearSourceContent */
249 ** tuiEraseSourceContent().
252 tuiEraseSourceContent (TuiWinInfoPtr winInfo
, int displayPrompt
)
255 int halfWidth
= (winInfo
->generic
.width
- 2) / 2;
257 if (winInfo
->generic
.handle
!= (WINDOW
*) NULL
)
259 werase (winInfo
->generic
.handle
);
260 checkAndDisplayHighlightIfNeeded (winInfo
);
261 if (displayPrompt
== EMPTY_SOURCE_PROMPT
)
265 if (winInfo
->generic
.type
== SRC_WIN
)
266 noSrcStr
= NO_SRC_STRING
;
268 noSrcStr
= NO_DISASSEM_STRING
;
269 if (strlen (noSrcStr
) >= halfWidth
)
272 xPos
= halfWidth
- strlen (noSrcStr
);
273 mvwaddstr (winInfo
->generic
.handle
,
274 (winInfo
->generic
.height
/ 2),
278 /* elz: added this function call to set the real contents of
279 the window to what is on the screen, so that later calls
280 to refresh, do display
281 the correct stuff, and not the old image */
283 tuiSetSourceContentNil (winInfo
, noSrcStr
);
285 tuiRefreshWin (&winInfo
->generic
);
288 } /* tuiEraseSourceContent */
291 /* Redraw the complete line of a source or disassembly window. */
293 tui_show_source_line (TuiWinInfoPtr winInfo
, int lineno
)
295 TuiWinElementPtr line
;
298 line
= (TuiWinElementPtr
) winInfo
->generic
.content
[lineno
- 1];
299 if (line
->whichElement
.source
.isExecPoint
)
300 wattron (winInfo
->generic
.handle
, A_STANDOUT
);
302 mvwaddstr (winInfo
->generic
.handle
, lineno
, 1,
303 line
->whichElement
.source
.line
);
304 if (line
->whichElement
.source
.isExecPoint
)
305 wattroff (winInfo
->generic
.handle
, A_STANDOUT
);
307 /* Clear to end of line but stop before the border. */
308 getyx (winInfo
->generic
.handle
, y
, x
);
309 while (x
+ 1 < winInfo
->generic
.width
)
311 waddch (winInfo
->generic
.handle
, ' ');
312 getyx (winInfo
->generic
.handle
, y
, x
);
317 ** tuiShowSourceContent().
320 tuiShowSourceContent (TuiWinInfoPtr winInfo
)
322 if (winInfo
->generic
.contentSize
> 0)
326 for (lineno
= 1; lineno
<= winInfo
->generic
.contentSize
; lineno
++)
327 tui_show_source_line (winInfo
, lineno
);
330 tuiEraseSourceContent (winInfo
, TRUE
);
332 checkAndDisplayHighlightIfNeeded (winInfo
);
333 tuiRefreshWin (&winInfo
->generic
);
334 winInfo
->generic
.contentInUse
= TRUE
;
339 ** tuiHorizontalSourceScroll().
340 ** Scroll the source forward or backward horizontally
343 tuiHorizontalSourceScroll (TuiWinInfoPtr winInfo
,
344 TuiScrollDirection direction
,
347 if (winInfo
->generic
.content
!= (OpaquePtr
) NULL
)
352 if (current_source_symtab
== (struct symtab
*) NULL
)
353 s
= find_pc_symtab (selected_frame
->pc
);
355 s
= current_source_symtab
;
357 if (direction
== LEFT_SCROLL
)
358 offset
= winInfo
->detail
.sourceInfo
.horizontalOffset
+ numToScroll
;
362 winInfo
->detail
.sourceInfo
.horizontalOffset
- numToScroll
) < 0)
365 winInfo
->detail
.sourceInfo
.horizontalOffset
= offset
;
366 tuiUpdateSourceWindowAsIs (
370 winInfo
->generic
.content
[0])->whichElement
.source
.lineOrAddr
,
375 } /* tuiHorizontalSourceScroll */
379 ** tuiSetHasExecPointAt().
380 ** Set or clear the hasBreak flag in the line whose line is lineNo.
383 tuiSetIsExecPointAt (TuiLineOrAddress l
, TuiWinInfoPtr winInfo
)
386 TuiWinContent content
= (TuiWinContent
) winInfo
->generic
.content
;
389 while (i
< winInfo
->generic
.contentSize
)
391 if (content
[i
]->whichElement
.source
.lineOrAddr
.addr
== l
.addr
)
392 content
[i
]->whichElement
.source
.isExecPoint
= TRUE
;
394 content
[i
]->whichElement
.source
.isExecPoint
= FALSE
;
399 } /* tuiSetIsExecPointAt */
401 /* Update the execution windows to show the active breakpoints.
402 This is called whenever a breakpoint is inserted, removed or
403 has its state changed. */
405 tui_update_all_breakpoint_info ()
407 TuiList
* list
= sourceWindows ();
410 for (i
= 0; i
< list
->count
; i
++)
412 TuiWinInfoPtr win
= (TuiWinInfoPtr
) list
->list
[i
];
414 if (tui_update_breakpoint_info (win
, FALSE
))
416 tuiUpdateExecInfo (win
);
422 /* Scan the source window and the breakpoints to update the
423 hasBreak information for each line.
424 Returns 1 if something changed and the execution window
425 must be refreshed. */
427 tui_update_breakpoint_info (TuiWinInfoPtr win
, int current_only
)
430 int need_refresh
= 0;
431 TuiSourceInfoPtr src
= &win
->detail
.sourceInfo
;
433 for (i
= 0; i
< win
->generic
.contentSize
; i
++)
435 struct breakpoint
*bp
;
436 extern struct breakpoint
*breakpoint_chain
;
438 TuiSourceElement
* line
;
440 line
= &((TuiWinElementPtr
) win
->generic
.content
[i
])->whichElement
.source
;
441 if (current_only
&& !line
->isExecPoint
)
444 /* Scan each breakpoint to see if the current line has something to
445 do with it. Identify enable/disabled breakpoints as well as
446 those that we already hit. */
448 for (bp
= breakpoint_chain
;
449 bp
!= (struct breakpoint
*) NULL
;
454 && (strcmp (src
->filename
, bp
->source_file
) == 0)
455 && bp
->line_number
== line
->lineOrAddr
.lineNo
)
456 || (win
== disassemWin
457 && bp
->address
== line
->lineOrAddr
.addr
))
459 if (bp
->enable_state
== bp_disabled
)
460 mode
|= TUI_BP_DISABLED
;
462 mode
|= TUI_BP_ENABLED
;
466 mode
|= TUI_BP_CONDITIONAL
;
467 if (bp
->type
== bp_hardware_breakpoint
)
468 mode
|= TUI_BP_HARDWARE
;
471 if (line
->hasBreak
!= mode
)
473 line
->hasBreak
= mode
;
482 ** tuiSetExecInfoContent().
483 ** Function to initialize the content of the execution info window,
484 ** based upon the input window which is either the source or
485 ** disassembly window.
488 tuiSetExecInfoContent (TuiWinInfoPtr winInfo
)
490 TuiStatus ret
= TUI_SUCCESS
;
492 if (winInfo
->detail
.sourceInfo
.executionInfo
!= (TuiGenWinInfoPtr
) NULL
)
494 TuiGenWinInfoPtr execInfoPtr
= winInfo
->detail
.sourceInfo
.executionInfo
;
496 if (execInfoPtr
->content
== (OpaquePtr
) NULL
)
497 execInfoPtr
->content
=
498 (OpaquePtr
) allocContent (winInfo
->generic
.height
,
500 if (execInfoPtr
->content
!= (OpaquePtr
) NULL
)
504 tui_update_breakpoint_info (winInfo
, 1);
505 for (i
= 0; i
< winInfo
->generic
.contentSize
; i
++)
507 TuiWinElementPtr element
;
508 TuiWinElementPtr srcElement
;
511 element
= (TuiWinElementPtr
) execInfoPtr
->content
[i
];
512 srcElement
= (TuiWinElementPtr
) winInfo
->generic
.content
[i
];
514 memset(element
->whichElement
.simpleString
, ' ',
515 sizeof(element
->whichElement
.simpleString
));
516 element
->whichElement
.simpleString
[TUI_EXECINFO_SIZE
- 1] = 0;
518 /* Now update the exec info content based upon the state
519 of each line as indicated by the source content. */
520 mode
= srcElement
->whichElement
.source
.hasBreak
;
521 if (mode
& TUI_BP_HIT
)
522 element
->whichElement
.simpleString
[TUI_BP_HIT_POS
] =
523 (mode
& TUI_BP_HARDWARE
) ? 'H' : 'B';
524 else if (mode
& (TUI_BP_ENABLED
| TUI_BP_DISABLED
))
525 element
->whichElement
.simpleString
[TUI_BP_HIT_POS
] =
526 (mode
& TUI_BP_HARDWARE
) ? 'h' : 'b';
528 if (mode
& TUI_BP_ENABLED
)
529 element
->whichElement
.simpleString
[TUI_BP_BREAK_POS
] = '+';
530 else if (mode
& TUI_BP_DISABLED
)
531 element
->whichElement
.simpleString
[TUI_BP_BREAK_POS
] = '-';
533 if (srcElement
->whichElement
.source
.isExecPoint
)
534 element
->whichElement
.simpleString
[TUI_EXEC_POS
] = '>';
536 execInfoPtr
->contentSize
= winInfo
->generic
.contentSize
;
547 ** tuiShowExecInfoContent().
550 tuiShowExecInfoContent (TuiWinInfoPtr winInfo
)
552 TuiGenWinInfoPtr execInfo
= winInfo
->detail
.sourceInfo
.executionInfo
;
555 werase (execInfo
->handle
);
556 tuiRefreshWin (execInfo
);
557 for (curLine
= 1; (curLine
<= execInfo
->contentSize
); curLine
++)
558 mvwaddstr (execInfo
->handle
,
562 execInfo
->content
[curLine
- 1])->whichElement
.simpleString
);
563 tuiRefreshWin (execInfo
);
564 execInfo
->contentInUse
= TRUE
;
567 } /* tuiShowExecInfoContent */
571 ** tuiEraseExecInfoContent().
574 tuiEraseExecInfoContent (TuiWinInfoPtr winInfo
)
576 TuiGenWinInfoPtr execInfo
= winInfo
->detail
.sourceInfo
.executionInfo
;
578 werase (execInfo
->handle
);
579 tuiRefreshWin (execInfo
);
582 } /* tuiEraseExecInfoContent */
585 ** tuiClearExecInfoContent().
588 tuiClearExecInfoContent (TuiWinInfoPtr winInfo
)
590 winInfo
->detail
.sourceInfo
.executionInfo
->contentInUse
= FALSE
;
591 tuiEraseExecInfoContent (winInfo
);
594 } /* tuiClearExecInfoContent */
597 ** tuiUpdateExecInfo().
598 ** Function to update the execution info window
601 tuiUpdateExecInfo (TuiWinInfoPtr winInfo
)
603 tuiSetExecInfoContent (winInfo
);
604 tuiShowExecInfoContent (winInfo
);
605 } /* tuiUpdateExecInfo */
609 ** tuiUpdateAllExecInfos()
612 tuiUpdateAllExecInfos (void)
616 for (i
= 0; i
< (sourceWindows ())->count
; i
++)
617 tuiUpdateExecInfo ((TuiWinInfoPtr
) (sourceWindows ())->list
[i
]);
620 } /* tuiUpdateAllExecInfos */
623 tuiAllocSourceBuffer (TuiWinInfoPtr winInfo
)
625 register char *srcLineBuf
;
626 register int i
, lineWidth
, maxLines
;
627 TuiStatus ret
= TUI_FAILURE
;
629 maxLines
= winInfo
->generic
.height
; /* less the highlight box */
630 lineWidth
= winInfo
->generic
.width
- 1;
632 ** Allocate the buffer for the source lines. Do this only once since they
633 ** will be re-used for all source displays. The only other time this will
634 ** be done is when a window's size changes.
636 if (winInfo
->generic
.content
== (OpaquePtr
) NULL
)
638 srcLineBuf
= (char *) xmalloc ((maxLines
* lineWidth
) * sizeof (char));
639 if (srcLineBuf
== (char *) NULL
)
641 "Unable to Allocate Memory for Source or Disassembly Display.\n",
645 /* allocate the content list */
646 if ((winInfo
->generic
.content
=
647 (OpaquePtr
) allocContent (maxLines
, SRC_WIN
)) == (OpaquePtr
) NULL
)
649 tuiFree (srcLineBuf
);
650 srcLineBuf
= (char *) NULL
;
652 "Unable to Allocate Memory for Source or Disassembly Display.\n",
656 for (i
= 0; i
< maxLines
; i
++)
658 winInfo
->generic
.content
[i
])->whichElement
.source
.line
=
659 srcLineBuf
+ (lineWidth
* i
);
666 } /* tuiAllocSourceBuffer */
670 ** tuiLineIsDisplayed().
671 ** Answer whether the a particular line number or address is displayed
672 ** in the current source window.
675 tuiLineIsDisplayed (int line
, TuiWinInfoPtr winInfo
,
678 int isDisplayed
= FALSE
;
682 threshold
= SCROLL_THRESHOLD
;
686 while (i
< winInfo
->generic
.contentSize
- threshold
&& !isDisplayed
)
688 isDisplayed
= (((TuiWinElementPtr
)
689 winInfo
->generic
.content
[i
])->whichElement
.source
.lineOrAddr
.lineNo
695 } /* tuiLineIsDisplayed */
699 ** tuiLineIsDisplayed().
700 ** Answer whether the a particular line number or address is displayed
701 ** in the current source window.
704 tuiAddrIsDisplayed (CORE_ADDR addr
, TuiWinInfoPtr winInfo
,
707 int isDisplayed
= FALSE
;
711 threshold
= SCROLL_THRESHOLD
;
715 while (i
< winInfo
->generic
.contentSize
- threshold
&& !isDisplayed
)
717 isDisplayed
= (((TuiWinElementPtr
)
718 winInfo
->generic
.content
[i
])->whichElement
.source
.lineOrAddr
.addr
727 /*****************************************
728 ** STATIC LOCAL FUNCTIONS **
729 ******************************************/