1*b725ae77Skettenis /* TUI display source window.
2*b725ae77Skettenis
3*b725ae77Skettenis Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software
4*b725ae77Skettenis Foundation, Inc.
5*b725ae77Skettenis
6*b725ae77Skettenis Contributed by Hewlett-Packard Company.
7*b725ae77Skettenis
8*b725ae77Skettenis This file is part of GDB.
9*b725ae77Skettenis
10*b725ae77Skettenis This program is free software; you can redistribute it and/or modify
11*b725ae77Skettenis it under the terms of the GNU General Public License as published by
12*b725ae77Skettenis the Free Software Foundation; either version 2 of the License, or
13*b725ae77Skettenis (at your option) any later version.
14*b725ae77Skettenis
15*b725ae77Skettenis This program is distributed in the hope that it will be useful,
16*b725ae77Skettenis but WITHOUT ANY WARRANTY; without even the implied warranty of
17*b725ae77Skettenis MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18*b725ae77Skettenis GNU General Public License for more details.
19*b725ae77Skettenis
20*b725ae77Skettenis You should have received a copy of the GNU General Public License
21*b725ae77Skettenis along with this program; if not, write to the Free Software
22*b725ae77Skettenis Foundation, Inc., 59 Temple Place - Suite 330,
23*b725ae77Skettenis Boston, MA 02111-1307, USA. */
24*b725ae77Skettenis
25*b725ae77Skettenis #include "defs.h"
26*b725ae77Skettenis #include <ctype.h>
27*b725ae77Skettenis #include "symtab.h"
28*b725ae77Skettenis #include "frame.h"
29*b725ae77Skettenis #include "breakpoint.h"
30*b725ae77Skettenis #include "source.h"
31*b725ae77Skettenis #include "symtab.h"
32*b725ae77Skettenis
33*b725ae77Skettenis #include "tui/tui.h"
34*b725ae77Skettenis #include "tui/tui-data.h"
35*b725ae77Skettenis #include "tui/tui-stack.h"
36*b725ae77Skettenis #include "tui/tui-winsource.h"
37*b725ae77Skettenis #include "tui/tui-source.h"
38*b725ae77Skettenis
39*b725ae77Skettenis #include "gdb_string.h"
40*b725ae77Skettenis #include "gdb_curses.h"
41*b725ae77Skettenis
42*b725ae77Skettenis /* Function to display source in the source window. */
43*b725ae77Skettenis enum tui_status
tui_set_source_content(struct symtab * s,int line_no,int noerror)44*b725ae77Skettenis tui_set_source_content (struct symtab *s, int line_no, int noerror)
45*b725ae77Skettenis {
46*b725ae77Skettenis enum tui_status ret = TUI_FAILURE;
47*b725ae77Skettenis
48*b725ae77Skettenis if (s != (struct symtab *) NULL && s->filename != (char *) NULL)
49*b725ae77Skettenis {
50*b725ae77Skettenis FILE *stream;
51*b725ae77Skettenis int i, desc, c, line_width, nlines;
52*b725ae77Skettenis char *src_line = 0;
53*b725ae77Skettenis
54*b725ae77Skettenis if ((ret = tui_alloc_source_buffer (TUI_SRC_WIN)) == TUI_SUCCESS)
55*b725ae77Skettenis {
56*b725ae77Skettenis line_width = TUI_SRC_WIN->generic.width - 1;
57*b725ae77Skettenis /* Take hilite (window border) into account, when calculating
58*b725ae77Skettenis the number of lines */
59*b725ae77Skettenis nlines = (line_no + (TUI_SRC_WIN->generic.height - 2)) - line_no;
60*b725ae77Skettenis desc = open_source_file (s);
61*b725ae77Skettenis if (desc < 0)
62*b725ae77Skettenis {
63*b725ae77Skettenis if (!noerror)
64*b725ae77Skettenis {
65*b725ae77Skettenis char *name = alloca (strlen (s->filename) + 100);
66*b725ae77Skettenis sprintf (name, "%s:%d", s->filename, line_no);
67*b725ae77Skettenis print_sys_errmsg (name, errno);
68*b725ae77Skettenis }
69*b725ae77Skettenis ret = TUI_FAILURE;
70*b725ae77Skettenis }
71*b725ae77Skettenis else
72*b725ae77Skettenis {
73*b725ae77Skettenis if (s->line_charpos == 0)
74*b725ae77Skettenis find_source_lines (s, desc);
75*b725ae77Skettenis
76*b725ae77Skettenis if (line_no < 1 || line_no > s->nlines)
77*b725ae77Skettenis {
78*b725ae77Skettenis close (desc);
79*b725ae77Skettenis printf_unfiltered (
80*b725ae77Skettenis "Line number %d out of range; %s has %d lines.\n",
81*b725ae77Skettenis line_no, s->filename, s->nlines);
82*b725ae77Skettenis }
83*b725ae77Skettenis else if (lseek (desc, s->line_charpos[line_no - 1], 0) < 0)
84*b725ae77Skettenis {
85*b725ae77Skettenis close (desc);
86*b725ae77Skettenis perror_with_name (s->filename);
87*b725ae77Skettenis }
88*b725ae77Skettenis else
89*b725ae77Skettenis {
90*b725ae77Skettenis int offset, cur_line_no, cur_line, cur_len, threshold;
91*b725ae77Skettenis struct tui_gen_win_info * locator = tui_locator_win_info_ptr ();
92*b725ae77Skettenis struct tui_source_info * src = &TUI_SRC_WIN->detail.source_info;
93*b725ae77Skettenis
94*b725ae77Skettenis if (TUI_SRC_WIN->generic.title)
95*b725ae77Skettenis xfree (TUI_SRC_WIN->generic.title);
96*b725ae77Skettenis TUI_SRC_WIN->generic.title = xstrdup (s->filename);
97*b725ae77Skettenis
98*b725ae77Skettenis if (src->filename)
99*b725ae77Skettenis xfree (src->filename);
100*b725ae77Skettenis src->filename = xstrdup (s->filename);
101*b725ae77Skettenis
102*b725ae77Skettenis /* Determine the threshold for the length of the line
103*b725ae77Skettenis and the offset to start the display. */
104*b725ae77Skettenis offset = src->horizontal_offset;
105*b725ae77Skettenis threshold = (line_width - 1) + offset;
106*b725ae77Skettenis stream = fdopen (desc, FOPEN_RT);
107*b725ae77Skettenis clearerr (stream);
108*b725ae77Skettenis cur_line = 0;
109*b725ae77Skettenis cur_line_no = src->start_line_or_addr.line_no = line_no;
110*b725ae77Skettenis if (offset > 0)
111*b725ae77Skettenis src_line = (char *) xmalloc (
112*b725ae77Skettenis (threshold + 1) * sizeof (char));
113*b725ae77Skettenis while (cur_line < nlines)
114*b725ae77Skettenis {
115*b725ae77Skettenis struct tui_win_element * element = (struct tui_win_element *)
116*b725ae77Skettenis TUI_SRC_WIN->generic.content[cur_line];
117*b725ae77Skettenis
118*b725ae77Skettenis /* get the first character in the line */
119*b725ae77Skettenis c = fgetc (stream);
120*b725ae77Skettenis
121*b725ae77Skettenis if (offset == 0)
122*b725ae77Skettenis src_line = ((struct tui_win_element *)
123*b725ae77Skettenis TUI_SRC_WIN->generic.content[
124*b725ae77Skettenis cur_line])->which_element.source.line;
125*b725ae77Skettenis /* Init the line with the line number */
126*b725ae77Skettenis sprintf (src_line, "%-6d", cur_line_no);
127*b725ae77Skettenis cur_len = strlen (src_line);
128*b725ae77Skettenis i = cur_len -
129*b725ae77Skettenis ((cur_len / tui_default_tab_len ()) * tui_default_tab_len ());
130*b725ae77Skettenis while (i < tui_default_tab_len ())
131*b725ae77Skettenis {
132*b725ae77Skettenis src_line[cur_len] = ' ';
133*b725ae77Skettenis i++;
134*b725ae77Skettenis cur_len++;
135*b725ae77Skettenis }
136*b725ae77Skettenis src_line[cur_len] = (char) 0;
137*b725ae77Skettenis
138*b725ae77Skettenis /* Set whether element is the execution point and
139*b725ae77Skettenis whether there is a break point on it. */
140*b725ae77Skettenis element->which_element.source.line_or_addr.line_no =
141*b725ae77Skettenis cur_line_no;
142*b725ae77Skettenis element->which_element.source.is_exec_point =
143*b725ae77Skettenis (strcmp (((struct tui_win_element *)
144*b725ae77Skettenis locator->content[0])->which_element.locator.file_name,
145*b725ae77Skettenis s->filename) == 0
146*b725ae77Skettenis && cur_line_no == ((struct tui_win_element *)
147*b725ae77Skettenis locator->content[0])->which_element.locator.line_no);
148*b725ae77Skettenis if (c != EOF)
149*b725ae77Skettenis {
150*b725ae77Skettenis i = strlen (src_line) - 1;
151*b725ae77Skettenis do
152*b725ae77Skettenis {
153*b725ae77Skettenis if ((c != '\n') &&
154*b725ae77Skettenis (c != '\r') && (++i < threshold))
155*b725ae77Skettenis {
156*b725ae77Skettenis if (c < 040 && c != '\t')
157*b725ae77Skettenis {
158*b725ae77Skettenis src_line[i++] = '^';
159*b725ae77Skettenis src_line[i] = c + 0100;
160*b725ae77Skettenis }
161*b725ae77Skettenis else if (c == 0177)
162*b725ae77Skettenis {
163*b725ae77Skettenis src_line[i++] = '^';
164*b725ae77Skettenis src_line[i] = '?';
165*b725ae77Skettenis }
166*b725ae77Skettenis else
167*b725ae77Skettenis { /* Store the charcter in the line
168*b725ae77Skettenis buffer. If it is a tab, then
169*b725ae77Skettenis translate to the correct number of
170*b725ae77Skettenis chars so we don't overwrite our
171*b725ae77Skettenis buffer. */
172*b725ae77Skettenis if (c == '\t')
173*b725ae77Skettenis {
174*b725ae77Skettenis int j, max_tab_len = tui_default_tab_len ();
175*b725ae77Skettenis
176*b725ae77Skettenis for (j = i - (
177*b725ae77Skettenis (i / max_tab_len) * max_tab_len);
178*b725ae77Skettenis ((j < max_tab_len) &&
179*b725ae77Skettenis i < threshold);
180*b725ae77Skettenis i++, j++)
181*b725ae77Skettenis src_line[i] = ' ';
182*b725ae77Skettenis i--;
183*b725ae77Skettenis }
184*b725ae77Skettenis else
185*b725ae77Skettenis src_line[i] = c;
186*b725ae77Skettenis }
187*b725ae77Skettenis src_line[i + 1] = 0;
188*b725ae77Skettenis }
189*b725ae77Skettenis else
190*b725ae77Skettenis { /* If we have not reached EOL, then eat
191*b725ae77Skettenis chars until we do */
192*b725ae77Skettenis while (c != EOF && c != '\n' && c != '\r')
193*b725ae77Skettenis c = fgetc (stream);
194*b725ae77Skettenis }
195*b725ae77Skettenis }
196*b725ae77Skettenis while (c != EOF && c != '\n' && c != '\r' &&
197*b725ae77Skettenis i < threshold && (c = fgetc (stream)));
198*b725ae77Skettenis }
199*b725ae77Skettenis /* Now copy the line taking the offset into account */
200*b725ae77Skettenis if (strlen (src_line) > offset)
201*b725ae77Skettenis strcpy (((struct tui_win_element *) TUI_SRC_WIN->generic.content[
202*b725ae77Skettenis cur_line])->which_element.source.line,
203*b725ae77Skettenis &src_line[offset]);
204*b725ae77Skettenis else
205*b725ae77Skettenis ((struct tui_win_element *)
206*b725ae77Skettenis TUI_SRC_WIN->generic.content[
207*b725ae77Skettenis cur_line])->which_element.source.line[0] = (char) 0;
208*b725ae77Skettenis cur_line++;
209*b725ae77Skettenis cur_line_no++;
210*b725ae77Skettenis }
211*b725ae77Skettenis if (offset > 0)
212*b725ae77Skettenis xfree (src_line);
213*b725ae77Skettenis fclose (stream);
214*b725ae77Skettenis TUI_SRC_WIN->generic.content_size = nlines;
215*b725ae77Skettenis ret = TUI_SUCCESS;
216*b725ae77Skettenis }
217*b725ae77Skettenis }
218*b725ae77Skettenis }
219*b725ae77Skettenis }
220*b725ae77Skettenis return ret;
221*b725ae77Skettenis }
222*b725ae77Skettenis
223*b725ae77Skettenis
224*b725ae77Skettenis /* elz: this function sets the contents of the source window to empty
225*b725ae77Skettenis except for a line in the middle with a warning message about the
226*b725ae77Skettenis source not being available. This function is called by
227*b725ae77Skettenis tui_erase_source_contents(), which in turn is invoked when the
228*b725ae77Skettenis source files cannot be accessed. */
229*b725ae77Skettenis
230*b725ae77Skettenis void
tui_set_source_content_nil(struct tui_win_info * win_info,char * warning_string)231*b725ae77Skettenis tui_set_source_content_nil (struct tui_win_info * win_info, char *warning_string)
232*b725ae77Skettenis {
233*b725ae77Skettenis int line_width;
234*b725ae77Skettenis int n_lines;
235*b725ae77Skettenis int curr_line = 0;
236*b725ae77Skettenis
237*b725ae77Skettenis line_width = win_info->generic.width - 1;
238*b725ae77Skettenis n_lines = win_info->generic.height - 2;
239*b725ae77Skettenis
240*b725ae77Skettenis /* set to empty each line in the window, except for the one
241*b725ae77Skettenis which contains the message */
242*b725ae77Skettenis while (curr_line < win_info->generic.content_size)
243*b725ae77Skettenis {
244*b725ae77Skettenis /* set the information related to each displayed line
245*b725ae77Skettenis to null: i.e. the line number is 0, there is no bp,
246*b725ae77Skettenis it is not where the program is stopped */
247*b725ae77Skettenis
248*b725ae77Skettenis struct tui_win_element * element =
249*b725ae77Skettenis (struct tui_win_element *) win_info->generic.content[curr_line];
250*b725ae77Skettenis element->which_element.source.line_or_addr.line_no = 0;
251*b725ae77Skettenis element->which_element.source.is_exec_point = FALSE;
252*b725ae77Skettenis element->which_element.source.has_break = FALSE;
253*b725ae77Skettenis
254*b725ae77Skettenis /* set the contents of the line to blank */
255*b725ae77Skettenis element->which_element.source.line[0] = (char) 0;
256*b725ae77Skettenis
257*b725ae77Skettenis /* if the current line is in the middle of the screen, then we
258*b725ae77Skettenis want to display the 'no source available' message in it.
259*b725ae77Skettenis Note: the 'weird' arithmetic with the line width and height
260*b725ae77Skettenis comes from the function tui_erase_source_content(). We need
261*b725ae77Skettenis to keep the screen and the window's actual contents in synch. */
262*b725ae77Skettenis
263*b725ae77Skettenis if (curr_line == (n_lines / 2 + 1))
264*b725ae77Skettenis {
265*b725ae77Skettenis int i;
266*b725ae77Skettenis int xpos;
267*b725ae77Skettenis int warning_length = strlen (warning_string);
268*b725ae77Skettenis char *src_line;
269*b725ae77Skettenis
270*b725ae77Skettenis src_line = element->which_element.source.line;
271*b725ae77Skettenis
272*b725ae77Skettenis if (warning_length >= ((line_width - 1) / 2))
273*b725ae77Skettenis xpos = 1;
274*b725ae77Skettenis else
275*b725ae77Skettenis xpos = (line_width - 1) / 2 - warning_length;
276*b725ae77Skettenis
277*b725ae77Skettenis for (i = 0; i < xpos; i++)
278*b725ae77Skettenis src_line[i] = ' ';
279*b725ae77Skettenis
280*b725ae77Skettenis sprintf (src_line + i, "%s", warning_string);
281*b725ae77Skettenis
282*b725ae77Skettenis for (i = xpos + warning_length; i < line_width; i++)
283*b725ae77Skettenis src_line[i] = ' ';
284*b725ae77Skettenis
285*b725ae77Skettenis src_line[i] = '\n';
286*b725ae77Skettenis
287*b725ae77Skettenis } /* end if */
288*b725ae77Skettenis
289*b725ae77Skettenis curr_line++;
290*b725ae77Skettenis
291*b725ae77Skettenis } /* end while */
292*b725ae77Skettenis }
293*b725ae77Skettenis
294*b725ae77Skettenis
295*b725ae77Skettenis /* Function to display source in the source window. This function
296*b725ae77Skettenis initializes the horizontal scroll to 0. */
297*b725ae77Skettenis void
tui_show_symtab_source(struct symtab * s,union tui_line_or_address line,int noerror)298*b725ae77Skettenis tui_show_symtab_source (struct symtab *s, union tui_line_or_address line, int noerror)
299*b725ae77Skettenis {
300*b725ae77Skettenis TUI_SRC_WIN->detail.source_info.horizontal_offset = 0;
301*b725ae77Skettenis tui_update_source_window_as_is (TUI_SRC_WIN, s, line, noerror);
302*b725ae77Skettenis }
303*b725ae77Skettenis
304*b725ae77Skettenis
305*b725ae77Skettenis /* Answer whether the source is currently displayed in the source
306*b725ae77Skettenis window. */
307*b725ae77Skettenis int
tui_source_is_displayed(char * fname)308*b725ae77Skettenis tui_source_is_displayed (char *fname)
309*b725ae77Skettenis {
310*b725ae77Skettenis return (TUI_SRC_WIN->generic.content_in_use &&
311*b725ae77Skettenis (strcmp (((struct tui_win_element *) (tui_locator_win_info_ptr ())->
312*b725ae77Skettenis content[0])->which_element.locator.file_name, fname) == 0));
313*b725ae77Skettenis }
314*b725ae77Skettenis
315*b725ae77Skettenis
316*b725ae77Skettenis /* Scroll the source forward or backward vertically. */
317*b725ae77Skettenis void
tui_vertical_source_scroll(enum tui_scroll_direction scroll_direction,int num_to_scroll)318*b725ae77Skettenis tui_vertical_source_scroll (enum tui_scroll_direction scroll_direction,
319*b725ae77Skettenis int num_to_scroll)
320*b725ae77Skettenis {
321*b725ae77Skettenis if (TUI_SRC_WIN->generic.content != NULL)
322*b725ae77Skettenis {
323*b725ae77Skettenis union tui_line_or_address l;
324*b725ae77Skettenis struct symtab *s;
325*b725ae77Skettenis tui_win_content content = (tui_win_content) TUI_SRC_WIN->generic.content;
326*b725ae77Skettenis struct symtab_and_line cursal = get_current_source_symtab_and_line ();
327*b725ae77Skettenis
328*b725ae77Skettenis if (cursal.symtab == (struct symtab *) NULL)
329*b725ae77Skettenis s = find_pc_symtab (get_frame_pc (deprecated_selected_frame));
330*b725ae77Skettenis else
331*b725ae77Skettenis s = cursal.symtab;
332*b725ae77Skettenis
333*b725ae77Skettenis if (scroll_direction == FORWARD_SCROLL)
334*b725ae77Skettenis {
335*b725ae77Skettenis l.line_no = content[0]->which_element.source.line_or_addr.line_no +
336*b725ae77Skettenis num_to_scroll;
337*b725ae77Skettenis if (l.line_no > s->nlines)
338*b725ae77Skettenis /*line = s->nlines - win_info->generic.content_size + 1; */
339*b725ae77Skettenis /*elz: fix for dts 23398 */
340*b725ae77Skettenis l.line_no = content[0]->which_element.source.line_or_addr.line_no;
341*b725ae77Skettenis }
342*b725ae77Skettenis else
343*b725ae77Skettenis {
344*b725ae77Skettenis l.line_no = content[0]->which_element.source.line_or_addr.line_no -
345*b725ae77Skettenis num_to_scroll;
346*b725ae77Skettenis if (l.line_no <= 0)
347*b725ae77Skettenis l.line_no = 1;
348*b725ae77Skettenis }
349*b725ae77Skettenis
350*b725ae77Skettenis print_source_lines (s, l.line_no, l.line_no + 1, 0);
351*b725ae77Skettenis }
352*b725ae77Skettenis }
353