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