* tuiSourceWin.h (tui_update_all_breakpoint_info): Declare.
[deliverable/binutils-gdb.git] / gdb / tui / tuiSourceWin.c
1 /* TUI display source/assembly window.
2
3 Copyright 1998, 1999, 2000, 2001, 2002 Free Software Foundation,
4 Inc.
5
6 Contributed by Hewlett-Packard Company.
7
8 This file is part of GDB.
9
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.
14
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.
19
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. */
24
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>
31 first. */
32
33 #include "config.h"
34 #ifdef HAVE_NCURSES_H
35 #include <ncurses.h>
36 #else
37 #ifdef HAVE_CURSES_H
38 #include <curses.h>
39 #endif
40 #endif
41
42 #include "defs.h"
43 #include <ctype.h>
44 #include "symtab.h"
45 #include "frame.h"
46 #include "breakpoint.h"
47 #include "value.h"
48
49 #include "tui.h"
50 #include "tuiData.h"
51 #include "tuiStack.h"
52 #include "tuiWin.h"
53 #include "tuiGeneralWin.h"
54 #include "tuiSourceWin.h"
55 #include "tuiSource.h"
56 #include "tuiDisassem.h"
57
58
59 /* Function to display the "main" routine. */
60 void
61 tui_display_main (void)
62 {
63 if ((sourceWindows ())->count > 0)
64 {
65 CORE_ADDR addr;
66
67 addr = tuiGetBeginAsmAddress ();
68 if (addr != (CORE_ADDR) 0)
69 {
70 struct symtab_and_line sal;
71
72 tuiUpdateSourceWindowsWithAddr (addr);
73 sal = find_pc_line (addr, 0);
74 if (sal.symtab)
75 tuiUpdateLocatorFilename (sal.symtab->filename);
76 else
77 tuiUpdateLocatorFilename ("??");
78 }
79 }
80 }
81
82
83
84 /*
85 ** tuiUpdateSourceWindow().
86 ** Function to display source in the source window. This function
87 ** initializes the horizontal scroll to 0.
88 */
89 void
90 tuiUpdateSourceWindow (TuiWinInfoPtr winInfo, struct symtab *s,
91 TuiLineOrAddress lineOrAddr, int noerror)
92 {
93 winInfo->detail.sourceInfo.horizontalOffset = 0;
94 tuiUpdateSourceWindowAsIs (winInfo, s, lineOrAddr, noerror);
95
96 return;
97 } /* tuiUpdateSourceWindow */
98
99
100 /*
101 ** tuiUpdateSourceWindowAsIs().
102 ** Function to display source in the source/asm window. This
103 ** function shows the source as specified by the horizontal offset.
104 */
105 void
106 tuiUpdateSourceWindowAsIs (TuiWinInfoPtr winInfo, struct symtab *s,
107 TuiLineOrAddress lineOrAddr, int noerror)
108 {
109 TuiStatus ret;
110
111 if (winInfo->generic.type == SRC_WIN)
112 ret = tuiSetSourceContent (s, lineOrAddr.lineNo, noerror);
113 else
114 ret = tuiSetDisassemContent (lineOrAddr.addr);
115
116 if (ret == TUI_FAILURE)
117 {
118 tuiClearSourceContent (winInfo, EMPTY_SOURCE_PROMPT);
119 tuiClearExecInfoContent (winInfo);
120 }
121 else
122 {
123 tui_update_breakpoint_info (winInfo, 0);
124 tuiShowSourceContent (winInfo);
125 tuiUpdateExecInfo (winInfo);
126 if (winInfo->generic.type == SRC_WIN)
127 {
128 current_source_line = lineOrAddr.lineNo +
129 (winInfo->generic.contentSize - 2);
130 current_source_symtab = s;
131 /*
132 ** If the focus was in the asm win, put it in the src
133 ** win if we don't have a split layout
134 */
135 if (tuiWinWithFocus () == disassemWin &&
136 currentLayout () != SRC_DISASSEM_COMMAND)
137 tuiSetWinFocusTo (srcWin);
138 }
139 }
140
141
142 return;
143 } /* tuiUpdateSourceWindowAsIs */
144
145
146 /*
147 ** tuiUpdateSourceWindowsWithAddr().
148 ** Function to ensure that the source and/or disassemly windows
149 ** reflect the input address.
150 */
151 void
152 tuiUpdateSourceWindowsWithAddr (CORE_ADDR addr)
153 {
154 if (addr != 0)
155 {
156 struct symtab_and_line sal;
157 TuiLineOrAddress l;
158
159 switch (currentLayout ())
160 {
161 case DISASSEM_COMMAND:
162 case DISASSEM_DATA_COMMAND:
163 tuiShowDisassem (addr);
164 break;
165 case SRC_DISASSEM_COMMAND:
166 tuiShowDisassemAndUpdateSource (addr);
167 break;
168 default:
169 sal = find_pc_line (addr, 0);
170 l.lineNo = sal.line;
171 tuiShowSource (sal.symtab, l, FALSE);
172 break;
173 }
174 }
175 else
176 {
177 int i;
178
179 for (i = 0; i < (sourceWindows ())->count; i++)
180 {
181 TuiWinInfoPtr winInfo = (TuiWinInfoPtr) (sourceWindows ())->list[i];
182
183 tuiClearSourceContent (winInfo, EMPTY_SOURCE_PROMPT);
184 tuiClearExecInfoContent (winInfo);
185 }
186 }
187
188 return;
189 } /* tuiUpdateSourceWindowsWithAddr */
190
191 /*
192 ** tuiUpdateSourceWindowsWithLine().
193 ** Function to ensure that the source and/or disassemly windows
194 ** reflect the input address.
195 */
196 void
197 tuiUpdateSourceWindowsWithLine (struct symtab *s, int line)
198 {
199 CORE_ADDR pc;
200 TuiLineOrAddress l;
201
202 switch (currentLayout ())
203 {
204 case DISASSEM_COMMAND:
205 case DISASSEM_DATA_COMMAND:
206 find_line_pc (s, line, &pc);
207 tuiUpdateSourceWindowsWithAddr (pc);
208 break;
209 default:
210 l.lineNo = line;
211 tuiShowSource (s, l, FALSE);
212 if (currentLayout () == SRC_DISASSEM_COMMAND)
213 {
214 find_line_pc (s, line, &pc);
215 tuiShowDisassem (pc);
216 }
217 break;
218 }
219
220 return;
221 } /* tuiUpdateSourceWindowsWithLine */
222
223 /*
224 ** tuiClearSourceContent().
225 */
226 void
227 tuiClearSourceContent (TuiWinInfoPtr winInfo, int displayPrompt)
228 {
229 if (m_winPtrNotNull (winInfo))
230 {
231 register int i;
232
233 winInfo->generic.contentInUse = FALSE;
234 tuiEraseSourceContent (winInfo, displayPrompt);
235 for (i = 0; i < winInfo->generic.contentSize; i++)
236 {
237 TuiWinElementPtr element =
238 (TuiWinElementPtr) winInfo->generic.content[i];
239 element->whichElement.source.hasBreak = FALSE;
240 element->whichElement.source.isExecPoint = FALSE;
241 }
242 }
243
244 return;
245 } /* tuiClearSourceContent */
246
247
248 /*
249 ** tuiEraseSourceContent().
250 */
251 void
252 tuiEraseSourceContent (TuiWinInfoPtr winInfo, int displayPrompt)
253 {
254 int xPos;
255 int halfWidth = (winInfo->generic.width - 2) / 2;
256
257 if (winInfo->generic.handle != (WINDOW *) NULL)
258 {
259 werase (winInfo->generic.handle);
260 checkAndDisplayHighlightIfNeeded (winInfo);
261 if (displayPrompt == EMPTY_SOURCE_PROMPT)
262 {
263 char *noSrcStr;
264
265 if (winInfo->generic.type == SRC_WIN)
266 noSrcStr = NO_SRC_STRING;
267 else
268 noSrcStr = NO_DISASSEM_STRING;
269 if (strlen (noSrcStr) >= halfWidth)
270 xPos = 1;
271 else
272 xPos = halfWidth - strlen (noSrcStr);
273 mvwaddstr (winInfo->generic.handle,
274 (winInfo->generic.height / 2),
275 xPos,
276 noSrcStr);
277
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 */
282
283 tuiSetSourceContentNil (winInfo, noSrcStr);
284 }
285 tuiRefreshWin (&winInfo->generic);
286 }
287 return;
288 } /* tuiEraseSourceContent */
289
290
291 /* Redraw the complete line of a source or disassembly window. */
292 static void
293 tui_show_source_line (TuiWinInfoPtr winInfo, int lineno)
294 {
295 TuiWinElementPtr line;
296 int x, y;
297
298 line = (TuiWinElementPtr) winInfo->generic.content[lineno - 1];
299 if (line->whichElement.source.isExecPoint)
300 wattron (winInfo->generic.handle, A_STANDOUT);
301
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);
306
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)
310 {
311 waddch (winInfo->generic.handle, ' ');
312 getyx (winInfo->generic.handle, y, x);
313 }
314 }
315
316 /*
317 ** tuiShowSourceContent().
318 */
319 void
320 tuiShowSourceContent (TuiWinInfoPtr winInfo)
321 {
322 if (winInfo->generic.contentSize > 0)
323 {
324 int lineno;
325
326 for (lineno = 1; lineno <= winInfo->generic.contentSize; lineno++)
327 tui_show_source_line (winInfo, lineno);
328 }
329 else
330 tuiEraseSourceContent (winInfo, TRUE);
331
332 checkAndDisplayHighlightIfNeeded (winInfo);
333 tuiRefreshWin (&winInfo->generic);
334 winInfo->generic.contentInUse = TRUE;
335 }
336
337
338 /*
339 ** tuiHorizontalSourceScroll().
340 ** Scroll the source forward or backward horizontally
341 */
342 void
343 tuiHorizontalSourceScroll (TuiWinInfoPtr winInfo,
344 TuiScrollDirection direction,
345 int numToScroll)
346 {
347 if (winInfo->generic.content != (OpaquePtr) NULL)
348 {
349 int offset;
350 struct symtab *s;
351
352 if (current_source_symtab == (struct symtab *) NULL)
353 s = find_pc_symtab (selected_frame->pc);
354 else
355 s = current_source_symtab;
356
357 if (direction == LEFT_SCROLL)
358 offset = winInfo->detail.sourceInfo.horizontalOffset + numToScroll;
359 else
360 {
361 if ((offset =
362 winInfo->detail.sourceInfo.horizontalOffset - numToScroll) < 0)
363 offset = 0;
364 }
365 winInfo->detail.sourceInfo.horizontalOffset = offset;
366 tuiUpdateSourceWindowAsIs (
367 winInfo,
368 s,
369 ((TuiWinElementPtr)
370 winInfo->generic.content[0])->whichElement.source.lineOrAddr,
371 FALSE);
372 }
373
374 return;
375 } /* tuiHorizontalSourceScroll */
376
377
378 /*
379 ** tuiSetHasExecPointAt().
380 ** Set or clear the hasBreak flag in the line whose line is lineNo.
381 */
382 void
383 tuiSetIsExecPointAt (TuiLineOrAddress l, TuiWinInfoPtr winInfo)
384 {
385 int i;
386 TuiWinContent content = (TuiWinContent) winInfo->generic.content;
387
388 i = 0;
389 while (i < winInfo->generic.contentSize)
390 {
391 if (content[i]->whichElement.source.lineOrAddr.addr == l.addr)
392 content[i]->whichElement.source.isExecPoint = TRUE;
393 else
394 content[i]->whichElement.source.isExecPoint = FALSE;
395 i++;
396 }
397
398 return;
399 } /* tuiSetIsExecPointAt */
400
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. */
404 void
405 tui_update_all_breakpoint_info ()
406 {
407 TuiList* list = sourceWindows ();
408 int i;
409
410 for (i = 0; i < list->count; i++)
411 {
412 TuiWinInfoPtr win = (TuiWinInfoPtr) list->list[i];
413
414 if (tui_update_breakpoint_info (win, FALSE))
415 {
416 tuiUpdateExecInfo (win);
417 }
418 }
419 }
420
421
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. */
426 int
427 tui_update_breakpoint_info (TuiWinInfoPtr win, int current_only)
428 {
429 int i;
430 int need_refresh = 0;
431 TuiSourceInfoPtr src = &win->detail.sourceInfo;
432
433 for (i = 0; i < win->generic.contentSize; i++)
434 {
435 struct breakpoint *bp;
436 extern struct breakpoint *breakpoint_chain;
437 int mode;
438 TuiSourceElement* line;
439
440 line = &((TuiWinElementPtr) win->generic.content[i])->whichElement.source;
441 if (current_only && !line->isExecPoint)
442 continue;
443
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. */
447 mode = 0;
448 for (bp = breakpoint_chain;
449 bp != (struct breakpoint *) NULL;
450 bp = bp->next)
451 {
452 if ((win == srcWin
453 && bp->source_file
454 && (strcmp (src->filename, bp->source_file) == 0)
455 && bp->line_number == line->lineOrAddr.lineNo)
456 || (win == disassemWin
457 && bp->address == line->lineOrAddr.addr))
458 {
459 if (bp->enable_state == bp_disabled)
460 mode |= TUI_BP_DISABLED;
461 else
462 mode |= TUI_BP_ENABLED;
463 if (bp->hit_count)
464 mode |= TUI_BP_HIT;
465 if (bp->cond)
466 mode |= TUI_BP_CONDITIONAL;
467 if (bp->type == bp_hardware_breakpoint)
468 mode |= TUI_BP_HARDWARE;
469 }
470 }
471 if (line->hasBreak != mode)
472 {
473 line->hasBreak = mode;
474 need_refresh = 1;
475 }
476 }
477 return need_refresh;
478 }
479
480
481 /*
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.
486 */
487 TuiStatus
488 tuiSetExecInfoContent (TuiWinInfoPtr winInfo)
489 {
490 TuiStatus ret = TUI_SUCCESS;
491
492 if (winInfo->detail.sourceInfo.executionInfo != (TuiGenWinInfoPtr) NULL)
493 {
494 TuiGenWinInfoPtr execInfoPtr = winInfo->detail.sourceInfo.executionInfo;
495
496 if (execInfoPtr->content == (OpaquePtr) NULL)
497 execInfoPtr->content =
498 (OpaquePtr) allocContent (winInfo->generic.height,
499 execInfoPtr->type);
500 if (execInfoPtr->content != (OpaquePtr) NULL)
501 {
502 int i;
503
504 tui_update_breakpoint_info (winInfo, 1);
505 for (i = 0; i < winInfo->generic.contentSize; i++)
506 {
507 TuiWinElementPtr element;
508 TuiWinElementPtr srcElement;
509 int mode;
510
511 element = (TuiWinElementPtr) execInfoPtr->content[i];
512 srcElement = (TuiWinElementPtr) winInfo->generic.content[i];
513
514 memset(element->whichElement.simpleString, ' ',
515 sizeof(element->whichElement.simpleString));
516 element->whichElement.simpleString[TUI_EXECINFO_SIZE - 1] = 0;
517
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';
527
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] = '-';
532
533 if (srcElement->whichElement.source.isExecPoint)
534 element->whichElement.simpleString[TUI_EXEC_POS] = '>';
535 }
536 execInfoPtr->contentSize = winInfo->generic.contentSize;
537 }
538 else
539 ret = TUI_FAILURE;
540 }
541
542 return ret;
543 }
544
545
546 /*
547 ** tuiShowExecInfoContent().
548 */
549 void
550 tuiShowExecInfoContent (TuiWinInfoPtr winInfo)
551 {
552 TuiGenWinInfoPtr execInfo = winInfo->detail.sourceInfo.executionInfo;
553 int curLine;
554
555 werase (execInfo->handle);
556 tuiRefreshWin (execInfo);
557 for (curLine = 1; (curLine <= execInfo->contentSize); curLine++)
558 mvwaddstr (execInfo->handle,
559 curLine,
560 0,
561 ((TuiWinElementPtr)
562 execInfo->content[curLine - 1])->whichElement.simpleString);
563 tuiRefreshWin (execInfo);
564 execInfo->contentInUse = TRUE;
565
566 return;
567 } /* tuiShowExecInfoContent */
568
569
570 /*
571 ** tuiEraseExecInfoContent().
572 */
573 void
574 tuiEraseExecInfoContent (TuiWinInfoPtr winInfo)
575 {
576 TuiGenWinInfoPtr execInfo = winInfo->detail.sourceInfo.executionInfo;
577
578 werase (execInfo->handle);
579 tuiRefreshWin (execInfo);
580
581 return;
582 } /* tuiEraseExecInfoContent */
583
584 /*
585 ** tuiClearExecInfoContent().
586 */
587 void
588 tuiClearExecInfoContent (TuiWinInfoPtr winInfo)
589 {
590 winInfo->detail.sourceInfo.executionInfo->contentInUse = FALSE;
591 tuiEraseExecInfoContent (winInfo);
592
593 return;
594 } /* tuiClearExecInfoContent */
595
596 /*
597 ** tuiUpdateExecInfo().
598 ** Function to update the execution info window
599 */
600 void
601 tuiUpdateExecInfo (TuiWinInfoPtr winInfo)
602 {
603 tuiSetExecInfoContent (winInfo);
604 tuiShowExecInfoContent (winInfo);
605 } /* tuiUpdateExecInfo */
606
607
608 /*
609 ** tuiUpdateAllExecInfos()
610 */
611 void
612 tuiUpdateAllExecInfos (void)
613 {
614 int i;
615
616 for (i = 0; i < (sourceWindows ())->count; i++)
617 tuiUpdateExecInfo ((TuiWinInfoPtr) (sourceWindows ())->list[i]);
618
619 return;
620 } /* tuiUpdateAllExecInfos */
621
622 TuiStatus
623 tuiAllocSourceBuffer (TuiWinInfoPtr winInfo)
624 {
625 register char *srcLineBuf;
626 register int i, lineWidth, maxLines;
627 TuiStatus ret = TUI_FAILURE;
628
629 maxLines = winInfo->generic.height; /* less the highlight box */
630 lineWidth = winInfo->generic.width - 1;
631 /*
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.
635 */
636 if (winInfo->generic.content == (OpaquePtr) NULL)
637 {
638 srcLineBuf = (char *) xmalloc ((maxLines * lineWidth) * sizeof (char));
639 if (srcLineBuf == (char *) NULL)
640 fputs_unfiltered (
641 "Unable to Allocate Memory for Source or Disassembly Display.\n",
642 gdb_stderr);
643 else
644 {
645 /* allocate the content list */
646 if ((winInfo->generic.content =
647 (OpaquePtr) allocContent (maxLines, SRC_WIN)) == (OpaquePtr) NULL)
648 {
649 tuiFree (srcLineBuf);
650 srcLineBuf = (char *) NULL;
651 fputs_unfiltered (
652 "Unable to Allocate Memory for Source or Disassembly Display.\n",
653 gdb_stderr);
654 }
655 }
656 for (i = 0; i < maxLines; i++)
657 ((TuiWinElementPtr)
658 winInfo->generic.content[i])->whichElement.source.line =
659 srcLineBuf + (lineWidth * i);
660 ret = TUI_SUCCESS;
661 }
662 else
663 ret = TUI_SUCCESS;
664
665 return ret;
666 } /* tuiAllocSourceBuffer */
667
668
669 /*
670 ** tuiLineIsDisplayed().
671 ** Answer whether the a particular line number or address is displayed
672 ** in the current source window.
673 */
674 int
675 tuiLineIsDisplayed (int line, TuiWinInfoPtr winInfo,
676 int checkThreshold)
677 {
678 int isDisplayed = FALSE;
679 int i, threshold;
680
681 if (checkThreshold)
682 threshold = SCROLL_THRESHOLD;
683 else
684 threshold = 0;
685 i = 0;
686 while (i < winInfo->generic.contentSize - threshold && !isDisplayed)
687 {
688 isDisplayed = (((TuiWinElementPtr)
689 winInfo->generic.content[i])->whichElement.source.lineOrAddr.lineNo
690 == (int) line);
691 i++;
692 }
693
694 return isDisplayed;
695 } /* tuiLineIsDisplayed */
696
697
698 /*
699 ** tuiLineIsDisplayed().
700 ** Answer whether the a particular line number or address is displayed
701 ** in the current source window.
702 */
703 int
704 tuiAddrIsDisplayed (CORE_ADDR addr, TuiWinInfoPtr winInfo,
705 int checkThreshold)
706 {
707 int isDisplayed = FALSE;
708 int i, threshold;
709
710 if (checkThreshold)
711 threshold = SCROLL_THRESHOLD;
712 else
713 threshold = 0;
714 i = 0;
715 while (i < winInfo->generic.contentSize - threshold && !isDisplayed)
716 {
717 isDisplayed = (((TuiWinElementPtr)
718 winInfo->generic.content[i])->whichElement.source.lineOrAddr.addr
719 == addr);
720 i++;
721 }
722
723 return isDisplayed;
724 }
725
726
727 /*****************************************
728 ** STATIC LOCAL FUNCTIONS **
729 ******************************************/
This page took 0.044074 seconds and 4 git commands to generate.