1 /* TUI display source/assembly window.
3 Copyright 1998, 1999, 2000, 2001, 2002, 2003 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. */
29 #include "breakpoint.h"
37 #include "tuiGeneralWin.h"
38 #include "tuiSourceWin.h"
39 #include "tuiSource.h"
40 #include "tuiDisassem.h"
50 /* Function to display the "main" routine. */
52 tui_display_main (void)
54 if ((sourceWindows ())->count
> 0)
58 addr
= tuiGetBeginAsmAddress ();
59 if (addr
!= (CORE_ADDR
) 0)
61 struct symtab_and_line sal
;
63 tuiUpdateSourceWindowsWithAddr (addr
);
64 sal
= find_pc_line (addr
, 0);
66 tuiUpdateLocatorFilename (sal
.symtab
->filename
);
68 tuiUpdateLocatorFilename ("??");
76 ** tuiUpdateSourceWindow().
77 ** Function to display source in the source window. This function
78 ** initializes the horizontal scroll to 0.
81 tuiUpdateSourceWindow (TuiWinInfoPtr winInfo
, struct symtab
*s
,
82 TuiLineOrAddress lineOrAddr
, int noerror
)
84 winInfo
->detail
.sourceInfo
.horizontalOffset
= 0;
85 tuiUpdateSourceWindowAsIs (winInfo
, s
, lineOrAddr
, noerror
);
88 } /* tuiUpdateSourceWindow */
92 ** tuiUpdateSourceWindowAsIs().
93 ** Function to display source in the source/asm window. This
94 ** function shows the source as specified by the horizontal offset.
97 tuiUpdateSourceWindowAsIs (TuiWinInfoPtr winInfo
, struct symtab
*s
,
98 TuiLineOrAddress lineOrAddr
, int noerror
)
102 if (winInfo
->generic
.type
== SRC_WIN
)
103 ret
= tuiSetSourceContent (s
, lineOrAddr
.lineNo
, noerror
);
105 ret
= tuiSetDisassemContent (lineOrAddr
.addr
);
107 if (ret
== TUI_FAILURE
)
109 tuiClearSourceContent (winInfo
, EMPTY_SOURCE_PROMPT
);
110 tuiClearExecInfoContent (winInfo
);
114 tui_update_breakpoint_info (winInfo
, 0);
115 tuiShowSourceContent (winInfo
);
116 tuiUpdateExecInfo (winInfo
);
117 if (winInfo
->generic
.type
== SRC_WIN
)
119 struct symtab_and_line sal
;
121 sal
.line
= lineOrAddr
.lineNo
+
122 (winInfo
->generic
.contentSize
- 2);
124 set_current_source_symtab_and_line (&sal
);
126 ** If the focus was in the asm win, put it in the src
127 ** win if we don't have a split layout
129 if (tuiWinWithFocus () == disassemWin
&&
130 currentLayout () != SRC_DISASSEM_COMMAND
)
131 tuiSetWinFocusTo (srcWin
);
137 } /* tuiUpdateSourceWindowAsIs */
141 ** tuiUpdateSourceWindowsWithAddr().
142 ** Function to ensure that the source and/or disassemly windows
143 ** reflect the input address.
146 tuiUpdateSourceWindowsWithAddr (CORE_ADDR addr
)
150 struct symtab_and_line sal
;
153 switch (currentLayout ())
155 case DISASSEM_COMMAND
:
156 case DISASSEM_DATA_COMMAND
:
157 tuiShowDisassem (addr
);
159 case SRC_DISASSEM_COMMAND
:
160 tuiShowDisassemAndUpdateSource (addr
);
163 sal
= find_pc_line (addr
, 0);
165 tuiShowSource (sal
.symtab
, l
, FALSE
);
173 for (i
= 0; i
< (sourceWindows ())->count
; i
++)
175 TuiWinInfoPtr winInfo
= (TuiWinInfoPtr
) (sourceWindows ())->list
[i
];
177 tuiClearSourceContent (winInfo
, EMPTY_SOURCE_PROMPT
);
178 tuiClearExecInfoContent (winInfo
);
183 } /* tuiUpdateSourceWindowsWithAddr */
186 ** tuiUpdateSourceWindowsWithLine().
187 ** Function to ensure that the source and/or disassemly windows
188 ** reflect the input address.
191 tuiUpdateSourceWindowsWithLine (struct symtab
*s
, int line
)
196 switch (currentLayout ())
198 case DISASSEM_COMMAND
:
199 case DISASSEM_DATA_COMMAND
:
200 find_line_pc (s
, line
, &pc
);
201 tuiUpdateSourceWindowsWithAddr (pc
);
205 tuiShowSource (s
, l
, FALSE
);
206 if (currentLayout () == SRC_DISASSEM_COMMAND
)
208 find_line_pc (s
, line
, &pc
);
209 tuiShowDisassem (pc
);
215 } /* tuiUpdateSourceWindowsWithLine */
218 ** tuiClearSourceContent().
221 tuiClearSourceContent (TuiWinInfoPtr winInfo
, int displayPrompt
)
223 if (m_winPtrNotNull (winInfo
))
227 winInfo
->generic
.contentInUse
= FALSE
;
228 tuiEraseSourceContent (winInfo
, displayPrompt
);
229 for (i
= 0; i
< winInfo
->generic
.contentSize
; i
++)
231 TuiWinElementPtr element
=
232 (TuiWinElementPtr
) winInfo
->generic
.content
[i
];
233 element
->whichElement
.source
.hasBreak
= FALSE
;
234 element
->whichElement
.source
.isExecPoint
= FALSE
;
239 } /* tuiClearSourceContent */
243 ** tuiEraseSourceContent().
246 tuiEraseSourceContent (TuiWinInfoPtr winInfo
, int displayPrompt
)
249 int halfWidth
= (winInfo
->generic
.width
- 2) / 2;
251 if (winInfo
->generic
.handle
!= (WINDOW
*) NULL
)
253 werase (winInfo
->generic
.handle
);
254 checkAndDisplayHighlightIfNeeded (winInfo
);
255 if (displayPrompt
== EMPTY_SOURCE_PROMPT
)
259 if (winInfo
->generic
.type
== SRC_WIN
)
260 noSrcStr
= NO_SRC_STRING
;
262 noSrcStr
= NO_DISASSEM_STRING
;
263 if (strlen (noSrcStr
) >= halfWidth
)
266 xPos
= halfWidth
- strlen (noSrcStr
);
267 mvwaddstr (winInfo
->generic
.handle
,
268 (winInfo
->generic
.height
/ 2),
272 /* elz: added this function call to set the real contents of
273 the window to what is on the screen, so that later calls
274 to refresh, do display
275 the correct stuff, and not the old image */
277 tuiSetSourceContentNil (winInfo
, noSrcStr
);
279 tuiRefreshWin (&winInfo
->generic
);
282 } /* tuiEraseSourceContent */
285 /* Redraw the complete line of a source or disassembly window. */
287 tui_show_source_line (TuiWinInfoPtr winInfo
, int lineno
)
289 TuiWinElementPtr line
;
292 line
= (TuiWinElementPtr
) winInfo
->generic
.content
[lineno
- 1];
293 if (line
->whichElement
.source
.isExecPoint
)
294 wattron (winInfo
->generic
.handle
, A_STANDOUT
);
296 mvwaddstr (winInfo
->generic
.handle
, lineno
, 1,
297 line
->whichElement
.source
.line
);
298 if (line
->whichElement
.source
.isExecPoint
)
299 wattroff (winInfo
->generic
.handle
, A_STANDOUT
);
301 /* Clear to end of line but stop before the border. */
302 getyx (winInfo
->generic
.handle
, y
, x
);
303 while (x
+ 1 < winInfo
->generic
.width
)
305 waddch (winInfo
->generic
.handle
, ' ');
306 getyx (winInfo
->generic
.handle
, y
, x
);
311 ** tuiShowSourceContent().
314 tuiShowSourceContent (TuiWinInfoPtr winInfo
)
316 if (winInfo
->generic
.contentSize
> 0)
320 for (lineno
= 1; lineno
<= winInfo
->generic
.contentSize
; lineno
++)
321 tui_show_source_line (winInfo
, lineno
);
324 tuiEraseSourceContent (winInfo
, TRUE
);
326 checkAndDisplayHighlightIfNeeded (winInfo
);
327 tuiRefreshWin (&winInfo
->generic
);
328 winInfo
->generic
.contentInUse
= TRUE
;
333 ** tuiHorizontalSourceScroll().
334 ** Scroll the source forward or backward horizontally
337 tuiHorizontalSourceScroll (TuiWinInfoPtr winInfo
,
338 TuiScrollDirection direction
,
341 if (winInfo
->generic
.content
!= (OpaquePtr
) NULL
)
345 struct symtab_and_line cursal
= get_current_source_symtab_and_line ();
347 if (cursal
.symtab
== (struct symtab
*) NULL
)
348 s
= find_pc_symtab (get_frame_pc (deprecated_selected_frame
));
352 if (direction
== LEFT_SCROLL
)
353 offset
= winInfo
->detail
.sourceInfo
.horizontalOffset
+ numToScroll
;
357 winInfo
->detail
.sourceInfo
.horizontalOffset
- numToScroll
) < 0)
360 winInfo
->detail
.sourceInfo
.horizontalOffset
= offset
;
361 tuiUpdateSourceWindowAsIs (
365 winInfo
->generic
.content
[0])->whichElement
.source
.lineOrAddr
,
370 } /* tuiHorizontalSourceScroll */
373 /* Set or clear the hasBreak flag in the line whose line is lineNo. */
375 tuiSetIsExecPointAt (TuiLineOrAddress l
, TuiWinInfoPtr winInfo
)
379 TuiWinContent content
= (TuiWinContent
) winInfo
->generic
.content
;
382 while (i
< winInfo
->generic
.contentSize
)
386 if (content
[i
]->whichElement
.source
.lineOrAddr
.addr
== l
.addr
)
390 if (newState
!= content
[i
]->whichElement
.source
.isExecPoint
)
393 content
[i
]->whichElement
.source
.isExecPoint
= newState
;
394 tui_show_source_line (winInfo
, i
+ 1);
399 tuiRefreshWin (&winInfo
->generic
);
402 /* Update the execution windows to show the active breakpoints.
403 This is called whenever a breakpoint is inserted, removed or
404 has its state changed. */
406 tui_update_all_breakpoint_info ()
408 TuiList
* list
= sourceWindows ();
411 for (i
= 0; i
< list
->count
; i
++)
413 TuiWinInfoPtr win
= (TuiWinInfoPtr
) list
->list
[i
];
415 if (tui_update_breakpoint_info (win
, FALSE
))
417 tuiUpdateExecInfo (win
);
423 /* Scan the source window and the breakpoints to update the
424 hasBreak information for each line.
425 Returns 1 if something changed and the execution window
426 must be refreshed. */
428 tui_update_breakpoint_info (TuiWinInfoPtr win
, int current_only
)
431 int need_refresh
= 0;
432 TuiSourceInfoPtr src
= &win
->detail
.sourceInfo
;
434 for (i
= 0; i
< win
->generic
.contentSize
; i
++)
436 struct breakpoint
*bp
;
437 extern struct breakpoint
*breakpoint_chain
;
439 TuiSourceElement
* line
;
441 line
= &((TuiWinElementPtr
) win
->generic
.content
[i
])->whichElement
.source
;
442 if (current_only
&& !line
->isExecPoint
)
445 /* Scan each breakpoint to see if the current line has something to
446 do with it. Identify enable/disabled breakpoints as well as
447 those that we already hit. */
449 for (bp
= breakpoint_chain
;
450 bp
!= (struct breakpoint
*) NULL
;
455 && (strcmp (src
->filename
, bp
->source_file
) == 0)
456 && bp
->line_number
== line
->lineOrAddr
.lineNo
)
457 || (win
== disassemWin
458 && bp
->loc
->address
== line
->lineOrAddr
.addr
))
460 if (bp
->enable_state
== bp_disabled
)
461 mode
|= TUI_BP_DISABLED
;
463 mode
|= TUI_BP_ENABLED
;
467 mode
|= TUI_BP_CONDITIONAL
;
468 if (bp
->type
== bp_hardware_breakpoint
)
469 mode
|= TUI_BP_HARDWARE
;
472 if (line
->hasBreak
!= mode
)
474 line
->hasBreak
= mode
;
483 ** tuiSetExecInfoContent().
484 ** Function to initialize the content of the execution info window,
485 ** based upon the input window which is either the source or
486 ** disassembly window.
489 tuiSetExecInfoContent (TuiWinInfoPtr winInfo
)
491 TuiStatus ret
= TUI_SUCCESS
;
493 if (winInfo
->detail
.sourceInfo
.executionInfo
!= (TuiGenWinInfoPtr
) NULL
)
495 TuiGenWinInfoPtr execInfoPtr
= winInfo
->detail
.sourceInfo
.executionInfo
;
497 if (execInfoPtr
->content
== (OpaquePtr
) NULL
)
498 execInfoPtr
->content
=
499 (OpaquePtr
) allocContent (winInfo
->generic
.height
,
501 if (execInfoPtr
->content
!= (OpaquePtr
) NULL
)
505 tui_update_breakpoint_info (winInfo
, 1);
506 for (i
= 0; i
< winInfo
->generic
.contentSize
; i
++)
508 TuiWinElementPtr element
;
509 TuiWinElementPtr srcElement
;
512 element
= (TuiWinElementPtr
) execInfoPtr
->content
[i
];
513 srcElement
= (TuiWinElementPtr
) winInfo
->generic
.content
[i
];
515 memset(element
->whichElement
.simpleString
, ' ',
516 sizeof(element
->whichElement
.simpleString
));
517 element
->whichElement
.simpleString
[TUI_EXECINFO_SIZE
- 1] = 0;
519 /* Now update the exec info content based upon the state
520 of each line as indicated by the source content. */
521 mode
= srcElement
->whichElement
.source
.hasBreak
;
522 if (mode
& TUI_BP_HIT
)
523 element
->whichElement
.simpleString
[TUI_BP_HIT_POS
] =
524 (mode
& TUI_BP_HARDWARE
) ? 'H' : 'B';
525 else if (mode
& (TUI_BP_ENABLED
| TUI_BP_DISABLED
))
526 element
->whichElement
.simpleString
[TUI_BP_HIT_POS
] =
527 (mode
& TUI_BP_HARDWARE
) ? 'h' : 'b';
529 if (mode
& TUI_BP_ENABLED
)
530 element
->whichElement
.simpleString
[TUI_BP_BREAK_POS
] = '+';
531 else if (mode
& TUI_BP_DISABLED
)
532 element
->whichElement
.simpleString
[TUI_BP_BREAK_POS
] = '-';
534 if (srcElement
->whichElement
.source
.isExecPoint
)
535 element
->whichElement
.simpleString
[TUI_EXEC_POS
] = '>';
537 execInfoPtr
->contentSize
= winInfo
->generic
.contentSize
;
548 ** tuiShowExecInfoContent().
551 tuiShowExecInfoContent (TuiWinInfoPtr winInfo
)
553 TuiGenWinInfoPtr execInfo
= winInfo
->detail
.sourceInfo
.executionInfo
;
556 werase (execInfo
->handle
);
557 tuiRefreshWin (execInfo
);
558 for (curLine
= 1; (curLine
<= execInfo
->contentSize
); curLine
++)
559 mvwaddstr (execInfo
->handle
,
563 execInfo
->content
[curLine
- 1])->whichElement
.simpleString
);
564 tuiRefreshWin (execInfo
);
565 execInfo
->contentInUse
= TRUE
;
568 } /* tuiShowExecInfoContent */
572 ** tuiEraseExecInfoContent().
575 tuiEraseExecInfoContent (TuiWinInfoPtr winInfo
)
577 TuiGenWinInfoPtr execInfo
= winInfo
->detail
.sourceInfo
.executionInfo
;
579 werase (execInfo
->handle
);
580 tuiRefreshWin (execInfo
);
583 } /* tuiEraseExecInfoContent */
586 ** tuiClearExecInfoContent().
589 tuiClearExecInfoContent (TuiWinInfoPtr winInfo
)
591 winInfo
->detail
.sourceInfo
.executionInfo
->contentInUse
= FALSE
;
592 tuiEraseExecInfoContent (winInfo
);
595 } /* tuiClearExecInfoContent */
598 ** tuiUpdateExecInfo().
599 ** Function to update the execution info window
602 tuiUpdateExecInfo (TuiWinInfoPtr winInfo
)
604 tuiSetExecInfoContent (winInfo
);
605 tuiShowExecInfoContent (winInfo
);
606 } /* tuiUpdateExecInfo */
609 tuiAllocSourceBuffer (TuiWinInfoPtr winInfo
)
611 register char *srcLineBuf
;
612 register int i
, lineWidth
, maxLines
;
613 TuiStatus ret
= TUI_FAILURE
;
615 maxLines
= winInfo
->generic
.height
; /* less the highlight box */
616 lineWidth
= winInfo
->generic
.width
- 1;
618 ** Allocate the buffer for the source lines. Do this only once since they
619 ** will be re-used for all source displays. The only other time this will
620 ** be done is when a window's size changes.
622 if (winInfo
->generic
.content
== (OpaquePtr
) NULL
)
624 srcLineBuf
= (char *) xmalloc ((maxLines
* lineWidth
) * sizeof (char));
625 if (srcLineBuf
== (char *) NULL
)
627 "Unable to Allocate Memory for Source or Disassembly Display.\n",
631 /* allocate the content list */
632 if ((winInfo
->generic
.content
=
633 (OpaquePtr
) allocContent (maxLines
, SRC_WIN
)) == (OpaquePtr
) NULL
)
635 tuiFree (srcLineBuf
);
636 srcLineBuf
= (char *) NULL
;
638 "Unable to Allocate Memory for Source or Disassembly Display.\n",
642 for (i
= 0; i
< maxLines
; i
++)
644 winInfo
->generic
.content
[i
])->whichElement
.source
.line
=
645 srcLineBuf
+ (lineWidth
* i
);
652 } /* tuiAllocSourceBuffer */
656 ** tuiLineIsDisplayed().
657 ** Answer whether the a particular line number or address is displayed
658 ** in the current source window.
661 tuiLineIsDisplayed (int line
, TuiWinInfoPtr winInfo
,
664 int isDisplayed
= FALSE
;
668 threshold
= SCROLL_THRESHOLD
;
672 while (i
< winInfo
->generic
.contentSize
- threshold
&& !isDisplayed
)
674 isDisplayed
= (((TuiWinElementPtr
)
675 winInfo
->generic
.content
[i
])->whichElement
.source
.lineOrAddr
.lineNo
681 } /* tuiLineIsDisplayed */
685 ** tuiLineIsDisplayed().
686 ** Answer whether the a particular line number or address is displayed
687 ** in the current source window.
690 tuiAddrIsDisplayed (CORE_ADDR addr
, TuiWinInfoPtr winInfo
,
693 int isDisplayed
= FALSE
;
697 threshold
= SCROLL_THRESHOLD
;
701 while (i
< winInfo
->generic
.contentSize
- threshold
&& !isDisplayed
)
703 isDisplayed
= (((TuiWinElementPtr
)
704 winInfo
->generic
.content
[i
])->whichElement
.source
.lineOrAddr
.addr
713 /*****************************************
714 ** STATIC LOCAL FUNCTIONS **
715 ******************************************/