Link with C++ linker
[oweals/cde.git] / cde / programs / dtcalc / ds_popup.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these librararies and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /* $XConsortium: ds_popup.c /main/5 1996/03/25 18:18:07 ageorge $ */
24 /*                                                                      *
25  *  ds_popup.c                                                          *
26  *   Contains some common functions used by the popups throughout       * 
27  *   the Desktop Calculator.                                            * 
28  *                                                                      * 
29  * (c) Copyright 1993, 1994 Hewlett-Packard Company                     *
30  * (c) Copyright 1993, 1994 International Business Machines Corp.       *
31  * (c) Copyright 1993, 1994 Sun Microsystems, Inc.                      *
32  * (c) Copyright 1993, 1994 Novell, Inc.                                *
33  */
34
35 #include <Xm/Xm.h>
36 #include <Xm/XmP.h>
37 #include <Xm/VendorSEP.h>
38 /* Copied from BaseClassI.h */
39 extern XmWidgetExtData _XmGetWidgetExtData( 
40                         Widget widget,
41 #if NeedWidePrototypes
42                         unsigned int extType) ;
43 #else
44                         unsigned char extType) ;
45 #endif /* NeedWidePrototypes */
46
47 #include <X11/ShellP.h>
48 #include <X11/Shell.h>
49
50 #include "calctool.h"
51 #include "motif.h"
52
53 void _DtChildPosition     P((Widget, Widget, Position *, Position *)) ;
54
55 /* ARGSUSED */
56 void
57 _DtmapCB(
58          Widget w,
59          XtPointer client_data,
60          XtPointer call_data )
61 {
62    Arg         args[2];
63    Widget      parent;
64    Position newX, newY;
65
66    parent = (Widget)client_data;
67
68    if (parent)
69    {
70       _DtChildPosition(w, parent, &newX, &newY);
71       XtSetArg(args[0], XmNx, newX);
72       XtSetArg(args[1], XmNy, newY);
73       XtSetValues(w, args, 2);
74       XSync(X->dpy, False);
75    }
76 }
77
78
79 /*
80  */
81
82 void
83 _DtMappedCB(
84          Widget w,
85          XtPointer client_data,
86          XtPointer call_data )
87 {
88   _DtmapCB(w, client_data, call_data);
89
90   XtRemoveCallback(w, XmNmapCallback, (XtCallbackProc)_DtMappedCB, 
91                                         client_data);
92 }
93
94
95 /*
96  * This is the generic function for registering the map callback.
97  */
98
99 void
100 _DtGenericMapWindow (
101      Widget shell,
102      Widget parent )
103 {
104    XtAddCallback (parent, XmNmapCallback,
105                   (XtCallbackProc)_DtMappedCB, (XtPointer) shell);
106 }
107
108
109 /*
110  * _DtChildPosition:
111  *   Choose a position for a popup window ("child") so that the main
112  *   window ("parent") is not obscured.  The child will be positioned
113  *   to the right, below, left, or above the parent, depending on where
114  *   there is the most space.
115  */
116
117 void
118 _DtChildPosition(
119          Widget w,
120          Widget parent,
121          Position *newX,
122          Position *newY)
123 {
124    Position pY, pX;
125    XmVendorShellExtObject vendorExt;
126    XmWidgetExtData        extData;
127    int xOffset, yOffset;
128    int pHeight, myHeight, sHeight;
129    int pWidth, myWidth, sWidth;
130    enum { posRight, posBelow, posLeft, posAbove } pos;
131    int space;
132
133    /* get x, y offsets for the parent's window frame */
134    extData = _XmGetWidgetExtData(parent, XmSHELL_EXTENSION);
135    if (extData)
136    {
137      vendorExt = (XmVendorShellExtObject)extData->widget;
138      xOffset = vendorExt->vendor.xOffset;
139      yOffset = vendorExt->vendor.yOffset;
140    }
141    else
142      xOffset = yOffset = 0;
143
144    /* get size/position of screen, parent, and widget */
145    sHeight = HeightOfScreen(XtScreen(parent));;
146    sWidth = WidthOfScreen(XtScreen(parent));
147    pX = XtX(parent) - xOffset;
148    pY = XtY(parent) - yOffset;
149    pHeight = XtHeight(parent) + yOffset + xOffset;
150    pWidth = XtWidth(parent) + 2*xOffset;
151    myHeight = XtHeight(w) + yOffset + xOffset;
152    myWidth = XtWidth(w) + 2*xOffset;
153
154    /*
155     * Determine how much space would be left if the child was positioned
156     * to the right, below, left, or above the parent.  Choose the child
157     * positioning so that the maximum space is left.
158     */
159    pos = posBelow;
160    space = sHeight - (pY + pHeight + myHeight);
161
162    if (pY - myHeight > space)
163    {
164       pos = posAbove;
165       space = pY - myHeight;
166    }
167
168    if(space <= 0)
169    {
170       pos = posRight;
171       sWidth - (pX + pWidth + myWidth);
172       if (pX - myWidth > space)
173       {
174          pos = posLeft;
175          space = pX - myWidth;
176       }
177    }
178
179    /* Given relative positioning, determine x, y coordinates for the child */
180
181    switch (pos)
182    {
183      case posRight:
184        *newX = pX + pWidth - 5;
185        *newY = pY + (pHeight - myHeight)/2;
186        break;
187
188      case posBelow:
189        *newX = pX + (pWidth - myWidth)/2;
190        *newY = pY + pHeight;
191        break;
192
193      case posLeft:
194        *newX = pX - myWidth + 10;
195        *newY = pY + (pHeight - myHeight)/2;
196        break;
197
198      case posAbove:
199        *newX = pX + (pWidth - myWidth)/2;
200        *newY = pY - myHeight;
201        break;
202    }
203    /*
204     * Defect 177440, put HelpDialog within the monitor
205     */
206     if ( *newX < 0 )
207         *newX = 0;
208     if ( *newY < 0 )
209         *newY = 0;
210
211     if ( ( *newX + myWidth ) > sWidth ) {
212         Position _tmp;
213
214         _tmp = sWidth - myWidth;
215         if ( _tmp >= 0 )
216             *newX = _tmp;       
217     }
218
219     if ( ( *newY + myHeight ) > sHeight ) {
220         Position _tmp;
221
222         _tmp = sHeight - myHeight;
223         if ( _tmp >= 0 )
224             *newY = _tmp;       
225     }
226 }
227