b2ce594dbe3f5a56f5f246696c4d3db79273c20e
[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 tuiEraseSourceContent (winInfo, NO_EMPTY_SOURCE_PROMPT);
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 /*
402 ** tuiSetHasBreakAt().
403 ** Set or clear the hasBreak flag in the line whose line is lineNo.
404 */
405 void
406 tuiSetHasBreakAt (struct breakpoint *bp, TuiWinInfoPtr winInfo, int hasBreak)
407 {
408 int i;
409 TuiWinContent content = (TuiWinContent) winInfo->generic.content;
410
411 i = 0;
412 while (i < winInfo->generic.contentSize)
413 {
414 int gotIt;
415 TuiGenWinInfoPtr locator = locatorWinInfoPtr ();
416
417 if (winInfo == srcWin)
418 {
419 TuiSourceInfoPtr src = &winInfo->detail.sourceInfo;
420
421 gotIt = (src->filename != (char *) NULL &&
422 bp->source_file != NULL &&
423 (strcmp (bp->source_file, src->filename) == 0) &&
424 content[i]->whichElement.source.lineOrAddr.lineNo ==
425 bp->line_number);
426 }
427 else
428 gotIt = (content[i]->whichElement.source.lineOrAddr.addr
429 == bp->address);
430 if (gotIt)
431 {
432 content[i]->whichElement.source.hasBreak = hasBreak;
433 break;
434 }
435 i++;
436 }
437
438 return;
439 } /* tuiSetHasBreakAt */
440
441
442 /*
443 ** tuiAllSetHasBreakAt().
444 ** Set or clear the hasBreak flag in all displayed source windows.
445 */
446 void
447 tuiAllSetHasBreakAt (struct breakpoint *bp, int hasBreak)
448 {
449 int i;
450
451 for (i = 0; i < (sourceWindows ())->count; i++)
452 tuiSetHasBreakAt (bp,
453 (TuiWinInfoPtr) (sourceWindows ())->list[i], hasBreak);
454
455 return;
456 } /* tuiAllSetHasBreakAt */
457
458
459 /*********************************
460 ** EXECUTION INFO FUNCTIONS **
461 *********************************/
462
463 /*
464 ** tuiSetExecInfoContent().
465 ** Function to initialize the content of the execution info window,
466 ** based upon the input window which is either the source or
467 ** disassembly window.
468 */
469 TuiStatus
470 tuiSetExecInfoContent (TuiWinInfoPtr winInfo)
471 {
472 TuiStatus ret = TUI_SUCCESS;
473
474 if (winInfo->detail.sourceInfo.executionInfo != (TuiGenWinInfoPtr) NULL)
475 {
476 TuiGenWinInfoPtr execInfoPtr = winInfo->detail.sourceInfo.executionInfo;
477
478 if (execInfoPtr->content == (OpaquePtr) NULL)
479 execInfoPtr->content =
480 (OpaquePtr) allocContent (winInfo->generic.height,
481 execInfoPtr->type);
482 if (execInfoPtr->content != (OpaquePtr) NULL)
483 {
484 int i;
485
486 for (i = 0; i < winInfo->generic.contentSize; i++)
487 {
488 TuiWinElementPtr element;
489 TuiWinElementPtr srcElement;
490
491 element = (TuiWinElementPtr) execInfoPtr->content[i];
492 srcElement = (TuiWinElementPtr) winInfo->generic.content[i];
493 /*
494 ** First check to see if we have a breakpoint that is
495 ** temporary. If so, and this is our current execution point,
496 ** then clear the break indicator.
497 */
498 if (srcElement->whichElement.source.hasBreak &&
499 srcElement->whichElement.source.isExecPoint)
500 {
501 struct breakpoint *bp;
502 int found = FALSE;
503 extern struct breakpoint *breakpoint_chain;
504
505 for (bp = breakpoint_chain;
506 (bp != (struct breakpoint *) NULL && !found);
507 bp = bp->next)
508 {
509 found =
510 (winInfo == srcWin &&
511 bp->line_number ==
512 srcElement->whichElement.source.lineOrAddr.lineNo) ||
513 (winInfo == disassemWin &&
514 bp->address == (CORE_ADDR)
515 srcElement->whichElement.source.lineOrAddr.addr);
516 if (found)
517 srcElement->whichElement.source.hasBreak =
518 (bp->disposition != disp_del || bp->hit_count <= 0);
519 }
520 if (!found)
521 srcElement->whichElement.source.hasBreak = FALSE;
522 }
523 /*
524 ** Now update the exec info content based upon the state
525 ** of each line as indicated by the source content.
526 */
527 if (srcElement->whichElement.source.hasBreak &&
528 srcElement->whichElement.source.isExecPoint)
529 element->whichElement.simpleString = breakLocationStr ();
530 else if (srcElement->whichElement.source.hasBreak)
531 element->whichElement.simpleString = breakStr ();
532 else if (srcElement->whichElement.source.isExecPoint)
533 element->whichElement.simpleString = locationStr ();
534 else
535 element->whichElement.simpleString = blankStr ();
536 }
537 execInfoPtr->contentSize = winInfo->generic.contentSize;
538 }
539 else
540 ret = TUI_FAILURE;
541 }
542
543 return ret;
544 } /* tuiSetExecInfoContent */
545
546
547 /*
548 ** tuiShowExecInfoContent().
549 */
550 void
551 tuiShowExecInfoContent (TuiWinInfoPtr winInfo)
552 {
553 TuiGenWinInfoPtr execInfo = winInfo->detail.sourceInfo.executionInfo;
554 int curLine;
555
556 werase (execInfo->handle);
557 tuiRefreshWin (execInfo);
558 for (curLine = 1; (curLine <= execInfo->contentSize); curLine++)
559 mvwaddstr (execInfo->handle,
560 curLine,
561 0,
562 ((TuiWinElementPtr)
563 execInfo->content[curLine - 1])->whichElement.simpleString);
564 tuiRefreshWin (execInfo);
565 execInfo->contentInUse = TRUE;
566
567 return;
568 } /* tuiShowExecInfoContent */
569
570
571 /*
572 ** tuiEraseExecInfoContent().
573 */
574 void
575 tuiEraseExecInfoContent (TuiWinInfoPtr winInfo)
576 {
577 TuiGenWinInfoPtr execInfo = winInfo->detail.sourceInfo.executionInfo;
578
579 werase (execInfo->handle);
580 tuiRefreshWin (execInfo);
581
582 return;
583 } /* tuiEraseExecInfoContent */
584
585 /*
586 ** tuiClearExecInfoContent().
587 */
588 void
589 tuiClearExecInfoContent (TuiWinInfoPtr winInfo)
590 {
591 winInfo->detail.sourceInfo.executionInfo->contentInUse = FALSE;
592 tuiEraseExecInfoContent (winInfo);
593
594 return;
595 } /* tuiClearExecInfoContent */
596
597 /*
598 ** tuiUpdateExecInfo().
599 ** Function to update the execution info window
600 */
601 void
602 tuiUpdateExecInfo (TuiWinInfoPtr winInfo)
603 {
604 tuiSetExecInfoContent (winInfo);
605 tuiShowExecInfoContent (winInfo);
606 } /* tuiUpdateExecInfo */
607
608
609 /*
610 ** tuiUpdateAllExecInfos()
611 */
612 void
613 tuiUpdateAllExecInfos (void)
614 {
615 int i;
616
617 for (i = 0; i < (sourceWindows ())->count; i++)
618 tuiUpdateExecInfo ((TuiWinInfoPtr) (sourceWindows ())->list[i]);
619
620 return;
621 } /* tuiUpdateAllExecInfos */
622
623 TuiStatus
624 tuiAllocSourceBuffer (TuiWinInfoPtr winInfo)
625 {
626 register char *srcLineBuf;
627 register int i, lineWidth, maxLines;
628 TuiStatus ret = TUI_FAILURE;
629
630 maxLines = winInfo->generic.height; /* less the highlight box */
631 lineWidth = winInfo->generic.width - 1;
632 /*
633 ** Allocate the buffer for the source lines. Do this only once since they
634 ** will be re-used for all source displays. The only other time this will
635 ** be done is when a window's size changes.
636 */
637 if (winInfo->generic.content == (OpaquePtr) NULL)
638 {
639 srcLineBuf = (char *) xmalloc ((maxLines * lineWidth) * sizeof (char));
640 if (srcLineBuf == (char *) NULL)
641 fputs_unfiltered (
642 "Unable to Allocate Memory for Source or Disassembly Display.\n",
643 gdb_stderr);
644 else
645 {
646 /* allocate the content list */
647 if ((winInfo->generic.content =
648 (OpaquePtr) allocContent (maxLines, SRC_WIN)) == (OpaquePtr) NULL)
649 {
650 tuiFree (srcLineBuf);
651 srcLineBuf = (char *) NULL;
652 fputs_unfiltered (
653 "Unable to Allocate Memory for Source or Disassembly Display.\n",
654 gdb_stderr);
655 }
656 }
657 for (i = 0; i < maxLines; i++)
658 ((TuiWinElementPtr)
659 winInfo->generic.content[i])->whichElement.source.line =
660 srcLineBuf + (lineWidth * i);
661 ret = TUI_SUCCESS;
662 }
663 else
664 ret = TUI_SUCCESS;
665
666 return ret;
667 } /* tuiAllocSourceBuffer */
668
669
670 /*
671 ** tuiLineIsDisplayed().
672 ** Answer whether the a particular line number or address is displayed
673 ** in the current source window.
674 */
675 int
676 tuiLineIsDisplayed (int line, TuiWinInfoPtr winInfo,
677 int checkThreshold)
678 {
679 int isDisplayed = FALSE;
680 int i, threshold;
681
682 if (checkThreshold)
683 threshold = SCROLL_THRESHOLD;
684 else
685 threshold = 0;
686 i = 0;
687 while (i < winInfo->generic.contentSize - threshold && !isDisplayed)
688 {
689 isDisplayed = (((TuiWinElementPtr)
690 winInfo->generic.content[i])->whichElement.source.lineOrAddr.lineNo
691 == (int) line);
692 i++;
693 }
694
695 return isDisplayed;
696 } /* tuiLineIsDisplayed */
697
698
699 /*
700 ** tuiLineIsDisplayed().
701 ** Answer whether the a particular line number or address is displayed
702 ** in the current source window.
703 */
704 int
705 tuiAddrIsDisplayed (CORE_ADDR addr, TuiWinInfoPtr winInfo,
706 int checkThreshold)
707 {
708 int isDisplayed = FALSE;
709 int i, threshold;
710
711 if (checkThreshold)
712 threshold = SCROLL_THRESHOLD;
713 else
714 threshold = 0;
715 i = 0;
716 while (i < winInfo->generic.contentSize - threshold && !isDisplayed)
717 {
718 isDisplayed = (((TuiWinElementPtr)
719 winInfo->generic.content[i])->whichElement.source.lineOrAddr.addr
720 == addr);
721 i++;
722 }
723
724 return isDisplayed;
725 }
726
727
728 /*****************************************
729 ** STATIC LOCAL FUNCTIONS **
730 ******************************************/
This page took 0.072178 seconds and 4 git commands to generate.