Initial git import
[sxemacs] / src / extw-Xt.c
1 /* Common code between client and shell widgets -- Xt only.
2    Copyright (C) 1993, 1994 Sun Microsystems, Inc.
3
4 This file is part of SXEmacs
5
6 SXEmacs is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10
11 SXEmacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program.  If not, see <http://www.gnu.org/licenses/>. */
18
19
20 /* Synched up with: Not in FSF. */
21
22 /* Written by Ben Wing, September 1993. */
23
24 #ifdef emacs
25
26 #include <config.h>
27
28 #ifndef EXTERNAL_WIDGET
29 ERROR ! This ought not be getting compiled if EXTERNAL_WIDGET
30         is undefined
31 #endif
32         void fatal(const char *fmt, ...);
33 #else                           /* not emacs */
34 static void fatal(char *msg);
35 #endif
36
37 #include <X11/Intrinsic.h>
38 #include <X11/IntrinsicP.h>
39 #include <stdlib.h>
40 #include <stdio.h>
41 #include "ui/X11/extw-Xt.h"
42
43 /* Yeah, that's portable!
44
45    Why the hell didn't the Xt people just export this function
46    for real? */
47
48 #if (XT_REVISION > 5)
49 int _XtWaitForSomething(XtAppContext app,
50                         _XtBoolean ignoreEvents,
51                         _XtBoolean ignoreTimers,
52                         _XtBoolean ignoreInputs,
53                         _XtBoolean ignoreSignals, _XtBoolean block,
54 #ifdef XTHREADS
55                         _XtBoolean drop_lock,
56 #endif
57                         unsigned long *howlong);
58
59 # ifndef XTHREADS
60 #  define _XtwaitForSomething(timers,inputs,events,block,howlong,appCtx) \
61           _XtWaitForSomething(appCtx,events,timers,inputs,0,block,howlong)
62 # else
63 #  define _XtwaitForSomething(timers,inputs,events,block,howlong,appCtx) \
64           _XtWaitForSomething(appCtx,events,timers,inputs,0,block,1,howlong)
65 # endif
66 #else
67 int _XtwaitForSomething(Boolean ignoreTimers,
68                         Boolean ignoreInputs,
69                         Boolean ignoreEvents,
70                         Boolean block,
71                         unsigned long *howlong, XtAppContext app);
72 #endif
73
74 #ifdef DEBUG_WIDGET
75
76 static int geom_masks[] = {
77         CWX, CWY, CWWidth, CWHeight, CWBorderWidth, CWSibling, CWStackMode,
78         XtCWQueryOnly
79 };
80 static char *geom_mask_strings[] = {
81         "CWX", "CWY", "CWWidth", "CWHeight", "CWBorderWidth",
82         "CWSibling", "CWStackMode", "XtCWQueryOnly"
83 };
84 static int stack_modes[] = {
85         Below, TopIf, BottomIf, Opposite, XtSMDontChange
86 };
87 static char *stack_mode_strings[] = {
88         "Below", "TopIf", "BottomIf", "Opposite", "XtSMDontChange"
89 };
90
91 static void print_geometry_structure(XtWidgetGeometry * xwg)
92 {
93         int num = sizeof(geom_masks) / sizeof(int);
94         int i;
95
96         printf("  masks:");
97         for (i = 0; i < num; i++)
98                 if (xwg->request_mode & geom_masks[i])
99                         printf(" %s", geom_mask_strings[i]);
100         printf("\n");
101         printf("  x:%d y:%d\n", xwg->x, xwg->y);
102         printf("  width:%d height:%d border_width:%d\n", xwg->width,
103                xwg->height, xwg->border_width);
104         printf("  sibling: %x\n", xwg->sibling);
105         printf("  stack_mode: ");
106         for (i = 0, num = sizeof(stack_modes) / sizeof(int); i < num; i++)
107                 if (xwg->stack_mode == stack_modes[i]) {
108                         printf("%s", stack_mode_strings[i]);
109                         break;
110                 }
111         printf("\n");
112 }
113
114 static void print_geometry_result(XtGeometryResult res)
115 {
116         printf("result: %s\n",
117                res == XtGeometryYes ? "XtGeometryYes" :
118                res == XtGeometryNo ? "XtGeometryNo" :
119                res == XtGeometryAlmost ? "XtGeometryAlmost" :
120                res == XtGeometryDone ? "XtGeometryDone" : "unknown");
121 }
122
123 #endif
124
125 #ifndef emacs
126
127 static void fatal(char *msg)
128 {
129         fprintf(stderr, "%s", msg);
130         exit(1);
131 }
132
133 #endif
134
135 /* put a geometry specification in the specified property on the window
136    of the specified widget, and send a notification message to tell the
137    client-side widget about this. */
138
139 void
140 extw_send_geometry_value(Display * display, Window win, Atom property,
141                          en_extw_notify type, XtWidgetGeometry * xwg,
142                          long data0)
143 {
144         if (xwg != NULL)
145                 XChangeProperty(display, win, property,
146                                 a_EXTW_WIDGET_GEOMETRY, 32, PropModeReplace,
147                                 (unsigned char *)xwg,
148                                 sizeof(*xwg) / sizeof(int));
149         extw_send_notify_3(display, win, type, data0, 0, 0);
150 }
151
152 /* get the geometry specification stored in the specified property of the
153    specified widget's window. */
154
155 void
156 extw_get_geometry_value(Display * display, Window win, Atom property,
157                         XtWidgetGeometry * xwg)
158 {
159         Atom dummy;
160         int format;
161         unsigned long nitems, bytes_after;
162         unsigned char *prop;
163
164         if (XGetWindowProperty(display, win, property, 0,
165                                sizeof(*xwg) / 4, False, a_EXTW_WIDGET_GEOMETRY,
166                                &dummy, &format, &nitems, &bytes_after,
167                                &prop) != Success)
168                 goto error;
169         if (format != 8 * sizeof(int) || bytes_after) {
170                 XFree((char *)prop);
171                 goto error;
172         }
173         *xwg = *(XtWidgetGeometry *) prop;
174         return;
175
176       error:
177         fatal("Unable to retrieve property for widget-geometry");
178 #if 0
179         XtAppErrorMsg(XtWidgetToApplicationContext((Widget) w),
180                       "invalidProperty", "get_geometry_value",
181                       XtCXtToolkitError,
182                       "Unable to retrieve property for widget-geometry",
183                       (String *) NULL, (Cardinal *) NULL);
184 #endif
185 }
186
187 typedef struct {
188         Widget w;
189         unsigned long request_num;
190         en_extw_notify type;
191 } QueryStruct;
192
193 /* check if an event is of the sort we're looking for */
194
195 static Bool isMine(Display * dpy, XEvent * event, char *arg)
196 {
197         QueryStruct *q = (QueryStruct *) arg;
198         Widget w = q->w;
199
200         if ((dpy != XtDisplay(w)) || (event->xany.window != XtWindow(w))) {
201                 return FALSE;
202         }
203         if (event->xany.serial >= q->request_num) {
204                 if (event->type == ClientMessage &&
205                     event->xclient.message_type == a_EXTW_NOTIFY &&
206                     event->xclient.data.l[0] == 1 - extw_which_side &&
207                     event->xclient.data.l[1] == q->type)
208                         return TRUE;
209         }
210         return FALSE;
211 }
212
213 /* wait for a ClientMessage of the specified type from the other widget, or
214    time-out.  isMine() determines whether an event matches.  Culled from
215    Shell.c. */
216
217 Bool
218 extw_wait_for_response(Widget w, XEvent * event, unsigned long request_num,
219                        en_extw_notify type, unsigned long timeout)
220 {
221         XtAppContext app = XtWidgetToApplicationContext(w);
222         QueryStruct q;
223
224         XFlush(XtDisplay(w));
225         q.w = w;
226         q.request_num = request_num;
227         q.type = type;
228
229         for (;;) {
230                 /*
231                  * look for match event
232                  */
233                 if (XCheckIfEvent(XtDisplay(w), event, isMine, (char *)&q))
234                         return TRUE;
235                 if (_XtwaitForSomething(TRUE, TRUE, FALSE, TRUE, &timeout, app)
236                     != -1)
237                         continue;
238                 if (timeout == 0)
239                         return FALSE;
240         }
241 }