(file_name_as_directory, Ffile_name_directory)
[emacs.git] / lwlib / lwlib-Xolmb.c
blobf253e3e576b2056f3fe891c7b1a3fc6830233162
1 /* An OLIT menubar widget, by Chuck Thompson <cthomp@cs.uiuc.edu>
2 Copyright (C) 1993 Lucid, Inc.
4 This file is part of the Lucid Widget Library.
6 The Lucid Widget Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 1, or (at your option)
9 any later version.
11 The Lucid Widget Library 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.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
20 #include <X11/IntrinsicP.h>
21 #include <X11/Intrinsic.h>
22 #include <X11/CompositeP.h>
23 #include <X11/Composite.h>
24 #include "lwlib-Xol-mbP.h"
25 #include "lwlib-Xol-mb.h"
27 #define HORIZ_SPACING 4
28 #define VERT_SPACING 4
30 static void Initialize();
31 static void Resize();
32 static void ChangeManaged();
33 static Boolean SetValues();
34 static XtGeometryResult GeometryManager();
35 static XtGeometryResult PreferredSize();
36 static void do_layout();
37 static XtGeometryResult try_layout();
39 lwMenuBarClassRec lwMenubarClassRec =
42 /* core_class members */
44 (WidgetClass) &compositeClassRec, /* superclass */
45 "Menubar", /* class_name */
46 sizeof(lwMenuBarRec), /* widget_size */
47 NULL, /* class_initialize */
48 NULL, /* class_part_initialize */
49 FALSE, /* class_inited */
50 Initialize, /* initialize */
51 NULL, /* initialize_hook */
52 XtInheritRealize, /* realize */
53 NULL, /* actions */
54 0, /* num_actions */
55 NULL, /* resources */
56 0, /* num_resources */
57 NULLQUARK, /* xrm_class */
58 TRUE, /* compress_motion */
59 XtExposeCompressMaximal, /* compress_exposure */
60 TRUE, /* compress_enterleave */
61 FALSE, /* visible_interest */
62 NULL, /* destroy */
63 Resize, /* resize */
64 NULL, /* expose */
65 NULL, /* set_values */
66 NULL, /* set_values_hook */
67 XtInheritSetValuesAlmost, /* set_values_almost */
68 NULL, /* get_values_hook */
69 NULL, /* accept_focus */
70 XtVersion, /* version */
71 NULL, /* callback_private */
72 NULL, /* tm_table */
73 PreferredSize, /* query_geometry */
74 NULL, /* display_accelerator */
75 NULL, /* extension */
78 /* composite_class members */
80 GeometryManager, /* geometry_manager */
81 ChangeManaged, /* change_managed */
82 XtInheritInsertChild, /* insert_child */
83 XtInheritDeleteChild, /* delete_child */
84 NULL, /* extension */
87 /* Menubar class members */
89 0, /* empty */
92 WidgetClass lwMenubarWidgetClass = (WidgetClass) &lwMenubarClassRec;
95 static void Initialize (request, new)
96 lwMenuBarWidget request, new;
98 if (request->core.width <= 0)
99 new->core.width = 1;
100 if (request->core.height <= 0)
101 new->core.height = 23;
104 static void
105 Resize (w)
106 lwMenuBarWidget w;
108 do_layout(w);
111 static void
112 do_layout (parent)
113 lwMenuBarWidget parent;
115 Widget child;
116 int cnt;
117 int managed_children = 0;
118 int managed_width = 0;
119 int new_pos = 0;
122 * Determine number of children which will fit on one line.
123 * For now we ignore the rest, making sure they are unmanaged.
126 cnt = 0;
127 while ((cnt < (int) parent->composite.num_children) &&
128 (managed_width < (int) parent->core.width))
130 child = parent->composite.children[cnt++];
131 managed_children++;
132 managed_width += child->core.width + child->core.border_width * 2 +
133 HORIZ_SPACING;
136 if (managed_width > (int) parent->core.width)
137 managed_children--;
140 * Correct positioning of children.
143 cnt = 0;
144 while (managed_children)
146 child = parent->composite.children[cnt++];
148 if (!child->core.managed)
149 XtManageChild (child);
151 if ((child->core.x != new_pos) || (child->core.y != 0))
152 XtMoveWidget (child, new_pos, 0);
153 new_pos += child->core.width + child->core.border_width * 2 +
154 HORIZ_SPACING;
156 managed_children--;
160 * Make sure all remaining children are unmanaged.
163 while (cnt < parent->composite.num_children)
165 child = parent->composite.children[cnt];
167 if (child->core.managed)
168 XtUnmanageChild (child);
170 if ((child->core.x != parent->core.width) ||
171 (child->core.y != parent->core.height))
172 XtMoveWidget (child, parent->core.width, parent->core.height);
174 cnt++;
179 static XtGeometryResult
180 PreferredSize (w, request, preferred)
181 lwMenuBarWidget w;
182 XtWidgetGeometry *request, *preferred;
184 Widget child;
185 int cnt;
188 * If no changes are being made to the width or height, just agree.
191 if (!(request->request_mode & CWWidth) &&
192 !(request->request_mode & CWHeight))
193 return (XtGeometryYes);
196 * Right now assume everything goes in one row. Calculate the
197 * minimum required width and height.
200 preferred->width = 0;
201 preferred->height = 0;
203 for (cnt = 0; cnt < w->composite.num_children; cnt++)
205 child = w->composite.children[cnt];
206 if (child->core.managed)
208 preferred->width += child->core.width + child->core.border_width*2 +
209 HORIZ_SPACING;
210 if (preferred->height < (Dimension) (child->core.height +
211 child->core.border_width * 2))
212 preferred->height = child->core.height +
213 child->core.border_width * 2;
217 preferred->request_mode = CWWidth | CWHeight;
220 * Case: both height and width requested
223 if ((request->request_mode & CWWidth) &&
224 (request->request_mode & CWHeight))
227 * Ok if same or bigger.
230 if (preferred->width <= request->width &&
231 preferred->height <= request->height)
233 preferred->width = request->width;
234 return (XtGeometryYes);
238 * If both dimensions are too small, say no.
241 else
242 if (preferred->width > request->width &&
243 preferred->height > request->height)
244 return (XtGeometryNo);
247 * Otherwise one must be right, so say almost.
250 else
251 return (XtGeometryAlmost);
255 * If only one dimension is requested, either its OK or it isn't.
258 else
260 if (request->request_mode & CWWidth)
262 if (preferred->width <= request->width)
264 preferred->width = request->width;
265 return (XtGeometryYes);
267 else
268 return (XtGeometryNo);
270 else if (request->request_mode & CWHeight)
272 if (preferred->height <= request->height)
274 return (XtGeometryYes);
276 else
277 return (XtGeometryNo);
280 return (XtGeometryYes);
285 static XtGeometryResult
286 GeometryManager (w, request, reply)
287 Widget w;
288 XtWidgetGeometry *request;
289 XtWidgetGeometry *reply;
292 lwMenuBarWidget parent = (lwMenuBarWidget) w->core.parent;
295 * If the widget wants to move, just say no.
298 if ((request->request_mode & CWX && request->x != w->core.x) ||
299 (request->request_mode & CWY && request->y != w->core.y))
300 return (XtGeometryNo);
303 * Since everything "fits" for now, grant all requests.
306 if (request->request_mode & CWWidth)
307 w->core.width = request->width;
308 if (request->request_mode & CWHeight)
309 w->core.height = request->height;
310 if (request->request_mode & CWBorderWidth)
311 w->core.border_width = request->border_width;
313 do_layout (parent);
314 return (XtGeometryYes);
318 static XtGeometryResult
319 try_layout (parent)
320 lwMenuBarWidget parent;
322 Widget child;
323 int cnt;
324 int managed_children = 0;
325 int managed_width = 0;
326 int new_pos = 0;
329 * Determine number of children which will fit on one line.
330 * For now we ignore the rest, making sure they are unmanaged.
333 cnt = 0;
334 while ((cnt < (int) parent->composite.num_children) &&
335 (managed_width < (int) parent->core.width))
337 child = parent->composite.children[cnt++];
338 if (child->core.managed)
340 managed_children++;
341 managed_width += child->core.width + child->core.border_width * 2 +
342 HORIZ_SPACING;
346 if (managed_width > (int) parent->core.width)
347 return (XtGeometryNo);
348 else
349 return (XtGeometryYes);
354 static void
355 ChangeManaged (w)
356 lwMenuBarWidget w;
358 XtGeometryResult result;
360 result = try_layout (w);
362 if (result != XtGeometryYes)
364 XtUnmanageChild (w->composite.children[w->composite.num_children - 1]);
365 XtMoveWidget (w->composite.children[w->composite.num_children-1],
366 w->core.width, w->core.height);
369 do_layout (w);