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