binutils-gdb/gdb/tui/tui-source.c
Andrew Burgess f237f998d1 gdb/tui: remove special handling of locator/status window
The locator window, or status window as it is sometimes called is
handled differently to all the other windows.

The reason for this is that the class representing this
window (tui_locator_window) does two jobs, first this class represents
a window just like any other that has space on the screen and fills
the space with content.  The second job is that this class serves as a
storage area to hold information about the current location that the
TUI windows represent, so the class has members like 'addr' and
'line_no', for example which are used within this class, and others
when they want to know which line/address the TUI windows should be
showing to the user.

Because of this dual purpose we must always have an instance of the
tui_locator_window so that there is somewhere to store this location
information.

The result of this is that the locator window must never be deleted
like other windows, which results in some special case code.

In this patch I propose splitting the two roles of the
tui_locator_window class.  The tui_locator_window class will retain
just its window drawing parts, and will be treated just like any other
window.  This should allow all special case code for this window to be
deleted.

The other role, that of tracking the current tui location will be
moved into a new class (tui_location_tracker), of which there will be
a single global instance.  All of the places where we previously use
the locator window to get location information will now be updated to
get this from the tui_location_tracker.

There should be no user visible changes after this commit.

gdb/ChangeLog:

	* Makefile.in (SUBDIR_TUI_SRCS): Add tui/tui-location.c.
	(HFILES_NO_SRCDIR): Add tui/tui-location.h.
	* tui/tui-data.h (TUI_STATUS_WIN): Define.
	(tui_locator_win_info_ptr): Delete declaration.
	* tui/tui-disasm.c: Add 'tui/tui-location.h' include.
	(tui_disasm_window::set_contents): Fetch state from tui_location
	global.
	(tui_get_begin_asm_address): Likewise.
	* tui/tui-layout.c (tui_apply_current_layout): Remove special case
	for locator window.
	(get_locator_window): Delete.
	(initialize_known_windows): Treat locator window just like all the
	rest.
	* tui/tui-source.c: Add 'tui/tui-location.h' include.
	(tui_source_window::set_contents): Fetch state from tui_location
	global.
	(tui_source_window::showing_source_p): Likewise.
	* tui/tui-stack.c: Add 'tui/tui-location.h' include.
	(_locator): Delete.
	(tui_locator_win_info_ptr): Delete.
	(tui_locator_window::make_status_line): Fetch state from
	tui_location global.
	(tui_locator_window::rerender): Remove check of 'handle',
	reindent function body.
	(tui_locator_window::set_locator_fullname): Delete.
	(tui_locator_window::set_locator_info): Delete.
	(tui_update_locator_fullname): Delete.
	(tui_show_frame_info): Likewise.
	(tui_show_locator_content): Access window through TUI_STATUS_WIN.
	* tui/tui-stack.h (tui_locator_window::set_locator_info): Moved to
	tui/tui-location.h and renamed to
	tui_location_tracker::set_location.
	(tui_locator_window::set_locator_fullname): Moved to
	tui/tui-location.h and renamed to
	tui_location_tracker::set_fullname.
	(tui_locator_window::full_name): Delete.
	(tui_locator_window::proc_name): Delete.
	(tui_locator_window::line_no): Delete.
	(tui_locator_window::addr): Delete.
	(tui_locator_window::gdbarch): Delete.
	(tui_update_locator_fullname): Delete declaration.
	* tui/tui-wingeneral.c (tui_refresh_all): Removed special handling
	for locator window.
	* tui/tui-winsource.c: Add 'tui/tui-location.h' include.
	(tui_display_main): Call function on tui_location directly.
	* tui/tui.h (enum tui_win_type): Add STATUS_WIN.
	* tui/tui-location.c: New file.
	* tui/tui-location.h: New file.
2021-01-28 17:00:30 +00:00

240 lines
6.4 KiB
C

