2002-02-08 Daniel Jacobowitz <drow@mvista.com>
[deliverable/binutils-gdb.git] / gdb / tui / tuiSource.c
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. */
21
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
32 #include "defs.h"
33 #include <ctype.h>
34 #include "symtab.h"
35 #include "frame.h"
36 #include "breakpoint.h"
37 #include "source.h"
38 #include "symtab.h"
39
40 #include "tui.h"
41 #include "tuiData.h"
42 #include "tuiStack.h"
43 #include "tuiSourceWin.h"
44 #include "tuiSource.h"
45
46
47 /*****************************************
48 ** EXTERNAL DATA DECLS **
49 ******************************************/
50 extern int current_source_line;
51 extern struct symtab *current_source_symtab;
52
53
54 /*****************************************
55 ** STATIC LOCAL FUNCTIONS FORWARD DECLS **
56 ******************************************/
57
58 static struct breakpoint *_hasBreak (char *, int);
59
60
61 /*****************************************
62 ** STATIC LOCAL DATA **
63 ******************************************/
64
65
66 /*****************************************
67 ** PUBLIC FUNCTIONS **
68 ******************************************/
69
70 /*********************************
71 ** SOURCE/DISASSEM FUNCTIONS **
72 *********************************/
73
74 /*
75 ** tuiSetSourceContent().
76 ** Function to display source in the source window.
77 */
78 TuiStatus
79 tuiSetSourceContent (struct symtab *s, int lineNo, int noerror)
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 /*
93 ** Take hilite (window border) into account, when calculating
94 ** the number of lines
95 */
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 /*
130 ** Determine the threshold for the length of the line
131 ** and the offset to start the display
132 */
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 /*
170 ** Set whether element is the execution point and
171 ** whether there is a break point on it.
172 */
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 ||
185 (bp->disposition != disp_del || bp->hit_count <= 0)));
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 { /*
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 */
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 { /*
231 ** if we have not reached EOL, then eat
232 ** chars until we do
233 */
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
270 cannot be accessed */
271
272 void
273 tuiSetSourceContentNil (TuiWinInfoPtr winInfo, char *warning_string)
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
283 which contains the message */
284 while (curr_line < winInfo->generic.contentSize)
285 {
286 /* set the information related to each displayed line
287 to null: i.e. the line number is 0, there is no bp,
288 it is not where the program is stopped */
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
296 /* set the contents of the line to blank */
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
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 */
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
333 } /* end while */
334
335 } /*tuiSetSourceContentNil */
336
337
338
339
340 /*
341 ** tuiShowSource().
342 ** Function to display source in the source window. This function
343 ** initializes the horizontal scroll to 0.
344 */
345 void
346 tuiShowSource (struct symtab *s, TuiLineOrAddress line, int noerror)
347 {
348 srcWin->detail.sourceInfo.horizontalOffset = 0;
349 tuiUpdateSourceWindowAsIs(srcWin, s, line, noerror);
350
351 return;
352 } /* tuiShowSource */
353
354
355 /*
356 ** tuiSourceIsDisplayed().
357 ** Answer whether the source is currently displayed in the source window.
358 */
359 int
360 tuiSourceIsDisplayed (char *fname)
361 {
362 return (srcWin->generic.contentInUse &&
363 (strcmp (((TuiWinElementPtr) (locatorWinInfoPtr ())->
364 content[0])->whichElement.locator.fileName, fname) == 0));
365 } /* tuiSourceIsDisplayed */
366
367
368 /*
369 ** tuiVerticalSourceScroll().
370 ** Scroll the source forward or backward vertically
371 */
372 void
373 tuiVerticalSourceScroll (TuiScrollDirection scrollDirection,
374 int numToScroll)
375 {
376 if (srcWin->generic.content != (OpaquePtr) NULL)
377 {
378 TuiLineOrAddress l;
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 {
389 l.lineNo = content[0]->whichElement.source.lineOrAddr.lineNo +
390 numToScroll;
391 if (l.lineNo > s->nlines)
392 /*line = s->nlines - winInfo->generic.contentSize + 1; */
393 /*elz: fix for dts 23398 */
394 l.lineNo = content[0]->whichElement.source.lineOrAddr.lineNo;
395 }
396 else
397 {
398 l.lineNo = content[0]->whichElement.source.lineOrAddr.lineNo -
399 numToScroll;
400 if (l.lineNo <= 0)
401 l.lineNo = 1;
402 }
403 if (identify_source_line (s, l.lineNo, 0, -1) == 1)
404 tuiUpdateSourceWindowAsIs (srcWin, s, l, FALSE);
405 }
406
407 return;
408 } /* tuiVerticalSourceScroll */
409
410
411 /*****************************************
412 ** STATIC LOCAL FUNCTIONS **
413 ******************************************/
414
415 /*
416 ** _hasBreak().
417 ** Answer whether there is a break point at the input line in
418 ** the source file indicated
419 */
420 static struct breakpoint *
421 _hasBreak (char *sourceFileName, int lineNo)
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)
432 if (bp->source_file
433 && (strcmp (sourceFileName, bp->source_file) == 0)
434 && (lineNo == bp->line_number))
435 bpWithBreak = bp;
436
437 return bpWithBreak;
438 } /* _hasBreak */
This page took 0.039309 seconds and 4 git commands to generate.