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 */
378 /* Set or clear the hasBreak flag in the line whose line is lineNo. */
380 tuiSetIsExecPointAt (TuiLineOrAddress l
, TuiWinInfoPtr winInfo
)
384 TuiWinContent content
= (TuiWinContent
) winInfo
->generic
.content
;
387 while (i
< winInfo
->generic
.contentSize
)
391 if (content
[i
]->whichElement
.source
.lineOrAddr
.addr
== l
.addr
)
395 if (newState
!= content
[i
]->whichElement
.source
.isExecPoint
)
398 content
[i
]->whichElement
.source
.isExecPoint
= newState
;
399 tui_show_source_line (winInfo
, i
+ 1);
404 tuiRefreshWin (&winInfo
->generic
);
407 /* Update the execution windows to show the active breakpoints.
408 This is called whenever a breakpoint is inserted, removed or
409 has its state changed. */
411 tui_update_all_breakpoint_info ()
413 TuiList
* list
= sourceWindows ();
416 for (i
= 0; i
< list
->count
; i
++)
418 TuiWinInfoPtr win
= (TuiWinInfoPtr
) list
->list
[i
];
420 if (tui_update_breakpoint_info (win
, FALSE
))
422 tuiUpdateExecInfo (win
);
428 /* Scan the source window and the breakpoints to update the
429 hasBreak information for each line.
430 Returns 1 if something changed and the execution window
431 must be refreshed. */
433 tui_update_breakpoint_info (TuiWinInfoPtr win
, int current_only
)
436 int need_refresh
= 0;
437 TuiSourceInfoPtr src
= &win
->detail
.sourceInfo
;
439 for (i
= 0; i
< win
->generic
.contentSize
; i
++)
441 struct breakpoint
*bp
;
442 extern struct breakpoint
*breakpoint_chain
;
444 TuiSourceElement
* line
;
446 line
= &((TuiWinElementPtr
) win
->generic
.content
[i
])->whichElement
.source
;
447 if (current_only
&& !line
->isExecPoint
)
450 /* Scan each breakpoint to see if the current line has something to
451 do with it. Identify enable/disabled breakpoints as well as
452 those that we already hit. */
454 for (bp
= breakpoint_chain
;
455 bp
!= (struct breakpoint
*) NULL
;
460 && (strcmp (src
->filename
, bp
->source_file
) == 0)
461 && bp
->line_number
== line
->lineOrAddr
.lineNo
)
462 || (win
== disassemWin
463 && bp
->address
== line
->lineOrAddr
.addr
))
465 if (bp
->enable_state
== bp_disabled
)
466 mode
|= TUI_BP_DISABLED
;
468 mode
|= TUI_BP_ENABLED
;
472 mode
|= TUI_BP_CONDITIONAL
;
473 if (bp
->type
== bp_hardware_breakpoint
)
474 mode
|= TUI_BP_HARDWARE
;
477 if (line
->hasBreak
!= mode
)
479 line
->hasBreak
= mode
;
488 ** tuiSetExecInfoContent().
489 ** Function to initialize the content of the execution info window,
490 ** based upon the input window which is either the source or
491 ** disassembly window.
494 tuiSetExecInfoContent (TuiWinInfoPtr winInfo
)
496 TuiStatus ret
= TUI_SUCCESS
;
498 if (winInfo
->detail
.sourceInfo
.executionInfo
!= (TuiGenWinInfoPtr
) NULL
)
500 TuiGenWinInfoPtr execInfoPtr
= winInfo
->detail
.sourceInfo
.executionInfo
;
502 if (execInfoPtr
->content
== (OpaquePtr
) NULL
)
503 execInfoPtr
->content
=
504 (OpaquePtr
) allocContent (winInfo
->generic
.height
,
506 if (execInfoPtr
->content
!= (OpaquePtr
) NULL
)
510 tui_update_breakpoint_info (winInfo
, 1);
511 for (i
= 0; i
< winInfo
->generic
.contentSize
; i
++)
513 TuiWinElementPtr element
;
514 TuiWinElementPtr srcElement
;
517 element
= (TuiWinElementPtr
) execInfoPtr
->content
[i
];
518 srcElement
= (TuiWinElementPtr
) winInfo
->generic
.content
[i
];
520 memset(element
->whichElement
.simpleString
, ' ',
521 sizeof(element
->whichElement
.simpleString
));
522 element
->whichElement
.simpleString
[TUI_EXECINFO_SIZE
- 1] = 0;
524 /* Now update the exec info content based upon the state
525 of each line as indicated by the source content. */
526 mode
= srcElement
->whichElement
.source
.hasBreak
;
527 if (mode
& TUI_BP_HIT
)
528 element
->whichElement
.simpleString
[TUI_BP_HIT_POS
] =
529 (mode
& TUI_BP_HARDWARE
) ? 'H' : 'B';
530 else if (mode
& (TUI_BP_ENABLED
| TUI_BP_DISABLED
))
531 element
->whichElement
.simpleString
[TUI_BP_HIT_POS
] =
532 (mode
& TUI_BP_HARDWARE
) ? 'h' : 'b';
534 if (mode
& TUI_BP_ENABLED
)
535 element
->whichElement
.simpleString
[TUI_BP_BREAK_POS
] = '+';
536 else if (mode
& TUI_BP_DISABLED
)
537 element
->whichElement
.simpleString
[TUI_BP_BREAK_POS
] = '-';
539 if (srcElement
->whichElement
.source
.isExecPoint
)
540 element
->whichElement
.simpleString
[TUI_EXEC_POS
] = '>';
542 execInfoPtr
->contentSize
= winInfo
->generic
.contentSize
;
553 ** tuiShowExecInfoContent().
556 tuiShowExecInfoContent (TuiWinInfoPtr winInfo
)
558 TuiGenWinInfoPtr execInfo
= winInfo
->detail
.sourceInfo
.executionInfo
;
561 werase (execInfo
->handle
);
562 tuiRefreshWin (execInfo
);
563 for (curLine
= 1; (curLine
<= execInfo
->contentSize
); curLine
++)
564 mvwaddstr (execInfo
->handle
,
568 execInfo
->content
[curLine
- 1])->whichElement
.simpleString
);
569 tuiRefreshWin (execInfo
);
570 execInfo
->contentInUse
= TRUE
;
573 } /* tuiShowExecInfoContent */
577 ** tuiEraseExecInfoContent().
580 tuiEraseExecInfoContent (TuiWinInfoPtr winInfo
)
582 TuiGenWinInfoPtr execInfo
= winInfo
->detail
.sourceInfo
.executionInfo
;
584 werase (execInfo
->handle
);
585 tuiRefreshWin (execInfo
);
588 } /* tuiEraseExecInfoContent */
591 ** tuiClearExecInfoContent().
594 tuiClearExecInfoContent (TuiWinInfoPtr winInfo
)
596 winInfo
->detail
.sourceInfo
.executionInfo
->contentInUse
= FALSE
;
597 tuiEraseExecInfoContent (winInfo
);
600 } /* tuiClearExecInfoContent */
603 ** tuiUpdateExecInfo().
604 ** Function to update the execution info window
607 tuiUpdateExecInfo (TuiWinInfoPtr winInfo
)
609 tuiSetExecInfoContent (winInfo
);
610 tuiShowExecInfoContent (winInfo
);
611 } /* tuiUpdateExecInfo */
614 tuiAllocSourceBuffer (TuiWinInfoPtr winInfo
)
616 register char *srcLineBuf
;
617 register int i
, lineWidth
, maxLines
;
618 TuiStatus ret
= TUI_FAILURE
;
620 maxLines
= winInfo
->generic
.height
; /* less the highlight box */
621 lineWidth
= winInfo
->generic
.width
- 1;
623 ** Allocate the buffer for the source lines. Do this only once since they
624 ** will be re-used for all source displays. The only other time this will
625 ** be done is when a window's size changes.
627 if (winInfo
->generic
.content
== (OpaquePtr
) NULL
)
629 srcLineBuf
= (char *) xmalloc ((maxLines
* lineWidth
) * sizeof (char));
630 if (srcLineBuf
== (char *) NULL
)
632 "Unable to Allocate Memory for Source or Disassembly Display.\n",
636 /* allocate the content list */
637 if ((winInfo
->generic
.content
=
638 (OpaquePtr
) allocContent (maxLines
, SRC_WIN
)) == (OpaquePtr
) NULL
)
640 tuiFree (srcLineBuf
);
641 srcLineBuf
= (char *) NULL
;
643 "Unable to Allocate Memory for Source or Disassembly Display.\n",
647 for (i
= 0; i
< maxLines
; i
++)
649 winInfo
->generic
.content
[i
])->whichElement
.source
.line
=
650 srcLineBuf
+ (lineWidth
* i
);
657 } /* tuiAllocSourceBuffer */
661 ** tuiLineIsDisplayed().
662 ** Answer whether the a particular line number or address is displayed
663 ** in the current source window.
666 tuiLineIsDisplayed (int line
, TuiWinInfoPtr winInfo
,
669 int isDisplayed
= FALSE
;
673 threshold
= SCROLL_THRESHOLD
;
677 while (i
< winInfo
->generic
.contentSize
- threshold
&& !isDisplayed
)
679 isDisplayed
= (((TuiWinElementPtr
)
680 winInfo
->generic
.content
[i
])->whichElement
.source
.lineOrAddr
.lineNo
686 } /* tuiLineIsDisplayed */
690 ** tuiLineIsDisplayed().
691 ** Answer whether the a particular line number or address is displayed
692 ** in the current source window.
695 tuiAddrIsDisplayed (CORE_ADDR addr
, TuiWinInfoPtr winInfo
,
698 int isDisplayed
= FALSE
;
702 threshold
= SCROLL_THRESHOLD
;
706 while (i
< winInfo
->generic
.contentSize
- threshold
&& !isDisplayed
)
708 isDisplayed
= (((TuiWinElementPtr
)
709 winInfo
->generic
.content
[i
])->whichElement
.source
.lineOrAddr
.addr
718 /*****************************************
719 ** STATIC LOCAL FUNCTIONS **
720 ******************************************/