📄 tuilayout.c
字号:
/* TUI layout window management. Copyright 1998, 1999, 2000, 2001, 2002, 2003 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.h"#include "tuiData.h"#include "tuiDataWin.h"#include "tuiGeneralWin.h"#include "tuiStack.h"#include "tuiRegs.h"#include "tuiWin.h"#include "tuiSourceWin.h"#include "tuiDisassem.h"#ifdef HAVE_NCURSES_H #include <ncurses.h>#else#ifdef HAVE_CURSES_H#include <curses.h>#endif#endif/********************************* Static Local Decls********************************/static void showLayout (TuiLayoutType);static void _initGenWinInfo (TuiGenWinInfoPtr, TuiWinType, int, int, int, int);static void _initAndMakeWin (Opaque *, TuiWinType, int, int, int, int, int);static void _showSourceOrDisassemAndCommand (TuiLayoutType);static void _makeSourceOrDisassemWindow (TuiWinInfoPtr *, TuiWinType, int, int);static void _makeCommandWindow (TuiWinInfoPtr *, int, int);static void _makeSourceWindow (TuiWinInfoPtr *, int, int);static void _makeDisassemWindow (TuiWinInfoPtr *, int, int);static void _makeDataWindow (TuiWinInfoPtr *, int, int);static void _showSourceCommand (void);static void _showDisassemCommand (void);static void _showSourceDisassemCommand (void);static void _showData (TuiLayoutType);static TuiLayoutType _nextLayout (void);static TuiLayoutType _prevLayout (void);static void _tuiLayout_command (char *, int);static void _tuiToggleLayout_command (char *, int);static void _tuiToggleSplitLayout_command (char *, int);static CORE_ADDR _extractDisplayStartAddr (void);static void _tuiHandleXDBLayout (TuiLayoutDefPtr);/***************************************** DEFINITIONS***************************************/#define LAYOUT_USAGE "Usage: layout prev | next | <layout_name> \n"/* Show the screen layout defined. */static voidshowLayout (TuiLayoutType layout){ TuiLayoutType curLayout = currentLayout (); if (layout != curLayout) { /* ** Since the new layout may cause changes in window size, we ** should free the content and reallocate on next display of ** source/asm */ freeAllSourceWinsContent (); clearSourceWindows (); if (layout == SRC_DATA_COMMAND || layout == DISASSEM_DATA_COMMAND) { _showData (layout); refreshAll (winList); } else { /* First make the current layout be invisible */ m_allBeInvisible (); m_beInvisible (locatorWinInfoPtr ()); switch (layout) { /* Now show the new layout */ case SRC_COMMAND: _showSourceCommand (); addToSourceWindows (srcWin); break; case DISASSEM_COMMAND: _showDisassemCommand (); addToSourceWindows (disassemWin); break; case SRC_DISASSEM_COMMAND: _showSourceDisassemCommand (); addToSourceWindows (srcWin); addToSourceWindows (disassemWin); break; default: break; } } }}/* ** tuiSetLayout() ** 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 regsDisplayType. */TuiStatustuiSetLayout (TuiLayoutType layoutType, TuiRegisterDisplayType regsDisplayType){ TuiStatus status = TUI_SUCCESS; if (layoutType != UNDEFINED_LAYOUT || regsDisplayType != TUI_UNDEFINED_REGS) { TuiLayoutType curLayout = currentLayout (), newLayout = UNDEFINED_LAYOUT; int regsPopulate = FALSE; CORE_ADDR addr = _extractDisplayStartAddr (); TuiWinInfoPtr newWinWithFocus = (TuiWinInfoPtr) NULL, winWithFocus = tuiWinWithFocus (); TuiLayoutDefPtr layoutDef = tuiLayoutDef (); if (layoutType == UNDEFINED_LAYOUT && regsDisplayType != TUI_UNDEFINED_REGS) { if (curLayout == SRC_DISASSEM_COMMAND) newLayout = DISASSEM_DATA_COMMAND; else if (curLayout == SRC_COMMAND || curLayout == SRC_DATA_COMMAND) newLayout = SRC_DATA_COMMAND; else if (curLayout == DISASSEM_COMMAND || curLayout == DISASSEM_DATA_COMMAND) newLayout = DISASSEM_DATA_COMMAND; } else newLayout = layoutType; regsPopulate = (newLayout == SRC_DATA_COMMAND || newLayout == DISASSEM_DATA_COMMAND || regsDisplayType != TUI_UNDEFINED_REGS); if (newLayout != curLayout || regsDisplayType != TUI_UNDEFINED_REGS) { if (newLayout != curLayout) { showLayout (newLayout); /* ** Now determine where focus should be */ if (winWithFocus != cmdWin) { switch (newLayout) { case SRC_COMMAND: tuiSetWinFocusTo (srcWin); layoutDef->displayMode = SRC_WIN; layoutDef->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 = tuiGetBeginAsmAddress (); tuiSetWinFocusTo (disassemWin); layoutDef->displayMode = DISASSEM_WIN; layoutDef->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 = tuiGetBeginAsmAddress (); if (winWithFocus == srcWin) tuiSetWinFocusTo (srcWin); else tuiSetWinFocusTo (disassemWin); layoutDef->split = TRUE; break; case SRC_DATA_COMMAND: if (winWithFocus != dataWin) tuiSetWinFocusTo (srcWin); else tuiSetWinFocusTo (dataWin); layoutDef->displayMode = SRC_WIN; layoutDef->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 = tuiGetBeginAsmAddress (); if (winWithFocus != dataWin) tuiSetWinFocusTo (disassemWin); else tuiSetWinFocusTo (dataWin); layoutDef->displayMode = DISASSEM_WIN; layoutDef->split = FALSE; break; default: break; } } if (newWinWithFocus != (TuiWinInfoPtr) NULL) tuiSetWinFocusTo (newWinWithFocus); /* ** Now update the window content */ if (!regsPopulate && (newLayout == SRC_DATA_COMMAND || newLayout == DISASSEM_DATA_COMMAND)) tuiDisplayAllData (); tuiUpdateSourceWindowsWithAddr (addr); } if (regsPopulate) { layoutDef->regsDisplayType = (regsDisplayType == TUI_UNDEFINED_REGS ? TUI_GENERAL_REGS : regsDisplayType); tuiShowRegisters (layoutDef->regsDisplayType); } } } else status = TUI_FAILURE; return status;}/* ** tuiAddWinToLayout(). ** 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. */voidtuiAddWinToLayout (TuiWinType type){ TuiLayoutType curLayout = currentLayout (); switch (type) { case SRC_WIN: if (curLayout != SRC_COMMAND && curLayout != SRC_DISASSEM_COMMAND && curLayout != SRC_DATA_COMMAND) { clearSourceWindowsDetail (); if (curLayout == DISASSEM_DATA_COMMAND) showLayout (SRC_DATA_COMMAND); else showLayout (SRC_COMMAND); } break; case DISASSEM_WIN: if (curLayout != DISASSEM_COMMAND && curLayout != SRC_DISASSEM_COMMAND && curLayout != DISASSEM_DATA_COMMAND) { clearSourceWindowsDetail (); if (curLayout == SRC_DATA_COMMAND) showLayout (DISASSEM_DATA_COMMAND); else showLayout (DISASSEM_COMMAND); } break; case DATA_WIN: if (curLayout != SRC_DATA_COMMAND && curLayout != DISASSEM_DATA_COMMAND) { if (curLayout == DISASSEM_COMMAND) showLayout (DISASSEM_DATA_COMMAND); else showLayout (SRC_DATA_COMMAND); } break; default: break; } return;} /* tuiAddWinToLayout *//* ** tuiDefaultWinHeight(). ** 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. */inttuiDefaultWinHeight (TuiWinType type, TuiLayoutType layout){ int h; if (winList[type] != (TuiWinInfoPtr) NULL) h = winList[type]->generic.height; else { switch (layout) { case SRC_COMMAND: case DISASSEM_COMMAND: if (m_winPtrIsNull (cmdWin)) h = termHeight () / 2; else h = termHeight () - cmdWin->generic.height; break; case SRC_DISASSEM_COMMAND: case SRC_DATA_COMMAND: case DISASSEM_DATA_COMMAND: if (m_winPtrIsNull (cmdWin)) h = termHeight () / 3; else h = (termHeight () - cmdWin->generic.height) / 2; break; default: h = 0; break; } } return h;} /* tuiDefaultWinHeight *//* ** tuiDefaultWinViewportHeight(). ** 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. */inttuiDefaultWinViewportHeight (TuiWinType type, TuiLayoutType layout){ int h; h = tuiDefaultWinHeight (type, layout); if (winList[type] == cmdWin) h -= 1; else h -= 2; return h;} /* tuiDefaultWinViewportHeight *//* ** _initialize_tuiLayout(). ** Function to initialize gdb commands, for tui window layout ** manipulation. */void_initialize_tuiLayout (void){ add_com ("layout", class_tui, _tuiLayout_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, _tuiToggleLayout_command, "Toggle between Source/Command and Disassembly/Command layouts.\n"); add_com ("ts", class_tui, _tuiToggleSplitLayout_command, "Toggle between Source/Command or Disassembly/Command and \n\Source/Disassembly/Command layouts.\n"); }}/*************************** STATIC LOCAL FUNCTIONS**************************//* ** _tuiSetLayoutTo() ** Function to set the layout to SRC, ASM, SPLIT, NEXT, PREV, DATA, REGS, ** $REGS, $GREGS, $FREGS, $SREGS. */TuiStatustui_set_layout (const char *layoutName){ TuiStatus status = TUI_SUCCESS; if (layoutName != (char *) NULL) { register int i; register char *bufPtr; TuiLayoutType newLayout = UNDEFINED_LAYOUT; TuiRegisterDisplayType dpyType = TUI_UNDEFINED_REGS; TuiLayoutType curLayout = currentLayout (); bufPtr = (char *) xstrdup (layoutName); for (i = 0; (i < strlen (layoutName)); i++) bufPtr[i] = toupper (bufPtr[i]); /* First check for ambiguous input */ if (strlen (bufPtr) <= 1 && (*bufPtr == 'S' || *bufPtr == '$')) { warning ("Ambiguous command input.\n"); status = TUI_FAILURE; } else { if (subset_compare (bufPtr, "SRC")) newLayout = SRC_COMMAND; else if (subset_compare (bufPtr, "ASM")) newLayout = DISASSEM_COMMAND; else if (subset_compare (bufPtr, "SPLIT")) newLayout = SRC_DISASSEM_COMMAND; else if (subset_compare (bufPtr, "REGS") || subset_compare (bufPtr, TUI_GENERAL_SPECIAL_REGS_NAME) || subset_compare (bufPtr, TUI_GENERAL_REGS_NAME) || subset_compare (bufPtr, TUI_FLOAT_REGS_NAME) || subset_compare (bufPtr, TUI_SPECIAL_REGS_NAME)) { if (curLayout == SRC_COMMAND || curLayout == SRC_DATA_COMMAND) newLayout = SRC_DATA_COMMAND; else newLayout = 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 (bufPtr, TUI_FLOAT_REGS_NAME)) { if (dataWin->detail.dataDisplayInfo.regsDisplayType != TUI_SFLOAT_REGS && dataWin->detail.dataDisplayInfo.regsDisplayType != TUI_DFLOAT_REGS) dpyType = TUI_SFLOAT_REGS; else dpyType = dataWin->detail.dataDisplayInfo.regsDisplayType; } else if (subset_compare (bufPtr, TUI_GENERAL_SPECIAL_REGS_NAME)) dpyType = TUI_GENERAL_AND_SPECIAL_REGS; else if (subset_compare (bufPtr, TUI_GENERAL_REGS_NAME)) dpyType = TUI_GENERAL_REGS; else if (subset_compare (bufPtr, TUI_SPECIAL_REGS_NAME)) dpyType = TUI_SPECIAL_REGS; else if (dataWin) { if (dataWin->detail.dataDisplayInfo.regsDisplayType != TUI_UNDEFINED_REGS) dpyType = dataWin->detail.dataDisplayInfo.regsDisplayType; else dpyType = TUI_GENERAL_REGS; }/* end of potential ifdef *//* if ifdefed out code above, then assume that the user wishes to display the general purpose registers *//* dpyType = TUI_GENERAL_REGS; */ } else if (subset_compare (bufPtr, "NEXT")) newLayout = _nextLayout (); else if (subset_compare (bufPtr, "PREV")) newLayout = _prevLayout (); else status = TUI_FAILURE; xfree (bufPtr); tuiSetLayout (newLayout, dpyType); } } else status = TUI_FAILURE; return status;}static CORE_ADDR_extractDisplayStartAddr (void){ TuiLayoutType curLayout = currentLayout (); CORE_ADDR addr; CORE_ADDR pc; struct symtab_and_line cursal = get_current_source_symtab_and_line (); switch (curLayout) { case SRC_COMMAND: case SRC_DATA_COMMAND: find_line_pc (cursal.symtab, srcWin->detail.sourceInfo.startLineOrAddr.lineNo, &pc); addr = pc; break; case DISASSEM_COMMAND: case SRC_DISASSEM_COMMAND: case DISASSEM_DATA_COMMAND: addr = disassemWin->detail.sourceInfo.startLineOrAddr.addr; break; default: addr = 0; break; } return addr;} /* _extractDisplayStartAddr */static void_tuiHandleXDBLayout (TuiLayoutDefPtr layoutDef){ if (layoutDef->split) { tuiSetLayout (SRC_DISASSEM_COMMAND, TUI_UNDEFINED_REGS); tuiSetWinFocusTo (winList[layoutDef->displayMode]); } else {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -