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