Update FSF's address in the preamble.
[bpt/emacs.git] / lwlib / lwlib-Xolmb.c
CommitLineData
40a6a4dd
RS
1/* An OLIT menubar widget, by Chuck Thompson <cthomp@cs.uiuc.edu>
2 Copyright (C) 1993 Lucid, Inc.
3
4This file is part of the Lucid Widget Library.
5
6The Lucid Widget Library is free software; you can redistribute it and/or
7modify it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 1, or (at your option)
9any later version.
10
11The Lucid Widget Library is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Emacs; see the file COPYING. If not, write to
3b7ad313
EN
18the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19Boston, MA 02111-1307, USA. */
40a6a4dd
RS
20
21#include <X11/IntrinsicP.h>
22#include <X11/Intrinsic.h>
23#include <X11/CompositeP.h>
24#include <X11/Composite.h>
25#include "lwlib-Xol-mbP.h"
26#include "lwlib-Xol-mb.h"
27
28#define HORIZ_SPACING 4
29#define VERT_SPACING 4
30
31static void Initialize();
32static void Resize();
33static void ChangeManaged();
34static Boolean SetValues();
35static XtGeometryResult GeometryManager();
36static XtGeometryResult PreferredSize();
37static void do_layout();
38static XtGeometryResult try_layout();
39
40lwMenuBarClassRec lwMenubarClassRec =
41{
42 {
43 /* core_class members */
44
45 (WidgetClass) &compositeClassRec, /* superclass */
46 "Menubar", /* class_name */
47 sizeof(lwMenuBarRec), /* widget_size */
48 NULL, /* class_initialize */
49 NULL, /* class_part_initialize */
50 FALSE, /* class_inited */
51 Initialize, /* initialize */
52 NULL, /* initialize_hook */
53 XtInheritRealize, /* realize */
54 NULL, /* actions */
55 0, /* num_actions */
56 NULL, /* resources */
57 0, /* num_resources */
58 NULLQUARK, /* xrm_class */
59 TRUE, /* compress_motion */
60 XtExposeCompressMaximal, /* compress_exposure */
61 TRUE, /* compress_enterleave */
62 FALSE, /* visible_interest */
63 NULL, /* destroy */
64 Resize, /* resize */
65 NULL, /* expose */
66 NULL, /* set_values */
67 NULL, /* set_values_hook */
68 XtInheritSetValuesAlmost, /* set_values_almost */
69 NULL, /* get_values_hook */
70 NULL, /* accept_focus */
71 XtVersion, /* version */
72 NULL, /* callback_private */
73 NULL, /* tm_table */
74 PreferredSize, /* query_geometry */
75 NULL, /* display_accelerator */
76 NULL, /* extension */
77 },
78 {
79 /* composite_class members */
80
81 GeometryManager, /* geometry_manager */
82 ChangeManaged, /* change_managed */
83 XtInheritInsertChild, /* insert_child */
84 XtInheritDeleteChild, /* delete_child */
85 NULL, /* extension */
86 },
87 {
88 /* Menubar class members */
89
90 0, /* empty */
91 }
92};
93WidgetClass lwMenubarWidgetClass = (WidgetClass) &lwMenubarClassRec;
94
95
96static void Initialize (request, new)
97 lwMenuBarWidget request, new;
98{
99 if (request->core.width <= 0)
100 new->core.width = 1;
101 if (request->core.height <= 0)
102 new->core.height = 23;
103}
104
105static void
106Resize (w)
107 lwMenuBarWidget w;
108{
109 do_layout(w);
110}
111
112static void
113do_layout (parent)
114 lwMenuBarWidget parent;
115{
116 Widget child;
117 int cnt;
118 int managed_children = 0;
119 int managed_width = 0;
120 int new_pos = 0;
121
122 /*
123 * Determine number of children which will fit on one line.
124 * For now we ignore the rest, making sure they are unmanaged.
125 */
126
127 cnt = 0;
128 while ((cnt < (int) parent->composite.num_children) &&
129 (managed_width < (int) parent->core.width))
130 {
131 child = parent->composite.children[cnt++];
132 managed_children++;
133 managed_width += child->core.width + child->core.border_width * 2 +
134 HORIZ_SPACING;
135 }
136
137 if (managed_width > (int) parent->core.width)
138 managed_children--;
139
140 /*
141 * Correct positioning of children.
142 */
143
144 cnt = 0;
145 while (managed_children)
146 {
147 child = parent->composite.children[cnt++];
148
149 if (!child->core.managed)
150 XtManageChild (child);
151
152 if ((child->core.x != new_pos) || (child->core.y != 0))
153 XtMoveWidget (child, new_pos, 0);
154 new_pos += child->core.width + child->core.border_width * 2 +
155 HORIZ_SPACING;
156
157 managed_children--;
158 }
159
160 /*
161 * Make sure all remaining children are unmanaged.
162 */
163
164 while (cnt < parent->composite.num_children)
165 {
166 child = parent->composite.children[cnt];
167
168 if (child->core.managed)
169 XtUnmanageChild (child);
170
171 if ((child->core.x != parent->core.width) ||
172 (child->core.y != parent->core.height))
173 XtMoveWidget (child, parent->core.width, parent->core.height);
174
175 cnt++;
176 }
177}
178
179
180static XtGeometryResult
181PreferredSize (w, request, preferred)
182 lwMenuBarWidget w;
183 XtWidgetGeometry *request, *preferred;
184{
185 Widget child;
186 int cnt;
187
188 /*
189 * If no changes are being made to the width or height, just agree.
190 */
191
192 if (!(request->request_mode & CWWidth) &&
193 !(request->request_mode & CWHeight))
194 return (XtGeometryYes);
195
196 /*
197 * Right now assume everything goes in one row. Calculate the
198 * minimum required width and height.
199 */
200
201 preferred->width = 0;
202 preferred->height = 0;
203
204 for (cnt = 0; cnt < w->composite.num_children; cnt++)
205 {
206 child = w->composite.children[cnt];
207 if (child->core.managed)
208 {
209 preferred->width += child->core.width + child->core.border_width*2 +
210 HORIZ_SPACING;
211 if (preferred->height < (Dimension) (child->core.height +
212 child->core.border_width * 2))
213 preferred->height = child->core.height +
214 child->core.border_width * 2;
215 }
216 }
217
218 preferred->request_mode = CWWidth | CWHeight;
219
220 /*
221 * Case: both height and width requested
222 */
223
224 if ((request->request_mode & CWWidth) &&
225 (request->request_mode & CWHeight))
226 {
227 /*
228 * Ok if same or bigger.
229 */
230
231 if (preferred->width <= request->width &&
232 preferred->height <= request->height)
233 {
234 preferred->width = request->width;
235 return (XtGeometryYes);
236 }
237
238 /*
239 * If both dimensions are too small, say no.
240 */
241
242 else
243 if (preferred->width > request->width &&
244 preferred->height > request->height)
245 return (XtGeometryNo);
246
247 /*
248 * Otherwise one must be right, so say almost.
249 */
250
251 else
252 return (XtGeometryAlmost);
253 }
254
255 /*
256 * If only one dimension is requested, either its OK or it isn't.
257 */
258
259 else
260 {
261 if (request->request_mode & CWWidth)
262 {
263 if (preferred->width <= request->width)
264 {
265 preferred->width = request->width;
266 return (XtGeometryYes);
267 }
268 else
269 return (XtGeometryNo);
270 }
271 else if (request->request_mode & CWHeight)
272 {
273 if (preferred->height <= request->height)
274 {
275 return (XtGeometryYes);
276 }
277 else
278 return (XtGeometryNo);
279 }
280
281 return (XtGeometryYes);
282 }
283}
284
285
286static XtGeometryResult
287GeometryManager (w, request, reply)
288 Widget w;
289 XtWidgetGeometry *request;
290 XtWidgetGeometry *reply;
291{
292
293 lwMenuBarWidget parent = (lwMenuBarWidget) w->core.parent;
294
295 /*
296 * If the widget wants to move, just say no.
297 */
298
299 if ((request->request_mode & CWX && request->x != w->core.x) ||
300 (request->request_mode & CWY && request->y != w->core.y))
301 return (XtGeometryNo);
302
303 /*
304 * Since everything "fits" for now, grant all requests.
305 */
306
307 if (request->request_mode & CWWidth)
308 w->core.width = request->width;
309 if (request->request_mode & CWHeight)
310 w->core.height = request->height;
311 if (request->request_mode & CWBorderWidth)
312 w->core.border_width = request->border_width;
313
314 do_layout (parent);
315 return (XtGeometryYes);
316}
317
318
319static XtGeometryResult
320try_layout (parent)
321 lwMenuBarWidget parent;
322{
323 Widget child;
324 int cnt;
325 int managed_children = 0;
326 int managed_width = 0;
327 int new_pos = 0;
328
329 /*
330 * Determine number of children which will fit on one line.
331 * For now we ignore the rest, making sure they are unmanaged.
332 */
333
334 cnt = 0;
335 while ((cnt < (int) parent->composite.num_children) &&
336 (managed_width < (int) parent->core.width))
337 {
338 child = parent->composite.children[cnt++];
339 if (child->core.managed)
340 {
341 managed_children++;
342 managed_width += child->core.width + child->core.border_width * 2 +
343 HORIZ_SPACING;
344 }
345 }
346
347 if (managed_width > (int) parent->core.width)
348 return (XtGeometryNo);
349 else
350 return (XtGeometryYes);
351}
352
353
354
355static void
356ChangeManaged (w)
357 lwMenuBarWidget w;
358{
359 XtGeometryResult result;
360
361 result = try_layout (w);
362
363 if (result != XtGeometryYes)
364 {
365 XtUnmanageChild (w->composite.children[w->composite.num_children - 1]);
366 XtMoveWidget (w->composite.children[w->composite.num_children-1],
367 w->core.width, w->core.height);
368 }
369
370 do_layout (w);
371}