File: | SimpleMenu.c |
Location: | line 1000, column 12 |
Description: | Dereference of null pointer (loaded from variable 'child') |
1 | /* | |||
2 | Copyright (c) 1989, 1994 X Consortium | |||
3 | ||||
4 | Permission is hereby granted, free of charge, to any person obtaining a copy | |||
5 | of this software and associated documentation files (the "Software"), to deal | |||
6 | in the Software without restriction, including without limitation the rights | |||
7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |||
8 | copies of the Software, and to permit persons to whom the Software is | |||
9 | furnished to do so, subject to the following conditions: | |||
10 | ||||
11 | The above copyright notice and this permission notice shall be included in | |||
12 | all copies or substantial portions of the Software. | |||
13 | ||||
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |||
17 | X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN | |||
18 | AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | |||
19 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |||
20 | ||||
21 | Except as contained in this notice, the name of the X Consortium shall not be | |||
22 | used in advertising or otherwise to promote the sale, use or other dealings | |||
23 | in this Software without prior written authorization from the X Consortium. | |||
24 | */ | |||
25 | ||||
26 | /* | |||
27 | * SimpleMenu.c - Source code file for SimpleMenu widget. | |||
28 | * | |||
29 | * Date: April 3, 1989 | |||
30 | * | |||
31 | * By: Chris D. Peterson | |||
32 | * MIT X Consortium | |||
33 | * kit@expo.lcs.mit.edu | |||
34 | */ | |||
35 | ||||
36 | #ifdef HAVE_CONFIG_H1 | |||
37 | #include "config.h" | |||
38 | #endif | |||
39 | #include <stdio.h> | |||
40 | #include <limits.h> | |||
41 | #include <X11/IntrinsicP.h> | |||
42 | #include <X11/StringDefs.h> | |||
43 | ||||
44 | #include <X11/Xaw3d/Xaw3dP.h> | |||
45 | #include <X11/Xaw3d/XawInit.h> | |||
46 | #include <X11/Xaw3d/SimpleMenP.h> | |||
47 | #include <X11/Xaw3d/SmeBSBP.h> | |||
48 | #include <X11/Xaw3d/SmeLine.h> | |||
49 | #include <X11/Xaw3d/Cardinals.h> | |||
50 | #include <X11/Xaw3d/ThreeDP.h> | |||
51 | ||||
52 | #include <X11/Xmu/Initer.h> | |||
53 | #include <X11/Xmu/CharSet.h> | |||
54 | ||||
55 | #define streq(a, b)( strcmp((a), (b)) == 0 ) ( strcmp((a), (b)) == 0 ) | |||
56 | ||||
57 | #define offset(field) XtOffsetOf(SimpleMenuRec, simple_menu.field)__builtin_offsetof(SimpleMenuRec, simple_menu.field) | |||
58 | ||||
59 | static XtResource resources[] = { | |||
60 | ||||
61 | /* | |||
62 | * Label Resources. | |||
63 | */ | |||
64 | ||||
65 | {XtNlabel((char*)&XtStrings[429]), XtCLabel((char*)&XtStrings[1151]), XtRString((char*)&XtStrings[1797]), sizeof(String), | |||
66 | offset(label_string), XtRString((char*)&XtStrings[1797]), NULL((void*)0)}, | |||
67 | {XtNlabelClass"labelClass", XtCLabelClass"LabelClass", XtRPointer((char*)&XtStrings[1767]), sizeof(WidgetClass), | |||
68 | offset(label_class), XtRImmediate((char*)&XtStrings[1695]), (XtPointer) NULL((void*)0)}, | |||
69 | ||||
70 | /* | |||
71 | * Layout Resources. | |||
72 | */ | |||
73 | ||||
74 | {XtNrowHeight"rowHeight", XtCRowHeight"RowHeight", XtRDimension((char*)&XtStrings[1618]), sizeof(Dimension), | |||
75 | offset(row_height), XtRImmediate((char*)&XtStrings[1695]), (XtPointer) 0}, | |||
76 | {XtNtopMargin"topMargin", XtCVerticalMargins"VerticalMargins", XtRDimension((char*)&XtStrings[1618]), sizeof(Dimension), | |||
77 | offset(top_margin), XtRImmediate((char*)&XtStrings[1695]), (XtPointer) 0}, | |||
78 | {XtNbottomMargin"bottomMargin", XtCVerticalMargins"VerticalMargins", XtRDimension((char*)&XtStrings[1618]), sizeof(Dimension), | |||
79 | offset(bottom_margin), XtRImmediate((char*)&XtStrings[1695]), (XtPointer) 0}, | |||
80 | {XtNleftWhitespace"leftWhitespace", XtCHorizontalWhitespace"HorizontalWhitespace", XtRDimension((char*)&XtStrings[1618]), sizeof(Dimension), | |||
81 | offset(left_whitespace), XtRImmediate((char*)&XtStrings[1695]), (XtPointer) 0}, | |||
82 | {XtNrightWhitespace"rightWhitespace", XtCHorizontalWhitespace"HorizontalWhitespace", XtRDimension((char*)&XtStrings[1618]), sizeof(Dimension), | |||
83 | offset(right_whitespace), XtRImmediate((char*)&XtStrings[1695]), (XtPointer) 0}, | |||
84 | ||||
85 | /* | |||
86 | * Misc. Resources | |||
87 | */ | |||
88 | ||||
89 | { XtNallowShellResize((char*)&XtShellStrings[280]), XtCAllowShellResize((char*)&XtShellStrings[297]), XtRBoolean((char*)&XtStrings[1561]), sizeof(Boolean), | |||
90 | XtOffsetOf(SimpleMenuRec, shell.allow_shell_resize)__builtin_offsetof(SimpleMenuRec, shell.allow_shell_resize), | |||
91 | XtRImmediate((char*)&XtStrings[1695]), (XtPointer) TRUE1 }, | |||
92 | {XtNcursor"cursor", XtCCursor((char*)&XtStrings[976]), XtRCursor((char*)&XtStrings[1611]), sizeof(Cursor), | |||
93 | offset(cursor), XtRImmediate((char*)&XtStrings[1695]), (XtPointer) None0L}, | |||
94 | {XtNmenuOnScreen"menuOnScreen", XtCMenuOnScreen"MenuOnScreen", XtRBoolean((char*)&XtStrings[1561]), sizeof(Boolean), | |||
95 | offset(menu_on_screen), XtRImmediate((char*)&XtStrings[1695]), (XtPointer) TRUE1}, | |||
96 | {XtNpopupOnEntry"popupOnEntry", XtCPopupOnEntry"PopupOnEntry", XtRWidget((char*)&XtStrings[1865]), sizeof(Widget), | |||
97 | offset(popup_entry), XtRWidget((char*)&XtStrings[1865]), NULL((void*)0)}, | |||
98 | {XtNbackingStore"backingStore", XtCBackingStore"BackingStore", XtRBackingStore"BackingStore", sizeof (int), | |||
99 | offset(backing_store), | |||
100 | XtRImmediate((char*)&XtStrings[1695]), (XtPointer) (Always2 + WhenMapped1 + NotUseful0)}, | |||
101 | {XtNjumpScroll"jumpScroll", XtCJumpScroll"JumpScroll", XtRInt((char*)&XtStrings[1718]), sizeof(int), | |||
102 | offset(jump_val), XtRImmediate((char*)&XtStrings[1695]), (XtPointer)1}, | |||
103 | }; | |||
104 | #undef offset | |||
105 | ||||
106 | static char defaultTranslations[] = | |||
107 | "<EnterWindow>: highlight() \n\ | |||
108 | <LeaveWindow>: unhighlight() \n\ | |||
109 | <BtnMotion>: highlight() \n\ | |||
110 | <BtnUp>: notify() unhighlight() popdown()"; | |||
111 | ||||
112 | /* | |||
113 | * Semi Public function definitions. | |||
114 | */ | |||
115 | ||||
116 | static void Redisplay(Widget, XEvent *, Region); | |||
117 | static void Realize(Widget, XtValueMask *, XSetWindowAttributes *); | |||
118 | static void Resize(Widget); | |||
119 | static void ChangeManaged(Widget); | |||
120 | static void Initialize(Widget, Widget, ArgList, Cardinal *); | |||
121 | static void ClassInitialize(void); | |||
122 | static void ClassPartInitialize(WidgetClass); | |||
123 | static Boolean SetValues(Widget, Widget, Widget, ArgList, Cardinal *); | |||
124 | static Boolean SetValuesHook(Widget, ArgList, Cardinal *); | |||
125 | static XtGeometryResult GeometryManager(Widget, XtWidgetGeometry *, XtWidgetGeometry *); | |||
126 | static void PopupCB(Widget, XtPointer, XtPointer); | |||
127 | static void PopupSubMenu(SimpleMenuWidget); | |||
128 | static void PopdownSubMenu(SimpleMenuWidget); | |||
129 | ||||
130 | /* | |||
131 | * Action Routine Definitions | |||
132 | */ | |||
133 | ||||
134 | static void Highlight(Widget, XEvent *, String *, Cardinal *); | |||
135 | static void Unhighlight(Widget, XEvent *, String *, Cardinal *); | |||
136 | static void Notify(Widget, XEvent *, String *, Cardinal *); | |||
137 | static void PositionMenuAction(Widget, XEvent *, String *, Cardinal *); | |||
138 | static void Popdown(Widget, XEvent *, String *, Cardinal *); | |||
139 | ||||
140 | /* | |||
141 | * Private Function Definitions. | |||
142 | */ | |||
143 | ||||
144 | static void MakeSetValuesRequest(Widget, Dimension, Dimension); | |||
145 | static void CreateLabel(Widget); | |||
146 | static void Layout(Widget, Dimension *, Dimension *); | |||
147 | static void AddPositionAction(XtAppContext, XPointer); | |||
148 | static void PositionMenu(Widget, XPoint *); | |||
149 | static void ChangeCursorOnGrab(Widget, XtPointer, XtPointer); | |||
150 | static void SetMarginWidths(Widget); | |||
151 | static Dimension GetMenuWidth(Widget, Widget); | |||
152 | static Dimension GetMenuHeight(Widget); | |||
153 | static Widget FindMenu(Widget, String); | |||
154 | static SmeObject GetEventEntry(Widget, XEvent *); | |||
155 | static void MoveMenu(Widget, Position, Position); | |||
156 | ||||
157 | static XtActionsRec actionsList[] = | |||
158 | { | |||
159 | {"notify", Notify}, | |||
160 | {"highlight", Highlight}, | |||
161 | {"unhighlight", Unhighlight}, | |||
162 | {"popdown", Popdown} | |||
163 | }; | |||
164 | ||||
165 | static CompositeClassExtensionRec extension_rec = { | |||
166 | /* next_extension */ NULL((void*)0), | |||
167 | /* record_type */ NULLQUARK((XrmQuark) 0), | |||
168 | /* version */ XtCompositeExtensionVersion2L, | |||
169 | /* record_size */ sizeof(CompositeClassExtensionRec), | |||
170 | /* accepts_objects */ TRUE1, | |||
171 | }; | |||
172 | ||||
173 | #define superclass(&overrideShellClassRec) (&overrideShellClassRec) | |||
174 | ||||
175 | SimpleMenuClassRec simpleMenuClassRec = { | |||
176 | { | |||
177 | /* superclass */ (WidgetClass) superclass(&overrideShellClassRec), | |||
178 | /* class_name */ "SimpleMenu", | |||
179 | /* size */ sizeof(SimpleMenuRec), | |||
180 | /* class_initialize */ ClassInitialize, | |||
181 | /* class_part_initialize*/ ClassPartInitialize, | |||
182 | /* Class init'ed */ FALSE0, | |||
183 | /* initialize */ Initialize, | |||
184 | /* initialize_hook */ NULL((void*)0), | |||
185 | /* realize */ Realize, | |||
186 | /* actions */ actionsList, | |||
187 | /* num_actions */ XtNumber(actionsList)((Cardinal) (sizeof(actionsList) / sizeof(actionsList[0]))), | |||
188 | /* resources */ resources, | |||
189 | /* resource_count */ XtNumber(resources)((Cardinal) (sizeof(resources) / sizeof(resources[0]))), | |||
190 | /* xrm_class */ NULLQUARK((XrmQuark) 0), | |||
191 | /* compress_motion */ TRUE1, | |||
192 | /* compress_exposure */ TRUE1, | |||
193 | /* compress_enterleave*/ TRUE1, | |||
194 | /* visible_interest */ FALSE0, | |||
195 | /* destroy */ NULL((void*)0), | |||
196 | /* resize */ Resize, | |||
197 | /* expose */ Redisplay, | |||
198 | /* set_values */ SetValues, | |||
199 | /* set_values_hook */ SetValuesHook, | |||
200 | /* set_values_almost */ XtInheritSetValuesAlmost((XtAlmostProc) _XtInherit), | |||
201 | /* get_values_hook */ NULL((void*)0), | |||
202 | /* accept_focus */ NULL((void*)0), | |||
203 | /* intrinsics version */ XtVersion(11 * 1000 + 6), | |||
204 | /* callback offsets */ NULL((void*)0), | |||
205 | /* tm_table */ defaultTranslations, | |||
206 | /* query_geometry */ NULL((void*)0), | |||
207 | /* display_accelerator*/ NULL((void*)0), | |||
208 | /* extension */ NULL((void*)0) | |||
209 | },{ | |||
210 | /* geometry_manager */ GeometryManager, | |||
211 | /* change_managed */ ChangeManaged, | |||
212 | /* insert_child */ XtInheritInsertChild((XtWidgetProc) _XtInherit), | |||
213 | /* delete_child */ XtInheritDeleteChild((XtWidgetProc) _XtInherit), | |||
214 | /* extension */ NULL((void*)0) | |||
215 | },{ | |||
216 | /* Shell extension */ NULL((void*)0) | |||
217 | },{ | |||
218 | /* Override extension */ NULL((void*)0) | |||
219 | },{ | |||
220 | /* Simple Menu extension*/ NULL((void*)0) | |||
221 | } | |||
222 | }; | |||
223 | ||||
224 | WidgetClass simpleMenuWidgetClass = (WidgetClass)&simpleMenuClassRec; | |||
225 | ||||
226 | #define SMW_ARROW_SIZE8 8 | |||
227 | #define SMW_UNMAPPING0x01 0x01 | |||
228 | #define SMW_POPLEFT0x02 0x02 | |||
229 | ||||
230 | #define ForAllChildren(smw, childP)for ((childP) = (SmeObject *) (smw)->composite.children; ( childP) < (SmeObject *) ((smw)->composite.children + (smw )->composite.num_children); (childP)++) \ | |||
231 | for ((childP) = (SmeObject *) (smw)->composite.children; \ | |||
232 | (childP) < (SmeObject *) ((smw)->composite.children + \ | |||
233 | (smw)->composite.num_children); \ | |||
234 | (childP)++) | |||
235 | ||||
236 | /************************************************************ | |||
237 | * | |||
238 | * Semi-Public Functions. | |||
239 | * | |||
240 | ************************************************************/ | |||
241 | ||||
242 | /* Function Name: ClassInitialize | |||
243 | * Description: Class Initialize routine, called only once. | |||
244 | * Arguments: none. | |||
245 | * Returns: none. | |||
246 | */ | |||
247 | ||||
248 | static void | |||
249 | ClassInitialize(void) | |||
250 | { | |||
251 | XawInitializeWidgetSet(); | |||
252 | XtAddConverter( XtRString((char*)&XtStrings[1797]), XtRBackingStore"BackingStore", XmuCvtStringToBackingStore, | |||
253 | (XtConvertArgList)NULL((void*)0), (Cardinal)0 ); | |||
254 | XmuAddInitializer( AddPositionAction, NULL((void*)0)); | |||
255 | } | |||
256 | ||||
257 | /* Function Name: ClassInitialize | |||
258 | * Description: Class Part Initialize routine, called for every | |||
259 | * subclass. Makes sure that the subclasses pick up | |||
260 | * the extension record. | |||
261 | * Arguments: wc - the widget class of the subclass. | |||
262 | * Returns: none. | |||
263 | */ | |||
264 | ||||
265 | static void | |||
266 | ClassPartInitialize(WidgetClass wc) | |||
267 | { | |||
268 | SimpleMenuWidgetClass smwc = (SimpleMenuWidgetClass) wc; | |||
269 | ||||
270 | /* | |||
271 | * Make sure that our subclass gets the extension rec too. | |||
272 | */ | |||
273 | ||||
274 | extension_rec.next_extension = smwc->composite_class.extension; | |||
275 | smwc->composite_class.extension = (XtPointer) &extension_rec; | |||
276 | } | |||
277 | ||||
278 | /* Function Name: Initialize | |||
279 | * Description: Initializes the simple menu widget | |||
280 | * Arguments: request - the widget requested by the argument list. | |||
281 | * new - the new widget with both resource and non | |||
282 | * resource values. | |||
283 | * Returns: none. | |||
284 | */ | |||
285 | ||||
286 | /* ARGSUSED */ | |||
287 | static void | |||
288 | Initialize(Widget request, Widget new, ArgList args, Cardinal *num_args) | |||
289 | { | |||
290 | SimpleMenuWidget smw = (SimpleMenuWidget) new; | |||
291 | ||||
292 | XmuCallInitializers(XtWidgetToApplicationContext(new)); | |||
293 | ||||
294 | smw->simple_menu.label = NULL((void*)0); | |||
295 | smw->simple_menu.entry_set = NULL((void*)0); | |||
296 | smw->simple_menu.recursive_set_values = FALSE0; | |||
297 | smw->simple_menu.first_entry = NULL((void*)0); | |||
298 | smw->simple_menu.current_first = NULL((void*)0); | |||
299 | smw->simple_menu.first_y = 0; | |||
300 | smw->simple_menu.too_tall = FALSE0; | |||
301 | smw->simple_menu.sub_menu = NULL((void*)0); | |||
302 | smw->simple_menu.state = 0; | |||
303 | ||||
304 | XtAddCallback(new, XtNpopupCallback((char*)&XtStrings[534]), PopupCB, NULL((void*)0)); | |||
305 | ||||
306 | if (smw->simple_menu.label_class == NULL((void*)0)) | |||
| ||||
307 | smw->simple_menu.label_class = smeBSBObjectClass; | |||
308 | ||||
309 | if (smw->simple_menu.label_string != NULL((void*)0)) | |||
310 | CreateLabel(new); | |||
311 | ||||
312 | /* GetMenuHeight() needs this */ | |||
313 | smw->simple_menu.threeD = XtVaCreateWidget("threeD", threeDWidgetClass, | |||
314 | new, | |||
315 | XtNx((char*)&XtStrings[885]), 0, XtNy((char*)&XtStrings[887]), 0, XtNwidth((char*)&XtStrings[872]), /* dummy */ 10, XtNheight((char*)&XtStrings[234]), /* dummy */ 10, | |||
316 | NULL((void*)0)); | |||
317 | ||||
318 | smw->simple_menu.menu_width = TRUE1; | |||
319 | ||||
320 | if (smw->core.width == 0) { | |||
321 | smw->simple_menu.menu_width = FALSE0; | |||
322 | smw->core.width = GetMenuWidth(new, (Widget)NULL((void*)0)); | |||
323 | } | |||
324 | ||||
325 | smw->simple_menu.menu_height = TRUE1; | |||
326 | ||||
327 | if (smw->core.height == 0) { | |||
328 | smw->simple_menu.menu_height = FALSE0; | |||
329 | smw->core.height = GetMenuHeight(new); | |||
330 | } | |||
331 | ||||
332 | /* add a popup_callback routine for changing the cursor */ | |||
333 | XtAddCallback(new, XtNpopupCallback((char*)&XtStrings[534]), ChangeCursorOnGrab, (XtPointer)NULL((void*)0)); | |||
334 | } | |||
335 | ||||
336 | /* Function Name: Redisplay | |||
337 | * Description: Redisplays the contents of the widget. | |||
338 | * Arguments: w - the simple menu widget. | |||
339 | * event - the X event that caused this redisplay. | |||
340 | * region - the region the needs to be repainted. | |||
341 | * Returns: none. | |||
342 | */ | |||
343 | ||||
344 | /* ARGSUSED */ | |||
345 | static void | |||
346 | Redisplay(Widget w, XEvent * event, Region region) | |||
347 | { | |||
348 | SimpleMenuWidget smw = (SimpleMenuWidget)w; | |||
349 | SmeObject *entry; | |||
350 | SmeObjectClass class; | |||
351 | ThreeDWidget tdw = (ThreeDWidget)smw->simple_menu.threeD; | |||
352 | RectObjPart old_pos; | |||
353 | int y, max_y, new_y, dy, s = tdw->threeD.shadow_width; | |||
354 | Boolean can_paint; | |||
355 | XPoint point[3]; | |||
356 | ||||
357 | if (region == NULL((void*)0)) | |||
358 | XClearWindow(XtDisplay(w)(((w)->core.screen)->display), XtWindow(w)((w)->core.window)); | |||
359 | ||||
360 | if (XtIsRealized((Widget)smw)(XtWindowOfObject((Widget)smw) != 0L)) | |||
361 | _ShadowSurroundedBox((Widget)smw, tdw, | |||
362 | 0, 0, smw->core.width, smw->core.height, | |||
363 | tdw->threeD.relief, True1); | |||
364 | ||||
365 | smw->simple_menu.didnt_fit = False0; | |||
366 | y = 0; | |||
367 | max_y = HeightOfScreen(XtScreen(w))((((w)->core.screen))->height) - s; | |||
368 | new_y = -(*(SmeObject *)(smw)->composite.children)->rectangle.y; | |||
369 | can_paint = False0; | |||
370 | ||||
371 | /* check and paint each of the entries - including the label */ | |||
372 | ForAllChildren(smw, entry)for ((entry) = (SmeObject *) (smw)->composite.children; (entry ) < (SmeObject *) ((smw)->composite.children + (smw)-> composite.num_children); (entry)++) | |||
373 | { | |||
374 | if (!XtIsManaged((Widget)*entry)) continue; | |||
375 | ||||
376 | if (smw->simple_menu.first_entry == NULL((void*)0)) | |||
377 | { | |||
378 | smw->simple_menu.first_entry = entry; | |||
379 | smw->simple_menu.current_first = entry; | |||
380 | } | |||
381 | ||||
382 | if (smw->simple_menu.too_tall) | |||
383 | { | |||
384 | dy = 0; | |||
385 | ||||
386 | if (entry == (smw->simple_menu.current_first)) | |||
387 | { | |||
388 | new_y = (*entry)->rectangle.y - 1; | |||
389 | ||||
390 | if (smw->simple_menu.current_first != smw->simple_menu.first_entry) | |||
391 | { | |||
392 | point[0].x = (*entry)->rectangle.width / 2; | |||
393 | point[0].y = s + 1; | |||
394 | point[1].x = (*entry)->rectangle.width / 2 - SMW_ARROW_SIZE8 / 2; | |||
395 | point[1].y = s + SMW_ARROW_SIZE8; | |||
396 | point[2].x = (*entry)->rectangle.width / 2 + SMW_ARROW_SIZE8 / 2; | |||
397 | point[2].y = s + SMW_ARROW_SIZE8; | |||
398 | XFillPolygon(XtDisplay(w)(((w)->core.screen)->display), smw->core.window, | |||
399 | tdw->threeD.bot_shadow_GC, point, 3, Convex2, | |||
400 | CoordModeOrigin0); | |||
401 | ||||
402 | new_y -= SMW_ARROW_SIZE8; | |||
403 | dy = SMW_ARROW_SIZE8; | |||
404 | } | |||
405 | ||||
406 | smw->simple_menu.first_y = new_y; | |||
407 | can_paint = True1; | |||
408 | } | |||
409 | else if (!can_paint) | |||
410 | continue; | |||
411 | ||||
412 | old_pos = (*entry)->rectangle; | |||
413 | (*entry)->rectangle.y -= new_y; | |||
414 | ||||
415 | if ((*entry)->rectangle.y + (*entry)->rectangle.height + dy > max_y) | |||
416 | { | |||
417 | smw->simple_menu.last_y = (*entry)->rectangle.y; | |||
418 | point[0].x = (*entry)->rectangle.width / 2; | |||
419 | point[0].y = max_y - 1; | |||
420 | point[1].x = (*entry)->rectangle.width / 2 - SMW_ARROW_SIZE8 / 2; | |||
421 | point[1].y = max_y - SMW_ARROW_SIZE8; | |||
422 | point[2].x = (*entry)->rectangle.width / 2 + SMW_ARROW_SIZE8 / 2; | |||
423 | point[2].y = max_y - SMW_ARROW_SIZE8; | |||
424 | XFillPolygon(XtDisplay(w)(((w)->core.screen)->display), smw->core.window, | |||
425 | tdw->threeD.bot_shadow_GC, point, 3, Convex2, | |||
426 | CoordModeOrigin0); | |||
427 | ||||
428 | smw->simple_menu.didnt_fit = True1; | |||
429 | (*entry)->rectangle = old_pos; | |||
430 | break; | |||
431 | } | |||
432 | } | |||
433 | ||||
434 | /* | |||
435 | if (region != NULL) | |||
436 | switch (XRectInRegion(region, | |||
437 | (int)(*entry)->rectangle.x, (int)(*entry)->rectangle.y, | |||
438 | (unsigned int)(*entry)->rectangle.width, | |||
439 | (unsigned int)(*entry)->rectangle.height)) | |||
440 | { | |||
441 | case RectangleIn: | |||
442 | case RectanglePart: | |||
443 | break; | |||
444 | default: | |||
445 | continue; | |||
446 | } | |||
447 | */ | |||
448 | ||||
449 | class = (SmeObjectClass)(*entry)->object.widget_class; | |||
450 | ||||
451 | if (class->rect_class.expose != NULL((void*)0)) | |||
452 | (class->rect_class.expose)((Widget)*entry, NULL((void*)0), NULL((void*)0)); | |||
453 | ||||
454 | if (smw->simple_menu.too_tall) (*entry)->rectangle = old_pos; | |||
455 | ||||
456 | y += (*entry)->rectangle.height; | |||
457 | } | |||
458 | } | |||
459 | ||||
460 | /* Function Name: Realize | |||
461 | * Description: Realizes the widget. | |||
462 | * Arguments: w - the simple menu widget. | |||
463 | * mask - value mask for the window to create. | |||
464 | * attrs - attributes for the window to create. | |||
465 | * Returns: none | |||
466 | */ | |||
467 | ||||
468 | static void | |||
469 | Realize(Widget w, XtValueMask * mask, XSetWindowAttributes * attrs) | |||
470 | { | |||
471 | SimpleMenuWidget smw = (SimpleMenuWidget) w; | |||
472 | ||||
473 | attrs->cursor = smw->simple_menu.cursor; | |||
474 | *mask |= CWCursor(1L<<14); | |||
475 | if ((smw->simple_menu.backing_store == Always2) || | |||
476 | (smw->simple_menu.backing_store == NotUseful0) || | |||
477 | (smw->simple_menu.backing_store == WhenMapped1) ) { | |||
478 | *mask |= CWBackingStore(1L<<6); | |||
479 | attrs->backing_store = smw->simple_menu.backing_store; | |||
480 | } | |||
481 | else | |||
482 | *mask &= ~CWBackingStore(1L<<6); | |||
483 | ||||
484 | /* check if the menu is too big */ | |||
485 | if (smw->core.height >= HeightOfScreen(XtScreen(w))((((w)->core.screen))->height)) { | |||
486 | smw->simple_menu.too_tall = TRUE1; | |||
487 | smw->core.height = HeightOfScreen(XtScreen(w))((((w)->core.screen))->height); | |||
488 | } | |||
489 | ||||
490 | (*superclass(&overrideShellClassRec)->core_class.realize) (w, mask, attrs); | |||
491 | } | |||
492 | ||||
493 | /* Function Name: Resize | |||
494 | * Description: Handle the menu being resized. | |||
495 | * Arguments: w - the simple menu widget or any of its object children. | |||
496 | * Returns: none. | |||
497 | */ | |||
498 | ||||
499 | static void | |||
500 | Resize(Widget w) | |||
501 | { | |||
502 | /* | |||
503 | * The sole purpose of this function is to force an initial | |||
504 | * layout by handling a call from some child widget. Ick. | |||
505 | */ | |||
506 | ||||
507 | if (XtIsSubclass(w, smeBSBObjectClass)) | |||
508 | { | |||
509 | Widget parent = XtParent(w)((w)->core.parent); | |||
510 | ||||
511 | if (!XtIsRealized(parent)(XtWindowOfObject(parent) != 0L)) | |||
512 | XtRealizeWidget(parent); | |||
513 | ||||
514 | Layout(w, (Dimension *)NULL((void*)0), (Dimension *)NULL((void*)0)); | |||
515 | } | |||
516 | } | |||
517 | ||||
518 | /* Function Name: SetValues | |||
519 | * Description: Relayout the menu when one of the resources is changed. | |||
520 | * Arguments: current - current state of the widget. | |||
521 | * request - what was requested. | |||
522 | * new - what the widget will become. | |||
523 | * Returns: none | |||
524 | */ | |||
525 | ||||
526 | /* ARGSUSED */ | |||
527 | static Boolean | |||
528 | SetValues(Widget current, Widget request, Widget new, ArgList args, Cardinal *num_args) | |||
529 | { | |||
530 | SimpleMenuWidget smw_old = (SimpleMenuWidget) current; | |||
531 | SimpleMenuWidget smw_new = (SimpleMenuWidget) new; | |||
532 | Boolean ret_val = FALSE0, layout = FALSE0; | |||
533 | ||||
534 | if (!XtIsRealized(current)(XtWindowOfObject(current) != 0L)) return(FALSE0); | |||
535 | ||||
536 | if (!smw_new->simple_menu.recursive_set_values) { | |||
537 | if (smw_new->core.width != smw_old->core.width) { | |||
538 | smw_new->simple_menu.menu_width = (smw_new->core.width != 0); | |||
539 | layout = TRUE1; | |||
540 | } | |||
541 | if (smw_new->core.height != smw_old->core.height) { | |||
542 | smw_new->simple_menu.menu_height = (smw_new->core.height != 0); | |||
543 | layout = TRUE1; | |||
544 | } | |||
545 | } | |||
546 | ||||
547 | if (smw_old->simple_menu.cursor != smw_new->simple_menu.cursor) | |||
548 | XDefineCursor(XtDisplay(new)(((new)->core.screen)->display), | |||
549 | XtWindow(new)((new)->core.window), smw_new->simple_menu.cursor); | |||
550 | ||||
551 | if (smw_old->simple_menu.label_string !=smw_new->simple_menu.label_string) { | |||
552 | if (smw_new->simple_menu.label_string == NULL((void*)0)) /* Destroy. */ | |||
553 | XtDestroyWidget((Widget) smw_old->simple_menu.label); | |||
554 | else if (smw_old->simple_menu.label_string == NULL((void*)0)) /* Create. */ | |||
555 | CreateLabel(new); | |||
556 | else { /* Change. */ | |||
557 | Arg arglist[1]; | |||
558 | ||||
559 | XtSetArg(arglist[0], XtNlabel, smw_new->simple_menu.label_string)((void)( (arglist[0]).name = (((char*)&XtStrings[429])), ( arglist[0]).value = (XtArgVal)(smw_new->simple_menu.label_string ) )); | |||
560 | XtSetValues((Widget) smw_new->simple_menu.label, arglist, ONE((Cardinal)1)); | |||
561 | } | |||
562 | } | |||
563 | ||||
564 | if (smw_old->simple_menu.label_class != smw_new->simple_menu.label_class) | |||
565 | XtAppWarning(XtWidgetToApplicationContext(new), | |||
566 | "No Dynamic class change of the SimpleMenu Label."); | |||
567 | ||||
568 | if ((smw_old->simple_menu.top_margin != smw_new->simple_menu.top_margin) || | |||
569 | (smw_old->simple_menu.bottom_margin != | |||
570 | smw_new->simple_menu.bottom_margin) /* filler................. */ ) { | |||
571 | layout = TRUE1; | |||
572 | ret_val = TRUE1; | |||
573 | } | |||
574 | ||||
575 | if (smw_old->simple_menu.left_whitespace != smw_new->simple_menu.left_whitespace) { | |||
576 | layout = TRUE1; | |||
577 | ret_val = TRUE1; | |||
578 | } | |||
579 | ||||
580 | if (smw_old->simple_menu.right_whitespace != smw_new->simple_menu.right_whitespace) { | |||
581 | layout = TRUE1; | |||
582 | ret_val = TRUE1; | |||
583 | } | |||
584 | ||||
585 | if (layout) | |||
586 | Layout(new, (Dimension *)NULL((void*)0), (Dimension *)NULL((void*)0)); | |||
587 | ||||
588 | return(ret_val); | |||
589 | } | |||
590 | ||||
591 | /* Function Name: SetValuesHook | |||
592 | * Description: To handle a special case, this is passed the | |||
593 | * actual arguments. | |||
594 | * Arguments: w - the menu widget. | |||
595 | * arglist - the argument list passed to XtSetValues. | |||
596 | * num_args - the number of args. | |||
597 | * Returns: none | |||
598 | */ | |||
599 | ||||
600 | /* | |||
601 | * If the user actually passed a width and height to the widget | |||
602 | * then this MUST be used, rather than our newly calculated width and | |||
603 | * height. | |||
604 | */ | |||
605 | ||||
606 | static Boolean | |||
607 | SetValuesHook(Widget w, ArgList arglist, Cardinal *num_args) | |||
608 | { | |||
609 | Cardinal i; | |||
610 | Dimension width, height; | |||
611 | ||||
612 | width = w->core.width; | |||
613 | height = w->core.height; | |||
614 | ||||
615 | for ( i = 0 ; i < *num_args ; i++) { | |||
616 | if ( streq(arglist[i].name, XtNwidth)( strcmp((arglist[i].name), (((char*)&XtStrings[872]))) == 0 ) ) | |||
617 | width = (Dimension) arglist[i].value; | |||
618 | if ( streq(arglist[i].name, XtNheight)( strcmp((arglist[i].name), (((char*)&XtStrings[234]))) == 0 ) ) | |||
619 | height = (Dimension) arglist[i].value; | |||
620 | } | |||
621 | ||||
622 | if ((width != w->core.width) || (height != w->core.height)) | |||
623 | MakeSetValuesRequest(w, width, height); | |||
624 | return(FALSE0); | |||
625 | } | |||
626 | ||||
627 | /************************************************************ | |||
628 | * | |||
629 | * Geometry Management routines. | |||
630 | * | |||
631 | ************************************************************/ | |||
632 | ||||
633 | /* Function Name: GeometryManager | |||
634 | * Description: This is the SimpleMenu Widget's Geometry Manager. | |||
635 | * Arguments: w - the Menu Entry making the request. | |||
636 | * request - requested new geometry. | |||
637 | * reply - the allowed geometry. | |||
638 | * Returns: XtGeometry{Yes, No, Almost}. | |||
639 | */ | |||
640 | ||||
641 | static XtGeometryResult | |||
642 | GeometryManager(Widget w, XtWidgetGeometry * request, XtWidgetGeometry * reply) | |||
643 | { | |||
644 | SimpleMenuWidget smw = (SimpleMenuWidget) XtParent(w)((w)->core.parent); | |||
645 | SmeObject entry = (SmeObject) w; | |||
646 | XtGeometryMask mode = request->request_mode; | |||
647 | XtGeometryResult answer; | |||
648 | Dimension old_height, old_width; | |||
649 | ||||
650 | if ( !(mode & CWWidth(1<<2)) && !(mode & CWHeight(1<<3)) ) | |||
651 | return(XtGeometryNo); | |||
652 | ||||
653 | reply->width = request->width; | |||
654 | reply->height = request->height; | |||
655 | ||||
656 | old_width = entry->rectangle.width; | |||
657 | old_height = entry->rectangle.height; | |||
658 | ||||
659 | Layout(w, &(reply->width), &(reply->height) ); | |||
660 | ||||
661 | /* | |||
662 | * Since we are an override shell and have no parent there is no one to | |||
663 | * ask to see if this geom change is okay, so I am just going to assume | |||
664 | * we can do whatever we want. If you subclass be very careful with this | |||
665 | * assumption, it could bite you. | |||
666 | * | |||
667 | * Chris D. Peterson - Sept. 1989. | |||
668 | */ | |||
669 | ||||
670 | if ( (reply->width == request->width) && | |||
671 | (reply->height == request->height) ) { | |||
672 | ||||
673 | if ( mode & XtCWQueryOnly(1 << 7) ) { | |||
674 | entry->rectangle.width = old_width; | |||
675 | entry->rectangle.height = old_height; | |||
676 | } | |||
677 | else { | |||
678 | /* Actually perform the layout */ | |||
679 | Layout(( Widget) smw, (Dimension *)NULL((void*)0), (Dimension *)NULL((void*)0)); | |||
680 | } | |||
681 | answer = XtGeometryDone; | |||
682 | } | |||
683 | else { | |||
684 | entry->rectangle.width = old_width; | |||
685 | entry->rectangle.height = old_height; | |||
686 | ||||
687 | if ( ((reply->width == request->width) && !(mode & CWHeight(1<<3))) || | |||
688 | ((reply->height == request->height) && !(mode & CWWidth(1<<2))) || | |||
689 | ((reply->width == request->width) && | |||
690 | (reply->height == request->height)) ) | |||
691 | answer = XtGeometryNo; | |||
692 | else { | |||
693 | answer = XtGeometryAlmost; | |||
694 | reply->request_mode = 0; | |||
695 | if (reply->width != request->width) | |||
696 | reply->request_mode |= CWWidth(1<<2); | |||
697 | if (reply->height != request->height) | |||
698 | reply->request_mode |= CWHeight(1<<3); | |||
699 | } | |||
700 | } | |||
701 | return(answer); | |||
702 | } | |||
703 | ||||
704 | /* Function Name: ChangeManaged | |||
705 | * Description: called whenever a new child is managed. | |||
706 | * Arguments: w - the simple menu widget. | |||
707 | * Returns: none. | |||
708 | */ | |||
709 | ||||
710 | static void | |||
711 | ChangeManaged(Widget w) | |||
712 | { | |||
713 | Layout(w, (Dimension *)NULL((void*)0), (Dimension *)NULL((void*)0)); | |||
714 | } | |||
715 | ||||
716 | /************************************************************ | |||
717 | * | |||
718 | * Global Action Routines. | |||
719 | * | |||
720 | * These actions routines will be added to the application's | |||
721 | * global action list. | |||
722 | * | |||
723 | ************************************************************/ | |||
724 | ||||
725 | /* Function Name: PositionMenuAction | |||
726 | * Description: Positions the simple menu widget. | |||
727 | * Arguments: w - a widget (no the simple menu widget.) | |||
728 | * event - the event that caused this action. | |||
729 | * params, num_params - parameters passed to the routine. | |||
730 | * we expect the name of the menu here. | |||
731 | * Returns: none | |||
732 | */ | |||
733 | ||||
734 | /* ARGSUSED */ | |||
735 | static void | |||
736 | PositionMenuAction(Widget w, XEvent * event, String * params, Cardinal * num_params) | |||
737 | { | |||
738 | Widget menu; | |||
739 | XPoint loc; | |||
740 | ||||
741 | if (*num_params != 1) { | |||
742 | char error_buf[BUFSIZ1024]; | |||
743 | (void) sprintf(error_buf, "%s %s",__builtin___sprintf_chk (error_buf, 0, __builtin_object_size ( error_buf, 2 > 1 ? 1 : 0), "%s %s", "Xaw - SimpleMenuWidget: position menu action expects only one" , "parameter which is the name of the menu.") | |||
744 | "Xaw - SimpleMenuWidget: position menu action expects only one",__builtin___sprintf_chk (error_buf, 0, __builtin_object_size ( error_buf, 2 > 1 ? 1 : 0), "%s %s", "Xaw - SimpleMenuWidget: position menu action expects only one" , "parameter which is the name of the menu.") | |||
745 | "parameter which is the name of the menu.")__builtin___sprintf_chk (error_buf, 0, __builtin_object_size ( error_buf, 2 > 1 ? 1 : 0), "%s %s", "Xaw - SimpleMenuWidget: position menu action expects only one" , "parameter which is the name of the menu."); | |||
746 | XtAppWarning(XtWidgetToApplicationContext(w), error_buf); | |||
747 | return; | |||
748 | } | |||
749 | ||||
750 | if ( (menu = FindMenu(w, params[0])) == NULL((void*)0)) { | |||
751 | char error_buf[BUFSIZ1024]; | |||
752 | (void) sprintf(error_buf, "%s '%s'",__builtin___sprintf_chk (error_buf, 0, __builtin_object_size ( error_buf, 2 > 1 ? 1 : 0), "%s '%s'", "Xaw - SimpleMenuWidget: could not find menu named: " , params[0]) | |||
753 | "Xaw - SimpleMenuWidget: could not find menu named: ", params[0])__builtin___sprintf_chk (error_buf, 0, __builtin_object_size ( error_buf, 2 > 1 ? 1 : 0), "%s '%s'", "Xaw - SimpleMenuWidget: could not find menu named: " , params[0]); | |||
754 | XtAppWarning(XtWidgetToApplicationContext(w), error_buf); | |||
755 | return; | |||
756 | } | |||
757 | ||||
758 | switch (event->type) { | |||
759 | case ButtonPress4: | |||
760 | case ButtonRelease5: | |||
761 | loc.x = event->xbutton.x_root; | |||
762 | loc.y = event->xbutton.y_root; | |||
763 | PositionMenu(menu, &loc); | |||
764 | break; | |||
765 | case EnterNotify7: | |||
766 | case LeaveNotify8: | |||
767 | loc.x = event->xcrossing.x_root; | |||
768 | loc.y = event->xcrossing.y_root; | |||
769 | PositionMenu(menu, &loc); | |||
770 | break; | |||
771 | case MotionNotify6: | |||
772 | loc.x = event->xmotion.x_root; | |||
773 | loc.y = event->xmotion.y_root; | |||
774 | PositionMenu(menu, &loc); | |||
775 | break; | |||
776 | default: | |||
777 | PositionMenu(menu, (XPoint *)NULL((void*)0)); | |||
778 | break; | |||
779 | } | |||
780 | } | |||
781 | ||||
782 | /************************************************************ | |||
783 | * | |||
784 | * Widget Action Routines. | |||
785 | * | |||
786 | ************************************************************/ | |||
787 | ||||
788 | /* Function Name: Unhighlight | |||
789 | * Description: Unhighlights current entry. | |||
790 | * Arguments: w - the simple menu widget. | |||
791 | * event - the event that caused this action. | |||
792 | * params, num_params - ** NOT USED ** | |||
793 | * Returns: none | |||
794 | */ | |||
795 | ||||
796 | /* ARGSUSED */ | |||
797 | static void | |||
798 | Unhighlight(Widget w, XEvent * event, String * params, Cardinal * num_params) | |||
799 | { | |||
800 | SimpleMenuWidget smw = (SimpleMenuWidget) w; | |||
801 | SimpleMenuWidget sub = (SimpleMenuWidget) smw->simple_menu.sub_menu; | |||
802 | SmeObject entry = smw->simple_menu.entry_set; | |||
803 | SmeObjectClass class; | |||
804 | int old_pos; | |||
805 | ||||
806 | if (entry == NULL((void*)0) || entry == GetEventEntry(w, event)) { | |||
807 | smw->simple_menu.entry_set = NULL((void*)0); | |||
808 | PopdownSubMenu(smw); | |||
809 | return; | |||
810 | } | |||
811 | ||||
812 | if (event->xcrossing.y < 0 || event->xcrossing.y >= (int)smw->core.height) | |||
813 | PopdownSubMenu(smw); | |||
814 | else if (sub && | |||
815 | ((event->xcrossing.x < 0 && | |||
816 | !(sub->simple_menu.state & SMW_POPLEFT0x02)) || | |||
817 | (event->xcrossing.x >= (int)smw->core.width && | |||
818 | (sub->simple_menu.state & SMW_POPLEFT0x02)))) | |||
819 | PopdownSubMenu(smw); | |||
820 | ||||
821 | smw->simple_menu.entry_set = NULL((void*)0); | |||
822 | class = (SmeObjectClass) entry->object.widget_class; | |||
823 | ||||
824 | /* backup, then restore, original entry position */ | |||
825 | old_pos = entry->rectangle.y; | |||
826 | entry->rectangle.y -= smw->simple_menu.first_y; | |||
827 | ||||
828 | (class->sme_class.unhighlight) ((Widget) entry); | |||
829 | ||||
830 | entry->rectangle.y = old_pos; | |||
831 | } | |||
832 | ||||
833 | /* Function Name: Highlight | |||
834 | * Description: Highlights current entry. | |||
835 | * Arguments: w - the simple menu widget. | |||
836 | * event - the event that caused this action. | |||
837 | * params, num_params - ** NOT USED ** | |||
838 | * Returns: none | |||
839 | */ | |||
840 | ||||
841 | /* ARGSUSED */ | |||
842 | static void | |||
843 | Highlight(Widget w, XEvent * event, String * params, Cardinal * num_params) | |||
844 | { | |||
845 | SimpleMenuWidget smw = (SimpleMenuWidget) w; | |||
846 | SmeObject entry; | |||
847 | SmeObjectClass class; | |||
848 | int old_pos; | |||
849 | ||||
850 | if (!XtIsSensitive(w)) return; | |||
851 | ||||
852 | entry = GetEventEntry(w, event); | |||
853 | if (entry == smw->simple_menu.entry_set) | |||
854 | return; | |||
855 | ||||
856 | PopdownSubMenu(smw); | |||
857 | Unhighlight(w, event, params, num_params); | |||
858 | ||||
859 | if (entry == NULL((void*)0)) | |||
860 | return; | |||
861 | if (!XtIsSensitive((Widget) entry)) { | |||
862 | smw->simple_menu.entry_set = NULL((void*)0); | |||
863 | return; | |||
864 | } | |||
865 | ||||
866 | if (!(smw->simple_menu.state & SMW_UNMAPPING0x01)) { | |||
867 | smw->simple_menu.entry_set = entry; | |||
868 | class = (SmeObjectClass) entry->object.widget_class; | |||
869 | ||||
870 | /* backup, then restore, original entry position */ | |||
871 | old_pos = entry->rectangle.y; | |||
872 | entry->rectangle.y -= smw->simple_menu.first_y; | |||
873 | ||||
874 | (class->sme_class.highlight) ((Widget) entry); | |||
875 | if (XtIsSubclass((Widget)entry, smeBSBObjectClass)) | |||
876 | PopupSubMenu(smw); | |||
877 | ||||
878 | entry->rectangle.y = old_pos; | |||
879 | } | |||
880 | } | |||
881 | ||||
882 | /* Function Name: Notify | |||
883 | * Description: Notify user of current entry. | |||
884 | * Arguments: w - the simple menu widget. | |||
885 | * event - the event that caused this action. | |||
886 | * params, num_params - ** NOT USED ** | |||
887 | * Returns: none | |||
888 | */ | |||
889 | ||||
890 | /* ARGSUSED */ | |||
891 | static void | |||
892 | Notify(Widget w, XEvent * event, String * params, Cardinal * num_params) | |||
893 | { | |||
894 | SimpleMenuWidget smw = (SimpleMenuWidget) w; | |||
895 | SmeObject entry = smw->simple_menu.entry_set; | |||
896 | SmeObjectClass class; | |||
897 | ||||
898 | if ( (entry == NULL((void*)0)) || !XtIsSensitive((Widget) entry ) ) return; | |||
899 | ||||
900 | class = (SmeObjectClass) entry->object.widget_class; | |||
901 | (class->sme_class.notify)( (Widget) entry ); | |||
902 | } | |||
903 | ||||
904 | /************************************************************ | |||
905 | * | |||
906 | * Public Functions. | |||
907 | * | |||
908 | ************************************************************/ | |||
909 | ||||
910 | /* Function Name: XawSimpleMenuAddGlobalActions | |||
911 | * Description: adds the global actions to the simple menu widget. | |||
912 | * Arguments: app_con - the appcontext. | |||
913 | * Returns: none. | |||
914 | */ | |||
915 | ||||
916 | void | |||
917 | XawSimpleMenuAddGlobalActions(XtAppContext app_con) | |||
918 | { | |||
919 | XtInitializeWidgetClass(simpleMenuWidgetClass); | |||
920 | XmuCallInitializers( app_con ); | |||
921 | } | |||
922 | ||||
923 | ||||
924 | /* Function Name: XawSimpleMenuGetActiveEntry | |||
925 | * Description: Gets the currently active (set) entry. | |||
926 | * Arguments: w - the smw widget. | |||
927 | * Returns: the currently set entry or NULL if none is set. | |||
928 | */ | |||
929 | ||||
930 | Widget | |||
931 | XawSimpleMenuGetActiveEntry(Widget w) | |||
932 | { | |||
933 | SimpleMenuWidget smw = (SimpleMenuWidget) w; | |||
934 | ||||
935 | return( (Widget) smw->simple_menu.entry_set); | |||
936 | } | |||
937 | ||||
938 | /* Function Name: XawSimpleMenuClearActiveEntry | |||
939 | * Description: Unsets the currently active (set) entry. | |||
940 | * Arguments: w - the smw widget. | |||
941 | * Returns: none. | |||
942 | */ | |||
943 | ||||
944 | void | |||
945 | XawSimpleMenuClearActiveEntry(Widget w) | |||
946 | { | |||
947 | SimpleMenuWidget smw = (SimpleMenuWidget) w; | |||
948 | ||||
949 | smw->simple_menu.entry_set = NULL((void*)0); | |||
950 | } | |||
951 | ||||
952 | /************************************************************ | |||
953 | * | |||
954 | * Private Functions. | |||
955 | * | |||
956 | ************************************************************/ | |||
957 | ||||
958 | /* Function Name: CreateLabel | |||
959 | * Description: Creates a the menu label. | |||
960 | * Arguments: w - the smw widget. | |||
961 | * Returns: none. | |||
962 | * | |||
963 | * Creates the label object and makes sure it is the first child in | |||
964 | * in the list. | |||
965 | */ | |||
966 | ||||
967 | static void | |||
968 | CreateLabel(Widget w) | |||
969 | { | |||
970 | SimpleMenuWidget smw = (SimpleMenuWidget) w; | |||
971 | Widget * child, * next_child; | |||
972 | int i; | |||
973 | Arg args[2]; | |||
974 | ||||
975 | if ( (smw->simple_menu.label_string == NULL((void*)0)) || | |||
976 | (smw->simple_menu.label != NULL((void*)0)) ) { | |||
977 | char error_buf[BUFSIZ1024]; | |||
978 | ||||
979 | (void) sprintf(error_buf, "Xaw Simple Menu Widget: %s or %s, %s",__builtin___sprintf_chk (error_buf, 0, __builtin_object_size ( error_buf, 2 > 1 ? 1 : 0), "Xaw Simple Menu Widget: %s or %s, %s" , "label string is NULL", "label already exists", "no label is being created." ) | |||
980 | "label string is NULL", "label already exists",__builtin___sprintf_chk (error_buf, 0, __builtin_object_size ( error_buf, 2 > 1 ? 1 : 0), "Xaw Simple Menu Widget: %s or %s, %s" , "label string is NULL", "label already exists", "no label is being created." ) | |||
981 | "no label is being created.")__builtin___sprintf_chk (error_buf, 0, __builtin_object_size ( error_buf, 2 > 1 ? 1 : 0), "Xaw Simple Menu Widget: %s or %s, %s" , "label string is NULL", "label already exists", "no label is being created." ); | |||
982 | XtAppWarning(XtWidgetToApplicationContext(w), error_buf); | |||
983 | return; | |||
984 | } | |||
985 | ||||
986 | XtSetArg(args[0], XtNlabel, smw->simple_menu.label_string)((void)( (args[0]).name = (((char*)&XtStrings[429])), (args [0]).value = (XtArgVal)(smw->simple_menu.label_string) )); | |||
987 | XtSetArg(args[1], XtNjustify, XtJustifyCenter)((void)( (args[1]).name = (((char*)&XtStrings[379])), (args [1]).value = (XtArgVal)(XtJustifyCenter) )); | |||
988 | smw->simple_menu.label = (SmeObject) | |||
989 | XtCreateManagedWidget("menuLabel", | |||
990 | smw->simple_menu.label_class, w, | |||
991 | args, TWO((Cardinal)2)); | |||
992 | ||||
993 | next_child = NULL((void*)0); | |||
994 | for (child = smw->composite.children + smw->composite.num_children, | |||
995 | i = smw->composite.num_children ; i > 0 ; i--, child--) { | |||
996 | if (next_child != NULL((void*)0)) | |||
997 | *next_child = *child; | |||
998 | next_child = child; | |||
999 | } | |||
1000 | *child = (Widget) smw->simple_menu.label; | |||
| ||||
1001 | } | |||
1002 | ||||
1003 | /* Function Name: Layout | |||
1004 | * Description: lays the menu entries out all nice and neat. | |||
1005 | * Arguments: w - See below (+++) | |||
1006 | * width_ret, height_ret - The returned width and | |||
1007 | * height values. | |||
1008 | * Returns: none. | |||
1009 | * | |||
1010 | * if width == NULL || height == NULL then it assumes the you do not care | |||
1011 | * about the return values, and just want a relayout. | |||
1012 | * | |||
1013 | * if this is not the case then it will set width_ret and height_ret | |||
1014 | * to be width and height that the child would get if it were layed out | |||
1015 | * at this time. | |||
1016 | * | |||
1017 | * +++ "w" can be the simple menu widget or any of its object children. | |||
1018 | */ | |||
1019 | ||||
1020 | static void | |||
1021 | Layout(Widget w, Dimension *width_ret, Dimension *height_ret) | |||
1022 | { | |||
1023 | SmeObject current_entry, *entry; | |||
1024 | SimpleMenuWidget smw; | |||
1025 | ThreeDWidget tdw; | |||
1026 | Dimension width, height; | |||
1027 | Boolean do_layout = (height_ret == NULL((void*)0) || width_ret == NULL((void*)0)); | |||
1028 | Boolean allow_change_size; | |||
1029 | height = 0; | |||
1030 | ||||
1031 | if (XtIsSubclass(w, simpleMenuWidgetClass)) | |||
1032 | { | |||
1033 | smw = (SimpleMenuWidget)w; | |||
1034 | current_entry = NULL((void*)0); | |||
1035 | } | |||
1036 | else | |||
1037 | { | |||
1038 | smw = (SimpleMenuWidget)XtParent(w)((w)->core.parent); | |||
1039 | current_entry = (SmeObject)w; | |||
1040 | } | |||
1041 | tdw = (ThreeDWidget)smw->simple_menu.threeD; | |||
1042 | ||||
1043 | do_layout |= (current_entry != NULL((void*)0)); | |||
1044 | allow_change_size = | |||
1045 | (!XtIsRealized((Widget)smw)(XtWindowOfObject((Widget)smw) != 0L) || smw->shell.allow_shell_resize); | |||
1046 | ||||
1047 | if (smw->simple_menu.menu_height) | |||
1048 | height = smw->core.height; | |||
1049 | else if (do_layout) | |||
1050 | { | |||
1051 | height = smw->simple_menu.top_margin + tdw->threeD.shadow_width; | |||
1052 | ||||
1053 | ForAllChildren(smw, entry)for ((entry) = (SmeObject *) (smw)->composite.children; (entry ) < (SmeObject *) ((smw)->composite.children + (smw)-> composite.num_children); (entry)++) | |||
1054 | { | |||
1055 | if (!XtIsManaged((Widget)*entry)) continue; | |||
1056 | ||||
1057 | if (smw->simple_menu.row_height != 0 && | |||
1058 | *entry != smw->simple_menu.label) | |||
1059 | (*entry)->rectangle.height = smw->simple_menu.row_height; | |||
1060 | ||||
1061 | (*entry)->rectangle.y = height; | |||
1062 | (*entry)->rectangle.x = 0; | |||
1063 | height += (*entry)->rectangle.height; | |||
1064 | } | |||
1065 | ||||
1066 | height += smw->simple_menu.bottom_margin + tdw->threeD.shadow_width; | |||
1067 | } | |||
1068 | else if (smw->simple_menu.row_height != 0 && | |||
1069 | current_entry != smw->simple_menu.label) | |||
1070 | { | |||
1071 | height = smw->simple_menu.row_height * smw->composite.num_children; | |||
1072 | height += tdw->threeD.shadow_width * 2; | |||
1073 | } | |||
1074 | ||||
1075 | if (smw->simple_menu.menu_width) | |||
1076 | width = smw->core.width; | |||
1077 | else if (allow_change_size) | |||
1078 | { | |||
1079 | SetMarginWidths((Widget)smw); | |||
1080 | ||||
1081 | width = GetMenuWidth((Widget)smw, (Widget)NULL((void*)0)); | |||
1082 | } | |||
1083 | else | |||
1084 | width = smw->core.width; | |||
1085 | ||||
1086 | if (do_layout) | |||
1087 | { | |||
1088 | ForAllChildren(smw, entry)for ((entry) = (SmeObject *) (smw)->composite.children; (entry ) < (SmeObject *) ((smw)->composite.children + (smw)-> composite.num_children); (entry)++) | |||
1089 | if (XtIsManaged((Widget)*entry)) | |||
1090 | (*entry)->rectangle.width = width; | |||
1091 | ||||
1092 | if (allow_change_size) | |||
1093 | MakeSetValuesRequest((Widget) smw, width, height); | |||
1094 | } | |||
1095 | else | |||
1096 | { | |||
1097 | *width_ret = width; | |||
1098 | if (height != 0) *height_ret = height; | |||
1099 | } | |||
1100 | } | |||
1101 | ||||
1102 | /* Function Name: AddPositionAction | |||
1103 | * Description: Adds the XawPositionSimpleMenu action to the global | |||
1104 | * action list for this appcon. | |||
1105 | * Arguments: app_con - the application context for this app. | |||
1106 | * data - NOT USED. | |||
1107 | * Returns: none. | |||
1108 | */ | |||
1109 | ||||
1110 | /* ARGSUSED */ | |||
1111 | static void | |||
1112 | AddPositionAction(XtAppContext app_con, XPointer data) | |||
1113 | { | |||
1114 | static XtActionsRec pos_action[] = { | |||
1115 | { "XawPositionSimpleMenu", PositionMenuAction }, | |||
1116 | }; | |||
1117 | ||||
1118 | XtAppAddActions(app_con, pos_action, XtNumber(pos_action)((Cardinal) (sizeof(pos_action) / sizeof(pos_action[0])))); | |||
1119 | } | |||
1120 | ||||
1121 | /* Function Name: FindMenu | |||
1122 | * Description: Find the menu give a name and reference widget. | |||
1123 | * Arguments: widget - reference widget. | |||
1124 | * name - the menu widget's name. | |||
1125 | * Returns: the menu widget or NULL. | |||
1126 | */ | |||
1127 | ||||
1128 | static Widget | |||
1129 | FindMenu(Widget widget, String name) | |||
1130 | { | |||
1131 | Widget w, menu; | |||
1132 | ||||
1133 | for ( w = widget ; w != NULL((void*)0) ; w = XtParent(w)((w)->core.parent) ) | |||
1134 | if ( (menu = XtNameToWidget(w, name)) != NULL((void*)0) ) | |||
1135 | return(menu); | |||
1136 | return(NULL((void*)0)); | |||
1137 | } | |||
1138 | ||||
1139 | /* Function Name: PositionMenu | |||
1140 | * Description: Places the menu | |||
1141 | * Arguments: w - the simple menu widget. | |||
1142 | * location - a pointer the the position or NULL. | |||
1143 | * Returns: none. | |||
1144 | */ | |||
1145 | ||||
1146 | static void | |||
1147 | PositionMenu(Widget w, XPoint * location) | |||
1148 | { | |||
1149 | SimpleMenuWidget smw = (SimpleMenuWidget) w; | |||
1150 | SmeObject entry; | |||
1151 | XPoint t_point; | |||
1152 | ||||
1153 | if (location == NULL((void*)0)) { | |||
1154 | Window junk1, junk2; | |||
1155 | int root_x, root_y, junkX, junkY; | |||
1156 | unsigned int junkM; | |||
1157 | ||||
1158 | location = &t_point; | |||
1159 | if (XQueryPointer(XtDisplay(w)(((w)->core.screen)->display), XtWindow(w)((w)->core.window), &junk1, &junk2, | |||
1160 | &root_x, &root_y, &junkX, &junkY, &junkM) == FALSE0) { | |||
1161 | char error_buf[BUFSIZ1024]; | |||
1162 | (void) sprintf(error_buf, "%s %s", "Xaw Simple Menu Widget:",__builtin___sprintf_chk (error_buf, 0, __builtin_object_size ( error_buf, 2 > 1 ? 1 : 0), "%s %s", "Xaw Simple Menu Widget:" , "Could not find location of mouse pointer") | |||
1163 | "Could not find location of mouse pointer")__builtin___sprintf_chk (error_buf, 0, __builtin_object_size ( error_buf, 2 > 1 ? 1 : 0), "%s %s", "Xaw Simple Menu Widget:" , "Could not find location of mouse pointer"); | |||
1164 | XtAppWarning(XtWidgetToApplicationContext(w), error_buf); | |||
1165 | return; | |||
1166 | } | |||
1167 | location->x = (short) root_x; | |||
1168 | location->y = (short) root_y; | |||
1169 | } | |||
1170 | ||||
1171 | /* | |||
1172 | * The width will not be correct unless it is realized. | |||
1173 | */ | |||
1174 | ||||
1175 | XtRealizeWidget(w); | |||
1176 | ||||
1177 | location->x -= (Position) w->core.width/2; | |||
1178 | ||||
1179 | if (smw->simple_menu.popup_entry == NULL((void*)0)) | |||
1180 | entry = smw->simple_menu.label; | |||
1181 | else | |||
1182 | entry = smw->simple_menu.popup_entry; | |||
1183 | ||||
1184 | if (entry != NULL((void*)0)) | |||
1185 | location->y -= entry->rectangle.y + entry->rectangle.height/2; | |||
1186 | ||||
1187 | MoveMenu(w, (Position) location->x, (Position) location->y); | |||
1188 | } | |||
1189 | ||||
1190 | /* Function Name: MoveMenu | |||
1191 | * Description: Actually moves the menu, may force it to | |||
1192 | * to be fully visable if menu_on_screen is TRUE. | |||
1193 | * Arguments: w - the simple menu widget. | |||
1194 | * x, y - the current location of the widget. | |||
1195 | * Returns: none | |||
1196 | */ | |||
1197 | ||||
1198 | static void | |||
1199 | MoveMenu(Widget w, Position x, Position y) | |||
1200 | { | |||
1201 | SimpleMenuWidget smw = (SimpleMenuWidget) w; | |||
1202 | Arg arglist[2]; | |||
1203 | ||||
1204 | if (smw->simple_menu.menu_on_screen) { | |||
1205 | int width = w->core.width + 2 * w->core.border_width; | |||
1206 | int height = w->core.height + 2 * w->core.border_width; | |||
1207 | ||||
1208 | if (x >= 0) { | |||
1209 | int scr_width = WidthOfScreen(XtScreen(w))((((w)->core.screen))->width); | |||
1210 | if (x + width > scr_width) | |||
1211 | x = scr_width - width; | |||
1212 | } | |||
1213 | if (x < 0) | |||
1214 | x = 0; | |||
1215 | ||||
1216 | if (y >= 0) { | |||
1217 | int scr_height = HeightOfScreen(XtScreen(w))((((w)->core.screen))->height); | |||
1218 | if (y + height > scr_height) | |||
1219 | y = scr_height - height; | |||
1220 | } | |||
1221 | if (y < 0) | |||
1222 | y = 0; | |||
1223 | } | |||
1224 | ||||
1225 | XtSetArg(arglist[0], XtNx, x)((void)( (arglist[0]).name = (((char*)&XtStrings[885])), ( arglist[0]).value = (XtArgVal)(x) )); | |||
1226 | XtSetArg(arglist[1], XtNy, y)((void)( (arglist[1]).name = (((char*)&XtStrings[887])), ( arglist[1]).value = (XtArgVal)(y) )); | |||
1227 | XtSetValues(w, arglist, TWO((Cardinal)2)); | |||
1228 | } | |||
1229 | ||||
1230 | /* Function Name: ChangeCursorOnGrab | |||
1231 | * Description: Changes the cursor on the active grab to the one | |||
1232 | * specified in out resource list. | |||
1233 | * Arguments: w - the widget. | |||
1234 | * junk, garbage - ** NOT USED **. | |||
1235 | * Returns: None. | |||
1236 | */ | |||
1237 | ||||
1238 | /* ARGSUSED */ | |||
1239 | static void | |||
1240 | ChangeCursorOnGrab(Widget w, XtPointer junk, XtPointer garbage) | |||
1241 | { | |||
1242 | SimpleMenuWidget smw = (SimpleMenuWidget) w; | |||
1243 | ||||
1244 | /* | |||
1245 | * The event mask here is what is currently in the MIT implementation. | |||
1246 | * There really needs to be a way to get the value of the mask out | |||
1247 | * of the toolkit (CDP 5/26/89). | |||
1248 | */ | |||
1249 | ||||
1250 | XChangeActivePointerGrab(XtDisplay(w)(((w)->core.screen)->display), ButtonPressMask(1L<<2)|ButtonReleaseMask(1L<<3), | |||
1251 | smw->simple_menu.cursor, | |||
1252 | XtLastTimestampProcessed(XtDisplay(w)(((w)->core.screen)->display))); | |||
1253 | } | |||
1254 | ||||
1255 | /* Function Name: MakeSetValuesRequest | |||
1256 | * Description: Makes a (possibly recursive) call to SetValues, | |||
1257 | * I take great pains to not go into an infinite loop. | |||
1258 | * Arguments: w - the simple menu widget. | |||
1259 | * width, height - the size of the ask for. | |||
1260 | * Returns: none | |||
1261 | */ | |||
1262 | ||||
1263 | static void | |||
1264 | MakeSetValuesRequest(Widget w, Dimension width, Dimension height) | |||
1265 | { | |||
1266 | SimpleMenuWidget smw = (SimpleMenuWidget) w; | |||
1267 | ||||
1268 | if ( !smw->simple_menu.recursive_set_values ) { | |||
1269 | if ( (smw->core.width != width) || (smw->core.height != height) ) { | |||
1270 | Arg arglist[2]; | |||
1271 | ||||
1272 | smw->simple_menu.recursive_set_values = TRUE1; | |||
1273 | XtSetArg(arglist[0], XtNwidth, width)((void)( (arglist[0]).name = (((char*)&XtStrings[872])), ( arglist[0]).value = (XtArgVal)(width) )); | |||
1274 | XtSetArg(arglist[1], XtNheight, height)((void)( (arglist[1]).name = (((char*)&XtStrings[234])), ( arglist[1]).value = (XtArgVal)(height) )); | |||
1275 | XtSetValues(w, arglist, TWO((Cardinal)2)); | |||
1276 | } | |||
1277 | else if (XtIsRealized( (Widget) smw)(XtWindowOfObject((Widget) smw) != 0L)) | |||
1278 | Redisplay((Widget) smw, (XEvent *) NULL((void*)0), (Region) NULL((void*)0)); | |||
1279 | } | |||
1280 | smw->simple_menu.recursive_set_values = FALSE0; | |||
1281 | } | |||
1282 | ||||
1283 | /* | |||
1284 | * Function Name: SetMarginWidths() | |||
1285 | * Description: Set new margin values for all menu children. | |||
1286 | * Arguments: w - the simple menu widget | |||
1287 | * w_ent - the current menu entry | |||
1288 | */ | |||
1289 | static void | |||
1290 | SetMarginWidths(Widget w) | |||
1291 | { | |||
1292 | SimpleMenuWidget smw = (SimpleMenuWidget)w; | |||
1293 | SmeObject *entry; | |||
1294 | SmeBSBObject bsb_entry; | |||
1295 | Dimension l_mrgn, l_bmw, r_mrgn, r_bmw; | |||
1296 | ||||
1297 | if (smw->simple_menu.left_whitespace || smw->simple_menu.right_whitespace) | |||
1298 | { | |||
1299 | /* determine the widest bitmaps */ | |||
1300 | l_bmw = r_bmw = (Dimension)0; | |||
1301 | ForAllChildren(smw, entry)for ((entry) = (SmeObject *) (smw)->composite.children; (entry ) < (SmeObject *) ((smw)->composite.children + (smw)-> composite.num_children); (entry)++) | |||
1302 | { | |||
1303 | if (!XtIsManaged((Widget)*entry)) continue; | |||
1304 | if (*entry == smw->simple_menu.label) continue; | |||
1305 | if (XtIsSubclass((Widget)*entry, smeLineObjectClass)) | |||
1306 | continue; | |||
1307 | ||||
1308 | bsb_entry = (SmeBSBObject)&((*entry)->object); | |||
1309 | if (bsb_entry->sme_bsb.left_bitmap_width > l_bmw) | |||
1310 | l_bmw = bsb_entry->sme_bsb.left_bitmap_width; | |||
1311 | if (bsb_entry->sme_bsb.right_bitmap_width > r_bmw) | |||
1312 | r_bmw = bsb_entry->sme_bsb.right_bitmap_width; | |||
1313 | } | |||
1314 | ||||
1315 | /* set the margin values */ | |||
1316 | if (smw->simple_menu.left_whitespace) | |||
1317 | l_mrgn = l_bmw + | |||
1318 | (smw->simple_menu.left_whitespace * ((l_bmw) ? 2 : 1)); | |||
1319 | if (smw->simple_menu.right_whitespace) | |||
1320 | r_mrgn = r_bmw + | |||
1321 | (smw->simple_menu.right_whitespace * ((r_bmw) ? 2 : 1)); | |||
1322 | ||||
1323 | /* make all the margins uniform */ | |||
1324 | ForAllChildren(smw, entry)for ((entry) = (SmeObject *) (smw)->composite.children; (entry ) < (SmeObject *) ((smw)->composite.children + (smw)-> composite.num_children); (entry)++) | |||
1325 | { | |||
1326 | if (!XtIsManaged((Widget)*entry)) continue; | |||
1327 | if (*entry == smw->simple_menu.label) continue; | |||
1328 | if (XtIsSubclass((Widget)*entry, smeLineObjectClass)) | |||
1329 | continue; | |||
1330 | ||||
1331 | bsb_entry = (SmeBSBObject)&((*entry)->object); | |||
1332 | if (smw->simple_menu.left_whitespace) | |||
1333 | bsb_entry->sme_bsb.left_margin = l_mrgn; | |||
1334 | if (smw->simple_menu.right_whitespace) | |||
1335 | bsb_entry->sme_bsb.right_margin = r_mrgn; | |||
1336 | } | |||
1337 | } | |||
1338 | } | |||
1339 | ||||
1340 | /* Function Name: GetMenuWidth | |||
1341 | * Description: Sets the width to the widest entry in pixels. | |||
1342 | * Arguments: w - the simple menu widget. | |||
1343 | * w_ent - the current menu entry. | |||
1344 | * Returns: width of menu. | |||
1345 | */ | |||
1346 | ||||
1347 | static Dimension | |||
1348 | GetMenuWidth(Widget w, Widget w_ent) | |||
1349 | { | |||
1350 | SmeObject cur_entry = (SmeObject) w_ent; | |||
1351 | SimpleMenuWidget smw = (SimpleMenuWidget) w; | |||
1352 | Dimension width, widest = (Dimension) 0; | |||
1353 | SmeObject * entry; | |||
1354 | ||||
1355 | if ( smw->simple_menu.menu_width ) | |||
1356 | return(smw->core.width); | |||
1357 | ||||
1358 | ForAllChildren(smw, entry)for ((entry) = (SmeObject *) (smw)->composite.children; (entry ) < (SmeObject *) ((smw)->composite.children + (smw)-> composite.num_children); (entry)++) { | |||
1359 | XtWidgetGeometry preferred; | |||
1360 | ||||
1361 | if (!XtIsManaged( (Widget) *entry)) continue; | |||
1362 | ||||
1363 | if (*entry != cur_entry) { | |||
1364 | XtQueryGeometry((Widget) *entry, (XtWidgetGeometry *)NULL((void*)0), &preferred); | |||
1365 | ||||
1366 | if (preferred.request_mode & CWWidth(1<<2)) | |||
1367 | width = preferred.width; | |||
1368 | else | |||
1369 | width = (*entry)->rectangle.width; | |||
1370 | } | |||
1371 | else | |||
1372 | width = (*entry)->rectangle.width; | |||
1373 | ||||
1374 | if ( width > widest ) | |||
1375 | widest = width; | |||
1376 | } | |||
1377 | ||||
1378 | return(widest); | |||
1379 | } | |||
1380 | ||||
1381 | /* Function Name: GetMenuHeight | |||
1382 | * Description: Sets the height to all the entries in pixels. | |||
1383 | * Arguments: w - the simple menu widget. | |||
1384 | * Returns: height of menu. | |||
1385 | */ | |||
1386 | ||||
1387 | static Dimension | |||
1388 | GetMenuHeight(Widget w) | |||
1389 | { | |||
1390 | SimpleMenuWidget smw = (SimpleMenuWidget) w; | |||
1391 | ThreeDWidget tdw = (ThreeDWidget) smw->simple_menu.threeD; | |||
1392 | SmeObject * entry; | |||
1393 | Dimension height; | |||
1394 | ||||
1395 | if (smw->simple_menu.menu_height) | |||
1396 | return(smw->core.height); | |||
1397 | ||||
1398 | height = smw->simple_menu.top_margin + smw->simple_menu.bottom_margin; | |||
1399 | height += tdw->threeD.shadow_width * 2; | |||
1400 | ||||
1401 | if (smw->simple_menu.row_height == 0) { | |||
1402 | ForAllChildren(smw, entry)for ((entry) = (SmeObject *) (smw)->composite.children; (entry ) < (SmeObject *) ((smw)->composite.children + (smw)-> composite.num_children); (entry)++) | |||
1403 | if (XtIsManaged ((Widget) *entry)) | |||
1404 | height += (*entry)->rectangle.height; | |||
1405 | } else | |||
1406 | height += smw->simple_menu.row_height * smw->composite.num_children; | |||
1407 | ||||
1408 | return(height); | |||
1409 | } | |||
1410 | ||||
1411 | /* Function Name: GetEventEntry | |||
1412 | * Description: Gets an entry given an event that has X and Y coords. | |||
1413 | * Arguments: w - the simple menu widget. | |||
1414 | * event - the event. | |||
1415 | * Returns: the entry that this point is in. | |||
1416 | */ | |||
1417 | ||||
1418 | static SmeObject | |||
1419 | GetEventEntry(Widget w, XEvent * event) | |||
1420 | { | |||
1421 | Position x_loc = 0, y_loc = 0; | |||
1422 | SimpleMenuWidget smw = (SimpleMenuWidget)w; | |||
1423 | SmeObject *entry; | |||
1424 | static XPoint last_pos; | |||
1425 | XPoint pos; | |||
1426 | int s = ((ThreeDWidget)smw->simple_menu.threeD)->threeD.shadow_width; | |||
1427 | ||||
1428 | switch (event->type) { | |||
1429 | case MotionNotify6: | |||
1430 | x_loc = event->xmotion.x; | |||
1431 | y_loc = event->xmotion.y; | |||
1432 | pos.y = event->xmotion.y_root; | |||
1433 | break; | |||
1434 | case EnterNotify7: | |||
1435 | case LeaveNotify8: | |||
1436 | x_loc = event->xcrossing.x; | |||
1437 | y_loc = event->xcrossing.y; | |||
1438 | pos.y = event->xcrossing.y_root; | |||
1439 | break; | |||
1440 | case ButtonPress4: | |||
1441 | case ButtonRelease5: | |||
1442 | x_loc = event->xbutton.x; | |||
1443 | y_loc = event->xbutton.y; | |||
1444 | pos.y = event->xbutton.y_root; | |||
1445 | break; | |||
1446 | default: | |||
1447 | XtAppError(XtWidgetToApplicationContext(w), | |||
1448 | "Unknown event type in GetEventEntry()."); | |||
1449 | break; | |||
1450 | } | |||
1451 | ||||
1452 | if (x_loc < 0 || x_loc >= (int)smw->core.width) | |||
1453 | return NULL((void*)0); | |||
1454 | else if (smw->simple_menu.too_tall) { | |||
1455 | if (pos.y >= smw->simple_menu.last_y && smw->simple_menu.didnt_fit) { | |||
1456 | if (last_pos.y && pos.y < last_pos.y) { | |||
1457 | last_pos.y = pos.y; | |||
1458 | return NULL((void*)0); | |||
1459 | } | |||
1460 | smw->simple_menu.current_first += smw->simple_menu.jump_val; | |||
1461 | Redisplay(w, (XEvent *)NULL((void*)0), (Region)NULL((void*)0)); | |||
1462 | last_pos.y = pos.y; | |||
1463 | return NULL((void*)0); | |||
1464 | } else if (pos.y <= s + SMW_ARROW_SIZE8 && | |||
1465 | smw->simple_menu.first_entry != smw->simple_menu.current_first) | |||
1466 | { | |||
1467 | if (pos.y && (!last_pos.y || pos.y > last_pos.y)) { | |||
1468 | last_pos.y = pos.y; | |||
1469 | return NULL((void*)0); | |||
1470 | } | |||
1471 | smw->simple_menu.current_first -= smw->simple_menu.jump_val; | |||
1472 | Redisplay(w, (XEvent *)NULL((void*)0), (Region)NULL((void*)0)); | |||
1473 | last_pos.y = pos.y; | |||
1474 | return NULL((void*)0); | |||
1475 | } | |||
1476 | else | |||
1477 | last_pos.y = 0; | |||
1478 | } else if (y_loc < 0 || y_loc >= (int)smw->core.height) | |||
1479 | return NULL((void*)0); | |||
1480 | ||||
1481 | ForAllChildren(smw, entry)for ((entry) = (SmeObject *) (smw)->composite.children; (entry ) < (SmeObject *) ((smw)->composite.children + (smw)-> composite.num_children); (entry)++) { | |||
1482 | int tmp_y; | |||
1483 | ||||
1484 | if (!XtIsManaged((Widget)*entry)) continue; | |||
1485 | ||||
1486 | tmp_y = (*entry)->rectangle.y - smw->simple_menu.first_y; | |||
1487 | if (tmp_y < y_loc && tmp_y + (int)(*entry)->rectangle.height > y_loc) { | |||
1488 | if (*entry == smw->simple_menu.label) | |||
1489 | return NULL((void*)0); /* cannot select the label */ | |||
1490 | else | |||
1491 | return *entry; | |||
1492 | } | |||
1493 | } | |||
1494 | ||||
1495 | return NULL((void*)0); | |||
1496 | } | |||
1497 | ||||
1498 | /*ARGSUSED*/ | |||
1499 | static void | |||
1500 | PopupCB(Widget w, XtPointer client_data, XtPointer call_data) | |||
1501 | { | |||
1502 | SimpleMenuWidget smw = (SimpleMenuWidget)w; | |||
1503 | ||||
1504 | smw->simple_menu.state &= ~SMW_UNMAPPING0x01; | |||
1505 | } | |||
1506 | ||||
1507 | static void | |||
1508 | PopupSubMenu(SimpleMenuWidget smw) | |||
1509 | { | |||
1510 | Widget menu; | |||
1511 | SmeBSBObject entry = (SmeBSBObject)smw->simple_menu.entry_set; | |||
1512 | Position menu_x, menu_y; | |||
1513 | Boolint popleft; | |||
1514 | Arg args[2]; | |||
1515 | ||||
1516 | if (entry->sme_bsb.menu_name == NULL((void*)0)) | |||
1517 | return; | |||
1518 | ||||
1519 | if ((menu = FindMenu((Widget)smw, entry->sme_bsb.menu_name)) == NULL((void*)0)) | |||
1520 | return; | |||
1521 | ||||
1522 | smw->simple_menu.sub_menu = menu; | |||
1523 | ||||
1524 | if (!XtIsRealized(menu)(XtWindowOfObject(menu) != 0L)) | |||
1525 | XtRealizeWidget(menu); | |||
1526 | ||||
1527 | popleft = (smw->simple_menu.state & SMW_POPLEFT0x02) != 0; | |||
1528 | ||||
1529 | if (popleft) | |||
1530 | XtTranslateCoords((Widget)smw, -(int)XtWidth(menu)(((RectObj)menu)->rectangle.width), | |||
1531 | XtY(entry)(((RectObj)entry)->rectangle.y) - XtBorderWidth(menu)(((RectObj)menu)->rectangle.border_width), &menu_x, &menu_y); | |||
1532 | else | |||
1533 | XtTranslateCoords((Widget)smw, XtWidth(smw)(((RectObj)smw)->rectangle.width), XtY(entry)(((RectObj)entry)->rectangle.y) | |||
1534 | - XtBorderWidth(menu)(((RectObj)menu)->rectangle.border_width), &menu_x, &menu_y); | |||
1535 | ||||
1536 | if (!popleft && menu_x >= 0) { | |||
1537 | int scr_width = WidthOfScreen(XtScreen(menu))((((menu)->core.screen))->width); | |||
1538 | ||||
1539 | if (menu_x + XtWidth(menu)(((RectObj)menu)->rectangle.width) > scr_width) { | |||
1540 | menu_x -= XtWidth(menu)(((RectObj)menu)->rectangle.width) + XtWidth(smw)(((RectObj)smw)->rectangle.width); | |||
1541 | popleft = True1; | |||
1542 | } | |||
1543 | } | |||
1544 | else if (popleft && menu_x < 0) { | |||
1545 | menu_x = 0; | |||
1546 | popleft = False0; | |||
1547 | } | |||
1548 | ||||
1549 | if (menu_y >= 0) { | |||
1550 | ThreeDWidget tdw = | |||
1551 | (ThreeDWidget)((SimpleMenuWidget)menu)->simple_menu.threeD; | |||
1552 | int scr_height = HeightOfScreen(XtScreen(menu))((((menu)->core.screen))->height); | |||
1553 | ||||
1554 | if (menu_y + XtHeight(menu)(((RectObj)menu)->rectangle.height) > scr_height) | |||
1555 | menu_y = scr_height - XtHeight(menu)(((RectObj)menu)->rectangle.height) - XtBorderWidth(menu)(((RectObj)menu)->rectangle.border_width); | |||
1556 | ||||
1557 | menu_y -= tdw->threeD.shadow_width; | |||
1558 | } | |||
1559 | if (menu_y < 0) | |||
1560 | menu_y = 0; | |||
1561 | ||||
1562 | XtSetArg(args[0], XtNx, menu_x)((void)( (args[0]).name = (((char*)&XtStrings[885])), (args [0]).value = (XtArgVal)(menu_x) )); | |||
1563 | XtSetArg(args[1], XtNy, menu_y)((void)( (args[1]).name = (((char*)&XtStrings[887])), (args [1]).value = (XtArgVal)(menu_y) )); | |||
1564 | XtSetValues(menu, args, TWO((Cardinal)2)); | |||
1565 | ||||
1566 | if (popleft) | |||
1567 | ((SimpleMenuWidget)menu)->simple_menu.state |= SMW_POPLEFT0x02; | |||
1568 | else | |||
1569 | ((SimpleMenuWidget)menu)->simple_menu.state &= ~SMW_POPLEFT0x02; | |||
1570 | ||||
1571 | XtPopup(menu, XtGrabNone); | |||
1572 | } | |||
1573 | ||||
1574 | static void | |||
1575 | Popdown(Widget w, XEvent *event, String *params, Cardinal *num_params) | |||
1576 | { | |||
1577 | SimpleMenuWidget smw = (SimpleMenuWidget)w; | |||
1578 | ||||
1579 | while (XtParent(w)((w)->core.parent) && | |||
1580 | XtIsSubclass(XtParent(w)((w)->core.parent), simpleMenuWidgetClass)) { | |||
1581 | if (((SimpleMenuWidget)XtParent(w)((w)->core.parent))->simple_menu.sub_menu == (Widget)w) | |||
1582 | { | |||
1583 | w = XtParent(w)((w)->core.parent); | |||
1584 | smw = (SimpleMenuWidget)w; | |||
1585 | smw->simple_menu.entry_set = NULL((void*)0); | |||
1586 | } | |||
1587 | else | |||
1588 | break; | |||
1589 | } | |||
1590 | ||||
1591 | smw->simple_menu.state |= SMW_UNMAPPING0x01; | |||
1592 | PopdownSubMenu(smw); | |||
1593 | ||||
1594 | XtCallActionProc(w, "XtMenuPopdown", event, params, *num_params); | |||
1595 | } | |||
1596 | ||||
1597 | static void | |||
1598 | PopdownSubMenu(SimpleMenuWidget smw) | |||
1599 | { | |||
1600 | SimpleMenuWidget menu = (SimpleMenuWidget)smw->simple_menu.sub_menu; | |||
1601 | ||||
1602 | if (!menu) return; | |||
1603 | ||||
1604 | menu->simple_menu.state &= ~SMW_POPLEFT0x02; | |||
1605 | menu->simple_menu.state |= SMW_UNMAPPING0x01; | |||
1606 | PopdownSubMenu(menu); | |||
1607 | ||||
1608 | XtPopdown((Widget)menu); | |||
1609 | ||||
1610 | smw->simple_menu.sub_menu = NULL((void*)0); | |||
1611 | } | |||
1612 |