Simplify tui_update_source_windows_with_line
[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,
9f7540a5 170 const struct symtab_and_line &sal)
c906108c 171{
017f9828 172 horizontal_offset = 0;
9f7540a5 173 update_source_window_as_is (gdbarch, sal);
f80bda8e 174}
c906108c
SS
175
176
f80bda8e
AC
177/* Function to display source in the source/asm window. This function
178 shows the source as specified by the horizontal offset. */
c906108c 179void
ed8358e9
TT
180tui_source_window_base::update_source_window_as_is
181 (struct gdbarch *gdbarch,
9f7540a5 182 const struct symtab_and_line &sal)
c906108c 183{
9f7540a5 184 bool ret = set_contents (gdbarch, sal);
c906108c 185
61c33f10 186 if (!ret)
ed8358e9 187 erase_source_content ();
c906108c
SS
188 else
189 {
2ddaf614 190 update_breakpoint_info (nullptr, false);
ed8358e9
TT
191 show_source_content ();
192 update_exec_info ();
193 if (type == SRC_WIN)
c906108c 194 {
9f7540a5 195 symtab_and_line new_sal = sal;
51abb421 196
9f7540a5
TT
197 new_sal.line = sal.line + (content.size () - 2);
198 set_current_source_symtab_and_line (new_sal);
c906108c
SS
199 }
200 }
f80bda8e 201}
c906108c
SS
202
203
f80bda8e
AC
204/* Function to ensure that the source and/or disassemly windows
205 reflect the input address. */
c906108c 206void
13274fc3 207tui_update_source_windows_with_addr (struct gdbarch *gdbarch, CORE_ADDR addr)
c906108c 208{
88180c08 209 struct symtab_and_line sal {};
c774cec6 210 if (addr != 0)
88180c08 211 sal = find_pc_line (addr, 0);
8acfefcc 212
88180c08
TT
213 for (struct tui_source_window_base *win_info : tui_source_windows ())
214 win_info->update_source_window (gdbarch, sal);
6ba8e26f 215}
c906108c 216
5d49bf1b
TT
217/* Function to ensure that the source and/or disassembly windows
218 reflect the symtab and line. */
c906108c 219void
5d49bf1b 220tui_update_source_windows_with_line (struct symtab_and_line sal)
c906108c 221{
5d49bf1b 222 if (!sal.symtab)
13274fc3
UW
223 return;
224
5d49bf1b
TT
225 find_line_pc (sal.symtab, sal.line, &sal.pc);
226 struct gdbarch *gdbarch = get_objfile_arch (SYMTAB_OBJFILE (sal.symtab));
13274fc3 227
5d49bf1b
TT
228 for (struct tui_source_window_base *win_info : tui_source_windows ())
229 win_info->update_source_window (gdbarch, sal);
f80bda8e 230}
c906108c 231
c906108c 232void
e25d2004 233tui_source_window_base::do_erase_source_content (const char *str)
c906108c 234{
6ba8e26f 235 int x_pos;
e25d2004 236 int half_width = (width - 2) / 2;
c906108c 237
c398c3d0 238 content.clear ();
e25d2004 239 if (handle != NULL)
c906108c 240 {
7523da63 241 werase (handle.get ());
e25d2004 242 check_and_display_highlight_if_needed ();
caf0bc4e 243
e25d2004 244 if (strlen (str) >= half_width)
caf0bc4e
TT
245 x_pos = 1;
246 else
e25d2004 247 x_pos = half_width - strlen (str);
7523da63 248 mvwaddstr (handle.get (),
e25d2004 249 (height / 2),
caf0bc4e 250 x_pos,
e25d2004 251 (char *) str);
93858ad3 252
e25d2004 253 refresh_window ();
c906108c 254 }
6ba8e26f 255}
c906108c
SS
256
257
bc712bbf
SC
258/* Redraw the complete line of a source or disassembly window. */
259static void
53e7cdba 260tui_show_source_line (struct tui_source_window_base *win_info, int lineno)
bc712bbf 261{
53e7cdba 262 struct tui_source_element *line;
798e1c30 263 int x;
bc712bbf 264
53e7cdba
TT
265 line = &win_info->content[lineno - 1];
266 if (line->is_exec_point)
7523da63 267 tui_set_reverse_mode (win_info->handle.get (), true);
bc712bbf 268
7523da63 269 wmove (win_info->handle.get (), lineno, TUI_EXECINFO_SIZE);
5d051055 270 tui_puts (line->line.c_str (), win_info->handle.get ());
53e7cdba 271 if (line->is_exec_point)
7523da63 272 tui_set_reverse_mode (win_info->handle.get (), false);
bc712bbf
SC
273
274 /* Clear to end of line but stop before the border. */
7523da63 275 x = getcurx (win_info->handle.get ());
cb2ce893 276 while (x + 1 < win_info->width)
798e1c30 277 {
7523da63
TT
278 waddch (win_info->handle.get (), ' ');
279 x = getcurx (win_info->handle.get ());
798e1c30 280 }
bc712bbf
SC
281}
282
c906108c 283void
0bd27e07 284tui_source_window_base::show_source_content ()
c906108c 285{
2ad52f6f 286 gdb_assert (!content.empty ());
bc712bbf 287
2ad52f6f
TT
288 for (int lineno = 1; lineno <= content.size (); lineno++)
289 tui_show_source_line (this, lineno);
bc712bbf 290
0bd27e07
TT
291 check_and_display_highlight_if_needed ();
292 refresh_window ();
bc712bbf 293}
c906108c 294
5104fe36 295tui_source_window_base::tui_source_window_base (enum tui_win_type type)
398fdd60 296 : tui_win_info (type)
5104fe36
TT
297{
298 gdb_assert (type == SRC_WIN || type == DISASSEM_WIN);
299 start_line_or_addr.loa = LOA_ADDRESS;
300 start_line_or_addr.u.addr = 0;
1df2f9ef
TT
301
302 gdb::observers::source_styling_changed.attach
303 (std::bind (&tui_source_window::style_changed, this),
304 m_observable);
5104fe36
TT
305}
306
1df2f9ef
TT
307tui_source_window_base::~tui_source_window_base ()
308{
309 gdb::observers::source_styling_changed.detach (m_observable);
310}
5104fe36 311
5104fe36
TT
312/* See tui-data.h. */
313
5104fe36
TT
314void
315tui_source_window_base::update_tab_width ()
316{
7523da63 317 werase (handle.get ());
3df505f6 318 rerender ();
5104fe36
TT
319}
320
5104fe36 321void
3df505f6 322tui_source_window_base::rerender ()
5104fe36 323{
5104fe36
TT
324 if (!content.empty ())
325 {
5104fe36
TT
326 struct symtab_and_line cursal
327 = get_current_source_symtab_and_line ();
328
9f7540a5
TT
329 if (start_line_or_addr.loa == LOA_LINE)
330 cursal.line = start_line_or_addr.u.line_no;
331 else
332 cursal.pc = start_line_or_addr.u.addr;
333 update_source_window (gdbarch, cursal);
5104fe36
TT
334 }
335 else if (deprecated_safe_get_selected_frame () != NULL)
336 {
5104fe36
TT
337 struct symtab_and_line cursal
338 = get_current_source_symtab_and_line ();
339 struct frame_info *frame = deprecated_safe_get_selected_frame ();
340 struct gdbarch *gdbarch = get_frame_arch (frame);
341
342 struct symtab *s = find_pc_line_symtab (get_frame_pc (frame));
9f7540a5
TT
343 if (type != SRC_WIN)
344 find_line_pc (s, cursal.line, &cursal.pc);
345 update_source_window (gdbarch, cursal);
5104fe36 346 }
3df505f6
TT
347 else
348 erase_source_content ();
5104fe36
TT
349}
350
351/* See tui-data.h. */
352
6f11e682 353void
ad54d15b 354tui_source_window_base::refill ()
6f11e682 355{
9f7540a5 356 symtab_and_line sal {};
6f11e682 357
cb2ce893 358 if (type == SRC_WIN)
6f11e682 359 {
9f7540a5
TT
360 sal = get_current_source_symtab_and_line ();
361 if (sal.symtab == NULL)
362 sal = find_pc_line (get_frame_pc (get_selected_frame (NULL)), 0);
6f11e682
TT
363 }
364
9f7540a5
TT
365 if (sal.pspace == nullptr)
366 sal.pspace = current_program_space;
367
368 if (start_line_or_addr.loa == LOA_LINE)
369 sal.line = start_line_or_addr.u.line_no;
370 else
371 sal.pc = start_line_or_addr.u.addr;
372
373 update_source_window_as_is (gdbarch, sal);
6f11e682 374}
c906108c 375
f80bda8e 376/* Scroll the source forward or backward horizontally. */
6f11e682 377
c906108c 378void
c3bd716f 379tui_source_window_base::do_scroll_horizontal (int num_to_scroll)
c906108c 380{
53e7cdba 381 if (!content.empty ())
c906108c 382 {
c3bd716f
TT
383 int offset = horizontal_offset + num_to_scroll;
384 if (offset < 0)
385 offset = 0;
e6e41501 386 horizontal_offset = offset;
ad54d15b 387 refill ();
c906108c 388 }
6ba8e26f 389}
c906108c
SS
390
391
0598af48 392/* Set or clear the is_exec_point flag in the line whose line is
1cc6d956
MS
393 line_no. */
394
c906108c 395void
ad54d15b 396tui_source_window_base::set_is_exec_point_at (struct tui_line_or_address l)
c906108c 397{
02c28df0 398 bool changed = false;
c906108c 399 int i;
c906108c
SS
400
401 i = 0;
53e7cdba 402 while (i < content.size ())
c906108c 403 {
02c28df0 404 bool new_state;
362c05fe 405 struct tui_line_or_address content_loa =
53e7cdba 406 content[i].line_or_addr;
362c05fe 407
362c05fe
AS
408 if (content_loa.loa == l.loa
409 && ((l.loa == LOA_LINE && content_loa.u.line_no == l.u.line_no)
f7952c57 410 || (l.loa == LOA_ADDRESS && content_loa.u.addr == l.u.addr)))
02c28df0 411 new_state = true;
c906108c 412 else
02c28df0 413 new_state = false;
53e7cdba 414 if (new_state != content[i].is_exec_point)
00b90ae2 415 {
02c28df0 416 changed = true;
53e7cdba 417 content[i].is_exec_point = new_state;
ad54d15b 418 tui_show_source_line (this, i + 1);
00b90ae2 419 }
c906108c
SS
420 i++;
421 }
00b90ae2 422 if (changed)
ad54d15b 423 refill ();
00b90ae2 424}
c906108c 425
0807ab7b
TT
426/* See tui-winsource.h. */
427
c906108c 428void
0807ab7b 429tui_update_all_breakpoint_info (struct breakpoint *being_deleted)
c906108c 430{
ad54d15b 431 for (tui_source_window_base *win : tui_source_windows ())
c906108c 432 {
2ddaf614
TT
433 if (win->update_breakpoint_info (being_deleted, false))
434 win->update_exec_info ();
c906108c 435 }
00b2bad4 436}
c906108c
SS
437
438
0807ab7b 439/* Scan the source window and the breakpoints to update the break_mode
1cc6d956
MS
440 information for each line.
441
0807ab7b 442 Returns true if something changed and the execution window must be
1cc6d956
MS
443 refreshed. */
444
0807ab7b 445bool
2ddaf614
TT
446tui_source_window_base::update_breakpoint_info
447 (struct breakpoint *being_deleted, bool current_only)
c906108c
SS
448{
449 int i;
0807ab7b 450 bool need_refresh = false;
c906108c 451
2ddaf614 452 for (i = 0; i < content.size (); i++)
00b2bad4 453 {
5b6fe301 454 struct tui_source_element *line;
00b2bad4 455
2ddaf614 456 line = &content[i];
6d012f14 457 if (current_only && !line->is_exec_point)
00b2bad4
SC
458 continue;
459
460 /* Scan each breakpoint to see if the current line has something to
461 do with it. Identify enable/disabled breakpoints as well as
462 those that we already hit. */
0598af48 463 tui_bp_flags mode = 0;
81e6b8eb 464 iterate_over_breakpoints ([&] (breakpoint *bp) -> bool
00b2bad4 465 {
f8eba3c6
TT
466 struct bp_location *loc;
467
0807ab7b 468 if (bp == being_deleted)
81e6b8eb 469 return false;
0807ab7b 470
f8eba3c6
TT
471 for (loc = bp->loc; loc != NULL; loc = loc->next)
472 {
2ddaf614 473 if (location_matches_p (loc, i))
f8eba3c6
TT
474 {
475 if (bp->enable_state == bp_disabled)
476 mode |= TUI_BP_DISABLED;
477 else
478 mode |= TUI_BP_ENABLED;
479 if (bp->hit_count)
480 mode |= TUI_BP_HIT;
481 if (bp->loc->cond)
482 mode |= TUI_BP_CONDITIONAL;
483 if (bp->type == bp_hardware_breakpoint)
484 mode |= TUI_BP_HARDWARE;
485 }
486 }
81e6b8eb
CB
487 return false;
488 });
0598af48 489 if (line->break_mode != mode)
00b2bad4 490 {
0598af48
TT
491 line->break_mode = mode;
492 need_refresh = true;
00b2bad4
SC
493 }
494 }
495 return need_refresh;
496}
c906108c 497
6ba8e26f
AC
498/* Function to initialize the content of the execution info window,
499 based upon the input window which is either the source or
500 disassembly window. */
73fbdc65 501void
5216580d 502tui_source_window_base::update_exec_info ()
c906108c 503{
2ddaf614 504 update_breakpoint_info (nullptr, true);
37a4a131 505 for (int i = 0; i < content.size (); i++)
098f9ed4 506 {
5216580d
TT
507 struct tui_source_element *src_element = &content[i];
508 char element[TUI_EXECINFO_SIZE] = " ";
098f9ed4
TT
509
510 /* Now update the exec info content based upon the state
511 of each line as indicated by the source content. */
5216580d 512 tui_bp_flags mode = src_element->break_mode;
098f9ed4
TT
513 if (mode & TUI_BP_HIT)
514 element[TUI_BP_HIT_POS] = (mode & TUI_BP_HARDWARE) ? 'H' : 'B';
515 else if (mode & (TUI_BP_ENABLED | TUI_BP_DISABLED))
516 element[TUI_BP_HIT_POS] = (mode & TUI_BP_HARDWARE) ? 'h' : 'b';
517
518 if (mode & TUI_BP_ENABLED)
519 element[TUI_BP_BREAK_POS] = '+';
520 else if (mode & TUI_BP_DISABLED)
521 element[TUI_BP_BREAK_POS] = '-';
522
523 if (src_element->is_exec_point)
524 element[TUI_EXEC_POS] = '>';
c906108c 525
7523da63 526 mvwaddstr (handle.get (), i + 1, 1, element);
5216580d 527 }
398fdd60 528 refresh_window ();
f80bda8e 529}
This page took 2.315428 seconds and 4 git commands to generate.