📄 tui-layout.c
字号:
/* TUI layout window management. Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */#include "defs.h"#include "command.h"#include "symtab.h"#include "frame.h"#include "source.h"#include <ctype.h>#include "tui/tui.h"#include "tui/tui-data.h"#include "tui/tui-windata.h"#include "tui/tui-wingeneral.h"#include "tui/tui-stack.h"#include "tui/tui-regs.h"#include "tui/tui-win.h"#include "tui/tui-winsource.h"#include "tui/tui-disasm.h"#include "gdb_string.h"#include "gdb_curses.h"/********************************* Static Local Decls********************************/static void show_layout (enum tui_layout_type);static void init_gen_win_info (struct tui_gen_win_info *, enum tui_win_type, int, int, int, int);static void init_and_make_win (void **, enum tui_win_type, int, int, int, int, int);static void show_source_or_disasm_and_command (enum tui_layout_type);static void make_source_or_disasm_window (struct tui_win_info * *, enum tui_win_type, int, int);static void make_command_window (struct tui_win_info * *, int, int);static void make_source_window (struct tui_win_info * *, int, int);static void make_disasm_window (struct tui_win_info * *, int, int);static void make_data_window (struct tui_win_info * *, int, int);static void show_source_command (void);static void show_disasm_command (void);static void show_source_disasm_command (void);static void show_data (enum tui_layout_type);static enum tui_layout_type next_layout (void);static enum tui_layout_type prev_layout (void);static void tui_layout_command (char *, int);static void tui_toggle_layout_command (char *, int);static void tui_toggle_split_layout_command (char *, int);static CORE_ADDR extract_display_start_addr (void);static void tui_handle_xdb_layout (struct tui_layout_def *);/***************************************** DEFINITIONS***************************************/#define LAYOUT_USAGE "Usage: layout prev | next | <layout_name> \n"/* Show the screen layout defined. */static voidshow_layout (enum tui_layout_type layout){ enum tui_layout_type cur_layout = tui_current_layout (); if (layout != cur_layout) { /* ** Since the new layout may cause changes in window size, we ** should free the content and reallocate on next display of ** source/asm */ tui_free_all_source_wins_content (); tui_clear_source_windows (); if (layout == SRC_DATA_COMMAND || layout == DISASSEM_DATA_COMMAND) { show_data (layout); tui_refresh_all (tui_win_list); } else { /* First make the current layout be invisible */ tui_make_all_invisible (); tui_make_invisible (tui_locator_win_info_ptr ()); switch (layout) { /* Now show the new layout */ case SRC_COMMAND: show_source_command (); tui_add_to_source_windows (TUI_SRC_WIN); break; case DISASSEM_COMMAND: show_disasm_command (); tui_add_to_source_windows (TUI_DISASM_WIN); break; case SRC_DISASSEM_COMMAND: show_source_disasm_command (); tui_add_to_source_windows (TUI_SRC_WIN); tui_add_to_source_windows (TUI_DISASM_WIN); break; default: break; } } }}/* Function to set the layout to SRC_COMMAND, DISASSEM_COMMAND, SRC_DISASSEM_COMMAND, SRC_DATA_COMMAND, or DISASSEM_DATA_COMMAND. If the layout is SRC_DATA_COMMAND, DISASSEM_DATA_COMMAND, or UNDEFINED_LAYOUT, then the data window is populated according to regs_display_type. */enum tui_statustui_set_layout (enum tui_layout_type layout_type, enum tui_register_display_type regs_display_type){ enum tui_status status = TUI_SUCCESS; if (layout_type != UNDEFINED_LAYOUT || regs_display_type != TUI_UNDEFINED_REGS) { enum tui_layout_type cur_layout = tui_current_layout (), new_layout = UNDEFINED_LAYOUT; int regs_populate = FALSE; CORE_ADDR addr = extract_display_start_addr (); struct tui_win_info * new_win_with_focus = (struct tui_win_info *) NULL; struct tui_win_info * win_with_focus = tui_win_with_focus (); struct tui_layout_def * layout_def = tui_layout_def (); if (layout_type == UNDEFINED_LAYOUT && regs_display_type != TUI_UNDEFINED_REGS) { if (cur_layout == SRC_DISASSEM_COMMAND) new_layout = DISASSEM_DATA_COMMAND; else if (cur_layout == SRC_COMMAND || cur_layout == SRC_DATA_COMMAND) new_layout = SRC_DATA_COMMAND; else if (cur_layout == DISASSEM_COMMAND || cur_layout == DISASSEM_DATA_COMMAND) new_layout = DISASSEM_DATA_COMMAND; } else new_layout = layout_type; regs_populate = (new_layout == SRC_DATA_COMMAND || new_layout == DISASSEM_DATA_COMMAND || regs_display_type != TUI_UNDEFINED_REGS); if (new_layout != cur_layout || regs_display_type != TUI_UNDEFINED_REGS) { if (new_layout != cur_layout) { show_layout (new_layout); /* ** Now determine where focus should be */ if (win_with_focus != TUI_CMD_WIN) { switch (new_layout) { case SRC_COMMAND: tui_set_win_focus_to (TUI_SRC_WIN); layout_def->display_mode = SRC_WIN; layout_def->split = FALSE; break; case DISASSEM_COMMAND: /* the previous layout was not showing ** code. this can happen if there is no ** source available: ** 1. if the source file is in another dir OR ** 2. if target was compiled without -g ** We still want to show the assembly though! */ addr = tui_get_begin_asm_address (); tui_set_win_focus_to (TUI_DISASM_WIN); layout_def->display_mode = DISASSEM_WIN; layout_def->split = FALSE; break; case SRC_DISASSEM_COMMAND: /* the previous layout was not showing ** code. this can happen if there is no ** source available: ** 1. if the source file is in another dir OR ** 2. if target was compiled without -g ** We still want to show the assembly though! */ addr = tui_get_begin_asm_address (); if (win_with_focus == TUI_SRC_WIN) tui_set_win_focus_to (TUI_SRC_WIN); else tui_set_win_focus_to (TUI_DISASM_WIN); layout_def->split = TRUE; break; case SRC_DATA_COMMAND: if (win_with_focus != TUI_DATA_WIN) tui_set_win_focus_to (TUI_SRC_WIN); else tui_set_win_focus_to (TUI_DATA_WIN); layout_def->display_mode = SRC_WIN; layout_def->split = FALSE; break; case DISASSEM_DATA_COMMAND: /* the previous layout was not showing ** code. this can happen if there is no ** source available: ** 1. if the source file is in another dir OR ** 2. if target was compiled without -g ** We still want to show the assembly though! */ addr = tui_get_begin_asm_address (); if (win_with_focus != TUI_DATA_WIN) tui_set_win_focus_to (TUI_DISASM_WIN); else tui_set_win_focus_to (TUI_DATA_WIN); layout_def->display_mode = DISASSEM_WIN; layout_def->split = FALSE; break; default: break; } } if (new_win_with_focus != (struct tui_win_info *) NULL) tui_set_win_focus_to (new_win_with_focus); /* ** Now update the window content */ if (!regs_populate && (new_layout == SRC_DATA_COMMAND || new_layout == DISASSEM_DATA_COMMAND)) tui_display_all_data (); tui_update_source_windows_with_addr (addr); } if (regs_populate) { tui_show_registers (TUI_DATA_WIN->detail.data_display_info.current_group); } } } else status = TUI_FAILURE; return status;}/* Add the specified window to the layout in a logical way. This means setting up the most logical layout given the window to be added. */voidtui_add_win_to_layout (enum tui_win_type type){ enum tui_layout_type cur_layout = tui_current_layout (); switch (type) { case SRC_WIN: if (cur_layout != SRC_COMMAND && cur_layout != SRC_DISASSEM_COMMAND && cur_layout != SRC_DATA_COMMAND) { tui_clear_source_windows_detail (); if (cur_layout == DISASSEM_DATA_COMMAND) show_layout (SRC_DATA_COMMAND); else show_layout (SRC_COMMAND); } break; case DISASSEM_WIN: if (cur_layout != DISASSEM_COMMAND && cur_layout != SRC_DISASSEM_COMMAND && cur_layout != DISASSEM_DATA_COMMAND) { tui_clear_source_windows_detail (); if (cur_layout == SRC_DATA_COMMAND) show_layout (DISASSEM_DATA_COMMAND); else show_layout (DISASSEM_COMMAND); } break; case DATA_WIN: if (cur_layout != SRC_DATA_COMMAND && cur_layout != DISASSEM_DATA_COMMAND) { if (cur_layout == DISASSEM_COMMAND) show_layout (DISASSEM_DATA_COMMAND); else show_layout (SRC_DATA_COMMAND); } break; default: break; }}/* Answer the height of a window. If it hasn't been created yet, answer what the height of a window would be based upon its type and the layout. */inttui_default_win_height (enum tui_win_type type, enum tui_layout_type layout){ int h; if (tui_win_list[type] != (struct tui_win_info *) NULL) h = tui_win_list[type]->generic.height; else { switch (layout) { case SRC_COMMAND: case DISASSEM_COMMAND: if (TUI_CMD_WIN == NULL) h = tui_term_height () / 2; else h = tui_term_height () - TUI_CMD_WIN->generic.height; break; case SRC_DISASSEM_COMMAND: case SRC_DATA_COMMAND: case DISASSEM_DATA_COMMAND: if (TUI_CMD_WIN == NULL) h = tui_term_height () / 3; else h = (tui_term_height () - TUI_CMD_WIN->generic.height) / 2; break; default: h = 0; break; } } return h;}/* Answer the height of a window. If it hasn't been created yet, answer what the height of a window would be based upon its type and the layout. */inttui_default_win_viewport_height (enum tui_win_type type, enum tui_layout_type layout){ int h; h = tui_default_win_height (type, layout); if (tui_win_list[type] == TUI_CMD_WIN) h -= 1; else h -= 2; return h;}/* Function to initialize gdb commands, for tui window layout manipulation. */void_initialize_tui_layout (void){ add_com ("layout", class_tui, tui_layout_command, "Change the layout of windows.\n\Usage: layout prev | next | <layout_name> \n\Layout names are:\n\ src : Displays source and command windows.\n\ asm : Displays disassembly and command windows.\n\ split : Displays source, disassembly and command windows.\n\ regs : Displays register window. If existing layout\n\ is source/command or assembly/command, the \n\ register window is displayed. If the\n\ source/assembly/command (split) is displayed, \n\ the register window is displayed with \n\ the window that has current logical focus.\n"); if (xdb_commands) { add_com ("td", class_tui, tui_toggle_layout_command, "Toggle between Source/Command and Disassembly/Command layouts.\n"); add_com ("ts", class_tui, tui_toggle_split_layout_command, "Toggle between Source/Command or Disassembly/Command and \n\Source/Disassembly/Command layouts.\n"); }}/*************************** STATIC LOCAL FUNCTIONS**************************//* Function to set the layout to SRC, ASM, SPLIT, NEXT, PREV, DATA, REGS, $REGS, $GREGS, $FREGS, $SREGS. */enum tui_statustui_set_layout_for_display_command (const char *layout_name){ enum tui_status status = TUI_SUCCESS; if (layout_name != (char *) NULL) { int i; char *buf_ptr; enum tui_layout_type new_layout = UNDEFINED_LAYOUT; enum tui_register_display_type dpy_type = TUI_UNDEFINED_REGS; enum tui_layout_type cur_layout = tui_current_layout (); buf_ptr = (char *) xstrdup (layout_name); for (i = 0; (i < strlen (layout_name)); i++) buf_ptr[i] = toupper (buf_ptr[i]); /* First check for ambiguous input */ if (strlen (buf_ptr) <= 1 && (*buf_ptr == 'S' || *buf_ptr == '$')) { warning ("Ambiguous command input.\n"); status = TUI_FAILURE; } else { if (subset_compare (buf_ptr, "SRC")) new_layout = SRC_COMMAND; else if (subset_compare (buf_ptr, "ASM")) new_layout = DISASSEM_COMMAND; else if (subset_compare (buf_ptr, "SPLIT")) new_layout = SRC_DISASSEM_COMMAND; else if (subset_compare (buf_ptr, "REGS") || subset_compare (buf_ptr, TUI_GENERAL_SPECIAL_REGS_NAME) || subset_compare (buf_ptr, TUI_GENERAL_REGS_NAME) || subset_compare (buf_ptr, TUI_FLOAT_REGS_NAME) || subset_compare (buf_ptr, TUI_SPECIAL_REGS_NAME)) { if (cur_layout == SRC_COMMAND || cur_layout == SRC_DATA_COMMAND) new_layout = SRC_DATA_COMMAND; else new_layout = DISASSEM_DATA_COMMAND;/* could ifdef out the following code. when compile with -z, there are null pointer references that cause a core dump if 'layout regs' is the first layout command issued by the user. HP has asked us to hook up this code - edie epstein */ if (subset_compare (buf_ptr, TUI_FLOAT_REGS_NAME)) { if (TUI_DATA_WIN->detail.data_display_info.regs_display_type != TUI_SFLOAT_REGS && TUI_DATA_WIN->detail.data_display_info.regs_display_type != TUI_DFLOAT_REGS) dpy_type = TUI_SFLOAT_REGS; else dpy_type = TUI_DATA_WIN->detail.data_display_info.regs_display_type; } else if (subset_compare (buf_ptr, TUI_GENERAL_SPECIAL_REGS_NAME)) dpy_type = TUI_GENERAL_AND_SPECIAL_REGS; else if (subset_compare (buf_ptr, TUI_GENERAL_REGS_NAME)) dpy_type = TUI_GENERAL_REGS; else if (subset_compare (buf_ptr, TUI_SPECIAL_REGS_NAME)) dpy_type = TUI_SPECIAL_REGS; else if (TUI_DATA_WIN) { if (TUI_DATA_WIN->detail.data_display_info.regs_display_type != TUI_UNDEFINED_REGS) dpy_type = TUI_DATA_WIN->detail.data_display_info.regs_display_type; else dpy_type = TUI_GENERAL_REGS; }/* end of potential ifdef *//* if ifdefed out code above, then assume that the user wishes to display the general purpose registers *//* dpy_type = TUI_GENERAL_REGS; */ } else if (subset_compare (buf_ptr, "NEXT")) new_layout = next_layout (); else if (subset_compare (buf_ptr, "PREV")) new_layout = prev_layout (); else status = TUI_FAILURE; xfree (buf_ptr); tui_set_layout (new_layout, dpy_type); } } else status = TUI_FAILURE; return status;}static CORE_ADDRextract_display_start_addr (void){ enum tui_layout_type cur_layout = tui_current_layout (); CORE_ADDR addr; CORE_ADDR pc; struct symtab_and_line cursal = get_current_source_symtab_and_line (); switch (cur_layout) { case SRC_COMMAND: case SRC_DATA_COMMAND: find_line_pc (cursal.symtab, TUI_SRC_WIN->detail.source_info.start_line_or_addr.line_no, &pc); addr = pc; break; case DISASSEM_COMMAND: case SRC_DISASSEM_COMMAND: case DISASSEM_DATA_COMMAND: addr = TUI_DISASM_WIN->detail.source_info.start_line_or_addr.addr; break; default: addr = 0; break; } return addr;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -