* tuiWin.c (_tuiAllWindowsInfo): Don't crash if the window
[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 /* Set or clear the hasBreak flag in the line whose line is lineNo. */
379 void
380 tuiSetIsExecPointAt (TuiLineOrAddress l, TuiWinInfoPtr winInfo)
381 {
382 int changed = 0;
383 int i;
384 TuiWinContent content = (TuiWinContent) winInfo->generic.content;
385
386 i = 0;
387 while (i < winInfo->generic.contentSize)
388 {
389 int newState;
390
391 if (content[i]->whichElement.source.lineOrAddr.addr == l.addr)
392 newState = TRUE;
393 else
394 newState = FALSE;
395 if (newState != content[i]->whichElement.source.isExecPoint)
396 {
397 changed++;
398 content[i]->whichElement.source.isExecPoint = newState;
399 tui_show_source_line (winInfo, i + 1);
400 }
401 i++;
402 }
403 if (changed)
404 tuiRefreshWin (&winInfo->generic);
405 }
406
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. */
410 void
411 tui_update_all_breakpoint_info ()
412 {
413 TuiList* list = sourceWindows ();
414 int i;
415
416 for (i = 0; i < list->count; i++)
417 {
418 TuiWinInfoPtr win = (TuiWinInfoPtr) list->list[i];
419
420 if (tui_update_breakpoint_info (win, FALSE))
421 {
422 tuiUpdateExecInfo (win);
423 }
424 }
425 }
426
427
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. */
432 int
433 tui_update_breakpoint_info (TuiWinInfoPtr win, int current_only)
434 {
435 int i;
436 int need_refresh = 0;
437 TuiSourceInfoPtr src = &win->detail.sourceInfo;
438
439 for (i = 0; i < win->generic.contentSize; i++)
440 {
441 struct breakpoint *bp;
442 extern struct breakpoint *breakpoint_chain;
443 int mode;
444 TuiSourceElement* line;
445
446 line = &((TuiWinElementPtr) win->generic.content[i])->whichElement.source;
447 if (current_only && !line->isExecPoint)
448 continue;
449
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. */
453 mode = 0;
454 for (bp = breakpoint_chain;
455 bp != (struct breakpoint *) NULL;
456 bp = bp->next)
457 {
458 if ((win == srcWin
459 && bp->source_file
460 && (strcmp (src->filename, bp->source_file) == 0)
461 && bp->line_number == line->lineOrAddr.lineNo)
462 || (win == disassemWin
463 && bp->address == line->lineOrAddr.addr))
464 {
465 if (bp->enable_state == bp_disabled)
466 mode |= TUI_BP_DISABLED;
467 else
468 mode |= TUI_BP_ENABLED;
469 if (bp->hit_count)
470 mode |= TUI_BP_HIT;
471 if (bp->cond)
472 mode |= TUI_BP_CONDITIONAL;
473 if (bp->type == bp_hardware_breakpoint)
474 mode |= TUI_BP_HARDWARE;
475 }
476 }
477 if (line->hasBreak != mode)
478 {
479 line->hasBreak = mode;
480 need_refresh = 1;
481 }
482 }
483 return need_refresh;
484 }
485
486
487 /*
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.
492 */
493 TuiStatus
494 tuiSetExecInfoContent (TuiWinInfoPtr winInfo)
495 {
496 TuiStatus ret = TUI_SUCCESS;
497
498 if (winInfo->detail.sourceInfo.executionInfo != (TuiGenWinInfoPtr) NULL)
499 {
500 TuiGenWinInfoPtr execInfoPtr = winInfo->detail.sourceInfo.executionInfo;
501
502 if (execInfoPtr->content == (OpaquePtr) NULL)
503 execInfoPtr->content =
504 (OpaquePtr) allocContent (winInfo->generic.height,
505 execInfoPtr->type);
506 if (execInfoPtr->content != (OpaquePtr) NULL)
507 {
508 int i;
509
510 tui_update_breakpoint_info (winInfo, 1);
511 for (i = 0; i < winInfo->generic.contentSize; i++)
512 {
513 TuiWinElementPtr element;
514 TuiWinElementPtr srcElement;
515 int mode;
516
517 element = (TuiWinElementPtr) execInfoPtr->content[i];
518 srcElement = (TuiWinElementPtr) winInfo->generic.content[i];
519
520 memset(element->whichElement.simpleString, ' ',
521 sizeof(element->whichElement.simpleString));
522 element->whichElement.simpleString[TUI_EXECINFO_SIZE - 1] = 0;
523
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';
533
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] = '-';
538
539 if (srcElement->whichElement.source.isExecPoint)
540 element->whichElement.simpleString[TUI_EXEC_POS] = '>';
541 }
542 execInfoPtr->contentSize = winInfo->generic.contentSize;
543 }
544 else
545 ret = TUI_FAILURE;
546 }
547
548 return ret;
549 }
550
551
552 /*
553 ** tuiShowExecInfoContent().
554 */
555 void
556 tuiShowExecInfoContent (TuiWinInfoPtr winInfo)
557 {
558 TuiGenWinInfoPtr execInfo = winInfo->detail.sourceInfo.executionInfo;
559 int curLine;
560
561 werase (execInfo->handle);
562 tuiRefreshWin (execInfo);
563 for (curLine = 1; (curLine <= execInfo->contentSize); curLine++)
564 mvwaddstr (execInfo->handle,
565 curLine,
566 0,
567 ((TuiWinElementPtr)
568 execInfo->content[curLine - 1])->whichElement.simpleString);
569 tuiRefreshWin (execInfo);
570 execInfo->contentInUse = TRUE;
571
572 return;
573 } /* tuiShowExecInfoContent */
574
575
576 /*
577 ** tuiEraseExecInfoContent().
578 */
579 void
580 tuiEraseExecInfoContent (TuiWinInfoPtr winInfo)
581 {
582 TuiGenWinInfoPtr execInfo = winInfo->detail.sourceInfo.executionInfo;
583
584 werase (execInfo->handle);
585 tuiRefreshWin (execInfo);
586
587 return;
588 } /* tuiEraseExecInfoContent */
589
590 /*
591 ** tuiClearExecInfoContent().
592 */
593 void
594 tuiClearExecInfoContent (TuiWinInfoPtr winInfo)
595 {
596 winInfo->detail.sourceInfo.executionInfo->contentInUse = FALSE;
597 tuiEraseExecInfoContent (winInfo);
598
599 return;
600 } /* tuiClearExecInfoContent */
601
602 /*
603 ** tuiUpdateExecInfo().
604 ** Function to update the execution info window
605 */
606 void
607 tuiUpdateExecInfo (TuiWinInfoPtr winInfo)
608 {
609 tuiSetExecInfoContent (winInfo);
610 tuiShowExecInfoContent (winInfo);
611 } /* tuiUpdateExecInfo */
612
613 TuiStatus
614 tuiAllocSourceBuffer (TuiWinInfoPtr winInfo)
615 {
616 register char *srcLineBuf;
617 register int i, lineWidth, maxLines;
618 TuiStatus ret = TUI_FAILURE;
619
620 maxLines = winInfo->generic.height; /* less the highlight box */
621 lineWidth = winInfo->generic.width - 1;
622 /*
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.
626 */
627 if (winInfo->generic.content == (OpaquePtr) NULL)
628 {
629 srcLineBuf = (char *) xmalloc ((maxLines * lineWidth) * sizeof (char));
630 if (srcLineBuf == (char *) NULL)
631 fputs_unfiltered (
632 "Unable to Allocate Memory for Source or Disassembly Display.\n",
633 gdb_stderr);
634 else
635 {
636 /* allocate the content list */
637 if ((winInfo->generic.content =
638 (OpaquePtr) allocContent (maxLines, SRC_WIN)) == (OpaquePtr) NULL)
639 {
640 tuiFree (srcLineBuf);
641 srcLineBuf = (char *) NULL;
642 fputs_unfiltered (
643 "Unable to Allocate Memory for Source or Disassembly Display.\n",
644 gdb_stderr);
645 }
646 }
647 for (i = 0; i < maxLines; i++)
648 ((TuiWinElementPtr)
649 winInfo->generic.content[i])->whichElement.source.line =
650 srcLineBuf + (lineWidth * i);
651 ret = TUI_SUCCESS;
652 }
653 else
654 ret = TUI_SUCCESS;
655
656 return ret;
657 } /* tuiAllocSourceBuffer */
658
659
660 /*
661 ** tuiLineIsDisplayed().
662 ** Answer whether the a particular line number or address is displayed
663 ** in the current source window.
664 */
665 int
666 tuiLineIsDisplayed (int line, TuiWinInfoPtr winInfo,
667 int checkThreshold)
668 {
669 int isDisplayed = FALSE;
670 int i, threshold;
671
672 if (checkThreshold)
673 threshold = SCROLL_THRESHOLD;
674 else
675 threshold = 0;
676 i = 0;
677 while (i < winInfo->generic.contentSize - threshold && !isDisplayed)
678 {
679 isDisplayed = (((TuiWinElementPtr)
680 winInfo->generic.content[i])->whichElement.source.lineOrAddr.lineNo
681 == (int) line);
682 i++;
683 }
684
685 return isDisplayed;
686 } /* tuiLineIsDisplayed */
687
688
689 /*
690 ** tuiLineIsDisplayed().
691 ** Answer whether the a particular line number or address is displayed
692 ** in the current source window.
693 */
694 int
695 tuiAddrIsDisplayed (CORE_ADDR addr, TuiWinInfoPtr winInfo,
696 int checkThreshold)
697 {
698 int isDisplayed = FALSE;
699 int i, threshold;
700
701 if (checkThreshold)
702 threshold = SCROLL_THRESHOLD;
703 else
704 threshold = 0;
705 i = 0;
706 while (i < winInfo->generic.contentSize - threshold && !isDisplayed)
707 {
708 isDisplayed = (((TuiWinElementPtr)
709 winInfo->generic.content[i])->whichElement.source.lineOrAddr.addr
710 == addr);
711 i++;
712 }
713
714 return isDisplayed;
715 }
716
717
718 /*****************************************
719 ** STATIC LOCAL FUNCTIONS **
720 ******************************************/
This page took 0.04403 seconds and 4 git commands to generate.