Initial git import
[sxemacs] / src / ui / lwlib / lwlib-utils.c
1 /* Defines some widget utility functions.
2    Copyright (C) 1992 Lucid, Inc.
3
4 This file is part of the Lucid Widget Library.
5
6 The Lucid Widget Library is free software: you can redistribute it
7 and/or modify it under the terms of the GNU General Public License as
8 published by the Free Software Foundation, either version 3 of the
9 License, or (at your option) any later version.
10
11 The Lucid Widget Library is distributed in the hope that it will be
12 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 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 #include <config.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <memory.h>
23 #ifdef HAVE_UNISTD_H
24 #include <unistd.h>
25 #endif
26
27 #include <X11/Xatom.h>
28 #include <X11/IntrinsicP.h>
29 #include <X11/ObjectP.h>
30 #include "lwlib-utils.h"
31
32 void destroy_all_children(Widget widget)
33 {
34         Widget *children;
35         unsigned int number;
36         int i;
37
38         children = XtCompositeChildren(widget, &number);
39         if (children) {
40                 /* Unmanage all children and destroy them.  They will only be
41                  * really destroyed when we get out of DispatchEvent. */
42                 for (i = 0; i < (int)number; i++) {
43                         Widget child = children[i];
44                         if (!child->core.being_destroyed) {
45                                 XtUnmanageChild(child);
46                                 XtDestroyWidget(child);
47                         }
48                 }
49                 XtFree((char *)children);
50         }
51 }
52
53 /* Redisplay the contents of the widget, without first clearing it. */
54 void XtNoClearRefreshWidget(Widget widget)
55 {
56         XEvent event;
57         XExposeEvent *ev = &event.xexpose;
58
59         ev->type = Expose;
60         ev->serial = 0;
61         ev->send_event = 0;
62         ev->display = XtDisplay(widget);
63         ev->window = XtWindow(widget);
64         ev->x = 0;
65         ev->y = 0;
66         ev->width = widget->core.width;
67         ev->height = widget->core.height;
68         ev->count = 0;
69
70         (*widget->core.widget_class->core_class.expose)
71             (widget, &event, (Region) NULL);
72 }
73
74 /* 
75  * Apply a function to all the subwidgets of a given widget recursively.
76 */
77 void XtApplyToWidgets(Widget w, XtApplyToWidgetsProc proc, XtPointer arg)
78 {
79         if (XtIsComposite(w)) {
80                 CompositeWidget cw = (CompositeWidget) w;
81                 /* We have to copy the children list before mapping over it, because
82                    the procedure might add/delete elements, which would lose badly. */
83                 int nkids = cw->composite.num_children;
84                 Widget *kids = (Widget *) malloc(sizeof(Widget) * nkids);
85                 int i;
86                 memcpy(kids, cw->composite.children, sizeof(Widget) * nkids);
87                 for (i = 0; i < nkids; i++)
88 /* This prevent us from using gadgets, why is it here? */
89 /*      if (XtIsWidget (kids [i])) */
90                 {
91                         /* do the kiddies first in case we're destroying */
92                         XtApplyToWidgets(kids[i], proc, arg);
93                         proc(kids[i], arg);
94                 }
95                 free(kids);
96         }
97 }
98
99 /*
100  * Apply a function to all the subwidgets of a given widget recursively.
101  * Stop as soon as the function returns non NULL and returns this as a value.
102  */
103 void *XtApplyUntilToWidgets(Widget w, XtApplyUntilToWidgetsProc proc,
104                             XtPointer arg)
105 {
106         void *result;
107         if (XtIsComposite(w)) {
108                 CompositeWidget cw = (CompositeWidget) w;
109                 unsigned int i;
110                 for (i = 0; i < cw->composite.num_children; i++)
111                         if (XtIsWidget(cw->composite.children[i])) {
112                                 result = proc(cw->composite.children[i], arg);
113                                 if (result)
114                                         return result;
115                                 result =
116                                     XtApplyUntilToWidgets(cw->composite.
117                                                           children[i], proc,
118                                                           arg);
119                                 if (result)
120                                         return result;
121                         }
122         }
123         return NULL;
124 }
125
126 /*
127  * Returns a copy of the list of all children of a composite widget
128  */
129 Widget *XtCompositeChildren(Widget widget, unsigned int *number)
130 {
131         CompositeWidget cw = (CompositeWidget) widget;
132         Widget *result;
133         int n;
134         int i;
135
136         if (!XtIsComposite(widget)) {
137                 *number = 0;
138                 return NULL;
139         }
140         n = cw->composite.num_children;
141         result = (Widget *) XtMalloc(n * sizeof(Widget));
142         *number = n;
143         for (i = 0; i < n; i++)
144                 result[i] = cw->composite.children[i];
145         return result;
146 }
147
148 Boolean XtWidgetBeingDestroyedP(Widget widget)
149 {
150         return widget->core.being_destroyed;
151 }
152
153 void XtSafelyDestroyWidget(Widget widget)
154 {
155 #if 0
156
157         /* this requires IntrinsicI.h (actually, InitialI.h) */
158
159         XtAppContext app = XtWidgetToApplicationContext(widget);
160
161         if (app->dispatch_level == 0) {
162                 app->dispatch_level = 1;
163                 XtDestroyWidget(widget);
164                 /* generates an event so that the event loop will be called */
165                 XChangeProperty(XtDisplay(widget), XtWindow(widget),
166                                 XA_STRING, XA_STRING, 32, PropModeAppend, NULL,
167                                 0);
168                 app->dispatch_level = 0;
169         } else
170                 XtDestroyWidget(widget);
171
172 #else
173         abort();
174 #endif
175 }