/* TUI data manipulation routines. 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 "symtab.h" #include "tui/tui.h" #include "tui/tui-data.h" #include "tui/tui-wingeneral.h" #ifdef HAVE_NCURSES_H #include #else #ifdef HAVE_CURSES_H #include #endif #endif /**************************** ** GLOBAL DECLARATIONS ****************************/ TuiWinInfoPtr winList[MAX_MAJOR_WINDOWS]; /*************************** ** Private data ****************************/ static TuiLayoutType _currentLayout = UNDEFINED_LAYOUT; static int _termHeight, _termWidth; static TuiGenWinInfo _locator; static TuiGenWinInfo _execInfo[2]; static TuiWinInfoPtr _srcWinList[2]; static TuiList _sourceWindows = {(OpaqueList) _srcWinList, 0}; static int _defaultTabLen = DEFAULT_TAB_LEN; static TuiWinInfoPtr _winWithFocus = (TuiWinInfoPtr) NULL; static TuiLayoutDef _layoutDef = {SRC_WIN, /* displayMode */ FALSE, /* split */ TUI_UNDEFINED_REGS, /* regsDisplayType */ TUI_SFLOAT_REGS}; /* floatRegsDisplayType */ static int _winResized = FALSE; /********************************* ** Static function forward decls **********************************/ static void freeContent (TuiWinContent, int, TuiWinType); static void freeContentElements (TuiWinContent, int, TuiWinType); /********************************* ** PUBLIC FUNCTIONS **********************************/ /****************************************** ** ACCESSORS & MUTATORS FOR PRIVATE DATA ******************************************/ /* ** tuiWinResized(). ** Answer a whether the terminal window has been resized or not */ int tuiWinResized (void) { return _winResized; } /* tuiWinResized */ /* ** tuiSetWinResized(). ** Set a whether the terminal window has been resized or not */ void tuiSetWinResizedTo (int resized) { _winResized = resized; return; } /* tuiSetWinResizedTo */ /* ** tuiLayoutDef(). ** Answer a pointer to the current layout definition */ TuiLayoutDefPtr tuiLayoutDef (void) { return &_layoutDef; } /* tuiLayoutDef */ /* ** tuiWinWithFocus(). ** Answer the window with the logical focus */ TuiWinInfoPtr tuiWinWithFocus (void) { return _winWithFocus; } /* tuiWinWithFocus */ /* ** tuiSetWinWithFocus(). ** Set the window that has the logical focus */ void tuiSetWinWithFocus (TuiWinInfoPtr winInfo) { _winWithFocus = winInfo; return; } /* tuiSetWinWithFocus */ /* ** tuiDefaultTabLen(). ** Answer the length in chars, of tabs */ int tuiDefaultTabLen (void) { return _defaultTabLen; } /* tuiDefaultTabLen */ /* ** tuiSetDefaultTabLen(). ** Set the length in chars, of tabs */ void tuiSetDefaultTabLen (int len) { _defaultTabLen = len; return; } /* tuiSetDefaultTabLen */ /* ** currentSourceWin() ** Accessor for the current source window. Usually there is only ** one source window (either source or disassembly), but both can ** be displayed at the same time. */ TuiListPtr sourceWindows (void) { return &_sourceWindows; } /* currentSourceWindows */ /* ** clearSourceWindows() ** Clear the list of source windows. Usually there is only one ** source window (either source or disassembly), but both can be ** displayed at the same time. */ void clearSourceWindows (void) { _sourceWindows.list[0] = (Opaque) NULL; _sourceWindows.list[1] = (Opaque) NULL; _sourceWindows.count = 0; return; } /* currentSourceWindows */ /* ** clearSourceWindowsDetail() ** Clear the pertinant detail in the source windows. */ void clearSourceWindowsDetail (void) { int i; for (i = 0; i < (sourceWindows ())->count; i++) clearWinDetail ((TuiWinInfoPtr) (sourceWindows ())->list[i]); return; } /* currentSourceWindows */ /* ** addSourceWindowToList(). ** Add a window to the list of source windows. Usually there is ** only one source window (either source or disassembly), but ** both can be displayed at the same time. */ void addToSourceWindows (TuiWinInfoPtr winInfo) { if (_sourceWindows.count < 2) _sourceWindows.list[_sourceWindows.count++] = (Opaque) winInfo; return; } /* addToSourceWindows */ /* ** clearWinDetail() ** Clear the pertinant detail in the windows. */ void clearWinDetail (TuiWinInfoPtr winInfo) { if (m_winPtrNotNull (winInfo)) { switch (winInfo->generic.type) { case SRC_WIN: case DISASSEM_WIN: winInfo->detail.sourceInfo.startLineOrAddr.addr = 0; winInfo->detail.sourceInfo.horizontalOffset = 0; break; case CMD_WIN: winInfo->detail.commandInfo.curLine = winInfo->detail.commandInfo.curch = 0; break; case DATA_WIN: winInfo->detail.dataDisplayInfo.dataContent = (TuiWinContent) NULL; winInfo->detail.dataDisplayInfo.dataContentCount = 0; winInfo->detail.dataDisplayInfo.regsContent = (TuiWinContent) NULL; winInfo->detail.dataDisplayInfo.regsContentCount = 0; winInfo->detail.dataDisplayInfo.regsDisplayType = TUI_UNDEFINED_REGS; winInfo->detail.dataDisplayInfo.regsColumnCount = 1; winInfo->detail.dataDisplayInfo.displayRegs = FALSE; break; default: break; } } return; } /* clearWinDetail */ /* ** sourceExecInfoPtr(). ** Accessor for the source execution info ptr. */ TuiGenWinInfoPtr sourceExecInfoWinPtr (void) { return &_execInfo[0]; } /* sourceExecInfoWinPtr */ /* ** disassemExecInfoPtr(). ** Accessor for the disassem execution info ptr. */ TuiGenWinInfoPtr disassemExecInfoWinPtr (void) { return &_execInfo[1]; } /* disassemExecInfoWinPtr */ /* ** locatorWinInfoPtr(). ** Accessor for the locator win info. Answers a pointer to the ** static locator win info struct. */ TuiGenWinInfoPtr locatorWinInfoPtr (void) { return &_locator; } /* locatorWinInfoPtr */ /* ** termHeight(). ** Accessor for the termHeight */ int termHeight (void) { return _termHeight; } /* termHeight */ /* ** setTermHeightTo(). ** Mutator for the term height */ void setTermHeightTo (int h) { _termHeight = h; return; } /* setTermHeightTo */ /* ** termWidth(). ** Accessor for the termWidth */ int termWidth (void) { return _termWidth; } /* termWidth */ /* ** setTermWidth(). ** Mutator for the termWidth */ void setTermWidthTo (int w) { _termWidth = w; return; } /* setTermWidthTo */ /* ** currentLayout(). ** Accessor for the current layout */ TuiLayoutType currentLayout (void) { return _currentLayout; } /* currentLayout */ /* ** setCurrentLayoutTo(). ** Mutator for the current layout */ void setCurrentLayoutTo (TuiLayoutType newLayout) { _currentLayout = newLayout; return; } /* setCurrentLayoutTo */ /* ** setGenWinOrigin(). ** Set the origin of the window */ void setGenWinOrigin (TuiGenWinInfoPtr winInfo, int x, int y) { winInfo->origin.x = x; winInfo->origin.y = y; return; } /* setGenWinOrigin */ /***************************** ** OTHER PUBLIC FUNCTIONS *****************************/ /* ** tuiNextWin(). ** Answer the next window in the list, cycling back to the top ** if necessary */ TuiWinInfoPtr tuiNextWin (TuiWinInfoPtr curWin) { TuiWinType type = curWin->generic.type; TuiWinInfoPtr nextWin = (TuiWinInfoPtr) NULL; if (curWin->generic.type == CMD_WIN) type = SRC_WIN; else type = curWin->generic.type + 1; while (type != curWin->generic.type && m_winPtrIsNull (nextWin)) { if (winList[type] && winList[type]->generic.isVisible) nextWin = winList[type]; else { if (type == CMD_WIN) type = SRC_WIN; else type++; } } return nextWin; } /* tuiNextWin */ /* ** tuiPrevWin(). ** Answer the prev window in the list, cycling back to the bottom ** if necessary */ TuiWinInfoPtr tuiPrevWin (TuiWinInfoPtr curWin) { TuiWinType type = curWin->generic.type; TuiWinInfoPtr prev = (TuiWinInfoPtr) NULL; if (curWin->generic.type == SRC_WIN) type = CMD_WIN; else type = curWin->generic.type - 1; while (type != curWin->generic.type && m_winPtrIsNull (prev)) { if (winList[type]->generic.isVisible) prev = winList[type]; else { if (type == SRC_WIN) type = CMD_WIN; else type--; } } return prev; } /* ** partialWinByName(). ** Answer the window represented by name */ TuiWinInfoPtr partialWinByName (char *name) { TuiWinInfoPtr winInfo = (TuiWinInfoPtr) NULL; if (name != (char *) NULL) { int i = 0; while (i < MAX_MAJOR_WINDOWS && m_winPtrIsNull (winInfo)) { if (winList[i] != 0) { char *curName = winName (&winList[i]->generic); if (strlen (name) <= strlen (curName) && strncmp (name, curName, strlen (name)) == 0) winInfo = winList[i]; } i++; } } return winInfo; } /* partialWinByName */ /* ** winName(). ** Answer the name of the window */ char * winName (TuiGenWinInfoPtr winInfo) { char *name = (char *) NULL; switch (winInfo->type) { case SRC_WIN: name = SRC_NAME; break; case CMD_WIN: name = CMD_NAME; break; case DISASSEM_WIN: name = DISASSEM_NAME; break; case DATA_WIN: name = DATA_NAME; break; default: name = ""; break; } return name; } /* winName */ /* ** initializeStaticData */ void initializeStaticData (void) { initGenericPart (sourceExecInfoWinPtr ()); initGenericPart (disassemExecInfoWinPtr ()); initGenericPart (locatorWinInfoPtr ()); return; } /* initializeStaticData */ /* ** allocGenericWinInfo(). */ TuiGenWinInfoPtr allocGenericWinInfo (void) { TuiGenWinInfoPtr win; if ((win = (TuiGenWinInfoPtr) xmalloc ( sizeof (TuiGenWinInfoPtr))) != (TuiGenWinInfoPtr) NULL) initGenericPart (win); return win; } /* allocGenericWinInfo */ /* ** initGenericPart(). */ void initGenericPart (TuiGenWinInfoPtr win) { win->width = win->height = win->origin.x = win->origin.y = win->viewportHeight = win->contentSize = win->lastVisibleLine = 0; win->handle = (WINDOW *) NULL; win->content = (OpaquePtr) NULL; win->contentInUse = win->isVisible = FALSE; win->title = 0; } /* ** initContentElement(). */ void initContentElement (TuiWinElementPtr element, TuiWinType type) { element->highlight = FALSE; switch (type) { case SRC_WIN: case DISASSEM_WIN: element->whichElement.source.line = (char *) NULL; element->whichElement.source.lineOrAddr.lineNo = 0; element->whichElement.source.isExecPoint = FALSE; element->whichElement.source.hasBreak = FALSE; break; case DATA_WIN: initGenericPart (&element->whichElement.dataWindow); element->whichElement.dataWindow.type = DATA_ITEM_WIN; ((TuiGenWinInfoPtr) & element->whichElement.dataWindow)->content = (OpaquePtr) allocContent (1, DATA_ITEM_WIN); ((TuiGenWinInfoPtr) & element->whichElement.dataWindow)->contentSize = 1; break; case CMD_WIN: element->whichElement.command.line = (char *) NULL; break; case DATA_ITEM_WIN: element->whichElement.data.name = (char *) NULL; element->whichElement.data.type = TUI_REGISTER; element->whichElement.data.itemNo = UNDEFINED_ITEM; element->whichElement.data.value = (Opaque) NULL; element->whichElement.data.highlight = FALSE; break; case LOCATOR_WIN: element->whichElement.locator.fileName[0] = element->whichElement.locator.procName[0] = (char) 0; element->whichElement.locator.lineNo = 0; element->whichElement.locator.addr = 0; break; case EXEC_INFO_WIN: memset(element->whichElement.simpleString, ' ', sizeof(element->whichElement.simpleString)); break; default: break; } return; } /* initContentElement */ /* ** initWinInfo(). */ void initWinInfo (TuiWinInfoPtr winInfo) { initGenericPart (&winInfo->generic); winInfo->canHighlight = winInfo->isHighlighted = FALSE; switch (winInfo->generic.type) { case SRC_WIN: case DISASSEM_WIN: winInfo->detail.sourceInfo.executionInfo = (TuiGenWinInfoPtr) NULL; winInfo->detail.sourceInfo.hasLocator = FALSE; winInfo->detail.sourceInfo.horizontalOffset = 0; winInfo->detail.sourceInfo.startLineOrAddr.addr = 0; winInfo->detail.sourceInfo.filename = 0; break; case DATA_WIN: winInfo->detail.dataDisplayInfo.dataContent = (TuiWinContent) NULL; winInfo->detail.dataDisplayInfo.dataContentCount = 0; winInfo->detail.dataDisplayInfo.regsContent = (TuiWinContent) NULL; winInfo->detail.dataDisplayInfo.regsContentCount = 0; winInfo->detail.dataDisplayInfo.regsDisplayType = TUI_UNDEFINED_REGS; winInfo->detail.dataDisplayInfo.regsColumnCount = 1; winInfo->detail.dataDisplayInfo.displayRegs = FALSE; break; case CMD_WIN: winInfo->detail.commandInfo.curLine = 0; winInfo->detail.commandInfo.curch = 0; break; default: winInfo->detail.opaque = (Opaque) NULL; break; } return; } /* initWinInfo */ /* ** allocWinInfo(). */ TuiWinInfoPtr allocWinInfo (TuiWinType type) { TuiWinInfoPtr winInfo = (TuiWinInfoPtr) NULL; winInfo = (TuiWinInfoPtr) xmalloc (sizeof (TuiWinInfo)); if (m_winPtrNotNull (winInfo)) { winInfo->generic.type = type; initWinInfo (winInfo); } return winInfo; } /* allocWinInfo */ /* ** allocContent(). ** Allocates the content and elements in a block. */ TuiWinContent allocContent (int numElements, TuiWinType type) { TuiWinContent content = (TuiWinContent) NULL; char *elementBlockPtr = (char *) NULL; int i; if ((content = (TuiWinContent) xmalloc (sizeof (TuiWinElementPtr) * numElements)) != (TuiWinContent) NULL) { /* ** All windows, except the data window, can allocate the elements ** in a chunk. The data window cannot because items can be ** added/removed from the data display by the user at any time. */ if (type != DATA_WIN) { if ((elementBlockPtr = (char *) xmalloc (sizeof (TuiWinElement) * numElements)) != (char *) NULL) { for (i = 0; i < numElements; i++) { content[i] = (TuiWinElementPtr) elementBlockPtr; initContentElement (content[i], type); elementBlockPtr += sizeof (TuiWinElement); } } else { tuiFree ((char *) content); content = (TuiWinContent) NULL; } } } return content; } /* allocContent */ /* ** addContentElements(). ** Adds the input number of elements to the windows's content. If ** no content has been allocated yet, allocContent() is called to ** do this. The index of the first element added is returned, ** unless there is a memory allocation error, in which case, (-1) ** is returned. */ int addContentElements (TuiGenWinInfoPtr winInfo, int numElements) { TuiWinElementPtr elementPtr; int i, indexStart; if (winInfo->content == (OpaquePtr) NULL) { winInfo->content = (OpaquePtr) allocContent (numElements, winInfo->type); indexStart = 0; } else indexStart = winInfo->contentSize; if (winInfo->content != (OpaquePtr) NULL) { for (i = indexStart; (i < numElements + indexStart); i++) { if ((elementPtr = (TuiWinElementPtr) xmalloc (sizeof (TuiWinElement))) != (TuiWinElementPtr) NULL) { winInfo->content[i] = (Opaque) elementPtr; initContentElement (elementPtr, winInfo->type); winInfo->contentSize++; } else /* things must be really hosed now! We ran out of memory!? */ return (-1); } } return indexStart; } /* addContentElements */ /* Delete all curses windows associated with winInfo, leaving everything else intact. */ void tuiDelWindow (TuiWinInfoPtr winInfo) { TuiGenWinInfoPtr genericWin; switch (winInfo->generic.type) { case SRC_WIN: case DISASSEM_WIN: genericWin = locatorWinInfoPtr (); if (genericWin != (TuiGenWinInfoPtr) NULL) { tui_delete_win (genericWin->handle); genericWin->handle = (WINDOW *) NULL; genericWin->isVisible = FALSE; } if (winInfo->detail.sourceInfo.filename) { xfree (winInfo->detail.sourceInfo.filename); winInfo->detail.sourceInfo.filename = 0; } genericWin = winInfo->detail.sourceInfo.executionInfo; if (genericWin != (TuiGenWinInfoPtr) NULL) { tui_delete_win (genericWin->handle); genericWin->handle = (WINDOW *) NULL; genericWin->isVisible = FALSE; } break; case DATA_WIN: if (winInfo->generic.content != (OpaquePtr) NULL) { tuiDelDataWindows (winInfo->detail.dataDisplayInfo.regsContent, winInfo->detail.dataDisplayInfo.regsContentCount); tuiDelDataWindows (winInfo->detail.dataDisplayInfo.dataContent, winInfo->detail.dataDisplayInfo.dataContentCount); } break; default: break; } if (winInfo->generic.handle != (WINDOW *) NULL) { tui_delete_win (winInfo->generic.handle); winInfo->generic.handle = (WINDOW *) NULL; winInfo->generic.isVisible = FALSE; } } /* ** freeWindow(). */ void freeWindow (TuiWinInfoPtr winInfo) { TuiGenWinInfoPtr genericWin; switch (winInfo->generic.type) { case SRC_WIN: case DISASSEM_WIN: genericWin = locatorWinInfoPtr (); if (genericWin != (TuiGenWinInfoPtr) NULL) { tui_delete_win (genericWin->handle); genericWin->handle = (WINDOW *) NULL; } freeWinContent (genericWin); if (winInfo->detail.sourceInfo.filename) { xfree (winInfo->detail.sourceInfo.filename); winInfo->detail.sourceInfo.filename = 0; } genericWin = winInfo->detail.sourceInfo.executionInfo; if (genericWin != (TuiGenWinInfoPtr) NULL) { tui_delete_win (genericWin->handle); genericWin->handle = (WINDOW *) NULL; freeWinContent (genericWin); } break; case DATA_WIN: if (winInfo->generic.content != (OpaquePtr) NULL) { freeDataContent ( winInfo->detail.dataDisplayInfo.regsContent, winInfo->detail.dataDisplayInfo.regsContentCount); winInfo->detail.dataDisplayInfo.regsContent = (TuiWinContent) NULL; winInfo->detail.dataDisplayInfo.regsContentCount = 0; freeDataContent ( winInfo->detail.dataDisplayInfo.dataContent, winInfo->detail.dataDisplayInfo.dataContentCount); winInfo->detail.dataDisplayInfo.dataContent = (TuiWinContent) NULL; winInfo->detail.dataDisplayInfo.dataContentCount = 0; winInfo->detail.dataDisplayInfo.regsDisplayType = TUI_UNDEFINED_REGS; winInfo->detail.dataDisplayInfo.regsColumnCount = 1; winInfo->detail.dataDisplayInfo.displayRegs = FALSE; winInfo->generic.content = (OpaquePtr) NULL; winInfo->generic.contentSize = 0; } break; default: break; } if (winInfo->generic.handle != (WINDOW *) NULL) { tui_delete_win (winInfo->generic.handle); winInfo->generic.handle = (WINDOW *) NULL; freeWinContent (&winInfo->generic); } if (winInfo->generic.title) xfree (winInfo->generic.title); xfree (winInfo); } /* ** freeAllSourceWinsContent(). */ void freeAllSourceWinsContent (void) { int i; for (i = 0; i < (sourceWindows ())->count; i++) { TuiWinInfoPtr winInfo = (TuiWinInfoPtr) (sourceWindows ())->list[i]; if (m_winPtrNotNull (winInfo)) { freeWinContent (&(winInfo->generic)); freeWinContent (winInfo->detail.sourceInfo.executionInfo); } } return; } /* freeAllSourceWinsContent */ /* ** freeWinContent(). */ void freeWinContent (TuiGenWinInfoPtr winInfo) { if (winInfo->content != (OpaquePtr) NULL) { freeContent ((TuiWinContent) winInfo->content, winInfo->contentSize, winInfo->type); winInfo->content = (OpaquePtr) NULL; } winInfo->contentSize = 0; return; } /* freeWinContent */ void tuiDelDataWindows (TuiWinContent content, int contentSize) { int i; /* ** Remember that data window content elements are of type TuiGenWinInfoPtr, ** each of which whose single element is a data element. */ for (i = 0; i < contentSize; i++) { TuiGenWinInfoPtr genericWin = &content[i]->whichElement.dataWindow; if (genericWin != (TuiGenWinInfoPtr) NULL) { tui_delete_win (genericWin->handle); genericWin->handle = (WINDOW *) NULL; genericWin->isVisible = FALSE; } } return; } /* tuiDelDataWindows */ void freeDataContent (TuiWinContent content, int contentSize) { int i; /* ** Remember that data window content elements are of type TuiGenWinInfoPtr, ** each of which whose single element is a data element. */ for (i = 0; i < contentSize; i++) { TuiGenWinInfoPtr genericWin = &content[i]->whichElement.dataWindow; if (genericWin != (TuiGenWinInfoPtr) NULL) { tui_delete_win (genericWin->handle); genericWin->handle = (WINDOW *) NULL; freeWinContent (genericWin); } } freeContent (content, contentSize, DATA_WIN); return; } /* freeDataContent */ /********************************** ** LOCAL STATIC FUNCTIONS ** **********************************/ /* ** freeContent(). */ static void freeContent (TuiWinContent content, int contentSize, TuiWinType winType) { if (content != (TuiWinContent) NULL) { freeContentElements (content, contentSize, winType); tuiFree ((char *) content); } return; } /* freeContent */ /* ** freeContentElements(). */ static void freeContentElements (TuiWinContent content, int contentSize, TuiWinType type) { if (content != (TuiWinContent) NULL) { int i; if (type == SRC_WIN || type == DISASSEM_WIN) { /* free whole source block */ if (content[0]->whichElement.source.line != (char *) NULL) tuiFree (content[0]->whichElement.source.line); } else { for (i = 0; i < contentSize; i++) { TuiWinElementPtr element; element = content[i]; if (element != (TuiWinElementPtr) NULL) { switch (type) { case DATA_WIN: tuiFree ((char *) element); break; case DATA_ITEM_WIN: /* ** Note that data elements are not allocated ** in a single block, but individually, as needed. */ if (element->whichElement.data.type != TUI_REGISTER) tuiFree ((char *) element->whichElement.data.name); tuiFree ((char *) element->whichElement.data.value); tuiFree ((char *) element); break; case CMD_WIN: tuiFree ((char *) element->whichElement.command.line); break; default: break; } } } } if (type != DATA_WIN && type != DATA_ITEM_WIN) tuiFree ((char *) content[0]); /* free the element block */ } return; } /* freeContentElements */