/* TUI display source window.
Copyright (C) 1998-2021 Free Software Foundation, Inc.
Contributed by Hewlett-Packard Company.
This file is part of GDB.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "defs.h"
#include <math.h>
#include <ctype.h>
#include "symtab.h"
#include "frame.h"
#include "breakpoint.h"
#include "source.h"
#include "objfiles.h"
#include "filenames.h"
#include "source-cache.h"
#include "tui/tui.h"
#include "tui/tui-data.h"
#include "tui/tui-io.h"
#include "tui/tui-stack.h"
#include "tui/tui-win.h"
#include "tui/tui-winsource.h"
#include "tui/tui-source.h"
#include "tui/tui-location.h"
#include "gdb_curses.h"
/* Function to display source in the source window. */
bool
tui_source_window::set_contents (struct gdbarch *arch,
const struct symtab_and_line &sal)
{
struct symtab *s = sal.symtab;
int line_no = sal.line;
if (s == NULL)
return false;
/* Take hilite (window border) into account, when
calculating the number of lines. */
int nlines = height - 2;
std::string srclines;
const std::vector<off_t> *offsets;
if (!g_source_cache.get_source_lines (s, line_no, line_no + nlines,
&srclines)
|| !g_source_cache.get_line_charpos (s, &offsets))
return false;
int cur_line_no, cur_line;
const char *s_filename = symtab_to_filename_for_display (s);
title = s_filename;
m_fullname = make_unique_xstrdup (symtab_to_fullname (s));
cur_line = 0;
m_gdbarch = SYMTAB_OBJFILE (s)->arch ();
m_start_line_or_addr.loa = LOA_LINE;
cur_line_no = m_start_line_or_addr.u.line_no = line_no;
m_digits = 7;
if (compact_source)
{
/* Solaris 11+gcc 5.5 has ambiguous overloads of log10, so we
cast to double to get the right one. */
double l = log10 ((double) offsets->size ());
m_digits = 1 + (int) l;
}
m_max_length = -1;
const char *iter = srclines.c_str ();
m_content.resize (nlines);
while (cur_line < nlines)
{
struct tui_source_element *element = &m_content[cur_line];
std::string text;
if (*iter != '\0')
{
int line_len;
text = tui_copy_source_line (&iter, &line_len);
m_max_length = std::max (m_max_length, line_len);
}
/* Set whether element is the execution point
and whether there is a break point on it. */
element->line_or_addr.loa = LOA_LINE;
element->line_or_addr.u.line_no = cur_line_no;
element->is_exec_point
= (filename_cmp (tui_location.full_name ().c_str (),
symtab_to_fullname (s)) == 0
&& cur_line_no == tui_location.line_no ());
m_content[cur_line].line = std::move (text);
cur_line++;
cur_line_no++;
}
return true;
}
/* Answer whether the source is currently displayed in the source
window. */
bool
tui_source_window::showing_source_p (const char *fullname) const
{
return (!m_content.empty ()
&& (filename_cmp (tui_location.full_name ().c_str (),
fullname) == 0));
}
/* Scroll the source forward or backward vertically. */
void
tui_source_window::do_scroll_vertical (int num_to_scroll)
{
if (!m_content.empty ())
{
struct symtab *s;
struct symtab_and_line cursal = get_current_source_symtab_and_line ();
struct gdbarch *arch = m_gdbarch;
if (cursal.symtab == NULL)
{
struct frame_info *fi = get_selected_frame (NULL);
s = find_pc_line_symtab (get_frame_pc (fi));
arch = get_frame_arch (fi);
}
else
s = cursal.symtab;
int line_no = m_start_line_or_addr.u.line_no + num_to_scroll;
const std::vector<off_t> *offsets;
if (g_source_cache.get_line_charpos (s, &offsets)
&& line_no > offsets->size ())
line_no = m_start_line_or_addr.u.line_no;
if (line_no <= 0)
line_no = 1;
cursal.line = line_no;
find_line_pc (cursal.symtab, cursal.line, &cursal.pc);
for (struct tui_source_window_base *win_info : tui_source_windows ())
win_info->update_source_window_as_is (arch, cursal);
}
}
bool
tui_source_window::location_matches_p (struct bp_location *loc, int line_no)
{
return (m_content[line_no].line_or_addr.loa == LOA_LINE
&& m_content[line_no].line_or_addr.u.line_no == loc->line_number
&& loc->symtab != NULL
&& filename_cmp (m_fullname.get (),
symtab_to_fullname (loc->symtab)) == 0);
}
/* See tui-source.h. */
bool
tui_source_window::line_is_displayed (int line) const
{
if (m_content.size () < SCROLL_THRESHOLD)
return false;
for (size_t i = 0; i < m_content.size () - SCROLL_THRESHOLD; ++i)
{
if (m_content[i].line_or_addr.loa == LOA_LINE
&& m_content[i].line_or_addr.u.line_no == line)
return true;
}
return false;
}
void
tui_source_window::maybe_update (struct frame_info *fi, symtab_and_line sal)
{
int start_line = (sal.line - ((height - 2) / 2)) + 1;
if (start_line <= 0)
start_line = 1;
bool source_already_displayed = (sal.symtab != 0
&& showing_source_p (m_fullname.get ()));
if (!(source_already_displayed && line_is_displayed (sal.line)))
{
sal.line = start_line;
update_source_window (get_frame_arch (fi), sal);
}
else
{
struct tui_line_or_address l;
l.loa = LOA_LINE;
l.u.line_no = sal.line;
set_is_exec_point_at (l);
}
}
void
tui_source_window::display_start_addr (struct gdbarch **gdbarch_p,
CORE_ADDR *addr_p)
{
struct symtab_and_line cursal = get_current_source_symtab_and_line ();
*gdbarch_p = m_gdbarch;
find_line_pc (cursal.symtab, m_start_line_or_addr.u.line_no, addr_p);
}
/* See tui-winsource.h. */
void
tui_source_window::show_line_number (int offset) const
{
int lineno = m_content[0].line_or_addr.u.line_no + offset;
char text[20];
/* To completely overwrite the previous border when the source window height
is increased, both spaces after the line number have to be redrawn. */
xsnprintf (text, sizeof (text), "%*d ", m_digits - 1, lineno);
waddstr (handle.get (), text);
}