Change tui_source_window_base::set_contents to return bool
[deliverable/binutils-gdb.git] / gdb / tui / tui-winsource.c
CommitLineData
f377b406 1/* TUI display source/assembly 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"
fd0407d6 27#include "value.h"
52575520 28#include "source.h"
13274fc3 29#include "objfiles.h"
a7417d46 30#include "filenames.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-win.h"
37#include "tui/tui-wingeneral.h"
38#include "tui/tui-winsource.h"
39#include "tui/tui-source.h"
40#include "tui/tui-disasm.h"
6a83354a 41#include "gdb_curses.h"
c906108c 42
1f393769 43/* Function to display the "main" routine. */
c906108c 44void
b4eb2452 45tui_display_main ()
c906108c 46{
3891b65e
TT
47 auto adapter = tui_source_windows ();
48 if (adapter.begin () != adapter.end ())
c906108c 49 {
13274fc3 50 struct gdbarch *gdbarch;
c906108c
SS
51 CORE_ADDR addr;
52
13274fc3 53 tui_get_begin_asm_address (&gdbarch, &addr);
c774cec6 54 if (addr != (CORE_ADDR) 0)
c906108c 55 {
34248c3a 56 struct symtab *s;
c906108c 57
13274fc3 58 tui_update_source_windows_with_addr (gdbarch, addr);
34248c3a 59 s = find_pc_line_symtab (addr);
c1b167d7 60 tui_update_locator_fullname (s);
c906108c
SS
61 }
62 }
2e17b763 63}
c906108c 64
1df2f9ef 65/* See tui-winsource.h. */
c906108c 66
1df2f9ef
TT
67std::string
68tui_copy_source_line (const char **ptr, int line_no, int first_col,
d1da6b01 69 int line_width, int ndigits)
1df2f9ef
TT
70{
71 const char *lineptr = *ptr;
72
73 /* Init the line with the line number. */
74 std::string result;
75
76 if (line_no > 0)
77 {
d1da6b01
TT
78 if (ndigits > 0)
79 result = string_printf ("%*d ", ndigits, line_no);
80 else
81 {
82 result = string_printf ("%-6d", line_no);
83 int len = result.size ();
84 len = len - ((len / tui_tab_width) * tui_tab_width);
85 result.append (len, ' ');
86 }
1df2f9ef
TT
87 }
88
89 int column = 0;
90 char c;
91 do
92 {
93 int skip_bytes;
94
95 c = *lineptr;
96 if (c == '\033' && skip_ansi_escape (lineptr, &skip_bytes))
97 {
98 /* We always have to preserve escapes. */
99 result.append (lineptr, lineptr + skip_bytes);
100 lineptr += skip_bytes;
101 continue;
102 }
517d261d
TT
103 if (c == '\0')
104 break;
1df2f9ef
TT
105
106 ++lineptr;
107 ++column;
108
109 auto process_tab = [&] ()
110 {
111 int max_tab_len = tui_tab_width;
112
113 --column;
114 for (int j = column % max_tab_len;
115 j < max_tab_len && column < first_col + line_width;
116 column++, j++)
117 if (column >= first_col)
118 result.push_back (' ');
119 };
120
121 /* We have to process all the text in order to pick up all the
122 escapes. */
123 if (column <= first_col || column > first_col + line_width)
124 {
125 if (c == '\t')
126 process_tab ();
127 continue;
128 }
129
130 if (c == '\n' || c == '\r' || c == '\0')
131 {
132 /* Nothing. */
133 }
134 else if (c < 040 && c != '\t')
135 {
136 result.push_back ('^');
137 result.push_back (c + 0100);
138 }
139 else if (c == 0177)
140 {
141 result.push_back ('^');
142 result.push_back ('?');
143 }
144 else if (c == '\t')
145 process_tab ();
146 else
147 result.push_back (c);
148 }
149 while (c != '\0' && c != '\n' && c != '\r');
150
151 if (c == '\r' && *lineptr == '\n')
152 ++lineptr;
153 *ptr = lineptr;
154
155 return result;
156}
157
158void
159tui_source_window_base::style_changed ()
160{
161 if (tui_active && is_visible ())
162 refill ();
163}
c906108c 164
f80bda8e
AC
165/* Function to display source in the source window. This function
166 initializes the horizontal scroll to 0. */
c906108c 167void
017f9828
TT
168tui_source_window_base::update_source_window
169 (struct gdbarch *gdbarch,
170 struct symtab *s,
171 struct tui_line_or_address line_or_addr)
c906108c 172{
017f9828
TT
173 horizontal_offset = 0;
174 update_source_window_as_is (gdbarch, s, line_or_addr);
f80bda8e 175}
c906108c
SS
176
177
f80bda8e
AC
178/* Function to display source in the source/asm window. This function
179 shows the source as specified by the horizontal offset. */
c906108c 180void
ed8358e9
TT
181tui_source_window_base::update_source_window_as_is
182 (struct gdbarch *gdbarch,
183 struct symtab *s,
184 struct tui_line_or_address line_or_addr)
c906108c 185{
61c33f10 186 bool ret = set_contents (gdbarch, s, line_or_addr);
c906108c 187
61c33f10 188 if (!ret)
ed8358e9 189 erase_source_content ();
c906108c
SS
190 else
191 {
2ddaf614 192 update_breakpoint_info (nullptr, false);
ed8358e9
TT
193 show_source_content ();
194 update_exec_info ();
195 if (type == SRC_WIN)
c906108c 196 {
51abb421
PA
197 symtab_and_line sal;
198
ed8358e9 199 sal.line = line_or_addr.u.line_no + (content.size () - 2);
52575520 200 sal.symtab = s;
eb822aa6 201 sal.pspace = SYMTAB_PSPACE (s);
51abb421 202 set_current_source_symtab_and_line (sal);
c906108c
SS
203 }
204 }
f80bda8e 205}
c906108c
SS
206
207
f80bda8e
AC
208/* Function to ensure that the source and/or disassemly windows
209 reflect the input address. */
c906108c 210void
13274fc3 211tui_update_source_windows_with_addr (struct gdbarch *gdbarch, CORE_ADDR addr)
c906108c 212{
c774cec6 213 if (addr != 0)
c906108c 214 {
855f89b3 215 struct symtab_and_line sal = find_pc_line (addr, 0);
362c05fe 216 struct tui_line_or_address l;
a4b99e53 217
8acfefcc 218 if (TUI_DISASM_WIN != nullptr)
855f89b3
TT
219 {
220 l.loa = LOA_ADDRESS;
221 l.u.addr = addr;
222 TUI_DISASM_WIN->update_source_window (gdbarch, sal.symtab, l);
223 }
8acfefcc
TT
224
225 if (TUI_SRC_WIN != nullptr)
c906108c 226 {
362c05fe
AS
227 l.loa = LOA_LINE;
228 l.u.line_no = sal.line;
469b0731 229 TUI_SRC_WIN->update_source_window (gdbarch, sal.symtab, l);
c906108c
SS
230 }
231 }
232 else
233 {
ad54d15b 234 for (struct tui_source_window_base *win_info : tui_source_windows ())
c398c3d0 235 win_info->erase_source_content ();
c906108c 236 }
6ba8e26f 237}
c906108c 238
f80bda8e
AC
239/* Function to ensure that the source and/or disassemly windows
240 reflect the input address. */
c906108c 241void
f80bda8e 242tui_update_source_windows_with_line (struct symtab *s, int line)
c906108c 243{
13274fc3 244 struct gdbarch *gdbarch;
84b1e7c7 245 CORE_ADDR pc;
362c05fe 246 struct tui_line_or_address l;
13274fc3
UW
247
248 if (!s)
249 return;
250
eb822aa6 251 gdbarch = get_objfile_arch (SYMTAB_OBJFILE (s));
13274fc3 252
dd1abb8c 253 switch (tui_current_layout ())
c906108c
SS
254 {
255 case DISASSEM_COMMAND:
256 case DISASSEM_DATA_COMMAND:
84b1e7c7 257 find_line_pc (s, line, &pc);
13274fc3 258 tui_update_source_windows_with_addr (gdbarch, pc);
c906108c
SS
259 break;
260 default:
362c05fe
AS
261 l.loa = LOA_LINE;
262 l.u.line_no = line;
469b0731 263 TUI_SRC_WIN->update_source_window (gdbarch, s, l);
dd1abb8c 264 if (tui_current_layout () == SRC_DISASSEM_COMMAND)
84b1e7c7
SC
265 {
266 find_line_pc (s, line, &pc);
855f89b3
TT
267 l.loa = LOA_ADDRESS;
268 l.u.addr = pc;
269 TUI_DISASM_WIN->update_source_window (gdbarch, s, l);
84b1e7c7 270 }
c906108c
SS
271 break;
272 }
f80bda8e 273}
c906108c 274
c906108c 275void
e25d2004 276tui_source_window_base::do_erase_source_content (const char *str)
c906108c 277{
6ba8e26f 278 int x_pos;
e25d2004 279 int half_width = (width - 2) / 2;
c906108c 280
c398c3d0 281 content.clear ();
e25d2004 282 if (handle != NULL)
c906108c 283 {
7523da63 284 werase (handle.get ());
e25d2004 285 check_and_display_highlight_if_needed ();
caf0bc4e 286
e25d2004 287 if (strlen (str) >= half_width)
caf0bc4e
TT
288 x_pos = 1;
289 else
e25d2004 290 x_pos = half_width - strlen (str);
7523da63 291 mvwaddstr (handle.get (),
e25d2004 292 (height / 2),
caf0bc4e 293 x_pos,
e25d2004 294 (char *) str);
93858ad3 295
e25d2004 296 refresh_window ();
c906108c 297 }
6ba8e26f 298}
c906108c
SS
299
300
bc712bbf
SC
301/* Redraw the complete line of a source or disassembly window. */
302static void
53e7cdba 303tui_show_source_line (struct tui_source_window_base *win_info, int lineno)
bc712bbf 304{
53e7cdba 305 struct tui_source_element *line;
798e1c30 306 int x;
bc712bbf 307
53e7cdba
TT
308 line = &win_info->content[lineno - 1];
309 if (line->is_exec_point)
7523da63 310 tui_set_reverse_mode (win_info->handle.get (), true);
bc712bbf 311
7523da63 312 wmove (win_info->handle.get (), lineno, TUI_EXECINFO_SIZE);
5d051055 313 tui_puts (line->line.c_str (), win_info->handle.get ());
53e7cdba 314 if (line->is_exec_point)
7523da63 315 tui_set_reverse_mode (win_info->handle.get (), false);
bc712bbf
SC
316
317 /* Clear to end of line but stop before the border. */
7523da63 318 x = getcurx (win_info->handle.get ());
cb2ce893 319 while (x + 1 < win_info->width)
798e1c30 320 {
7523da63
TT
321 waddch (win_info->handle.get (), ' ');
322 x = getcurx (win_info->handle.get ());
798e1c30 323 }
bc712bbf
SC
324}
325
c906108c 326void
0bd27e07 327tui_source_window_base::show_source_content ()
c906108c 328{
2ad52f6f 329 gdb_assert (!content.empty ());
bc712bbf 330
2ad52f6f
TT
331 for (int lineno = 1; lineno <= content.size (); lineno++)
332 tui_show_source_line (this, lineno);
bc712bbf 333
0bd27e07
TT
334 check_and_display_highlight_if_needed ();
335 refresh_window ();
bc712bbf 336}
c906108c 337
5104fe36 338tui_source_window_base::tui_source_window_base (enum tui_win_type type)
398fdd60 339 : tui_win_info (type)
5104fe36
TT
340{
341 gdb_assert (type == SRC_WIN || type == DISASSEM_WIN);
342 start_line_or_addr.loa = LOA_ADDRESS;
343 start_line_or_addr.u.addr = 0;
1df2f9ef
TT
344
345 gdb::observers::source_styling_changed.attach
346 (std::bind (&tui_source_window::style_changed, this),
347 m_observable);
5104fe36
TT
348}
349
1df2f9ef
TT
350tui_source_window_base::~tui_source_window_base ()
351{
352 gdb::observers::source_styling_changed.detach (m_observable);
353}
5104fe36 354
5104fe36
TT
355/* See tui-data.h. */
356
5104fe36
TT
357void
358tui_source_window_base::update_tab_width ()
359{
7523da63 360 werase (handle.get ());
3df505f6 361 rerender ();
5104fe36
TT
362}
363
5104fe36 364void
3df505f6 365tui_source_window_base::rerender ()
5104fe36 366{
5104fe36
TT
367 if (!content.empty ())
368 {
369 struct tui_line_or_address line_or_addr;
370 struct symtab_and_line cursal
371 = get_current_source_symtab_and_line ();
372
373 line_or_addr = start_line_or_addr;
017f9828 374 update_source_window (gdbarch, cursal.symtab, line_or_addr);
5104fe36
TT
375 }
376 else if (deprecated_safe_get_selected_frame () != NULL)
377 {
378 struct tui_line_or_address line;
379 struct symtab_and_line cursal
380 = get_current_source_symtab_and_line ();
381 struct frame_info *frame = deprecated_safe_get_selected_frame ();
382 struct gdbarch *gdbarch = get_frame_arch (frame);
383
384 struct symtab *s = find_pc_line_symtab (get_frame_pc (frame));
385 if (type == SRC_WIN)
386 {
387 line.loa = LOA_LINE;
388 line.u.line_no = cursal.line;
389 }
390 else
391 {
392 line.loa = LOA_ADDRESS;
393 find_line_pc (s, cursal.line, &line.u.addr);
394 }
017f9828 395 update_source_window (gdbarch, s, line);
5104fe36 396 }
3df505f6
TT
397 else
398 erase_source_content ();
5104fe36
TT
399}
400
401/* See tui-data.h. */
402
6f11e682 403void
ad54d15b 404tui_source_window_base::refill ()
6f11e682
TT
405{
406 symtab *s = nullptr;
407
cb2ce893 408 if (type == SRC_WIN)
6f11e682
TT
409 {
410 symtab_and_line cursal = get_current_source_symtab_and_line ();
411 s = (cursal.symtab == NULL
412 ? find_pc_line_symtab (get_frame_pc (get_selected_frame (NULL)))
413 : cursal.symtab);
414 }
415
ed8358e9 416 update_source_window_as_is (gdbarch, s, content[0].line_or_addr);
6f11e682 417}
c906108c 418
f80bda8e 419/* Scroll the source forward or backward horizontally. */
6f11e682 420
c906108c 421void
c3bd716f 422tui_source_window_base::do_scroll_horizontal (int num_to_scroll)
c906108c 423{
53e7cdba 424 if (!content.empty ())
c906108c 425 {
c3bd716f
TT
426 int offset = horizontal_offset + num_to_scroll;
427 if (offset < 0)
428 offset = 0;
e6e41501 429 horizontal_offset = offset;
ad54d15b 430 refill ();
c906108c 431 }
6ba8e26f 432}
c906108c
SS
433
434
0598af48 435/* Set or clear the is_exec_point flag in the line whose line is
1cc6d956
MS
436 line_no. */
437
c906108c 438void
ad54d15b 439tui_source_window_base::set_is_exec_point_at (struct tui_line_or_address l)
c906108c 440{
02c28df0 441 bool changed = false;
c906108c 442 int i;
c906108c
SS
443
444 i = 0;
53e7cdba 445 while (i < content.size ())
c906108c 446 {
02c28df0 447 bool new_state;
362c05fe 448 struct tui_line_or_address content_loa =
53e7cdba 449 content[i].line_or_addr;
362c05fe 450
362c05fe
AS
451 if (content_loa.loa == l.loa
452 && ((l.loa == LOA_LINE && content_loa.u.line_no == l.u.line_no)
f7952c57 453 || (l.loa == LOA_ADDRESS && content_loa.u.addr == l.u.addr)))
02c28df0 454 new_state = true;
c906108c 455 else
02c28df0 456 new_state = false;
53e7cdba 457 if (new_state != content[i].is_exec_point)
00b90ae2 458 {
02c28df0 459 changed = true;
53e7cdba 460 content[i].is_exec_point = new_state;
ad54d15b 461 tui_show_source_line (this, i + 1);
00b90ae2 462 }
c906108c
SS
463 i++;
464 }
00b90ae2 465 if (changed)
ad54d15b 466 refill ();
00b90ae2 467}
c906108c 468
0807ab7b
TT
469/* See tui-winsource.h. */
470
c906108c 471void
0807ab7b 472tui_update_all_breakpoint_info (struct breakpoint *being_deleted)
c906108c 473{
ad54d15b 474 for (tui_source_window_base *win : tui_source_windows ())
c906108c 475 {
2ddaf614
TT
476 if (win->update_breakpoint_info (being_deleted, false))
477 win->update_exec_info ();
c906108c 478 }
00b2bad4 479}
c906108c
SS
480
481
0807ab7b 482/* Scan the source window and the breakpoints to update the break_mode
1cc6d956
MS
483 information for each line.
484
0807ab7b 485 Returns true if something changed and the execution window must be
1cc6d956
MS
486 refreshed. */
487
0807ab7b 488bool
2ddaf614
TT
489tui_source_window_base::update_breakpoint_info
490 (struct breakpoint *being_deleted, bool current_only)
c906108c
SS
491{
492 int i;
0807ab7b 493 bool need_refresh = false;
c906108c 494
2ddaf614 495 for (i = 0; i < content.size (); i++)
00b2bad4 496 {
5b6fe301 497 struct tui_source_element *line;
00b2bad4 498
2ddaf614 499 line = &content[i];
6d012f14 500 if (current_only && !line->is_exec_point)
00b2bad4
SC
501 continue;
502
503 /* Scan each breakpoint to see if the current line has something to
504 do with it. Identify enable/disabled breakpoints as well as
505 those that we already hit. */
0598af48 506 tui_bp_flags mode = 0;
81e6b8eb 507 iterate_over_breakpoints ([&] (breakpoint *bp) -> bool
00b2bad4 508 {
f8eba3c6
TT
509 struct bp_location *loc;
510
0807ab7b 511 if (bp == being_deleted)
81e6b8eb 512 return false;
0807ab7b 513
f8eba3c6
TT
514 for (loc = bp->loc; loc != NULL; loc = loc->next)
515 {
2ddaf614 516 if (location_matches_p (loc, i))
f8eba3c6
TT
517 {
518 if (bp->enable_state == bp_disabled)
519 mode |= TUI_BP_DISABLED;
520 else
521 mode |= TUI_BP_ENABLED;
522 if (bp->hit_count)
523 mode |= TUI_BP_HIT;
524 if (bp->loc->cond)
525 mode |= TUI_BP_CONDITIONAL;
526 if (bp->type == bp_hardware_breakpoint)
527 mode |= TUI_BP_HARDWARE;
528 }
529 }
81e6b8eb
CB
530 return false;
531 });
0598af48 532 if (line->break_mode != mode)
00b2bad4 533 {
0598af48
TT
534 line->break_mode = mode;
535 need_refresh = true;
00b2bad4
SC
536 }
537 }
538 return need_refresh;
539}
c906108c 540
6ba8e26f
AC
541/* Function to initialize the content of the execution info window,
542 based upon the input window which is either the source or
543 disassembly window. */
73fbdc65 544void
5216580d 545tui_source_window_base::update_exec_info ()
c906108c 546{
2ddaf614 547 update_breakpoint_info (nullptr, true);
37a4a131 548 for (int i = 0; i < content.size (); i++)
098f9ed4 549 {
5216580d
TT
550 struct tui_source_element *src_element = &content[i];
551 char element[TUI_EXECINFO_SIZE] = " ";
098f9ed4
TT
552
553 /* Now update the exec info content based upon the state
554 of each line as indicated by the source content. */
5216580d 555 tui_bp_flags mode = src_element->break_mode;
098f9ed4
TT
556 if (mode & TUI_BP_HIT)
557 element[TUI_BP_HIT_POS] = (mode & TUI_BP_HARDWARE) ? 'H' : 'B';
558 else if (mode & (TUI_BP_ENABLED | TUI_BP_DISABLED))
559 element[TUI_BP_HIT_POS] = (mode & TUI_BP_HARDWARE) ? 'h' : 'b';
560
561 if (mode & TUI_BP_ENABLED)
562 element[TUI_BP_BREAK_POS] = '+';
563 else if (mode & TUI_BP_DISABLED)
564 element[TUI_BP_BREAK_POS] = '-';
565
566 if (src_element->is_exec_point)
567 element[TUI_EXEC_POS] = '>';
c906108c 568
7523da63 569 mvwaddstr (handle.get (), i + 1, 1, element);
5216580d 570 }
398fdd60 571 refresh_window ();
f80bda8e 572}
This page took 2.419922 seconds and 4 git commands to generate.