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 * winInfo, struct symtab *s,
79 union tui_line_or_address lineOrAddr, int noerror)
81 winInfo->detail.sourceInfo.horizontalOffset = 0;
82 tui_update_source_window_as_is (winInfo, s, lineOrAddr, 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 * winInfo, struct symtab *s,
92 union tui_line_or_address lineOrAddr, int noerror)
96 if (winInfo->generic.type == SRC_WIN)
97 ret = tui_set_source_content (s, lineOrAddr.lineNo, noerror);
99 ret = tui_set_disassem_content (lineOrAddr.addr);
101 if (ret == TUI_FAILURE)
103 tui_clear_source_content (winInfo, EMPTY_SOURCE_PROMPT);
104 tui_clear_exec_info_content (winInfo);
108 tui_update_breakpoint_info (winInfo, 0);
109 tui_show_source_content (winInfo);
110 tui_update_exec_info (winInfo);
111 if (winInfo->generic.type == SRC_WIN)
113 struct symtab_and_line sal;
115 sal.line = lineOrAddr.lineNo +
116 (winInfo->generic.contentSize - 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 () == disassemWin &&
124 tui_current_layout () != SRC_DISASSEM_COMMAND)
125 tui_set_win_focus_to (srcWin);
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);
156 tui_show_symtab_source (sal.symtab, l, FALSE);
164 for (i = 0; i < (tui_source_windows ())->count; i++)
166 struct tui_win_info * winInfo = (struct tui_win_info *) (tui_source_windows ())->list[i];
168 tui_clear_source_content (winInfo, EMPTY_SOURCE_PROMPT);
169 tui_clear_exec_info_content (winInfo);
174 } /* tuiUpdateSourceWindowsWithAddr */
176 /* Function to ensure that the source and/or disassemly windows
177 reflect the input address. */
179 tui_update_source_windows_with_line (struct symtab *s, int line)
182 union tui_line_or_address l;
184 switch (tui_current_layout ())
186 case DISASSEM_COMMAND:
187 case DISASSEM_DATA_COMMAND:
188 find_line_pc (s, line, &pc);
189 tui_update_source_windows_with_addr (pc);
193 tui_show_symtab_source (s, l, FALSE);
194 if (tui_current_layout () == SRC_DISASSEM_COMMAND)
196 find_line_pc (s, line, &pc);
197 tui_show_disassem (pc);
206 tui_clear_source_content (struct tui_win_info * winInfo, int displayPrompt)
208 if (m_winPtrNotNull (winInfo))
212 winInfo->generic.contentInUse = FALSE;
213 tui_erase_source_content (winInfo, displayPrompt);
214 for (i = 0; i < winInfo->generic.contentSize; i++)
216 struct tui_win_element * element =
217 (struct tui_win_element *) winInfo->generic.content[i];
218 element->whichElement.source.hasBreak = FALSE;
219 element->whichElement.source.isExecPoint = FALSE;
224 } /* tuiClearSourceContent */
228 tui_erase_source_content (struct tui_win_info * winInfo, int displayPrompt)
231 int halfWidth = (winInfo->generic.width - 2) / 2;
233 if (winInfo->generic.handle != (WINDOW *) NULL)
235 werase (winInfo->generic.handle);
236 tui_check_and_display_highlight_if_needed (winInfo);
237 if (displayPrompt == EMPTY_SOURCE_PROMPT)
241 if (winInfo->generic.type == SRC_WIN)
242 noSrcStr = NO_SRC_STRING;
244 noSrcStr = NO_DISASSEM_STRING;
245 if (strlen (noSrcStr) >= halfWidth)
248 xPos = halfWidth - strlen (noSrcStr);
249 mvwaddstr (winInfo->generic.handle,
250 (winInfo->generic.height / 2),
254 /* elz: added this function call to set the real contents of
255 the window to what is on the screen, so that later calls
256 to refresh, do display
257 the correct stuff, and not the old image */
259 tui_set_source_content_nil (winInfo, noSrcStr);
261 tui_refresh_win (&winInfo->generic);
264 } /* tuiEraseSourceContent */
267 /* Redraw the complete line of a source or disassembly window. */
269 tui_show_source_line (struct tui_win_info * winInfo, int lineno)
271 struct tui_win_element * line;
274 line = (struct tui_win_element *) winInfo->generic.content[lineno - 1];
275 if (line->whichElement.source.isExecPoint)
276 wattron (winInfo->generic.handle, A_STANDOUT);
278 mvwaddstr (winInfo->generic.handle, lineno, 1,
279 line->whichElement.source.line);
280 if (line->whichElement.source.isExecPoint)
281 wattroff (winInfo->generic.handle, A_STANDOUT);
283 /* Clear to end of line but stop before the border. */
284 getyx (winInfo->generic.handle, y, x);
285 while (x + 1 < winInfo->generic.width)
287 waddch (winInfo->generic.handle, ' ');
288 getyx (winInfo->generic.handle, y, x);
293 tui_show_source_content (struct tui_win_info * winInfo)
295 if (winInfo->generic.contentSize > 0)
299 for (lineno = 1; lineno <= winInfo->generic.contentSize; lineno++)
300 tui_show_source_line (winInfo, lineno);
303 tui_erase_source_content (winInfo, TRUE);
305 tui_check_and_display_highlight_if_needed (winInfo);
306 tui_refresh_win (&winInfo->generic);
307 winInfo->generic.contentInUse = TRUE;
311 /* Scroll the source forward or backward horizontally. */
313 tui_horizontal_source_scroll (struct tui_win_info * winInfo,
314 enum tui_scroll_direction direction,
317 if (winInfo->generic.content != (OpaquePtr) NULL)
321 struct symtab_and_line cursal = get_current_source_symtab_and_line ();
323 if (cursal.symtab == (struct symtab *) NULL)
324 s = find_pc_symtab (get_frame_pc (deprecated_selected_frame));
328 if (direction == LEFT_SCROLL)
329 offset = winInfo->detail.sourceInfo.horizontalOffset + numToScroll;
333 winInfo->detail.sourceInfo.horizontalOffset - numToScroll) < 0)
336 winInfo->detail.sourceInfo.horizontalOffset = offset;
337 tui_update_source_window_as_is (winInfo, s,
338 ((struct tui_win_element *)
339 winInfo->generic.content[0])->whichElement.source.lineOrAddr,
344 } /* tuiHorizontalSourceScroll */
347 /* Set or clear the hasBreak flag in the line whose line is lineNo. */
349 tui_set_is_exec_point_at (union tui_line_or_address l, struct tui_win_info * winInfo)
353 tui_win_content content = (tui_win_content) winInfo->generic.content;
356 while (i < winInfo->generic.contentSize)
360 if (content[i]->whichElement.source.lineOrAddr.addr == l.addr)
364 if (newState != content[i]->whichElement.source.isExecPoint)
367 content[i]->whichElement.source.isExecPoint = newState;
368 tui_show_source_line (winInfo, i + 1);
373 tui_refresh_win (&winInfo->generic);
376 /* Update the execution windows to show the active breakpoints.
377 This is called whenever a breakpoint is inserted, removed or
378 has its state changed. */
380 tui_update_all_breakpoint_info ()
382 struct tui_list *list = tui_source_windows ();
385 for (i = 0; i < list->count; i++)
387 struct tui_win_info * win = (struct tui_win_info *) list->list[i];
389 if (tui_update_breakpoint_info (win, FALSE))
391 tui_update_exec_info (win);
397 /* Scan the source window and the breakpoints to update the
398 hasBreak information for each line.
399 Returns 1 if something changed and the execution window
400 must be refreshed. */
402 tui_update_breakpoint_info (struct tui_win_info * win, int current_only)
405 int need_refresh = 0;
406 struct tui_source_info * src = &win->detail.sourceInfo;
408 for (i = 0; i < win->generic.contentSize; i++)
410 struct breakpoint *bp;
411 extern struct breakpoint *breakpoint_chain;
413 struct tui_source_element* line;
415 line = &((struct tui_win_element *) win->generic.content[i])->whichElement.source;
416 if (current_only && !line->isExecPoint)
419 /* Scan each breakpoint to see if the current line has something to
420 do with it. Identify enable/disabled breakpoints as well as
421 those that we already hit. */
423 for (bp = breakpoint_chain;
424 bp != (struct breakpoint *) NULL;
429 && (strcmp (src->filename, bp->source_file) == 0)
430 && bp->line_number == line->lineOrAddr.lineNo)
431 || (win == disassemWin
432 && bp->loc->address == line->lineOrAddr.addr))
434 if (bp->enable_state == bp_disabled)
435 mode |= TUI_BP_DISABLED;
437 mode |= TUI_BP_ENABLED;
441 mode |= TUI_BP_CONDITIONAL;
442 if (bp->type == bp_hardware_breakpoint)
443 mode |= TUI_BP_HARDWARE;
446 if (line->hasBreak != mode)
448 line->hasBreak = mode;
457 ** tuiSetExecInfoContent().
458 ** Function to initialize the content of the execution info window,
459 ** based upon the input window which is either the source or
460 ** disassembly window.
463 tuiSetExecInfoContent (struct tui_win_info * winInfo)
465 TuiStatus ret = TUI_SUCCESS;
467 if (winInfo->detail.sourceInfo.executionInfo != (struct tui_gen_win_info *) NULL)
469 struct tui_gen_win_info * execInfoPtr = winInfo->detail.sourceInfo.executionInfo;
471 if (execInfoPtr->content == (OpaquePtr) NULL)
472 execInfoPtr->content =
473 (OpaquePtr) tui_alloc_content (winInfo->generic.height,
475 if (execInfoPtr->content != (OpaquePtr) NULL)
479 tui_update_breakpoint_info (winInfo, 1);
480 for (i = 0; i < winInfo->generic.contentSize; i++)
482 struct tui_win_element * element;
483 struct tui_win_element * srcElement;
486 element = (struct tui_win_element *) execInfoPtr->content[i];
487 srcElement = (struct tui_win_element *) winInfo->generic.content[i];
489 memset(element->whichElement.simpleString, ' ',
490 sizeof(element->whichElement.simpleString));
491 element->whichElement.simpleString[TUI_EXECINFO_SIZE - 1] = 0;
493 /* Now update the exec info content based upon the state
494 of each line as indicated by the source content. */
495 mode = srcElement->whichElement.source.hasBreak;
496 if (mode & TUI_BP_HIT)
497 element->whichElement.simpleString[TUI_BP_HIT_POS] =
498 (mode & TUI_BP_HARDWARE) ? 'H' : 'B';
499 else if (mode & (TUI_BP_ENABLED | TUI_BP_DISABLED))
500 element->whichElement.simpleString[TUI_BP_HIT_POS] =
501 (mode & TUI_BP_HARDWARE) ? 'h' : 'b';
503 if (mode & TUI_BP_ENABLED)
504 element->whichElement.simpleString[TUI_BP_BREAK_POS] = '+';
505 else if (mode & TUI_BP_DISABLED)
506 element->whichElement.simpleString[TUI_BP_BREAK_POS] = '-';
508 if (srcElement->whichElement.source.isExecPoint)
509 element->whichElement.simpleString[TUI_EXEC_POS] = '>';
511 execInfoPtr->contentSize = winInfo->generic.contentSize;
522 ** tuiShowExecInfoContent().
525 tuiShowExecInfoContent (struct tui_win_info * winInfo)
527 struct tui_gen_win_info * execInfo = winInfo->detail.sourceInfo.executionInfo;
530 werase (execInfo->handle);
531 tui_refresh_win (execInfo);
532 for (curLine = 1; (curLine <= execInfo->contentSize); curLine++)
533 mvwaddstr (execInfo->handle,
536 ((struct tui_win_element *)
537 execInfo->content[curLine - 1])->whichElement.simpleString);
538 tui_refresh_win (execInfo);
539 execInfo->contentInUse = TRUE;
546 tui_erase_exec_info_content (struct tui_win_info * winInfo)
548 struct tui_gen_win_info * execInfo = winInfo->detail.sourceInfo.executionInfo;
550 werase (execInfo->handle);
551 tui_refresh_win (execInfo);
557 tui_clear_exec_info_content (struct tui_win_info * winInfo)
559 winInfo->detail.sourceInfo.executionInfo->contentInUse = FALSE;
560 tui_erase_exec_info_content (winInfo);
565 /* Function to update the execution info window. */
567 tui_update_exec_info (struct tui_win_info * winInfo)
569 tuiSetExecInfoContent (winInfo);
570 tuiShowExecInfoContent (winInfo);
571 } /* tuiUpdateExecInfo */
574 tui_alloc_source_buffer (struct tui_win_info *winInfo)
576 register char *srcLineBuf;
577 register int i, lineWidth, maxLines;
578 TuiStatus ret = TUI_FAILURE;
580 maxLines = winInfo->generic.height; /* less the highlight box */
581 lineWidth = winInfo->generic.width - 1;
583 ** Allocate the buffer for the source lines. Do this only once since they
584 ** will be re-used for all source displays. The only other time this will
585 ** be done is when a window's size changes.
587 if (winInfo->generic.content == (OpaquePtr) NULL)
589 srcLineBuf = (char *) xmalloc ((maxLines * lineWidth) * sizeof (char));
590 if (srcLineBuf == (char *) NULL)
592 "Unable to Allocate Memory for Source or Disassembly Display.\n",
596 /* allocate the content list */
597 if ((winInfo->generic.content =
598 (OpaquePtr) tui_alloc_content (maxLines, SRC_WIN)) == (OpaquePtr) NULL)
600 tuiFree (srcLineBuf);
601 srcLineBuf = (char *) NULL;
603 "Unable to Allocate Memory for Source or Disassembly Display.\n",
607 for (i = 0; i < maxLines; i++)
608 ((struct tui_win_element *)
609 winInfo->generic.content[i])->whichElement.source.line =
610 srcLineBuf + (lineWidth * i);
617 } /* tuiAllocSourceBuffer */
620 /* Answer whether the a particular line number or address is displayed
621 in the current source window. */
623 tui_line_is_displayed (int line, struct tui_win_info * winInfo,
626 int isDisplayed = FALSE;
630 threshold = SCROLL_THRESHOLD;
634 while (i < winInfo->generic.contentSize - threshold && !isDisplayed)
636 isDisplayed = (((struct tui_win_element *)
637 winInfo->generic.content[i])->whichElement.source.lineOrAddr.lineNo
646 /* Answer whether the a particular line number or address is displayed
647 in the current source window. */
649 tui_addr_is_displayed (CORE_ADDR addr, struct tui_win_info * winInfo,
652 int isDisplayed = FALSE;
656 threshold = SCROLL_THRESHOLD;
660 while (i < winInfo->generic.contentSize - threshold && !isDisplayed)
662 isDisplayed = (((struct tui_win_element *)
663 winInfo->generic.content[i])->whichElement.source.lineOrAddr.addr
672 /*****************************************
673 ** STATIC LOCAL FUNCTIONS **
674 ******************************************/