home *** CD-ROM | disk | FTP | other *** search
- // $Id: windows.C,v 1.85 1998/11/12 14:07:43 zeller Exp $ -*- C++ -*-
- // DDD window management
-
- // Copyright (C) 1996-1998 Technische Universitaet Braunschweig, Germany.
- // Written by Andreas Zeller <zeller@ips.cs.tu-bs.de>.
- //
- // This file is part of DDD.
- //
- // DDD 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.
- //
- // DDD 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 DDD -- see the file COPYING.
- // If not, write to the Free Software Foundation, Inc.,
- // 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- //
- // DDD is the data display debugger.
- // For details, see the DDD World-Wide-Web page,
- // `http://www.cs.tu-bs.de/softech/ddd/',
- // or send a mail to the DDD developers <ddd@ips.cs.tu-bs.de>.
-
- char windows_rcsid[] =
- "$Id: windows.C,v 1.85 1998/11/12 14:07:43 zeller Exp $";
-
- #ifdef __GNUG__
- #pragma implementation
- #endif
-
- #define LOG_GEOMETRY 0
- #define LOG_EVENTS 0
-
- #include "windows.h"
-
- #include "AppData.h"
- #include "BoxRegion.h"
- #include "DataDisp.h"
- #include "SourceView.h"
- #include "TimeOut.h"
- #include "assert.h"
- #include "cmdtty.h"
- #include "ddd.h"
- #include "editing.h"
- #include "exectty.h"
- #include "exit.h"
- #include "findParent.h"
- #include "frame.h"
- #include "wm.h"
- #include "MinMaxA.h"
- #include "XErrorB.h"
-
- #include <Xm/Xm.h>
- #include <Xm/DialogS.h>
- #include <Xm/PanedW.h>
- #include <Xm/MainW.h>
- #include <Xm/ScrollBar.h>
- #if XmVersion >= 1002
- #include <Xm/VendorS.h> // XmIsMotifWMRunning()
- #else
- #include <Xm/VendorE.h> // XmIsMotifWMRunning()
- #endif
- #include <X11/Xutil.h>
-
- #include "Sash.h" // XmIsSash()
- #include <Xm/Separator.h> // XmIsSeparator()
- #include <Xm/SeparatoG.h> // XmIsSeparatorGadget()
-
- // ANSI C++ doesn't like the XtIsRealized() macro
- #ifdef XtIsRealized
- #undef XtIsRealized
- #endif
-
- //-----------------------------------------------------------------------------
- // Window management
- //-----------------------------------------------------------------------------
-
- // Shells (only used if separate windows are used)
- Widget command_shell;
- Widget data_disp_shell;
- Widget source_view_shell;
-
- // Command tool
- Widget tool_shell;
- Widget tool_buttons_w;
-
- // Shell state stuff
- enum WindowState { PoppingUp, PoppedUp, PoppedDown,
- Iconic, Transient, UnknownShell };
-
- #if LOG_EVENTS
- static ostream& operator << (ostream& os, WindowState s)
- {
- switch (s)
- {
- case PoppingUp:
- return os << "PoppingUp";
- case PoppedUp:
- return os << "PoppedUp";
- case PoppedDown:
- return os << "PoppedDown";
- case Iconic:
- return os << "Iconic";
- case Transient:
- return os << "Transient";
- case UnknownShell:
- return os << "UnknownShell";
- }
-
- return os;
- }
- #endif
-
- static WindowState& state(Widget w)
- {
- static WindowState command_shell_state = PoppedDown;
- static WindowState data_disp_shell_state = PoppedDown;
- static WindowState source_view_shell_state = PoppedDown;
- static WindowState tool_shell_state = PoppedDown;
-
- if (w == 0)
- /* do nothing */;
- else if (w == command_shell)
- return command_shell_state;
- else if (w == data_disp_shell)
- return data_disp_shell_state;
- else if (w == source_view_shell)
- return source_view_shell_state;
- else if (w == tool_shell)
- return tool_shell_state;
-
- static WindowState dummy;
- dummy = UnknownShell;
- return dummy;
- }
-
- static bool popped_down(Widget w)
- {
- WindowState st = state(w);
- return st == PoppedDown || st == UnknownShell;
- }
-
- static void set_state(WindowState& var, WindowState state)
- {
- if (state == PoppingUp && var == PoppedUp)
- return;
- var = state;
- }
-
- static void set_state(Widget w, WindowState s)
- {
- WindowState& var = state(w);
- if (var != UnknownShell)
- {
- set_state(var, s);
- #if LOG_EVENTS
- clog << XtName(w) << " is " << state(w) << "\n";
- #endif
- }
- }
-
- // Place command tool in upper right edge of REF
- static void recenter_tool_shell(Widget ref = 0);
-
- // Place command tool in upper right edge of REF, with a distance of
- // TOP_OFFSET and RIGHT_OFFSET
- static void recenter_tool_shell(Widget ref, int top_offset, int right_offset);
-
- // Have command tool follow REF
- static void follow_tool_shell(Widget ref = 0);
-
- // Get current offset of command tool in TOP_OFFSET and RIGHT_OFFSET;
- // return true iff successful.
- static bool get_tool_offset(Widget ref, int& top_offset, int& right_offset);
-
- // Last offsets as actually used
- static int last_top_offset;
- static int last_right_offset;
- static bool offsets_initialized = false;
-
- // Last saved geometry of tool shell
- static string last_tool_shell_geometry = "+0+0";
-
- static void initialize_offsets()
- {
- if (!offsets_initialized)
- {
- last_top_offset = app_data.tool_top_offset;
- last_right_offset = app_data.tool_right_offset;
- offsets_initialized = true;
- }
- }
-
- // Return current tool shell position relative to root window
- static BoxPoint tool_shell_pos()
- {
- int root_x = 0;
- int root_y = 0;
-
- if (tool_shell != 0 && XtIsRealized(tool_shell) &&
- state(tool_shell) == PoppedUp)
- {
- XWindowAttributes attr;
- XGetWindowAttributes(XtDisplay(tool_shell), XtWindow(tool_shell),
- &attr);
- Window child;
- XTranslateCoordinates(XtDisplay(tool_shell), XtWindow(tool_shell),
- attr.root, 0, 0, &root_x, &root_y, &child);
- }
-
- return BoxPoint(root_x, root_y);
- }
-
- // Move tool shell to POS
- static void move_tool_shell(BoxPoint pos)
- {
- #if 0
- // Make sure we don't move the tool shell off the screen
- pos[X] = max(pos[X], 0);
- pos[Y] = max(pos[Y], 0);
- #endif
-
- if (tool_shell == 0)
- return;
-
- if (pos != tool_shell_pos())
- {
- ostrstream os;
- os << "+" << pos[X] << "+" << pos[Y];
- last_tool_shell_geometry = string(os);
-
- // Move tool shell to POS
- XtVaSetValues(tool_shell,
- XmNgeometry, last_tool_shell_geometry.chars(),
- XmNx, pos[X],
- XmNy, pos[Y],
- NULL);
- }
- }
-
- static void RecenterToolShellCB(XtPointer = 0, XtIntervalId *id = 0)
- {
- if (tool_shell == 0)
- return;
-
- static XtIntervalId recenter_tool_shell_timer = 0;
-
- if (id != 0)
- {
- assert(*id = recenter_tool_shell_timer);
- recenter_tool_shell_timer = 0;
- }
- else if (recenter_tool_shell_timer != 0)
- {
- XtRemoveTimeOut(recenter_tool_shell_timer);
- recenter_tool_shell_timer = 0;
- }
-
- bool have_visible_tool_shell = false;
-
- if (XtIsRealized(tool_buttons_w) && state(tool_shell) == PoppedUp)
- {
- XWindowAttributes attr;
- XGetWindowAttributes(XtDisplay(tool_buttons_w),
- XtWindow(tool_buttons_w), &attr);
- have_visible_tool_shell = (attr.map_state == IsViewable);
- }
-
- if (have_visible_tool_shell)
- {
- recenter_tool_shell();
- }
- else
- {
- // Try again in 200 ms
- recenter_tool_shell_timer =
- XtAppAddTimeOut(XtWidgetToApplicationContext(tool_shell),
- 200, RecenterToolShellCB, XtPointer(0));
- }
- }
-
- static void follow_tool_shell(Widget ref)
- {
- initialize_offsets();
-
- recenter_tool_shell(ref, last_top_offset, last_right_offset);
- get_tool_offset(ref, last_top_offset, last_right_offset);
- }
-
- static void FollowToolShellCB(XtPointer = 0, XtIntervalId *id = 0)
- {
- if (tool_shell == 0)
- return;
-
- static XtIntervalId follow_tool_shell_timer = 0;
-
- if (id != 0)
- {
- assert(*id = follow_tool_shell_timer);
- follow_tool_shell_timer = 0;
- }
- else if (follow_tool_shell_timer != 0)
- {
- XtRemoveTimeOut(follow_tool_shell_timer);
- follow_tool_shell_timer = 0;
- }
-
- bool have_visible_tool_shell = false;
-
- if (XtIsRealized(tool_buttons_w) && state(tool_shell) == PoppedUp)
- {
- XWindowAttributes attr;
- XGetWindowAttributes(XtDisplay(tool_buttons_w),
- XtWindow(tool_buttons_w), &attr);
- have_visible_tool_shell = (attr.map_state == IsViewable);
- }
-
- if (have_visible_tool_shell)
- {
- follow_tool_shell();
- }
- else
- {
- // Try again in 200 ms
- follow_tool_shell_timer =
- XtAppAddTimeOut(XtWidgetToApplicationContext(tool_shell),
- 200, FollowToolShellCB, XtPointer(0));
- }
- }
-
- bool started_iconified(Widget w)
- {
- Widget toplevel = w;
- while (XtParent(toplevel))
- toplevel = XtParent(toplevel);
-
- assert(XtIsTopLevelShell(toplevel));
-
- // Well isn't it iconic - don't you think?
- Boolean iconic;
- XtVaGetValues(toplevel, XmNiconic, &iconic, NULL);
- return iconic;
- }
-
- // Popup initial shell
- void initial_popup_shell(Widget w)
- {
- if (w == 0)
- return;
-
- Boolean iconic = started_iconified(w);
- XtVaSetValues(w,
- XmNiconic, iconic,
- XmNinitialState, iconic ? IconicState : NormalState,
- NULL);
- WindowState state = iconic ? Iconic : PoppingUp;
-
- set_state(w, state);
-
- if (iconic || w == tool_shell)
- XtVaSetValues(w,
- XmNgeometry, "+0+0",
- XmNx, 0,
- XmNy, 0,
- NULL);
-
- if (w == tool_shell)
- {
- XtManageChild(tool_buttons_w);
- if (!XtIsRealized(tool_shell))
- XtRealizeWidget(tool_shell);
- if (!iconic)
- RecenterToolShellCB();
- }
-
- Widget toplevel = w;
- while (XtParent(toplevel))
- toplevel = XtParent(toplevel);
- assert(XtIsTopLevelShell(toplevel));
-
- if (w != toplevel && XtIsRealized(w))
- XtPopup(w, XtGrabNone);
- }
-
- void popup_shell(Widget w)
- {
- if (w == 0)
- return;
-
- if (w == tool_shell)
- {
- if (!XtIsRealized(tool_shell))
- {
- initial_popup_shell(tool_shell);
- RecenterToolShellCB();
- }
-
- XtManageChild(tool_buttons_w);
- }
-
- if (XtIsRealized(w))
- XtPopup(w, XtGrabNone);
-
- set_state(w, PoppingUp);
-
- // Uniconify window
- if (XtIsRealized(w))
- XMapWindow(XtDisplay(w), XtWindow(w));
- raise_shell(w);
- }
-
- void popdown_shell(Widget w)
- {
- if (w == 0)
- return;
-
- set_state(w, PoppedDown);
-
- if (w == tool_shell)
- XtUnmanageChild(tool_buttons_w);
-
- XtPopdown(w);
- }
-
- void iconify_shell(Widget w)
- {
- if (w == 0 || !XtIsRealized(w))
- return;
-
- set_state(w, Iconic);
-
- XIconifyWindow(XtDisplay(w), XtWindow(w),
- XScreenNumberOfScreen(XtScreen(w)));
- }
-
- void uniconify_shell(Widget w)
- {
- if (w == 0)
- return;
-
- if (state(w) == Iconic)
- {
- popup_shell(w);
- }
- }
-
- void popup_tty(Widget shell)
- {
- if (exec_tty_window())
- {
- XErrorBlocker blocker(XtDisplay(shell));
-
- // Uniconify window
- XMapWindow(XtDisplay(shell), exec_tty_window());
-
- // Place window on top
- XRaiseWindow(XtDisplay(shell), exec_tty_window());
- }
- }
-
- void iconify_tty(Widget shell)
- {
- if (exec_tty_window())
- {
- XIconifyWindow(XtDisplay(shell), exec_tty_window(),
- XScreenNumberOfScreen(XtScreen(shell)));
- }
- }
-
- // Shell visibility stuff
- static int& visibility(Widget w)
- {
- static int command_shell_visibility = VisibilityFullyObscured;
- static int data_disp_shell_visibility = VisibilityFullyObscured;
- static int source_view_shell_visibility = VisibilityFullyObscured;
- static int tool_shell_visibility = VisibilityFullyObscured;
-
- if (w == 0)
- /* do nothing */;
- else if (w == command_shell)
- return command_shell_visibility;
- else if (w == data_disp_shell)
- return data_disp_shell_visibility;
- else if (w == source_view_shell)
- return source_view_shell_visibility;
- else if (w == tool_shell)
- return tool_shell_visibility;
-
- static int dummy;
- dummy = VisibilityFullyObscured;
- return dummy;
- }
-
- static BoxRegion region(Display *display, Window win)
- {
- XWindowAttributes attr;
-
- Status ok;
- ok = XGetWindowAttributes(display, win, &attr);
- if (!ok)
- return BoxRegion();
-
- return BoxRegion(BoxPoint(attr.x, attr.y),
- BoxSize(attr.width, attr.height));
- }
-
- static bool obscures(Display *display, Window top, Window bottom)
- {
- if (top == 0 || bottom == 0)
- return false;
-
- return region(display, bottom) <= region(display, top);
- }
-
- static bool obscures(Widget top, Widget bottom)
- {
- if (top == 0 || bottom == 0 || !XtIsRealized(top) || !XtIsRealized(bottom))
- return false;
-
- if (visibility(bottom) == VisibilityUnobscured)
- return false;
-
- return obscures(XtDisplay(top), XtWindow(top), XtWindow(bottom));
- }
-
- // Raise WIN above SIBLING
- static void raise_above(Display *display, Window win, Window sibling)
- {
- if (win == 0 || sibling == 0)
- return;
-
- XErrorBlocker blocker(display);
-
- Window win_frame = frame(display, win);
- Window sibling_frame = frame(display, sibling);
-
- if (win_frame != 0 && sibling_frame != 0 && win_frame != sibling_frame)
- {
- // Raise WIN just above SIBLING
- XWindowChanges changes;
- changes.stack_mode = Above;
- changes.sibling = sibling_frame;
-
- XConfigureWindow(display, win_frame,
- CWSibling | CWStackMode, &changes);
- }
- else
- {
- // Raise WIN on top
- XRaiseWindow(display, win);
- }
- }
-
- inline void raise_tool_above(Window sibling)
- {
- if (tool_shell && XtIsRealized(tool_shell) &&
- state(tool_shell) == PoppedUp)
- raise_above(XtDisplay(tool_shell), XtWindow(tool_shell), sibling);
- }
-
- inline void raise_tool_above(Widget w)
- {
- if (w != 0 && XtIsRealized(w))
- raise_tool_above(XtWindow(w));
- }
-
- void StructureNotifyEH(Widget w, XtPointer, XEvent *event, Boolean *)
- {
- bool synthetic = (state(w) == Transient);
-
- #if LOG_EVENTS
- if (synthetic)
- clog << "Synthetic event: ";
- #endif
-
- switch (event->type)
- {
- case MapNotify:
- if (state(w) == UnknownShell)
- return;
-
- // Reflect state
- set_state(w, PoppedUp);
-
- #if 0
- if (!synthetic
- && (w == source_view_shell
- || (source_view_shell == 0 && w == command_shell))
- && !app_data.command_toolbar && app_data.source_window)
- {
- // Popup command tool again
- popup_shell(tool_shell);
- set_state(tool_shell, Transient);
- }
- #endif
-
- if (tool_shell != 0)
- {
- // Check position of command tool
- BoxPoint max_pos(WidthOfScreen(XtScreen(tool_shell)) - 1,
- HeightOfScreen(XtScreen(tool_shell)) - 1);
- if (tool_shell_pos() >= max_pos)
- RecenterToolShellCB();
- }
-
- if (!synthetic && app_data.group_iconify)
- {
- // Some shell was mapped - map all other shells as well
- if (state(command_shell) == Iconic)
- {
- popup_shell(command_shell);
- set_state(command_shell, Transient);
- }
- if (state(data_disp_shell) == Iconic)
- {
- popup_shell(data_disp_shell);
- set_state(data_disp_shell, Transient);
- }
- if (state(source_view_shell) == Iconic)
- {
- popup_shell(source_view_shell);
- set_state(source_view_shell, Transient);
- }
- popup_tty(command_shell);
- }
- break;
-
- case UnmapNotify:
- // Reflect state
- if (state(w) == UnknownShell)
- return;
-
- if (state(w) != Iconic && state(w) != PoppedDown)
- set_state(w, Iconic);
-
- if (!synthetic
- && (w == source_view_shell
- || (source_view_shell == 0 && w == command_shell)))
- {
- // Iconify command tool, too
- iconify_shell(tool_shell);
- set_state(tool_shell, Transient);
- }
-
- if (!synthetic && state(w) != PoppedDown && app_data.group_iconify)
- {
- // Iconify all other windows as well
- if (state(command_shell) == PoppedUp)
- {
- iconify_shell(command_shell);
- set_state(command_shell, Transient);
- }
- if (state(data_disp_shell) == PoppedUp)
- {
- iconify_shell(data_disp_shell);
- set_state(data_disp_shell, Transient);
- }
- if (state(source_view_shell) == PoppedUp)
- {
- iconify_shell(source_view_shell);
- set_state(source_view_shell, Transient);
- }
- iconify_tty(command_shell);
- }
- break;
-
- case VisibilityNotify:
- {
- visibility(w) = event->xvisibility.state;
-
- // Check whether command tool is obscured by some DDD shell
- if (app_data.auto_raise_tool
- && (obscures(command_shell, tool_shell)
- || obscures(data_disp_shell, tool_shell)
- || obscures(source_view_shell, tool_shell)))
- {
- // Command tool is obscured
- if (XmIsMotifWMRunning(tool_shell) && XmIsDialogShell(tool_shell))
- {
- // We have MWM and the command tool is a Dialog Shell.
- // Hence, let MWM keep the command tool on top.
- }
- else
- {
- // Raise command tool
- Widget shell =
- source_view_shell ? source_view_shell : command_shell;
- raise_tool_above(shell);
- }
- }
-
- #if 0 // Doesn't work yet - AZ
- // Check whether command tool is obscured by the exec window
- if (app_data.auto_raise_tool
- && obscures(XtDisplay(tool_shell), exec_tty_window(),
- XtWindow(tool_shell)))
- raise_tool_above(exec_tty_window());
- #endif
-
- break;
- }
-
- case ConfigureNotify:
- {
- if (app_data.sticky_tool
- && have_tool_window()
- && (state(tool_shell) == PoppedUp
- || state(tool_shell) == Transient))
- {
- // Let `sticky' command tool follow the source window
- initialize_offsets();
-
- if (w == tool_shell)
- {
- // Command tool has been moved
- #if LOG_EVENTS
- clog << "Tool has been moved to " << point(event) << "\n";
- #endif
-
- // Record offset
- get_tool_offset(0, last_top_offset, last_right_offset);
- }
-
- if (w == source_view_shell ||
- w == command_shell && source_view_shell == 0)
- {
- // Source shell has been moved -- let command tool follow
- #if LOG_EVENTS
- clog << "Shell has been moved to " << point(event) << "\n";
- #endif
-
- FollowToolShellCB();
- }
- }
- break;
- }
-
- default:
- // Any other event...
- break;
- }
- }
-
-
- //-----------------------------------------------------------------------------
- // Closing shells
- //-----------------------------------------------------------------------------
-
- // Return number of running input shells
- int running_shells()
- {
- int shells = 0;
-
- if (!popped_down(command_shell))
- shells++;
- if (!popped_down(source_view_shell))
- shells++;
- if (!popped_down(data_disp_shell))
- shells++;
-
- return shells;
- }
-
-
- // Generic close callback
- void DDDCloseCB(Widget w, XtPointer client_data, XtPointer call_data)
- {
- if (running_shells() == 1)
- {
- DDDExitCB(w, XtPointer(EXIT_SUCCESS), 0);
- return;
- }
-
- Widget shell = findTopLevelShellParent(w);
-
- if (shell == command_shell)
- gdbCloseCommandWindowCB(w, client_data, call_data);
- else if (shell == data_disp_shell)
- gdbCloseDataWindowCB(w, client_data, call_data);
- else if (shell == source_view_shell)
- gdbCloseSourceWindowCB(w, client_data, call_data);
- else if (shell == tool_shell)
- gdbCloseToolWindowCB(w, client_data, call_data);
- else
- popdown_shell(shell);
- }
-
-
-
- // Specific close and open callbacks
-
- // Debugger console
- void gdbCloseCommandWindowCB(Widget w, XtPointer, XtPointer)
- {
- if (!have_data_window() && !have_source_window() && !have_code_window())
- {
- DDDExitCB(w, XtPointer(EXIT_SUCCESS), 0);
- return;
- }
-
- if ((app_data.separate_source_window || !have_source_window())
- && (app_data.separate_data_window || !have_data_window()))
- {
- popdown_shell(command_shell);
- }
-
- unmanage_paned_child(XtParent(gdb_w));
-
- app_data.debugger_console = false;
-
- update_options();
- }
-
- void gdbOpenCommandWindowCB(Widget, XtPointer, XtPointer)
- {
- manage_paned_child(XtParent(gdb_w));
-
- if (app_data.separate_source_window)
- popup_shell(command_shell);
-
- app_data.debugger_console = true;
-
- update_options();
- }
-
- bool have_command_window()
- {
- return XtIsManaged(XtParent(gdb_w));
- }
-
-
- // Source window
- void gdbCloseSourceWindowCB(Widget w, XtPointer client_data,
- XtPointer call_data)
- {
- if (!have_command_window() && !have_data_window() && !have_code_window())
- {
- DDDExitCB(w, XtPointer(EXIT_SUCCESS), 0);
- return;
- }
-
- // Popdown shell
- popdown_shell(source_view_shell);
-
- // Unmanage source
- unmanage_paned_child(source_view->source_form());
-
- if (source_view_shell != 0)
- unmanage_paned_child(source_view->code_form());
-
- if (!XtIsManaged(source_view->code_form()))
- gdbCloseToolWindowCB(w, client_data, call_data);
-
- app_data.source_window = false;
-
- update_options();
- }
-
- void gdbCloseCodeWindowCB(Widget w, XtPointer client_data,
- XtPointer call_data)
- {
- if (!have_command_window() && !have_data_window() && !have_source_window())
- {
- DDDExitCB(w, XtPointer(EXIT_SUCCESS), 0);
- return;
- }
-
- // Unmanage code
- unmanage_paned_child(source_view->code_form());
-
- if (!XtIsManaged(source_view->source_form()))
- gdbCloseToolWindowCB(w, client_data, call_data);
-
- app_data.disassemble = false;
-
- update_options();
- }
-
- void gdbOpenSourceWindowCB(Widget w, XtPointer client_data,
- XtPointer call_data)
- {
- manage_paned_child(source_view->source_form());
- if (source_view_shell != 0 && app_data.disassemble)
- manage_paned_child(source_view->code_form());
- Widget arg_cmd_w = XtParent(source_arg->top());
- manage_paned_child(arg_cmd_w);
-
- popup_shell(source_view_shell);
-
- if (!app_data.command_toolbar)
- gdbOpenToolWindowCB(w, client_data, call_data);
-
- app_data.source_window = true;
-
- update_options();
- }
-
- void gdbOpenCodeWindowCB(Widget w, XtPointer client_data,
- XtPointer call_data)
- {
- manage_paned_child(source_view->code_form());
- Widget arg_cmd_w = XtParent(source_arg->top());
- manage_paned_child(arg_cmd_w);
-
- popup_shell(source_view_shell);
-
- if (!app_data.command_toolbar)
- gdbOpenToolWindowCB(w, client_data, call_data);
-
- app_data.disassemble = true;
-
- update_options();
- }
-
- bool have_source_window()
- {
- return XtIsManaged(source_view->source_form());
- }
-
- bool have_code_window()
- {
- return XtIsManaged(source_view->code_form());
- }
-
-
- // Data window
- void gdbCloseDataWindowCB(Widget w, XtPointer, XtPointer)
- {
- if (!have_source_window() && !have_command_window() && !have_code_window())
- {
- DDDExitCB(w, XtPointer(EXIT_SUCCESS), 0);
- return;
- }
-
- popdown_shell(data_disp_shell);
-
- Widget arg_cmd_w = XtParent(source_arg->top());
- if (data_disp->graph_cmd_w == arg_cmd_w)
- {
- // Don't close the common toolbar
- }
- else
- {
- unmanage_paned_child(data_disp->graph_cmd_w);
- }
-
- unmanage_paned_child(data_disp->graph_form());
-
- app_data.data_window = false;
-
- update_options();
- }
-
- void gdbOpenDataWindowCB(Widget, XtPointer, XtPointer)
- {
- manage_paned_child(data_disp->graph_cmd_w);
- manage_paned_child(data_disp->graph_form());
-
- popup_shell(data_disp_shell);
-
- app_data.data_window = true;
-
- update_options();
- }
-
- bool have_data_window()
- {
- return XtIsManaged(data_disp->graph_form());
- }
-
-
- // Execution window
- void gdbCloseExecWindowCB(Widget, XtPointer, XtPointer)
- {
- app_data.separate_exec_window = False;
-
- kill_exec_tty();
- update_options();
- }
-
- void gdbOpenExecWindowCB(Widget, XtPointer, XtPointer)
- {
- app_data.separate_exec_window = True;
-
- if (exec_tty_pid() == 0)
- startup_exec_tty();
- popup_tty(command_shell);
- update_options();
- }
-
- bool have_exec_window()
- {
- exec_tty_running();
- return exec_tty_pid() > 0;
- }
-
-
- // Tool window
- void gdbCloseToolWindowCB(Widget, XtPointer, XtPointer)
- {
- popdown_shell(tool_shell);
- update_options();
- }
-
- void gdbOpenToolWindowCB(Widget, XtPointer, XtPointer)
- {
- if (tool_shell == 0)
- return;
-
- XtVaSetValues(tool_shell,
- XmNgeometry, last_tool_shell_geometry.chars(),
- NULL);
-
- popup_shell(tool_shell);
-
- wait_until_mapped(tool_shell);
- RecenterToolShellCB();
-
- update_options();
- }
-
- bool have_tool_window()
- {
- return tool_shell != 0;
- }
-
-
- //-----------------------------------------------------------------------------
- // Toggling shells
- //-----------------------------------------------------------------------------
-
- void gdbToggleCommandWindowCB(Widget w, XtPointer client_data,
- XtPointer call_data)
- {
- XmToggleButtonCallbackStruct *info =
- (XmToggleButtonCallbackStruct *)call_data;
-
- if (info->set)
- gdbOpenCommandWindowCB(w, client_data, call_data);
- else
- gdbCloseCommandWindowCB(w, client_data, call_data);
- }
-
- void gdbToggleSourceWindowCB(Widget w, XtPointer client_data,
- XtPointer call_data)
- {
- XmToggleButtonCallbackStruct *info =
- (XmToggleButtonCallbackStruct *)call_data;
-
- if (info->set)
- gdbOpenSourceWindowCB(w, client_data, call_data);
- else
- gdbCloseSourceWindowCB(w, client_data, call_data);
- }
-
- void gdbToggleCodeWindowCB(Widget w, XtPointer client_data,
- XtPointer call_data)
- {
- XmToggleButtonCallbackStruct *info =
- (XmToggleButtonCallbackStruct *)call_data;
-
- if (info->set)
- gdbOpenCodeWindowCB(w, client_data, call_data);
- else
- gdbCloseCodeWindowCB(w, client_data, call_data);
-
- update_options();
- }
-
- void gdbToggleDataWindowCB(Widget w, XtPointer client_data,
- XtPointer call_data)
- {
- XmToggleButtonCallbackStruct *info =
- (XmToggleButtonCallbackStruct *)call_data;
-
- if (info->set)
- gdbOpenDataWindowCB(w, client_data, call_data);
- else
- gdbCloseDataWindowCB(w, client_data, call_data);
- }
-
- void gdbToggleExecWindowCB(Widget w, XtPointer client_data,
- XtPointer call_data)
- {
- XmToggleButtonCallbackStruct *info =
- (XmToggleButtonCallbackStruct *)call_data;
-
- if (info->set)
- gdbOpenExecWindowCB(w, client_data, call_data);
- else
- gdbCloseExecWindowCB(w, client_data, call_data);
- }
-
- void gdbToggleToolWindowCB(Widget w, XtPointer client_data,
- XtPointer call_data)
- {
- XmToggleButtonCallbackStruct *info =
- (XmToggleButtonCallbackStruct *)call_data;
-
- if (info->set)
- gdbOpenToolWindowCB(w, client_data, call_data);
- else
- gdbCloseToolWindowCB(w, client_data, call_data);
- }
-
-
- //-----------------------------------------------------------------------------
- // Command tool placement
- //-----------------------------------------------------------------------------
-
- // Place command tool in upper right edge of REF
- static void recenter_tool_shell(Widget ref)
- {
- recenter_tool_shell(ref,
- app_data.tool_top_offset, app_data.tool_right_offset);
- }
-
- // Place command tool in upper right edge of REF, with a distance of
- // TOP_OFFSET and RIGHT_OFFSET
- static void recenter_tool_shell(Widget ref, int top_offset, int right_offset)
- {
- if (ref == 0)
- ref = source_view->source();
- if (ref == 0 || !XtIsManaged(ref))
- ref = source_view->code();
-
- if (ref == 0 || tool_shell == 0 ||
- !XtIsRealized(ref) || !XtIsRealized(tool_shell) ||
- state(tool_shell) != PoppedUp)
- return;
-
- Window ref_window = XtWindow(ref);
- Window tool_window = XtWindow(tool_shell);
- Window tool_frame = frame(tool_shell);
-
- // Get location of upper right edge of REF
- XWindowAttributes ref_attributes;
- XGetWindowAttributes(XtDisplay(ref), ref_window, &ref_attributes);
-
- // Get tool shell attributes
- XWindowAttributes tool_attributes;
- XGetWindowAttributes(XtDisplay(tool_shell), tool_window, &tool_attributes);
-
- // Get tool frame attributes
- XWindowAttributes frame_attributes;
- XGetWindowAttributes(XtDisplay(tool_shell), tool_frame,
- &frame_attributes);
-
- // Determine new position relative to REF
- int x = ref_attributes.width - tool_attributes.width - right_offset;
- int y = top_offset;
-
- // Correct them relative to frame thickness
- int frame_x, frame_y;
- Window frame_child;
- XTranslateCoordinates(XtDisplay(ref), tool_window,
- tool_frame,
- tool_attributes.width, 0, &frame_x, &frame_y,
- &frame_child);
-
- x -= frame_attributes.width - frame_x + frame_attributes.border_width;
- y += frame_y + frame_attributes.border_width;
-
- // Get root coordinates
- int root_x, root_y;
- Window ref_child;
- XTranslateCoordinates(XtDisplay(ref), ref_window,
- ref_attributes.root,
- x, y, &root_x, &root_y,
- &ref_child);
-
- move_tool_shell(BoxPoint(root_x, root_y));
-
- last_top_offset = top_offset;
- last_right_offset = right_offset;
- offsets_initialized = true;
- }
-
-
- // Get current offset of command tool in TOP_OFFSET and RIGHT_OFFSET;
- // return true iff successful.
- static bool get_tool_offset(Widget ref, int& top_offset, int& right_offset)
- {
- if (ref == 0)
- ref = source_view->source();
- if (ref == 0 || !XtIsManaged(ref))
- ref = source_view->code();
-
- if (ref == 0 || tool_shell == 0 ||
- !XtIsRealized(ref) || !XtIsRealized(tool_shell) ||
- !XtIsManaged(tool_buttons_w) ||
- state(tool_shell) != PoppedUp)
- return false;
-
- Window ref_window = XtWindow(ref);
- Window tool_window = XtWindow(tool_shell);
- Window tool_frame = frame(tool_shell);
-
- // Get location of upper right edge of REF
- XWindowAttributes ref_attributes;
- XGetWindowAttributes(XtDisplay(ref), ref_window, &ref_attributes);
-
- // Get tool shell attributes
- XWindowAttributes tool_attributes;
- XGetWindowAttributes(XtDisplay(tool_shell), tool_window, &tool_attributes);
-
- // Get tool frame attributes
- XWindowAttributes frame_attributes;
- XGetWindowAttributes(XtDisplay(tool_shell), tool_frame,
- &frame_attributes);
-
- // If the tool frame is off the screen, don't store the offset
- if (frame_attributes.x < 0
- || frame_attributes.y < 0
- || frame_attributes.x + frame_attributes.width
- > WidthOfScreen(XtScreen(tool_shell))
- || frame_attributes.y + frame_attributes.height
- > HeightOfScreen(XtScreen(tool_shell)))
- {
- return false;
- }
-
- // Fetch root coordinates of upper right edge of command tool
- int tool_x, tool_y;
- Window tool_child;
- XTranslateCoordinates(XtDisplay(tool_shell), tool_window,
- tool_attributes.root,
- tool_attributes.width, 0,
- &tool_x, &tool_y, &tool_child);
-
- // Fetch root coordinates of upper right edge of ref
- int ref_x, ref_y;
- Window ref_child;
- XTranslateCoordinates(XtDisplay(ref), ref_window,
- ref_attributes.root,
- ref_attributes.width, 0,
- &ref_x, &ref_y, &ref_child);
-
- // Determine offsets
- int x = ref_x - tool_x;
- int y = tool_y - ref_y;
-
- // Correct them relative to frame thickness
- int frame_x, frame_y;
- Window frame_child;
- XTranslateCoordinates(XtDisplay(ref), tool_window,
- tool_frame,
- tool_attributes.width, 0, &frame_x, &frame_y,
- &frame_child);
-
- x -= frame_attributes.width - frame_x + frame_attributes.border_width;
- y -= frame_y + frame_attributes.border_width;
-
- top_offset = y;
- right_offset = x;
- return true;
- }
-
- // Store current offset of command tool in APP_DATA
- void get_tool_offset()
- {
- initialize_offsets();
-
- if (get_tool_offset(0, last_top_offset, last_right_offset))
- {
- app_data.tool_top_offset = last_top_offset;
- app_data.tool_right_offset = last_right_offset;
- }
- }
-
-
-
- // Manage paned child with minimum size
-
- inline bool is_internal_paned_child(Widget w)
- {
- return XmIsSash(w) || XmIsSeparator(w) || XmIsSeparatorGadget(w)
- || XtIsShell(w);
- }
-
- static MinMaxAssoc preferred_sizes;
-
- void save_preferred_paned_sizes(Widget paned)
- {
- // Fetch children
- WidgetList children;
- Cardinal numChildren = 0;
- XtVaGetValues(paned, XmNchildren, &children,
- XmNnumChildren, &numChildren, NULL);
-
- // Fetch preferred sizes
- Cardinal i;
- for (i = 0; i < numChildren; i++)
- {
- Widget child = children[i];
- if (is_internal_paned_child(child))
- continue;
-
- // Fetch preferred (= initial) height
- Dimension height = 0;
- XtVaGetValues(child, XmNheight, &height, NULL);
- {
- XtWidgetGeometry size;
- size.request_mode = CWHeight;
- XtQueryGeometry(child, NULL, &size);
- height = max(height, size.height);
- }
-
- #if LOG_GEOMETRY
- clog << XtName(paned) << ": child " << XtName(child)
- << " has preferred height " << height << '\n';
- #endif
-
- MinMax& preferred_size = preferred_sizes[child];
- preferred_size.min = preferred_size.max = height;
- }
- }
-
- const Dimension MIN_PANED_SIZE = 90;
-
- static void paned_changed(Widget /* paned */)
- {
- if (gdb_w != 0)
- {
- // Recenter the tool shell
- RecenterToolShellCB();
-
- // Make sure the current command line is visible
- end_of_lineAct(gdb_w, 0, 0, 0);
-
- // Redisplay source and code glyphs
- source_view->update_glyphs();
- }
- }
-
- void manage_paned_child(Widget w)
- {
- Widget paned = XtParent(w);
-
- if (paned == 0 || !XmIsPanedWindow(paned) || XtIsManaged(w))
- {
- XtManageChild(w);
- return;
- }
-
- #if LOG_GEOMETRY
- clog << XtName(paned) << ": managing child " << XtName(w) << "\n";
- if (preferred_sizes.has(w))
- {
- const MinMax& preferred_size = preferred_sizes[w];
- clog << XtName(paned) << ": child " << XtName(w)
- << " has preferred height " << preferred_size.max << '\n';
- }
- #endif
-
- // Fetch children
- WidgetList children;
- Cardinal numChildren = 0;
- XtVaGetValues(paned, XmNchildren, &children,
- XmNnumChildren, &numChildren, NULL);
-
-
- // Fetch current constraints
- MinMaxAssoc sizes;
- Cardinal i;
- for (i = 0; i < numChildren; i++)
- {
- Widget child = children[i];
- if (is_internal_paned_child(child))
- continue;
-
- MinMax& size = sizes[child];
- XtVaGetValues(children[i],
- XmNpaneMinimum, &size.min,
- XmNpaneMaximum, &size.max,
- NULL);
-
- #if LOG_GEOMETRY
- clog << XtName(paned) << ": child " << XtName(child)
- << " is managed (min = " << size.min
- << ", max = " << size.max << ")\n";
- #endif
- }
-
- assert(sizes.has(w));
- const MinMax& wsize = sizes[w];
- static const MinMax no_constraints;
-
- // Ensure that each child keeps at least the minimum size;
- // don't make it larger than its preferred maximum size.
- for (i = 0; i < numChildren; i++)
- {
- Widget child = children[i];
- if (!XtIsManaged(child) && child != w)
- continue;
- if (!sizes.has(child))
- continue;
-
- Arg args[10];
- Cardinal arg = 0;
-
- MinMax& size = sizes[child];
- Dimension current_max = size.max;
-
- if (child != w
- && wsize.min <= no_constraints.min
- && wsize.max >= no_constraints.max
- && preferred_sizes.has(child))
- {
- // W is resizable: give all other children at most their
- // preferred (= initial) height
- MinMax& preferred_size = preferred_sizes[child];
-
- if (preferred_size.max < size.max)
- {
- XtSetArg(args[arg], XmNpaneMaximum, preferred_size.max); arg++;
- current_max = preferred_size.max;
- }
-
- #if LOG_GEOMETRY
- clog << XtName(paned) << ": child " << XtName(child)
- << " has preferred height " << preferred_size.max << '\n';
- #endif
- }
-
- // Make each child (including W) at least MIN_PANED_SIZE high
- if (MIN_PANED_SIZE > size.min)
- {
- XtSetArg(args[arg], XmNpaneMinimum,
- min(MIN_PANED_SIZE, current_max)); arg++;
- }
-
- if (arg > 0)
- {
- XtSetValues(child, args, arg);
- size.changed = true;
- }
- }
-
- // Manage W
- XtManageChild(w);
-
- // Restore old constraints
- XtVaGetValues(paned, XmNchildren, &children,
- XmNnumChildren, &numChildren, NULL);
-
- for (i = 0; i < numChildren; i++)
- {
- Widget child = children[i];
- if (!sizes.has(child) || !XtIsManaged(child))
- continue;
-
- MinMax& size = sizes[child];
-
- if (size.changed)
- {
- XtVaSetValues(child,
- XmNpaneMinimum, size.min,
- XmNpaneMaximum, size.max,
- NULL);
- }
- }
-
- paned_changed(w);
- }
-
- // Return the number of resizable children of PANED
- static int resizable_children(Widget paned)
- {
- // Fetch children
- WidgetList children;
- Cardinal numChildren = 0;
- XtVaGetValues(paned, XmNchildren, &children,
- XmNnumChildren, &numChildren, NULL);
-
- // Fetch current constraints
- MinMaxAssoc sizes;
- Cardinal i;
- int n = 0;
- for (i = 0; i < numChildren; i++)
- {
- Widget child = children[i];
- if (is_internal_paned_child(child) || !XtIsManaged(child))
- continue;
-
- MinMax& size = sizes[child];
- XtVaGetValues(children[i],
- XmNpaneMinimum, &size.min,
- XmNpaneMaximum, &size.max,
- NULL);
-
- if (size.min < size.max)
- n++;
- }
-
- return n;
- }
-
-
- // Unmanage W, but be sure the command window doesn't grow.
- void unmanage_paned_child(Widget w)
- {
- Widget paned = XtParent(w);
- if (paned == 0 || !XmIsPanedWindow(paned) || !XtIsManaged(w))
- {
- XtUnmanageChild(w);
- return;
- }
-
- #if LOG_GEOMETRY
- clog << XtName(paned) << ": unmanaging child " << XtName(w) << "\n";
- #endif
-
- Widget command = XtParent(gdb_w);
-
- if (resizable_children(paned) <= 2)
- {
- // Only two resizable children left - the remaining one must
- // be resized to a maximum. Disable skipAdjust for a moment.
- Boolean skip_adjust = True;
- XtVaGetValues(command, XmNskipAdjust, &skip_adjust, NULL);
- XtVaSetValues(command, XmNskipAdjust, False, NULL);
-
- XtUnmanageChild(w);
-
- XtVaSetValues(command, XmNskipAdjust, skip_adjust, NULL);
- }
- else
- {
- // Resize the other child, but keep the command window intact
- Dimension height = 0;
- Dimension max = 1000;
- XtVaGetValues(command,
- XmNheight, &height,
- XmNpaneMaximum, &max,
- NULL);
- XtVaSetValues(command, XmNpaneMaximum, height, NULL);
-
- XtUnmanageChild(w);
-
- XtVaSetValues(command, XmNpaneMaximum, max, NULL);
- }
-
- paned_changed(w);
- }
-
-
- // Set the width of PANED to the maximum width of its children
-
- // Fetch the maximum width. Do this for each paned window.
- void get_paned_window_width(Widget paned, Dimension& max_width)
- {
- if (paned == 0 || !XtIsSubclass(paned, xmPanedWindowWidgetClass))
- return;
-
- WidgetList children = 0;
- Cardinal num_children = 0;
-
- XtVaGetValues(paned,
- XtNchildren, &children,
- XtNnumChildren, &num_children,
- NULL);
-
- for (Cardinal i = 0; i < num_children; i++)
- {
- Widget child = children[i];
- if (is_internal_paned_child(child) || !XtIsManaged(child))
- continue;
-
- // Fetch preferred width
- XtWidgetGeometry size;
- size.request_mode = CWWidth;
- XtQueryGeometry(child, NULL, &size);
-
- #if LOG_GEOMETRY
- clog << XtName(paned) << ": child " << XtName(child)
- << " wants width " << size.width << "\n";
- #endif
-
- max_width = max(size.width, max_width);
- }
- }
-
- // Set the found value.
- void set_paned_window_size(Widget paned, Dimension max_width)
- {
- if (paned == 0 || !XtIsSubclass(paned, xmPanedWindowWidgetClass))
- return;
-
- XtVaSetValues(paned, XmNwidth, max_width, NULL);
-
- WidgetList children = 0;
- Cardinal num_children = 0;
- Dimension spacing = 8;
- Dimension margin_width = 3;
- Dimension margin_height = 3;
-
- XtVaGetValues(paned,
- XtNchildren, &children,
- XtNnumChildren, &num_children,
- XmNspacing, &spacing,
- XmNmarginWidth, &margin_width,
- XmNmarginHeight, &margin_height,
- NULL);
-
- Dimension total_height = 0;
- int managed_children = 0;
- for (Cardinal i = 0; i < num_children; i++)
- {
- Widget child = children[i];
- if (is_internal_paned_child(child))
- continue;
-
- // Fetch preferred width
- Dimension width = 0;
- Dimension height = 0;
- XtVaGetValues(child, XmNwidth, &width, XmNheight, &height, NULL);
-
- {
- XtWidgetGeometry size;
- size.request_mode = CWWidth | CWHeight;
- XtQueryGeometry(child, NULL, &size);
-
- width = max(width, size.width);
- height = max(height, size.height);
- }
-
- #if LOG_GEOMETRY
- clog << XtName(paned) << ": child " << XtName(child)
- << " wants height " << height << "\n";
- #endif
-
- if (managed_children > 0)
- total_height += spacing;
-
- total_height += height;
- managed_children++;
- }
-
- XtVaSetValues(paned,
- XmNwidth, max_width + 2 * margin_width,
- XmNheight, total_height + 2 * margin_height,
- NULL);
- }
-
-
-
- //-----------------------------------------------------------------------------
- // Main Window stuff
- //-----------------------------------------------------------------------------
-
- // Set main window size
- void set_main_window_size(Widget main)
- {
- if (main == 0 || !XtIsSubclass(main, xmMainWindowWidgetClass))
- return;
-
- WidgetList children = 0;
- Cardinal num_children = 0;
-
- XtVaGetValues(main,
- XtNchildren, &children,
- XtNnumChildren, &num_children,
- NULL);
-
- Dimension max_width = 0;
- Dimension total_height = 0;
- for (Cardinal i = 0; i < num_children; i++)
- {
- Widget child = children[i];
- if (is_internal_paned_child(child))
- continue;
- if (XmIsScrollBar(child))
- continue;
-
- // Fetch sizes
- Dimension width = 0;
- Dimension height = 0;
- XtVaGetValues(child, XmNwidth, &width, XmNheight, &height, NULL);
-
- {
- XtWidgetGeometry size;
- size.request_mode = CWWidth | CWHeight;
- XtQueryGeometry(child, NULL, &size);
-
- width = max(width, size.width);
- height = max(height, size.height);
- }
-
- #if LOG_GEOMETRY
- clog << XtName(main) << ": child " << XtName(child) << " wants "
- << BoxSize(width, height) << "\n";
- #endif
-
- max_width = max(width, max_width);
- total_height += height;
- }
-
- XtVaSetValues(main, XmNwidth, max_width, XmNheight, total_height, NULL);
- }
-
-
- //-----------------------------------------------------------------------------
- // Scrolled Window stuff
- //-----------------------------------------------------------------------------
-
- // Promote child size to scrolled window
- void set_scrolled_window_size(Widget child, Widget target)
- {
- Widget scroll = XtParent(child);
-
- assert(XmIsScrolledWindow(scroll));
-
- Dimension scrollbar_width = 15; // Additional space for scrollbar
-
- Widget vertical_scroll_bar = 0;
- Dimension spacing = 4;
- Dimension margin_width = 2;
- Dimension margin_height = 2;
- XtVaGetValues(scroll,
- XmNverticalScrollBar, &vertical_scroll_bar,
- XmNspacing, &spacing,
- XmNmarginWidth, &margin_width,
- XmNmarginHeight, &margin_height,
- NULL);
-
- if (vertical_scroll_bar != 0)
- {
- XtWidgetGeometry size;
- size.request_mode = CWWidth;
- XtQueryGeometry(vertical_scroll_bar, NULL, &size);
- scrollbar_width = size.width;
- }
-
- // Give the ScrolledWindow the size specified for its child
- XtWidgetGeometry size;
- size.request_mode = CWWidth | CWHeight;
- XtQueryGeometry(child, NULL, &size);
-
- if (target == 0)
- target = scroll;
-
- #if LOG_GEOMETRY
- clog << XtName(target) << ": child " << XtName(child) << " wants "
- << BoxSize(size.width, size.height) << "\n";
- #endif
-
- Dimension border_width = 1;
- Dimension shadow_thickness = 2;
- XtVaGetValues(child,
- XmNborderWidth, &border_width,
- XmNshadowThickness, &shadow_thickness,
- NULL);
-
- Dimension width = size.width +
- border_width * 2 +
- // shadow_thickness * 2 +
- spacing +
- scrollbar_width +
- margin_width * 2;
-
- Dimension height = size.height +
- border_width * 2 +
- // shadow_thickness * 2 +
- margin_height * 2;
-
- XtVaSetValues(target, XmNwidth, width, XmNheight, height, NULL);
- }
-