Introduce tui_source_window_base::set_contents method
[deliverable/binutils-gdb.git] / gdb / tui / tui-source.c
CommitLineData
f377b406 1/* TUI display source window.
f33c6cbf 2
42a4f53d 3 Copyright (C) 1998-2019 Free Software Foundation, Inc.
f33c6cbf 4
f377b406
SC
5 Contributed by Hewlett-Packard Company.
6
7 This file is part of GDB.
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
a9762ec7 11 the Free Software Foundation; either version 3 of the License, or
f377b406
SC
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
a9762ec7 20 along with this program. If not, see <http://www.gnu.org/licenses/>. */
c906108c
SS
21
22#include "defs.h"
23#include <ctype.h>
24#include "symtab.h"
25#include "frame.h"
26#include "breakpoint.h"
c2c6d25f 27#include "source.h"
13274fc3 28#include "objfiles.h"
a7417d46 29#include "filenames.h"
62f29fda 30#include "source-cache.h"
c906108c 31
d7b2e967
AC
32#include "tui/tui.h"
33#include "tui/tui-data.h"
62f29fda 34#include "tui/tui-io.h"
d7b2e967
AC
35#include "tui/tui-stack.h"
36#include "tui/tui-winsource.h"
37#include "tui/tui-source.h"
6a83354a 38#include "gdb_curses.h"
c906108c 39
62f29fda
TT
40/* A helper function for tui_set_source_content that extracts some
41 source text from PTR. LINE_NO is the line number; FIRST_COL is the
42 first column to extract, and LINE_WIDTH is the number of characters
43 to display. Returns a string holding the desired text. */
44
45static std::string
46copy_source_line (const char **ptr, int line_no, int first_col,
47 int line_width)
48{
49 const char *lineptr = *ptr;
50
51 /* Init the line with the line number. */
52 std::string result = string_printf ("%-6d", line_no);
53 int len = result.size ();
54 len = len - ((len / tui_tab_width) * tui_tab_width);
55 result.append (len, ' ');
56
57 int column = 0;
58 char c;
59 do
60 {
61 int skip_bytes;
62
63 c = *lineptr;
64 if (c == '\033' && skip_ansi_escape (lineptr, &skip_bytes))
65 {
66 /* We always have to preserve escapes. */
67 result.append (lineptr, lineptr + skip_bytes);
68 lineptr += skip_bytes;
69 continue;
70 }
71
72 ++lineptr;
73 ++column;
647bb750
HD
74
75 auto process_tab = [&] ()
76 {
77 int max_tab_len = tui_tab_width;
78
79 --column;
80 for (int j = column % max_tab_len;
81 j < max_tab_len && column < first_col + line_width;
82 column++, j++)
83 if (column >= first_col)
84 result.push_back (' ');
85 };
86
62f29fda
TT
87 /* We have to process all the text in order to pick up all the
88 escapes. */
647bb750
HD
89 if (column <= first_col || column > first_col + line_width)
90 {
91 if (c == '\t')
92 process_tab ();
93 continue;
94 }
62f29fda
TT
95
96 if (c == '\n' || c == '\r' || c == '\0')
97 {
98 /* Nothing. */
99 }
100 else if (c < 040 && c != '\t')
101 {
102 result.push_back ('^');
103 result.push_back (c + 0100);
104 }
105 else if (c == 0177)
106 {
107 result.push_back ('^');
108 result.push_back ('?');
109 }
110 else if (c == '\t')
647bb750 111 process_tab ();
62f29fda
TT
112 else
113 result.push_back (c);
114 }
115 while (c != '\0' && c != '\n' && c != '\r');
116
117 if (c == '\r' && *lineptr == '\n')
118 ++lineptr;
119 *ptr = lineptr;
120
121 return result;
122}
123
98427f35 124/* Function to display source in the source window. */
a358af15 125enum tui_status
81c82c4b
TT
126tui_source_window::set_contents (struct gdbarch *arch,
127 struct symtab *s,
128 struct tui_line_or_address line_or_addr)
c906108c 129{
81c82c4b
TT
130 gdb_assert (line_or_addr.loa == LOA_LINE);
131 int line_no = line_or_addr.u.line_no;
132
22940a24 133 enum tui_status ret = TUI_FAILURE;
c906108c 134
cafb3438 135 if (s != NULL)
c906108c 136 {
62f29fda 137 int line_width, nlines;
c906108c 138
29d2c474 139 ret = TUI_SUCCESS;
81c82c4b 140 line_width = width - 1;
29d2c474
TT
141 /* Take hilite (window border) into account, when
142 calculating the number of lines. */
81c82c4b 143 nlines = (line_no + (height - 2)) - line_no;
29d2c474
TT
144
145 std::string srclines;
146 if (!g_source_cache.get_source_lines (s, line_no, line_no + nlines,
147 &srclines))
20149b6b 148 ret = TUI_FAILURE;
29d2c474
TT
149 else
150 {
151 int cur_line_no, cur_line;
3add462f 152 struct tui_locator_window *locator
29d2c474 153 = tui_locator_win_info_ptr ();
29d2c474
TT
154 const char *s_filename = symtab_to_filename_for_display (s);
155
81c82c4b
TT
156 xfree (title);
157 title = xstrdup (s_filename);
29d2c474 158
81c82c4b
TT
159 xfree (fullname);
160 fullname = xstrdup (symtab_to_fullname (s));
29d2c474
TT
161
162 cur_line = 0;
81c82c4b
TT
163 gdbarch = get_objfile_arch (SYMTAB_OBJFILE (s));
164 start_line_or_addr.loa = LOA_LINE;
165 cur_line_no = start_line_or_addr.u.line_no = line_no;
29d2c474
TT
166
167 const char *iter = srclines.c_str ();
81c82c4b 168 content.resize (nlines);
29d2c474 169 while (cur_line < nlines)
c906108c 170 {
53e7cdba 171 struct tui_source_element *element
81c82c4b 172 = &content[cur_line];
29d2c474
TT
173
174 std::string text;
175 if (*iter != '\0')
81c82c4b 176 text = copy_source_line (&iter, cur_line_no, horizontal_offset,
29d2c474
TT
177 line_width);
178
179 /* Set whether element is the execution point
180 and whether there is a break point on it. */
53e7cdba
TT
181 element->line_or_addr.loa = LOA_LINE;
182 element->line_or_addr.u.line_no = cur_line_no;
183 element->is_exec_point
184 = (filename_cmp (locator->full_name,
185 symtab_to_fullname (s)) == 0
186 && cur_line_no == locator->line_no);
187
81c82c4b
TT
188 xfree (content[cur_line].line);
189 content[cur_line].line
29d2c474
TT
190 = xstrdup (text.c_str ());
191
192 cur_line++;
193 cur_line_no++;
c906108c 194 }
29d2c474 195 ret = TUI_SUCCESS;
c906108c
SS
196 }
197 }
198 return ret;
98427f35 199}
c906108c
SS
200
201
98427f35
SC
202/* Function to display source in the source window. This function
203 initializes the horizontal scroll to 0. */
c906108c 204void
5813316f
TT
205tui_show_symtab_source (tui_source_window_base *win_info,
206 struct gdbarch *gdbarch, struct symtab *s,
20149b6b 207 struct tui_line_or_address line)
c906108c 208{
5813316f 209 win_info->horizontal_offset = 0;
ed8358e9 210 win_info->update_source_window_as_is (gdbarch, s, line);
98427f35 211}
c906108c 212
c906108c 213
a358af15
AC
214/* Answer whether the source is currently displayed in the source
215 window. */
a38da35d
TT
216bool
217tui_source_window::showing_source_p (const char *fullname) const
c906108c 218{
f6cc34a9 219 return (!content.empty ()
3add462f 220 && (filename_cmp (tui_locator_win_info_ptr ()->full_name,
56d397a3 221 fullname) == 0));
98427f35 222}
c906108c
SS
223
224
98427f35 225/* Scroll the source forward or backward vertically. */
c906108c 226void
c3bd716f 227tui_source_window::do_scroll_vertical (int num_to_scroll)
c906108c 228{
53e7cdba 229 if (!content.empty ())
c906108c 230 {
362c05fe 231 struct tui_line_or_address l;
c906108c 232 struct symtab *s;
52575520 233 struct symtab_and_line cursal = get_current_source_symtab_and_line ();
c906108c 234
cafb3438 235 if (cursal.symtab == NULL)
34248c3a 236 s = find_pc_line_symtab (get_frame_pc (get_selected_frame (NULL)));
c906108c 237 else
52575520 238 s = cursal.symtab;
c906108c 239
362c05fe 240 l.loa = LOA_LINE;
53e7cdba 241 l.u.line_no = content[0].line_or_addr.u.line_no
c3bd716f 242 + num_to_scroll;
cb44333d
TT
243 const std::vector<off_t> *offsets;
244 if (g_source_cache.get_line_charpos (s, &offsets)
245 && l.u.line_no > offsets->size ())
c3bd716f
TT
246 /* line = s->nlines - win_info->content_size + 1; */
247 /* elz: fix for dts 23398. */
53e7cdba 248 l.u.line_no = content[0].line_or_addr.u.line_no;
c3bd716f
TT
249 if (l.u.line_no <= 0)
250 l.u.line_no = 1;
27229e99 251
362c05fe 252 print_source_lines (s, l.u.line_no, l.u.line_no + 1, 0);
c906108c 253 }
98427f35 254}
b73dd877
TT
255
256tui_source_window::tui_source_window ()
257 : tui_source_window_base (SRC_WIN)
258{
259 gdb::observers::source_styling_changed.attach
260 (std::bind (&tui_source_window::style_changed, this),
261 m_observable);
262}
263
264tui_source_window::~tui_source_window ()
265{
266 gdb::observers::source_styling_changed.detach (m_observable);
267}
268
269void
270tui_source_window::style_changed ()
271{
2d83e710 272 if (tui_active && is_visible ())
b73dd877
TT
273 refill ();
274}
c2cd8994
TT
275
276bool
277tui_source_window::location_matches_p (struct bp_location *loc, int line_no)
278{
279 return (content[line_no].line_or_addr.loa == LOA_LINE
280 && content[line_no].line_or_addr.u.line_no == loc->line_number
281 && loc->symtab != NULL
282 && filename_cmp (fullname,
283 symtab_to_fullname (loc->symtab)) == 0);
284}
a54700c6 285
c9033fe8
TT
286/* See tui-source.h. */
287
288bool
289tui_source_window::line_is_displayed (int line) const
290{
291 bool is_displayed = false;
292 int threshold = SCROLL_THRESHOLD;
293 int i = 0;
294 while (i < content.size () - threshold && !is_displayed)
295 {
296 is_displayed
297 = (content[i].line_or_addr.loa == LOA_LINE
298 && content[i].line_or_addr.u.line_no == line);
299 i++;
300 }
301
302 return is_displayed;
303}
304
a54700c6
TT
305void
306tui_source_window::maybe_update (struct frame_info *fi, symtab_and_line sal,
307 int line_no, CORE_ADDR addr)
308{
309 int start_line = (line_no - (viewport_height / 2)) + 1;
310 if (start_line <= 0)
311 start_line = 1;
312
313 bool source_already_displayed = (sal.symtab != 0
314 && showing_source_p (fullname));
315
316 struct tui_line_or_address l;
317
318 l.loa = LOA_LINE;
319 l.u.line_no = start_line;
320 if (!(source_already_displayed
c9033fe8 321 && line_is_displayed (line_no)))
017f9828 322 update_source_window (get_frame_arch (fi), sal.symtab, l);
a54700c6
TT
323 else
324 {
325 l.u.line_no = line_no;
326 set_is_exec_point_at (l);
327 }
328}
This page took 2.794723 seconds and 4 git commands to generate.