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