* tuiSourceWin.h (tui_update_all_breakpoint_info): Declare.
[deliverable/binutils-gdb.git] / gdb / tui / tuiSource.c
CommitLineData
f377b406 1/* TUI display source window.
f33c6cbf
AC
2
3 Copyright 1998, 1999, 2000, 2001, 2002 Free Software Foundation,
4 Inc.
5
f377b406
SC
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. */
c906108c 24
f33c6cbf
AC
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
4e8f7a8b
DJ
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
c906108c
SS
42#include "defs.h"
43#include <ctype.h>
44#include "symtab.h"
45#include "frame.h"
46#include "breakpoint.h"
c2c6d25f 47#include "source.h"
a4b99e53 48#include "symtab.h"
c906108c
SS
49
50#include "tui.h"
51#include "tuiData.h"
52#include "tuiStack.h"
53#include "tuiSourceWin.h"
54#include "tuiSource.h"
55
56
c906108c
SS
57/*****************************************
58** STATIC LOCAL FUNCTIONS FORWARD DECLS **
59******************************************/
60
a14ed312 61static struct breakpoint *_hasBreak (char *, int);
c906108c
SS
62
63
c906108c 64/*
c5aa993b
JM
65 ** tuiSetSourceContent().
66 ** Function to display source in the source window.
67 */
c906108c 68TuiStatus
eca6576c 69tuiSetSourceContent (struct symtab *s, int lineNo, int noerror)
c906108c
SS
70{
71 TuiStatus ret = TUI_FAILURE;
72
73 if (s != (struct symtab *) NULL && s->filename != (char *) NULL)
74 {
75 register FILE *stream;
76 register int i, desc, c, lineWidth, nlines;
bc6b7f04 77 register char *srcLine = 0;
c906108c
SS
78
79 if ((ret = tuiAllocSourceBuffer (srcWin)) == TUI_SUCCESS)
80 {
81 lineWidth = srcWin->generic.width - 1;
82 /*
c5aa993b
JM
83 ** Take hilite (window border) into account, when calculating
84 ** the number of lines
85 */
c906108c
SS
86 nlines = (lineNo + (srcWin->generic.height - 2)) - lineNo;
87 desc = open_source_file (s);
88 if (desc < 0)
89 {
90 if (!noerror)
91 {
92 char *name = alloca (strlen (s->filename) + 100);
93 sprintf (name, "%s:%d", s->filename, lineNo);
94 print_sys_errmsg (name, errno);
95 }
96 ret = TUI_FAILURE;
97 }
98 else
99 {
100 if (s->line_charpos == 0)
101 find_source_lines (s, desc);
102
103 if (lineNo < 1 || lineNo > s->nlines)
104 {
105 close (desc);
106 printf_unfiltered (
107 "Line number %d out of range; %s has %d lines.\n",
108 lineNo, s->filename, s->nlines);
109 }
110 else if (lseek (desc, s->line_charpos[lineNo - 1], 0) < 0)
111 {
112 close (desc);
113 perror_with_name (s->filename);
114 }
115 else
116 {
117 register int offset, curLineNo, curLine, curLen, threshold;
118 TuiGenWinInfoPtr locator = locatorWinInfoPtr ();
bc6b7f04
SC
119 TuiSourceInfoPtr src = &srcWin->detail.sourceInfo;
120
121 if (srcWin->generic.title)
122 xfree (srcWin->generic.title);
123 srcWin->generic.title = xstrdup (s->filename);
124
125 if (src->filename)
126 xfree (src->filename);
127 src->filename = xstrdup (s->filename);
128
129 /* Determine the threshold for the length of the line
130 and the offset to start the display. */
131 offset = src->horizontalOffset;
c906108c
SS
132 threshold = (lineWidth - 1) + offset;
133 stream = fdopen (desc, FOPEN_RT);
134 clearerr (stream);
135 curLine = 0;
bc6b7f04 136 curLineNo = src->startLineOrAddr.lineNo = lineNo;
c906108c
SS
137 if (offset > 0)
138 srcLine = (char *) xmalloc (
139 (threshold + 1) * sizeof (char));
140 while (curLine < nlines)
141 {
142 TuiWinElementPtr element = (TuiWinElementPtr)
143 srcWin->generic.content[curLine];
144 struct breakpoint *bp;
145
146 /* get the first character in the line */
147 c = fgetc (stream);
148
149 if (offset == 0)
150 srcLine = ((TuiWinElementPtr)
151 srcWin->generic.content[
152 curLine])->whichElement.source.line;
153 /* Init the line with the line number */
154 sprintf (srcLine, "%-6d", curLineNo);
155 curLen = strlen (srcLine);
156 i = curLen -
157 ((curLen / tuiDefaultTabLen ()) * tuiDefaultTabLen ());
158 while (i < tuiDefaultTabLen ())
159 {
160 srcLine[curLen] = ' ';
161 i++;
162 curLen++;
163 }
164 srcLine[curLen] = (char) 0;
165
166 /*
c5aa993b
JM
167 ** Set whether element is the execution point and
168 ** whether there is a break point on it.
169 */
c906108c
SS
170 element->whichElement.source.lineOrAddr.lineNo =
171 curLineNo;
172 element->whichElement.source.isExecPoint =
173 (strcmp (((TuiWinElementPtr)
174 locator->content[0])->whichElement.locator.fileName,
175 s->filename) == 0
176 && curLineNo == ((TuiWinElementPtr)
177 locator->content[0])->whichElement.locator.lineNo);
178 bp = _hasBreak (s->filename, curLineNo);
179 element->whichElement.source.hasBreak =
180 (bp != (struct breakpoint *) NULL &&
181 (!element->whichElement.source.isExecPoint ||
b5de0fa7 182 (bp->disposition != disp_del || bp->hit_count <= 0)));
c906108c
SS
183 if (c != EOF)
184 {
185 i = strlen (srcLine) - 1;
186 do
187 {
188 if ((c != '\n') &&
189 (c != '\r') && (++i < threshold))
190 {
191 if (c < 040 && c != '\t')
192 {
193 srcLine[i++] = '^';
194 srcLine[i] = c + 0100;
195 }
196 else if (c == 0177)
197 {
198 srcLine[i++] = '^';
199 srcLine[i] = '?';
200 }
201 else
202 { /*
c5aa993b
JM
203 ** Store the charcter in the line
204 ** buffer. If it is a tab, then
205 ** translate to the correct number of
206 ** chars so we don't overwrite our
207 ** buffer.
208 */
c906108c
SS
209 if (c == '\t')
210 {
211 int j, maxTabLen = tuiDefaultTabLen ();
212
213 for (j = i - (
214 (i / maxTabLen) * maxTabLen);
215 ((j < maxTabLen) &&
216 i < threshold);
217 i++, j++)
218 srcLine[i] = ' ';
219 i--;
220 }
221 else
222 srcLine[i] = c;
223 }
224 srcLine[i + 1] = 0;
225 }
226 else
227 { /*
c5aa993b
JM
228 ** if we have not reached EOL, then eat
229 ** chars until we do
230 */
c906108c
SS
231 while (c != EOF && c != '\n' && c != '\r')
232 c = fgetc (stream);
233 }
234 }
235 while (c != EOF && c != '\n' && c != '\r' &&
236 i < threshold && (c = fgetc (stream)));
237 }
238 /* Now copy the line taking the offset into account */
239 if (strlen (srcLine) > offset)
240 strcpy (((TuiWinElementPtr) srcWin->generic.content[
241 curLine])->whichElement.source.line,
242 &srcLine[offset]);
243 else
244 ((TuiWinElementPtr)
245 srcWin->generic.content[
246 curLine])->whichElement.source.line[0] = (char) 0;
247 curLine++;
248 curLineNo++;
249 }
250 if (offset > 0)
251 tuiFree (srcLine);
252 fclose (stream);
253 srcWin->generic.contentSize = nlines;
254 ret = TUI_SUCCESS;
255 }
256 }
257 }
258 }
259 return ret;
260} /* tuiSetSourceContent */
261
262
263/* elz: this function sets the contents of the source window to empty
264 except for a line in the middle with a warning message about the
265 source not being available. This function is called by
266 tuiEraseSourceContents, which in turn is invoked when the source files
c5aa993b 267 cannot be accessed */
c906108c
SS
268
269void
eca6576c 270tuiSetSourceContentNil (TuiWinInfoPtr winInfo, char *warning_string)
c906108c
SS
271{
272 int lineWidth;
273 int nLines;
274 int curr_line = 0;
275
276 lineWidth = winInfo->generic.width - 1;
277 nLines = winInfo->generic.height - 2;
278
279 /* set to empty each line in the window, except for the one
c5aa993b 280 which contains the message */
c906108c
SS
281 while (curr_line < winInfo->generic.contentSize)
282 {
283 /* set the information related to each displayed line
c5aa993b
JM
284 to null: i.e. the line number is 0, there is no bp,
285 it is not where the program is stopped */
c906108c
SS
286
287 TuiWinElementPtr element =
288 (TuiWinElementPtr) winInfo->generic.content[curr_line];
289 element->whichElement.source.lineOrAddr.lineNo = 0;
290 element->whichElement.source.isExecPoint = FALSE;
291 element->whichElement.source.hasBreak = FALSE;
292
c5aa993b 293 /* set the contents of the line to blank */
c906108c
SS
294 element->whichElement.source.line[0] = (char) 0;
295
296 /* if the current line is in the middle of the screen, then we want to
c5aa993b
JM
297 display the 'no source available' message in it.
298 Note: the 'weird' arithmetic with the line width and height comes from
299 the function tuiEraseSourceContent. We need to keep the screen and the
300 window's actual contents in synch */
c906108c
SS
301
302 if (curr_line == (nLines / 2 + 1))
303 {
304 int i;
305 int xpos;
306 int warning_length = strlen (warning_string);
307 char *srcLine;
308
309 srcLine = element->whichElement.source.line;
310
311 if (warning_length >= ((lineWidth - 1) / 2))
312 xpos = 1;
313 else
314 xpos = (lineWidth - 1) / 2 - warning_length;
315
316 for (i = 0; i < xpos; i++)
317 srcLine[i] = ' ';
318
319 sprintf (srcLine + i, "%s", warning_string);
320
321 for (i = xpos + warning_length; i < lineWidth; i++)
322 srcLine[i] = ' ';
323
324 srcLine[i] = '\n';
325
326 } /* end if */
327
328 curr_line++;
329
c5aa993b 330 } /* end while */
c906108c 331
c5aa993b 332} /*tuiSetSourceContentNil */
c906108c
SS
333
334
335
336
337/*
c5aa993b
JM
338 ** tuiShowSource().
339 ** Function to display source in the source window. This function
340 ** initializes the horizontal scroll to 0.
341 */
c906108c 342void
a4b99e53 343tuiShowSource (struct symtab *s, TuiLineOrAddress line, int noerror)
c906108c
SS
344{
345 srcWin->detail.sourceInfo.horizontalOffset = 0;
a4b99e53 346 tuiUpdateSourceWindowAsIs(srcWin, s, line, noerror);
c906108c
SS
347
348 return;
349} /* tuiShowSource */
350
351
352/*
c5aa993b
JM
353 ** tuiSourceIsDisplayed().
354 ** Answer whether the source is currently displayed in the source window.
355 */
c906108c 356int
eca6576c 357tuiSourceIsDisplayed (char *fname)
c906108c
SS
358{
359 return (srcWin->generic.contentInUse &&
360 (strcmp (((TuiWinElementPtr) (locatorWinInfoPtr ())->
361 content[0])->whichElement.locator.fileName, fname) == 0));
362} /* tuiSourceIsDisplayed */
363
364
365/*
c5aa993b
JM
366 ** tuiVerticalSourceScroll().
367 ** Scroll the source forward or backward vertically
368 */
c906108c 369void
a4b99e53
SC
370tuiVerticalSourceScroll (TuiScrollDirection scrollDirection,
371 int numToScroll)
c906108c
SS
372{
373 if (srcWin->generic.content != (OpaquePtr) NULL)
374 {
a4b99e53 375 TuiLineOrAddress l;
c906108c
SS
376 struct symtab *s;
377 TuiWinContent content = (TuiWinContent) srcWin->generic.content;
378
379 if (current_source_symtab == (struct symtab *) NULL)
380 s = find_pc_symtab (selected_frame->pc);
381 else
382 s = current_source_symtab;
383
384 if (scrollDirection == FORWARD_SCROLL)
385 {
a4b99e53 386 l.lineNo = content[0]->whichElement.source.lineOrAddr.lineNo +
c906108c 387 numToScroll;
a4b99e53 388 if (l.lineNo > s->nlines)
c5aa993b
JM
389 /*line = s->nlines - winInfo->generic.contentSize + 1; */
390 /*elz: fix for dts 23398 */
a4b99e53 391 l.lineNo = content[0]->whichElement.source.lineOrAddr.lineNo;
c906108c
SS
392 }
393 else
394 {
a4b99e53 395 l.lineNo = content[0]->whichElement.source.lineOrAddr.lineNo -
c906108c 396 numToScroll;
a4b99e53
SC
397 if (l.lineNo <= 0)
398 l.lineNo = 1;
c906108c 399 }
a4b99e53
SC
400 if (identify_source_line (s, l.lineNo, 0, -1) == 1)
401 tuiUpdateSourceWindowAsIs (srcWin, s, l, FALSE);
c906108c
SS
402 }
403
404 return;
405} /* tuiVerticalSourceScroll */
406
407
408/*****************************************
409** STATIC LOCAL FUNCTIONS **
410******************************************/
411
412/*
c5aa993b
JM
413 ** _hasBreak().
414 ** Answer whether there is a break point at the input line in
415 ** the source file indicated
416 */
c906108c 417static struct breakpoint *
eca6576c 418_hasBreak (char *sourceFileName, int lineNo)
c906108c
SS
419{
420 struct breakpoint *bpWithBreak = (struct breakpoint *) NULL;
421 struct breakpoint *bp;
422 extern struct breakpoint *breakpoint_chain;
423
424
425 for (bp = breakpoint_chain;
426 (bp != (struct breakpoint *) NULL &&
427 bpWithBreak == (struct breakpoint *) NULL);
428 bp = bp->next)
75fd9bc1
SC
429 if (bp->source_file
430 && (strcmp (sourceFileName, bp->source_file) == 0)
431 && (lineNo == bp->line_number))
c906108c
SS
432 bpWithBreak = bp;
433
434 return bpWithBreak;
435} /* _hasBreak */
This page took 0.267187 seconds and 4 git commands to generate.