| /* TUI display source/assembly window. |
| |
| Copyright (C) 1998-2024 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/>. */ |
| |
| #ifndef TUI_TUI_WINSOURCE_H |
| #define TUI_TUI_WINSOURCE_H |
| |
| #include "gdbsupport/observable.h" |
| #include "tui/tui-data.h" |
| #include "symtab.h" |
| |
| enum tui_line_or_address_kind |
| { |
| LOA_LINE, |
| LOA_ADDRESS |
| }; |
| |
| /* Structure describing source line or line address. */ |
| struct tui_line_or_address |
| { |
| enum tui_line_or_address_kind loa; |
| union |
| { |
| int line_no; |
| CORE_ADDR addr; |
| } u; |
| }; |
| |
| /* Flags to tell what kind of breakpoint is at current line. */ |
| enum tui_bp_flag |
| { |
| TUI_BP_ENABLED = 0x01, |
| TUI_BP_DISABLED = 0x02, |
| TUI_BP_HIT = 0x04, |
| TUI_BP_CONDITIONAL = 0x08, |
| TUI_BP_HARDWARE = 0x10 |
| }; |
| |
| DEF_ENUM_FLAGS_TYPE (enum tui_bp_flag, tui_bp_flags); |
| |
| /* Position of breakpoint markers in the exec info string. */ |
| #define TUI_BP_HIT_POS 0 |
| #define TUI_BP_BREAK_POS 1 |
| #define TUI_EXEC_POS 2 |
| #define TUI_EXECINFO_SIZE 3 |
| |
| /* Elements in the Source/Disassembly Window. */ |
| struct tui_source_element |
| { |
| tui_source_element () |
| { |
| line_or_addr.loa = LOA_LINE; |
| line_or_addr.u.line_no = 0; |
| } |
| |
| DISABLE_COPY_AND_ASSIGN (tui_source_element); |
| |
| tui_source_element (tui_source_element &&other) |
| : line (std::move (other.line)), |
| line_or_addr (other.line_or_addr), |
| is_exec_point (other.is_exec_point), |
| break_mode (other.break_mode) |
| { |
| } |
| |
| std::string line; |
| struct tui_line_or_address line_or_addr; |
| bool is_exec_point = false; |
| tui_bp_flags break_mode = 0; |
| }; |
| |
| |
| /* The base class for all source-like windows, namely the source and |
| disassembly windows. */ |
| |
| struct tui_source_window_base : public tui_win_info |
| { |
| protected: |
| tui_source_window_base (); |
| ~tui_source_window_base (); |
| |
| DISABLE_COPY_AND_ASSIGN (tui_source_window_base); |
| |
| void do_scroll_horizontal (int num_to_scroll) override; |
| |
| /* Erase the content and display STRING. */ |
| void do_erase_source_content (const char *string); |
| |
| void rerender () override; |
| |
| virtual bool set_contents (struct gdbarch *gdbarch, |
| const struct symtab_and_line &sal) = 0; |
| |
| /* Return the number of extra margin characters needed by this |
| instance. */ |
| virtual int extra_margin () const |
| { |
| return 0; |
| } |
| |
| /* Display the line number in the window margin. OFFSET indicates |
| which line to display; it is 0-based, with 0 meaning the line at |
| the top of the window. */ |
| virtual void show_line_number (int offset) const |
| { |
| } |
| |
| /* Redraw the complete line of a source or disassembly window. */ |
| void show_source_line (int lineno); |
| |
| /* Where to start generating content from. */ |
| struct tui_line_or_address m_start_line_or_addr; |
| |
| /* Architecture associated with code at this location. */ |
| struct gdbarch *m_gdbarch = nullptr; |
| |
| std::vector<tui_source_element> m_content; |
| |
| /* Length of longest line to be displayed. */ |
| int m_max_length; |
| |
| public: |
| |
| /* Refill the source window's source cache and update it. If this |
| is a disassembly window, then just update it. */ |
| void refill (); |
| |
| /* Set the location of the execution point. */ |
| void set_is_exec_point_at (struct tui_line_or_address l); |
| |
| void update_tab_width () override; |
| |
| virtual bool location_matches_p (struct bp_location *loc, int line_no) = 0; |
| |
| /* Fill in the left margin of the current window with execution indicator |
| information, e.g. breakpoint indicators, and line numbers. When |
| REFRESH_P is true this function will call refresh_window to ensure |
| updates are written to the screen, otherwise the refresh is skipped, |
| which will leave the on screen contents out of date. When passing |
| false for REFRESH_P you should be planning to call refresh_window |
| yourself. */ |
| void update_exec_info (bool refresh_p = true); |
| |
| /* Update the window to display the given location. Does nothing if |
| the location is already displayed. */ |
| virtual void maybe_update (const frame_info_ptr &fi, symtab_and_line sal) = 0; |
| |
| void update_source_window_as_is (struct gdbarch *gdbarch, |
| const struct symtab_and_line &sal); |
| void update_source_window (struct gdbarch *gdbarch, |
| const struct symtab_and_line &sal); |
| |
| /* Scan the source window and the breakpoints to update the |
| break_mode information for each line. Returns true if something |
| changed and the execution window must be refreshed. See |
| tui_update_all_breakpoint_info for a description of |
| BEING_DELETED. */ |
| bool update_breakpoint_info (struct breakpoint *being_deleted, |
| bool current_only); |
| |
| /* Erase the source content. */ |
| virtual void erase_source_content () = 0; |
| |
| void refresh_window () override; |
| |
| /* Return the start address and gdbarch. */ |
| virtual void display_start_addr (struct gdbarch **gdbarch_p, |
| CORE_ADDR *addr_p) = 0; |
| |
| /* Function to ensure that the source or disassembly window |
| reflects the input address. Single window variant of |
| update_source_windows_with_addr. */ |
| void update_source_window_with_addr (struct gdbarch *, CORE_ADDR); |
| |
| private: |
| |
| /* Used for horizontal scroll. */ |
| int m_horizontal_offset = 0; |
| |
| /* Check that the current values of M_HORIZONTAL_OFFSET and M_PAD_OFFSET |
| make sense given the current M_MAX_LENGTH (content width), WIDTH |
| (window size), and window margins. After calling this function |
| M_HORIZONTAL_OFFSET and M_PAD_OFFSET might have been adjusted to |
| reduce unnecessary whitespace on the right side of the window. |
| |
| If M_PAD_OFFSET is adjusted then this function returns true |
| indicating that the pad contents need to be reloaded by calling |
| show_source_content. If M_PAD_OFFSET is not adjusted then this |
| function returns false, the window contents might still need |
| redrawing if M_HORIZONTAL_OFFSET was adjusted, but right now, this |
| function is only called in contexts where the window is going to be |
| redrawn anyway. */ |
| bool validate_scroll_offsets (); |
| |
| /* Return the size of the left margin space, this is the space used to |
| display things like breakpoint markers. */ |
| int left_margin () const |
| { return TUI_EXECINFO_SIZE + extra_margin (); } |
| |
| /* Return the width of the area that is available for window content. |
| This is the window width minus the borders and the left margin, which |
| is used for displaying things like breakpoint markers. */ |
| int view_width () const |
| { return width - left_margin () - box_size (); } |
| |
| void show_source_content (); |
| |
| /* Write STRING to the window M_PAD, but skip the first SKIP printable |
| characters. Any escape sequences within the first SKIP characters are |
| still processed though. This means if we have this string: |
| |
| "\033[31mABCDEFGHIJKLM\033[0m" |
| |
| and call this function with a skip value of 3, then we effectively |
| write this string to M_PAD: |
| |
| "\033[31mDEFGHIJKLM\033[0m" |
| |
| the initial escape that sets the color will still be applied. */ |
| void puts_to_pad_with_skip (const char *string, int skip); |
| |
| /* Called when the user "set style enabled" setting is changed. */ |
| void style_changed (); |
| |
| /* A token used to register and unregister an observer. */ |
| gdb::observers::token m_observable; |
| |
| /* Pad to hold some, or all, of the window contents. Content is then |
| copied from this pad to the screen as the user scrolls horizontally, |
| this avoids the need to recalculate the screen contents each time the |
| user does a horizontal scroll. */ |
| std::unique_ptr<WINDOW, curses_deleter> m_pad; |
| |
| /* When M_PAD was allocated, this holds the width that was initially |
| asked for. If we ask for a very large pad then the allocation may |
| fail, and we might instead allocate a narrower pad. */ |
| int m_pad_requested_width = 0; |
| |
| /* If M_PAD is not as wide as the content (so less than M_MAX_LENGTH) |
| then this value indicates the offset at which the pad contents begin. */ |
| int m_pad_offset = 0; |
| }; |
| |
| |
| /* A wrapper for a TUI window iterator that only iterates over source |
| windows. */ |
| |
| struct tui_source_window_iterator |
| { |
| public: |
| |
| typedef std::vector<tui_win_info *>::iterator inner_iterator; |
| |
| typedef tui_source_window_iterator self_type; |
| typedef struct tui_source_window_base *value_type; |
| typedef struct tui_source_window_base *&reference; |
| typedef struct tui_source_window_base **pointer; |
| typedef std::forward_iterator_tag iterator_category; |
| typedef int difference_type; |
| |
| explicit tui_source_window_iterator (const inner_iterator &it, |
| const inner_iterator &end) |
| : m_iter (it), |
| m_end (end) |
| { |
| advance (); |
| } |
| |
| explicit tui_source_window_iterator (const inner_iterator &it) |
| : m_iter (it) |
| { |
| } |
| |
| bool operator!= (const self_type &other) const |
| { |
| return m_iter != other.m_iter; |
| } |
| |
| value_type operator* () const |
| { |
| return dynamic_cast<tui_source_window_base *> (*m_iter); |
| } |
| |
| self_type &operator++ () |
| { |
| ++m_iter; |
| advance (); |
| return *this; |
| } |
| |
| private: |
| |
| void advance () |
| { |
| while (m_iter != m_end |
| && dynamic_cast<tui_source_window_base *> (*m_iter) == nullptr) |
| ++m_iter; |
| } |
| |
| inner_iterator m_iter; |
| inner_iterator m_end; |
| }; |
| |
| /* A range adapter for source windows. */ |
| |
| struct tui_source_windows |
| { |
| /* Work around Wmaybe-uninitialized warning with g++ 11.0.0, see also |
| PR gcc/96295. Note that "tui_source_windows () = default" doesn't work |
| around the warning. */ |
| tui_source_windows () {} |
| |
| tui_source_window_iterator begin () const |
| { |
| return tui_source_window_iterator (tui_windows.begin (), |
| tui_windows.end ()); |
| } |
| |
| tui_source_window_iterator end () const |
| { |
| return tui_source_window_iterator (tui_windows.end ()); |
| } |
| }; |
| |
| /* Update the execution windows to show the active breakpoints. This |
| is called whenever a breakpoint is inserted, removed or has its |
| state changed. Normally BEING_DELETED is nullptr; if not nullptr, |
| it indicates a breakpoint that is in the process of being deleted, |
| and which should therefore be ignored by the update. This is done |
| because the relevant observer is notified before the breakpoint is |
| removed from the list of breakpoints. */ |
| extern void tui_update_all_breakpoint_info (struct breakpoint *being_deleted); |
| |
| /* Function to display the "main" routine. */ |
| extern void tui_display_main (void); |
| extern void tui_update_source_windows_with_addr (struct gdbarch *, CORE_ADDR); |
| extern void tui_update_source_windows_with_line (struct symtab_and_line sal); |
| |
| /* Extract some source text from PTR. Returns a string holding the |
| desired text. PTR is updated to point to the start of the next |
| line. If LENGTH is non-NULL, then the length of the line is stored |
| there. Escape sequences are not counted against the length. |
| Actually an approximation is used -- each byte of a multi-byte |
| sequence counts as a character here. */ |
| |
| extern std::string tui_copy_source_line (const char **ptr, |
| int *length = nullptr); |
| |
| /* Constant definitions. */ |
| #define SCROLL_THRESHOLD 2 /* Threshold for lazy scroll. */ |
| |
| #endif /* TUI_TUI_WINSOURCE_H */ |