/* * @OPENGROUP_COPYRIGHT@ * COPYRIGHT NOTICE * Copyright (c) 1990, 1991, 1992, 1993 Open Software Foundation, Inc. * Copyright (c) 1996, 1997, 1998, 1999, 2000 The Open Group * ALL RIGHTS RESERVED (MOTIF). See the file named COPYRIGHT.MOTIF for * the full copyright text. * * This software is subject to an open license. It may only be * used on, with or for operating systems which are themselves open * source systems. You must contact The Open Group for a license * allowing distribution and sublicensing of this software on, with, * or for operating systems which are not Open Source programs. * * See http://www.opengroup.org/openmotif/license for full * details of the license agreement. Any use, reproduction, or * distribution of the program constitutes recipient's acceptance of * this agreement. * * EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS * PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY * WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY * OR FITNESS FOR A PARTICULAR PURPOSE * * EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT * NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE * EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. */ /* * HISTORY */ #ifdef REV_INFO #ifndef lint static char rcsid[] = "$XConsortium: MainW.c /main/20 1996/10/17 15:21:07 cde-osf $" #endif #endif /* (c) Copyright 1987, 1988, 1989, 1990, 1991, 1992 HEWLETT-PACKARD COMPANY */ #include "XmI.h" #include /* just access the position/dimension fields,*/ #include /* could live without that if needed */ #include #include #include #include "MessagesI.h" #include "RepTypeI.h" #include "GeoUtilsI.h" #define MWMessage1 _XmMMsgMainW_0000 #define MWMessage2 _XmMMsgMainW_0001 #define ExistManaged( wid) (wid && XtIsManaged( wid)) #define DEFAULT_SIZE 50 /******** Static Function Declarations ********/ static void ClassPartInitialize( WidgetClass wc) ; static void Initialize( Widget rw, Widget nw, ArgList args, Cardinal *num_args) ; static void DeleteChild( Widget w) ; static void InsertChild( Widget w) ; static void Layout( XmMainWindowWidget mw) ; static void Resize( Widget wid) ; static void GetSize( XmMainWindowWidget mw, Dimension *pwidth, Dimension *pheight) ; static XtGeometryResult GeometryManager( Widget w, XtWidgetGeometry *request, XtWidgetGeometry *reply) ; static void ChangeManaged( Widget wid) ; static Boolean SetValues( Widget cw, Widget rw, Widget nw, ArgList args, Cardinal *num_args) ; static void GetVertRects( Widget sw, XRectangle ** vrect, Cardinal * num_vrect); static void CheckKids( XmMainWindowWidget mw); /******** End Static Function Declarations ********/ /************************************************************************ * * * Main Window Resources * * * ************************************************************************/ static XtResource resources[] = { { XmNcommandWindow, XmCCommandWindow, XmRWidget, sizeof(Widget), XtOffsetOf(XmMainWindowRec, mwindow.CommandWindow), XmRImmediate, NULL }, { XmNcommandWindowLocation, XmCCommandWindowLocation, XmRCommandWindowLocation, sizeof(unsigned char), XtOffsetOf(XmMainWindowRec, mwindow.CommandLoc), XmRImmediate, (XtPointer) XmCOMMAND_ABOVE_WORKSPACE }, { XmNmenuBar, XmCMenuBar, XmRWidget, sizeof(Widget), XtOffsetOf(XmMainWindowRec, mwindow.MenuBar), XmRImmediate, NULL }, { XmNmessageWindow, XmCMessageWindow, XmRWidget, sizeof(Widget), XtOffsetOf(XmMainWindowRec, mwindow.Message), XmRImmediate, NULL }, { XmNmainWindowMarginWidth, XmCMainWindowMarginWidth, XmRHorizontalDimension, sizeof (Dimension), XtOffsetOf(XmMainWindowRec, mwindow.margin_width), XmRImmediate, (XtPointer) 0 }, { XmNmainWindowMarginHeight, XmCMainWindowMarginHeight, XmRVerticalDimension, sizeof (Dimension), XtOffsetOf(XmMainWindowRec, mwindow.margin_height), XmRImmediate, (XtPointer) 0 }, { XmNshowSeparator, XmCShowSeparator, XmRBoolean, sizeof(Boolean), XtOffsetOf(XmMainWindowRec, mwindow.ShowSep), XmRImmediate, (XtPointer) False } }; /**************** * * Resolution independent resources * ****************/ static XmSyntheticResource syn_resources[] = { { XmNmainWindowMarginWidth, sizeof (Dimension), XtOffsetOf(XmMainWindowRec, mwindow.margin_width), XmeFromHorizontalPixels, XmeToHorizontalPixels }, { XmNmainWindowMarginHeight, sizeof (Dimension), XtOffsetOf(XmMainWindowRec, mwindow.margin_height), XmeFromVerticalPixels, XmeToVerticalPixels }, }; /*******************************************/ /* Declaration of class extension records */ /*******************************************/ static XmScrolledWindowClassExtRec scrolled_windowClassExtRec = { NULL, NULLQUARK, XmScrolledWindowClassExtVersion, sizeof(XmScrolledWindowClassExtRec), NULL, /* inherit get_hor_rects */ GetVertRects, /* overide get_vert_rects */ }; /**************************************************************** * * Full class record constant * ****************************************************************/ externaldef(xmmainwindowclassrec) XmMainWindowClassRec xmMainWindowClassRec = { { /* core_class fields */ /* superclass */ (WidgetClass) &xmScrolledWindowClassRec, /* class_name */ "XmMainWindow", /* widget_size */ sizeof(XmMainWindowRec), /* class_initialize */ NULL, /* class_partinit */ ClassPartInitialize, /* class_inited */ False, /* initialize */ Initialize, /* Init hook */ NULL, /* realize */ XtInheritRealize, /* actions */ NULL, /* num_actions */ 0, /* resources */ resources, /* num_resources */ XtNumber(resources), /* xrm_class */ NULLQUARK, /* compress_motion */ True, /* compress_exposure */ XtExposeCompressSeries, /* compress_enterleave*/ True, /* visible_interest */ False, /* destroy */ NULL, /* resize */ Resize, /* expose */ XtInheritExpose, /* set_values */ SetValues, /* set values hook */ NULL, /* set values almost */ XtInheritSetValuesAlmost, /* get values hook */ NULL, /* accept_focus */ NULL, /* Version */ XtVersion, /* PRIVATE cb list */ NULL, /* tm_table */ XtInheritTranslations, /* query_geometry */ NULL, /* display_accelerator*/ NULL, /* extension */ NULL, }, { /* composite_class fields */ /* geometry_manager */ GeometryManager, /* change_managed */ ChangeManaged, /* insert_child */ InsertChild, /* delete_child */ DeleteChild, /* Extension */ NULL, },{ /* Constraint class Init */ NULL, 0, sizeof (XmScrolledWindowConstraintRec), NULL, NULL, NULL, NULL }, /* Manager Class */ { XtInheritTranslations, /* translations */ syn_resources, /* get resources */ XtNumber(syn_resources), /* num get_resources */ NULL, /* get_cont_resources */ 0, /* num_get_cont_resources */ XmInheritParentProcess, /* parent_process */ NULL, /* extension */ }, { /* Scrolled Window class */ (XtPointer) &scrolled_windowClassExtRec, /* auto drag extension */ }, { /* Main Window class - just the extension pointer */ /* extension */ (XtPointer) NULL } }; externaldef(xmmainwindowwidgetclass) WidgetClass xmMainWindowWidgetClass = (WidgetClass)&xmMainWindowClassRec; /************************************************************************ * * * ClassPartInitialize - Set up the fast subclassing. * * * ************************************************************************/ static void ClassPartInitialize( WidgetClass wc ) { _XmFastSubclassInit (wc, XmMAIN_WINDOW_BIT); } /************************************************************************ * * * Initialize * * * ************************************************************************/ /* ARGSUSED */ static void Initialize( Widget rw, Widget nw, ArgList args, Cardinal *num_args ) { XmMainWindowWidget new_w = (XmMainWindowWidget) nw ; int n; Arg loc_args[20]; /* First, undo our superclass defaulting to a real size in AUTOMATIC mode, because MainWindow can build a real size out of its children in AUTOMATIC */ if (new_w->swindow.ScrollPolicy == XmAUTOMATIC) { if ((rw->core.width == 0) && new_w->core.width) new_w->core.width = 0 ; if ((rw->core.height == 0) && new_w->core.height) new_w->core.height = 0 ; } if (!XmRepTypeValidValue(XmRID_COMMAND_WINDOW_LOCATION, new_w->mwindow.CommandLoc, nw)) new_w->mwindow.CommandLoc = XmCOMMAND_ABOVE_WORKSPACE; n = 0; XtSetArg (loc_args[n], XmNorientation, XmHORIZONTAL); n++; XtSetArg (loc_args[n], XmNscrolledWindowChildType, XmSEPARATOR); n++; new_w->mwindow.ManagingSep = True ; new_w->mwindow.Sep1 = (XmSeparatorGadget) XtCreateManagedWidget("Separator1", xmSeparatorGadgetClass, nw, loc_args, n); new_w->mwindow.Sep2 = (XmSeparatorGadget) XtCreateManagedWidget("Separator2", xmSeparatorGadgetClass, nw, loc_args, n); new_w->mwindow.Sep3 = (XmSeparatorGadget) XtCreateManagedWidget("Separator3", xmSeparatorGadgetClass, nw, loc_args, n); new_w->mwindow.ManagingSep = False ; /* override the SW setting here */ new_w->swindow.XOffset = new_w->mwindow.margin_width; new_w->swindow.YOffset = new_w->mwindow.margin_height; new_w->swindow.WidthPad = new_w->mwindow.margin_width; new_w->swindow.HeightPad = new_w->mwindow.margin_height; } /************************************************************************ * * * DeleteChild * * * ************************************************************************/ /* ARGSUSED */ static void DeleteChild( Widget child) { XmMainWindowWidget mw = (XmMainWindowWidget) XtParent(child); CompositeWidgetClass superclass = (CompositeWidgetClass) xmMainWindowClassRec.core_class.superclass ; XtWidgetProc delete_child; /* update our own internals first */ if (child == mw->mwindow.CommandWindow) mw->mwindow.CommandWindow = NULL; if (child == mw->mwindow.MenuBar) mw->mwindow.MenuBar = NULL; if (child == mw->mwindow.Message) mw->mwindow.Message = NULL; _XmProcessLock(); delete_child = superclass->composite_class.delete_child; _XmProcessUnlock(); (*delete_child)(child); } static void CheckKids( XmMainWindowWidget mw ) { /* do a sanity check */ if( mw->swindow.WorkWindow != NULL && mw->swindow.WorkWindow->core.being_destroyed ) { mw->swindow.WorkWindow = NULL; } if( mw->swindow.hScrollBar != NULL && mw->swindow.hScrollBar->core.being_destroyed ) { mw->swindow.hScrollBar = NULL; } if( mw->swindow.vScrollBar != NULL && mw->swindow.vScrollBar->core.being_destroyed ) { mw->swindow.vScrollBar = NULL; } if( mw->mwindow.CommandWindow != NULL && mw->mwindow.CommandWindow->core.being_destroyed ) { mw->mwindow.CommandWindow = NULL; } if( mw->mwindow.MenuBar != NULL && mw->mwindow.MenuBar->core.being_destroyed ) { mw->mwindow.MenuBar = NULL; } if( mw->mwindow.Message != NULL && mw->mwindow.Message->core.being_destroyed ) { mw->mwindow.Message = NULL; } } /************************************************************************ * * * InsertChild * * * ************************************************************************/ static void InsertChild( Widget w ) { CompositeWidgetClass superclass = (CompositeWidgetClass) xmMainWindowClassRec.core_class.superclass ; XmMainWindowWidget mw = (XmMainWindowWidget ) w->core.parent; XmScrolledWindowConstraint nc = GetSWConstraint(w); XtWidgetProc insert_child; if (!XtIsRectObj(w)) return; /* Try to guess the nature of the child_type . If we're lucky, fine, otherwise, something bad might happens: the scrolledwindow can take it as a workwindow and possibly reparents it to the clipwindow. In the absence of a set childType constraint resource set, there is not much we can do to avoid the problem */ /* Note: auto created Separator were already labelled in Initialize */ if (nc->child_type == (unsigned char) RESOURCE_DEFAULT) { XmMenuSystemTrait menuSTrait; if ((menuSTrait = (XmMenuSystemTrait) XmeTraitGet ((XtPointer) XtClass(w), XmQTmenuSystem)) != NULL) { if (menuSTrait->type(w) == XmMENU_BAR && !mw->mwindow.MenuBar) { /* If it's a menubar, and we don't have one yet, use it. */ nc->child_type = XmMENU_BAR ; } } else if (XmIsCommandBox(w)) { if (!mw->mwindow.CommandWindow) { /* If it's a command, and we don't have one, get it */ nc->child_type = XmCOMMAND_WINDOW ; } } else /* new in 2.0 */ if (XmIsMessageBox(w)) { if (!mw->mwindow.Message) { nc->child_type = XmMESSAGE_WINDOW ; } } } if (nc->child_type == XmMENU_BAR) { mw->mwindow.MenuBar = w; } else if (nc->child_type == XmCOMMAND_WINDOW) { mw->mwindow.CommandWindow = w; } else if (nc->child_type == XmMESSAGE_WINDOW) { mw->mwindow.Message = w; } /* call ScrolledWindow InsertChild directly, since it does nothing to the MainWindow known childType */ _XmProcessLock(); insert_child = superclass->composite_class.insert_child; _XmProcessUnlock(); (*insert_child)(w); } /************************************************************************ * * * Layout - Layout the main window. * * * * * ************************************************************************/ static void Layout( XmMainWindowWidget mw ) { Position mbx,mby, cwx,cwy, swy, mwx, mwy, sepy, sep2y = 0; Dimension mbwidth, mbheight, cwwidth= 0, cwheight; Dimension MyXpad, MyYpad, mwwidth, mwheight; Dimension bw = 0, sep2h, sep3h; XtWidgetGeometry desired, preferred; int tmp ; /* used for checking negative Dimension value */ CheckKids(mw); /**************** * * Query the kids - and we have definite preferences as to their sizes. * The Menubar gets top billing - we tell it it how wide it is going to be , * and let it have whatever height it wants. The command box gets to stay * it's current height, but has to go to the new width. The scrolled window * gets the leftovers. * ****************/ MyXpad = mw->mwindow.margin_width; MyYpad = mw->mwindow.margin_height; mw->swindow.XOffset = MyXpad; mw->swindow.YOffset = MyYpad; mw->swindow.HeightPad = mw->mwindow.margin_height; mw->swindow.WidthPad = mw->mwindow.margin_width; cwx = MyXpad; cwy = swy = MyYpad; mw->mwindow.ManagingSep = True; if (ExistManaged(mw->mwindow.MenuBar)) { bw = mw->mwindow.MenuBar->core.border_width; mbx = MyXpad; mby = MyYpad; tmp = mw->core.width - (2 * (MyXpad + bw)); if (tmp <= 0) mbwidth = 10; else mbwidth = tmp ; mbheight = mw->mwindow.MenuBar->core.height; desired.x = mbx; desired.y = mby; desired.border_width = bw; desired.width = mbwidth; desired.height = mbheight; desired.request_mode = (CWWidth); if (XtQueryGeometry(mw->mwindow.MenuBar, &desired, &preferred) != XtGeometryYes) { bw = preferred.border_width; mbheight = preferred.height; } XmeConfigureObject(mw->mwindow.MenuBar, mbx, mby, mbwidth, mbheight,bw); if (mw->mwindow.ShowSep) { XtManageChild((Widget) mw->mwindow.Sep1); XmeConfigureObject( (Widget) mw->mwindow.Sep1, 0, mby + mbheight + (2 * bw), mw->core.width, mw->mwindow.Sep1->rectangle.height, 0); cwy = swy = mw->mwindow.Sep1->rectangle.y + mw->mwindow.Sep1->rectangle.height ; } else { XtUnmanageChild((Widget) mw->mwindow.Sep1); cwy = swy = mby + mbheight + (2 * bw); } } else { XtUnmanageChild((Widget) mw->mwindow.Sep1); } if (ExistManaged(mw->mwindow.CommandWindow)) { bw = mw->mwindow.CommandWindow->core.border_width; tmp = mw->core.width - (2 * (MyXpad + bw)); if (tmp <= 0) cwwidth = 10; else cwwidth = tmp ; cwheight = mw->mwindow.CommandWindow->core.height; desired.x = cwx; desired.y = cwy; desired.border_width = bw; desired.width = cwwidth; desired.height = cwheight; desired.request_mode = (CWWidth); if (XtQueryGeometry(mw->mwindow.CommandWindow, &desired, &preferred) != XtGeometryYes) { bw = preferred.border_width; cwheight = preferred.height; } if ((cwheight + cwy + (2 * bw)) > (mw->core.height - MyYpad)) { tmp = mw->core.height - (2 * bw) - MyYpad - cwy; if (tmp <= 0) cwheight = 10 ; else cwheight = tmp; } if (mw->mwindow.ShowSep) sep2h = mw->mwindow.Sep2->rectangle.height; else sep2h = 0; sep2y = (cwy + cwheight) + 2 * bw; swy = sep2y + sep2h ; if (mw->mwindow.CommandLoc == XmCOMMAND_BELOW_WORKSPACE) { mby = swy; sep2y = cwy + (mw->core.height - swy - MyYpad); swy = cwy; mw->swindow.HeightPad = sep2h + cwheight + mw->mwindow.margin_height; if (mw->mwindow.ShowSep) cwy = sep2y + mw->mwindow.Sep2->rectangle.height; else cwy = sep2y; } } else { XtUnmanageChild((Widget) mw->mwindow.Sep2); sep2h = 0; cwheight = 0; } if (ExistManaged(mw->mwindow.Message)) { bw = mw->mwindow.Message->core.border_width; mwx = MyXpad; tmp = mw->core.width - (2 * (MyXpad + bw)); if (tmp <= 0) mwwidth = 10 ; else mwwidth = tmp ; mwheight = mw->mwindow.Message->core.height; desired.x = mwx; desired.y = swy; desired.border_width = bw; desired.width = mwwidth; desired.height = mwheight; desired.request_mode = (CWWidth); if (XtQueryGeometry(mw->mwindow.Message, &desired, &preferred) != XtGeometryYes) { bw = preferred.border_width; mwheight = preferred.height; } if (mw->mwindow.ShowSep) sep3h = mw->mwindow.Sep3->rectangle.height; else sep3h = 0; sepy = mw->core.height - mwheight - (2 * bw) - mw->mwindow.margin_height - sep3h; mwy = sepy + sep3h; if (mw->mwindow.CommandLoc == XmCOMMAND_BELOW_WORKSPACE) { mw->swindow.HeightPad = sep2h + cwheight + sep3h + mwheight + mw->mwindow.margin_height; sep2y -= (sep3h + mwheight); cwy -= (sep3h + mwheight); } else mw->swindow.HeightPad = sep3h + mwheight + mw->mwindow.margin_height; XmeConfigureObject(mw->mwindow.Message, mwx, mwy, mwwidth, mwheight, bw); if (mw->mwindow.ShowSep) { XtManageChild((Widget) mw->mwindow.Sep3); XmeConfigureObject( (Widget) mw->mwindow.Sep3, 0, sepy, mw->core.width, mw->mwindow.Sep3->rectangle.height, 0); } else XtUnmanageChild((Widget) mw->mwindow.Sep3); } else { XtUnmanageChild((Widget) mw->mwindow.Sep3); } if (ExistManaged(mw->mwindow.CommandWindow)) { XmeConfigureObject( mw->mwindow.CommandWindow, cwx, cwy, cwwidth, cwheight, bw); if (mw->mwindow.ShowSep) { XtManageChild((Widget) mw->mwindow.Sep2); XmeConfigureObject((Widget) mw->mwindow.Sep2, 0, sep2y, mw->core.width, mw->mwindow.Sep2->rectangle.height, 0); } else XtUnmanageChild((Widget) mw->mwindow.Sep2); } mw->swindow.YOffset = swy; mw->mwindow.ManagingSep = False; } /************************************************************************ * * * Relayout the main window. * * * ************************************************************************/ static void Resize( Widget wid ) { CompositeWidgetClass superclass = (CompositeWidgetClass) xmMainWindowClassRec.core_class.superclass ; XtWidgetProc resize; Layout((XmMainWindowWidget) wid); /* call our superclass layout now that MainWindow has updated some internal positional fields: offset, pads */ _XmProcessLock(); resize = superclass->core_class.resize; _XmProcessUnlock(); (*resize)(wid); } /************************************************************************ * * * GetSize - compute the size of the Main window to enclose all the * * visible widgets. * * * ************************************************************************/ static void GetSize( XmMainWindowWidget mw, Dimension *pwidth, Dimension *pheight) { Dimension newWidth,newHeight; XmScrollBarWidget hsb = mw->swindow.hScrollBar, vsb = mw->swindow.vScrollBar; Widget w; Dimension hsheight = 0, vmwidth = 0, ht = mw->manager.shadow_thickness * 2, hsbht = 0, vsbht = 0; Dimension width, MyXpad, MyYpad; XtWidgetGeometry preferred; MyXpad = mw->mwindow.margin_width * 2; MyYpad = mw->mwindow.margin_height * 2; /* what id to use for the sw frame */ if (mw->swindow.ScrollPolicy == XmAPPLICATION_DEFINED) w = mw->swindow.WorkWindow; else w = (Widget)mw->swindow.ClipWindow; /* note: first time through, all relevant values are 0, but we need to ** take account of the preferred size anyway */ if (ExistManaged((Widget) vsb) && ((0 == mw->core.width) || ((Dimension)vsb->core.x < mw->core.width))) /* needed */ { vsbht = 2 * vsb->primitive.highlight_thickness; vmwidth = vsb->core.width + mw->swindow.pad + (2 * vsb->primitive.highlight_thickness); } if (ExistManaged((Widget) hsb) && ((0 == mw->core.height) || ((Dimension)hsb->core.y < mw->core.height))) /* needed */ { hsbht = 2 * hsb->primitive.highlight_thickness; hsheight = hsb->core.height + mw->swindow.pad + (2 * hsb->primitive.highlight_thickness); } /**************** * * Use the work window as the basis for our height. If the mode is * constant, and we are not realized, use the areawidth and areaheight * variables instead of the clipwindow width and height, since they are a * match for the workspace until the swindow is realized. * ****************/ if (ExistManaged(w)) { if ((mw->swindow.ScrollPolicy == XmAUTOMATIC) && !XtIsRealized((Widget)mw)) { newWidth = mw->swindow.AreaWidth + (w->core.border_width * 2) + hsbht + vmwidth + ht + MyXpad; newHeight = mw->swindow.AreaHeight + (w->core.border_width * 2) + vsbht + hsheight + ht + MyYpad; } else { XtQueryGeometry(w, NULL, &preferred); newWidth = preferred.width + (w->core.border_width * 2) + hsbht + vmwidth + ht + MyXpad; newHeight = preferred.height + (w->core.border_width * 2) + vsbht + hsheight + ht + MyYpad; } } else { newWidth = MyXpad; newHeight = MyYpad; } /* Take the max width, add the height of the other kids */ if (ExistManaged(mw->mwindow.CommandWindow)) { XtQueryGeometry(mw->mwindow.CommandWindow, NULL, &preferred); width = preferred.width + MyXpad + (2 * mw->mwindow.CommandWindow->core.border_width); if (newWidth < width) newWidth = width; newHeight += preferred.height + (2 * mw->mwindow.CommandWindow->core.border_width); if (mw->mwindow.Sep2 && mw->mwindow.ShowSep) newHeight += mw->mwindow.Sep2->rectangle.height; } if (ExistManaged(mw->mwindow.MenuBar)) { XtQueryGeometry(mw->mwindow.MenuBar, NULL, &preferred); width = preferred.width + MyXpad + (2 * mw->mwindow.MenuBar->core.border_width); if (newWidth < width) newWidth = width; newHeight += preferred.height + (2 * mw->mwindow.MenuBar->core.border_width); if (mw->mwindow.Sep1 && mw->mwindow.ShowSep) newHeight += mw->mwindow.Sep1->rectangle.height; } if (ExistManaged(mw->mwindow.Message)) { XtQueryGeometry(mw->mwindow.Message, NULL, &preferred); width = preferred.width + MyXpad + (2 * mw->mwindow.Message->core.border_width); if (newWidth < width) newWidth = width; newHeight += preferred.height + (2 * mw->mwindow.Message->core.border_width); if (mw->mwindow.Sep3 && mw->mwindow.ShowSep) newHeight += mw->mwindow.Sep3->rectangle.height; } if (!*pwidth) *pwidth = newWidth ; if (!*pheight) *pheight = newHeight ; /* might still be null */ if (!*pwidth) *pwidth = DEFAULT_SIZE ; if (!*pheight) *pheight = DEFAULT_SIZE ; } /************************************************************************ * * * GeometryManager * * * ************************************************************************/ static XtGeometryResult GeometryManager( Widget w, XtWidgetGeometry *request, XtWidgetGeometry *reply ) { CompositeWidgetClass superclass = (CompositeWidgetClass) xmMainWindowClassRec.core_class.superclass ; XmMainWindowWidget mw = (XmMainWindowWidget ) w->core.parent; XtGeometryResult res; Dimension newWidth,newHeight, OldHeight; Dimension bw; XtWidgetGeometry parent_request ; XtWidgetGeometry desired, preferred; XtWidgetProc resize; CheckKids(mw); /**************** * * If it's not a mainwindow kid, let the scrolled window deal with it. * If it's from the workwindow, and the width changed, resize the menubar * and ask for a new height so my layout routine doesn't clip the workwindow. * ****************/ if (w != mw->mwindow.MenuBar && w != mw->mwindow.Message && w != mw->mwindow.CommandWindow && w != (Widget )mw->mwindow.Sep1 && w != (Widget) mw->mwindow.Sep2 && w != (Widget) mw->mwindow.Sep3) { /* this is the only case of geometry manager enveloping that I know of in Motif */ XtGeometryHandler geo_mgr; _XmProcessLock(); geo_mgr = superclass->composite_class.geometry_manager; _XmProcessUnlock(); res = (*geo_mgr)(w, request, reply); if (res == XtGeometryYes) { Widget mb = mw->mwindow.MenuBar; if ((w == mw->swindow.WorkWindow) && (request->request_mode & CWWidth) && mb && XtIsManaged(mb)) { desired.x = mb->core.x; desired.y = mb->core.y; desired.border_width = mb->core.border_width; desired.width = mw->core.width - (2 * mw->mwindow.margin_width); desired.height = mb->core.height; desired.request_mode = (CWWidth); XtQueryGeometry(mw->mwindow.MenuBar, &desired, &preferred); if (preferred.height != mb->core.height) { parent_request.request_mode = CWWidth | CWHeight; if (request->request_mode & XtCWQueryOnly) parent_request.request_mode |= XtCWQueryOnly; parent_request.width = mw->core.width ; parent_request.height = newHeight = mw->core.height - (mb->core.height - (2 * mb->core.border_width)) + preferred.height + (2 *preferred.border_width); if (XtMakeGeometryRequest((Widget) mw, &parent_request, NULL) == XtGeometryYes) { if (!(request->request_mode & XtCWQueryOnly)) XmeConfigureObject(mw->mwindow.MenuBar, mb->core.x, mb->core.y, preferred.width, preferred.height, preferred.border_width); else return XtGeometryYes ; } } } _XmProcessLock(); resize = XtCoreProc(mw, resize); _XmProcessUnlock(); (*resize)((Widget)mw) ; } return(res); } /** Disallow any X or Y changes for MainW children **/ if ((request -> request_mode & CWX || request -> request_mode & CWY)) return(XtGeometryNo); if(request->request_mode & CWBorderWidth) bw = request->border_width; else bw = w->core.border_width; if (request->request_mode & CWWidth) newWidth = request->width + 2 * (bw + mw->mwindow.margin_width); else newWidth = mw->core.width ; /* grow only in width */ if (newWidth <= mw->core.width) newWidth = mw->core.width; /**************** * * Margins are already included in the old width & height * ****************/ if(request->request_mode & CWHeight) newHeight = mw->core.height - (w->core.height - (2 * w->core.border_width)) + request->height + 2 * bw; else newHeight = mw->core.height; OldHeight = mw->core.height; parent_request.request_mode = CWWidth | CWHeight; if (request->request_mode & XtCWQueryOnly) parent_request.request_mode |= XtCWQueryOnly; parent_request.width = newWidth ; parent_request.height = newHeight; res = XtMakeGeometryRequest((Widget) mw, &parent_request, NULL) ; if (res == XtGeometryYes) { if (!(request->request_mode & XtCWQueryOnly)) { if(request->request_mode & CWWidth) w->core.width = request->width; if(request->request_mode & CWHeight) w->core.height = request->height; mw->swindow.YOffset = mw->swindow.YOffset + (newHeight - OldHeight); _XmProcessLock(); resize = XtCoreProc(mw, resize); _XmProcessUnlock(); (*resize) ((Widget)mw) ; } } return(res); } /************************************************************************ * * * ChangeManaged - called whenever there is a change in the managed * * set. * * * ************************************************************************/ static void ChangeManaged( Widget wid ) { XmMainWindowWidget mw = (XmMainWindowWidget) wid ; XtWidgetGeometry desired ; CompositeWidget cw = (CompositeWidget) mw->swindow.ClipWindow; Widget w; register int i; XtWidgetProc resize; if (mw->mwindow.ManagingSep || mw->swindow.FromResize) return; CheckKids(mw); /**************** * * This is an ugly bit of work... It's possible for the clip window to get * "extra" kids that really want to be mainwindow widgets. * ****************/ if ((mw->swindow.ScrollPolicy == XmAUTOMATIC) && (cw->composite.num_children > 1) && (mw->swindow.WorkWindow != NULL)) { /* loop over the clip window child list and treat the bogus */ for (i = 0; i < cw->composite.num_children; i++) { XmScrolledWindowConstraint swc ; int j ; w = cw->composite.children[i]; swc = GetSWConstraint(w); /* only those kind are allowed as clipwindow kids */ if ((swc->child_type != XmWORK_AREA) && (swc->child_type != XmSCROLL_HOR) && (swc->child_type != XmSCROLL_VERT) && (swc->child_type != XmNO_SCROLL)) { /* add it to the main window child list. first increase the list if needed- Gee, I wish I remember what made me keep this hacky code around... */ if (mw->composite.num_children == mw->composite.num_slots) { mw->composite.num_slots += (mw->composite.num_slots / 2) + 2; mw->composite.children = (WidgetList) XtRealloc( (char *) mw->composite.children, (unsigned) (mw->composite.num_slots) * sizeof(Widget)); } mw->composite.children[mw->composite.num_children++] = w; w->core.parent = (Widget) mw; /* remove it from the clipwindow child list by moving all the siblings that comes after it one slot down */ for (j = i+1; j < cw->composite.num_children; j++) { cw->composite.children[i-1] = cw->composite.children[i] ; } cw->composite.num_children -- ; } } } if (!XtIsRealized(wid)) { desired.width = XtWidth(wid) ; /* might be 0 */ desired.height = XtHeight(wid) ; /* might be 0 */ } else { desired.width = 0 ; desired.height = 0 ; } GetSize(mw, &desired.width, &desired.height); desired.request_mode = (CWWidth | CWHeight); (void) _XmMakeGeometryRequest(wid, &desired); _XmProcessLock(); resize = XtCoreProc(mw, resize); _XmProcessUnlock(); (*resize) (wid) ; XmeNavigChangeManaged(wid); } /************************************************************************ * * * SetValues * * * ************************************************************************/ /*ARGSUSED*/ static Boolean SetValues( Widget cw, Widget rw, /* unused */ Widget nw, ArgList args, /* unused */ Cardinal *num_args ) /* unused */ { XmMainWindowWidget current = (XmMainWindowWidget) cw ; XmMainWindowWidget new_w = (XmMainWindowWidget) nw ; Boolean flag = False; CheckKids(new_w); /* somehow, this used not to create problem in 1.2, some apps did setvalue of XmNmenubar to itself ? check that and change back */ if ((new_w->mwindow.MenuBar != current->mwindow.MenuBar) && (new_w->mwindow.MenuBar == nw)) { new_w->mwindow.MenuBar = current->mwindow.MenuBar; } /* fix for 8990: these warnings must be here for bc... */ if ((new_w->mwindow.MenuBar != current->mwindow.MenuBar) && (new_w->mwindow.MenuBar == NULL)) { XmeWarning( (Widget) new_w, MWMessage1); new_w->mwindow.MenuBar = current->mwindow.MenuBar; } if ((new_w->mwindow.CommandWindow != current->mwindow.CommandWindow) && (new_w->mwindow.CommandWindow == NULL)) { XmeWarning( (Widget) new_w, MWMessage2); new_w->mwindow.CommandWindow = current->mwindow.CommandWindow; } /* first deal with the layout attributes, and set up a flag */ /* There is a potential bug here: if the change in margin concur with a change on some other stuff, like separator or a new child, and the getSize call return the same size, no resize call will be generated by Xt. A way to fix that is to check this no change in size and to fake a request.. maybe not worth. */ if ((new_w->mwindow.margin_width != current->mwindow.margin_width) || (new_w->mwindow.margin_height != current->mwindow.margin_height) || (new_w->mwindow.ShowSep != current->mwindow.ShowSep)) { flag = True; } if ((new_w->mwindow.CommandLoc != current->mwindow.CommandLoc) && (XmRepTypeValidValue(XmRID_COMMAND_WINDOW_LOCATION, new_w->mwindow.CommandLoc, (Widget) new_w))) { XtWidgetProc resize; _XmProcessLock(); resize = XtCoreProc(nw, resize); _XmProcessUnlock(); (*resize) (nw) ; } else new_w->mwindow.CommandLoc = current->mwindow.CommandLoc; /* At InsertChild time, a lot of bad things might have happened. The command window, messagewindow and work window, which we have no real way to identify at that time, might have been mixed up. (MenuBar and application ScrollBars shouldn't be a problem) The first unidentifiable kid will take the workwindow slot (and possibly be reparented), and the followers will be just inserted in the child list without reparenting (to the clipwindow in AUTO mode I mean). After creation time, the application will use XtSetValues to set up things correctly (except changing the workwindow in AUTO, which is not allowed). The requirement, if a childType resource isn't provided, is that the workwindow be created first, at least in AUTO mode where the reparenting happens */ if ((new_w->mwindow.MenuBar != current->mwindow.MenuBar) || (new_w->mwindow.Message != current->mwindow.Message) || (new_w->mwindow.CommandWindow != current->mwindow.CommandWindow ) || (new_w->swindow.hScrollBar != current->swindow.hScrollBar) || (new_w->swindow.vScrollBar != current->swindow.vScrollBar) || (new_w->swindow.WorkWindow != current->swindow.WorkWindow ) || (flag)) { /* set our core geometry to the needed size - no resizePolicy here... Change in child type can happen before realize time, before change managed has been called, and we don't want to set up a size for the main window at this point, since its children size haven't been set up yet */ if (XtIsRealized((Widget)new_w)) { Dimension width = 0, height = 0 ; GetSize (new_w, &width, &height); new_w->core.width = width ; new_w->core.height = height ; } } return (False); } /************************************************************************ * * * GetAutoDragVertRects class methods * * * ************************************************************************/ static void GetVertRects( Widget sw, XRectangle ** vrect, Cardinal * num_vrect) { Widget w ; XmMainWindowWidget mw = (XmMainWindowWidget) sw ; *num_vrect = 2 ; *vrect = (XRectangle *) XtMalloc(sizeof(XRectangle) * (*num_vrect)) ; /* The vertical rectangles are the ones that vertically auto scroll, they are defined by areas on the top and bottom of the workarea, e.g. the margins, the spacing, the scrollbars and the shadows */ /* Both rects are computed using only the relative work_area or clipwindow (in AUTO) location within the scrolled window: this is the area between the widget and its parent frame. Then they need to be translated into the scrollbar coord system. */ /* what id to use for the sw child frame */ if (mw->swindow.ScrollPolicy == XmAPPLICATION_DEFINED) { w = mw->swindow.WorkWindow; if (!w) w = sw ; /* fallback */ } else w = (Widget) mw->swindow.ClipWindow; /* the vertical rectangle are more complex to compute than for the SW case because we cannot go blindy to the SW boundary, we have to stop at the next sibling window boundary */ /* We have to consider all case of existing/managed menubar, command, or message area, with the command up or down too. */ if (!ExistManaged(mw->mwindow.MenuBar) && !ExistManaged(mw->mwindow.CommandWindow)) { (*vrect)[0].y = 0 ; (*vrect)[0].height = w->core.y ; } else if (ExistManaged(mw->mwindow.MenuBar) && !ExistManaged(mw->mwindow.CommandWindow)) { (*vrect)[0].y = mw->mwindow.MenuBar->core.y + mw->mwindow.MenuBar->core.height ; (*vrect)[0].height = w->core.y - mw->mwindow.MenuBar->core.y - mw->mwindow.MenuBar->core.height ; } else if (ExistManaged(mw->mwindow.MenuBar) && ExistManaged(mw->mwindow.CommandWindow) && (mw->mwindow.CommandLoc == XmCOMMAND_ABOVE_WORKSPACE)) { (*vrect)[0].y = mw->mwindow.CommandWindow->core.y + mw->mwindow.CommandWindow->core.height ; (*vrect)[0].height = w->core.y - mw->mwindow.CommandWindow->core.y - mw->mwindow.CommandWindow->core.height ; } /* The first rectangle is the one that makes the scrollbar goes up */ (*vrect)[0].x = w->core.x - mw->swindow.vScrollBar->core.x ; /* just translate to the scrollbar coordinate */ (*vrect)[0].y =- mw->swindow.vScrollBar->core.y ; (*vrect)[0].width = w->core.width ; /* The second rectangle is the one that makes the scrollbar goes down */ (*vrect)[1].x = (*vrect)[0].x ; (*vrect)[1].y = w->core.y + w->core.height - mw->swindow.vScrollBar->core.y ; (*vrect)[1].width = (*vrect)[0].width ; if (!ExistManaged(mw->mwindow.CommandWindow) && !ExistManaged(mw->mwindow.Message)) { (*vrect)[1].height = mw->core.height - (*vrect)[1].y ; } else if (ExistManaged(mw->mwindow.CommandWindow) && (mw->mwindow.CommandLoc == XmCOMMAND_BELOW_WORKSPACE)) { (*vrect)[1].height = mw->mwindow.CommandWindow->core.y - w->core.y - w->core.height; } else if (ExistManaged(mw->mwindow.Message)) { (*vrect)[1].height = mw->mwindow.Message->core.y - w->core.y - w->core.height; } } /************************************************************************ * * * Public API Functions * * * ************************************************************************/ /************************************************************************ * * * XmMainWindowSetAreas - set a new children set. * * -to be deprecated in favor of XtSetValues * * -doesn't even handle message window * * * ************************************************************************/ void XmMainWindowSetAreas( Widget w, Widget menu, Widget command, Widget hscroll, Widget vscroll, Widget wregion ) { Arg args[5] ; Cardinal n; n = 0; if (menu) { XtSetArg (args[n], XmNmenuBar, menu); n++; } if (command) { XtSetArg (args[n], XmNcommandWindow, command); n++; } if (hscroll) { XtSetArg (args[n], XmNhorizontalScrollBar, hscroll); n++; } if (vscroll) { XtSetArg (args[n], XmNverticalScrollBar, vscroll); n++; } if (wregion) { XtSetArg (args[n], XmNworkWindow, wregion); n++; } XtSetValues(w, args, n); } /************************************************************************ * * * XmMainWindowSep1, 2 and 3 * * - return the id of the top seperator widget. * * - to be deprecated in favor of using XtNameToWidget * * * * * ************************************************************************/ Widget XmMainWindowSep1( Widget w ) { XmMainWindowWidget mw = (XmMainWindowWidget) w; Widget separator; _XmWidgetToAppContext(w); _XmAppLock(app); separator = (Widget) mw->mwindow.Sep1; _XmAppUnlock(app); return separator; } Widget XmMainWindowSep2( Widget w ) { XmMainWindowWidget mw = (XmMainWindowWidget) w; Widget separator; _XmWidgetToAppContext(w); _XmAppLock(app); separator = (Widget) mw->mwindow.Sep2; _XmAppUnlock(app); return separator; } Widget XmMainWindowSep3( Widget w ) { XmMainWindowWidget mw = (XmMainWindowWidget) w; Widget separator; _XmWidgetToAppContext(w); _XmAppLock(app); separator = (Widget) mw->mwindow.Sep3; _XmAppUnlock(app); return separator; } /************************************************************************ * * * XmCreateMainWindow - * * * ************************************************************************/ Widget XmCreateMainWindow( Widget parent, char *name, ArgList args, Cardinal argCount ) { return (XtCreateWidget(name, xmMainWindowWidgetClass, parent, args, argCount ) ); }