1 /* -*- c++ -*-
2 FILE: WidgetsX.cpp
3 RCS REVISION: $Revision: 1.33 $
4 
5 COPYRIGHT: (c) 1999 -- 2003 Melinda Green, Don Hatch, and Jay Berkenbilt - Superliminal Software
6 
7 LICENSE: Free to use and modify for non-commercial purposes as long as the
8     following conditions are adhered to:
9     1) Obvious credit for the source of this code and the designs it embodies
10        are clearly made, and
11     2) Ports and derived versions of 4D Magic Cube programs are not distributed
12        without the express written permission of the authors.
13 
14 DESCRIPTION:
15     This file does the menus and buttons and stuff using Athena Widgets.
16 */
17 
18 #include "WidgetsX.h"
19 
20 #include <stdio.h>
21 #include <stdarg.h>
22 
23 #include <X11/Xaw/Form.h>
24 #include <X11/Xaw/Dialog.h>
25 #include <X11/Xaw/Box.h>
26 #include <X11/Xaw/Command.h>
27 #include <X11/Xaw/Label.h>
28 #include <X11/Xaw/AsciiText.h>
29 #include <X11/Xaw/MenuButton.h>
30 #include <X11/Xaw/SimpleMenu.h>
31 #include <X11/Xaw/SmeBSB.h>
32 #include <X11/Xaw/Toggle.h>
33 
34 #include <X11/IntrinsicP.h>
35 #include <X11/CoreP.h>          /* for dbx */
36 
37 #include "MagicCube.h"
38 #include "EventHandler.h"
39 #include "MacroManager.h"       // XXX
40 
41 std::map<Widget, WidgetsX::MacroUIData*> WidgetsX::apply_to_ui_data;
42 std::map<Widget, WidgetsX::MacroUIData*> WidgetsX::invert_to_ui_data;
43 
44 void
macroApply_cb(Widget widget,XtPointer arg,XtPointer)45 WidgetsX::macroApply_cb(Widget widget, XtPointer arg, XtPointer)
46 {
47     EventHandler* e = (EventHandler *) arg;
48     MacroUIData* which = apply_to_ui_data[widget];
49     e->applyMacro_cb((void*) which);
50 }
51 
52 void
macroInvert_cb(Widget widget,XtPointer arg,XtPointer)53 WidgetsX::macroInvert_cb(Widget widget, XtPointer arg, XtPointer)
54 {
55     EventHandler* e = (EventHandler *) arg;
56     MacroUIData* which = invert_to_ui_data[widget];
57     e->invertMacro_cb((void*) which);
58 }
59 
60 void
callCallback(Widget,XtPointer arg,XtPointer)61 WidgetsX::callCallback(Widget, XtPointer arg, XtPointer)
62 {
63     EventHandler::Callback *callback = (EventHandler::Callback *) arg;
64     callback->apply();
65 }
66 
67 void
createMacrosForm()68 WidgetsX::createMacrosForm()
69 {
70     // FIX THIS -- hard-coded values
71     static char const *macroslabel = "Macros:";
72     static char const *addlabel = "Create";
73     static char const *deletelabel = "Delete";
74 
75     /*
76      * Create the macro box
77      */
78     bool macros_on_right = preferences.getBoolProperty(M4D_MACROS_ON_RIGHT);
79     if (macros_on_right)
80     {
81         macrosform = XtVaCreateManagedWidget(
82             "macrosform",
83             formWidgetClass, bigform, XtNdefaultDistance, 0,
84             /* since all children are boxes */
85             XtNwidth, 100,
86             XtNheight, 100,
87             XtNresizable, TRUE,
88             XtNfromHoriz, drawingwindow,
89             XtNvertDistance, 0,
90             /*
91              * Chain it to the top right of the form, so it doesn't
92              * change size with the form
93              */
94             XtNtop, XtChainTop,
95             XtNbottom, XtChainTop,
96             XtNleft, XtChainRight,
97             XtNright, XtChainRight, NULL);
98     }
99     else
100     {
101         macrosform = XtVaCreateManagedWidget(
102             "macrosform",
103             formWidgetClass, bigform, XtNdefaultDistance, 0,
104             /* since all children are boxes */
105             XtNresizable, TRUE,
106             XtNfromVert, buttonbox,
107             XtNvertDistance, 0,
108             /*
109              * Chain it to the bottom left of the form, so it doesn't
110              * change size with the form
111              */
112             XtNtop, XtChainBottom,
113             XtNbottom, XtChainBottom,
114             XtNleft, XtChainLeft,
115             XtNright, XtChainLeft, NULL);
116     }
117 
118     Widget thismacrobox =
119         XtVaCreateManagedWidget("thismacrobox",
120                                 boxWidgetClass,
121                                 macrosform,
122                                 XtNresizable, TRUE,
123                                 XtNorientation, XtorientHorizontal,
124                                 XtNborderWidth, 0, NULL);
125     /*
126      * Create the label and permanent buttons in the macro box
127      */
128     (void)XtVaCreateManagedWidget("macros label",
129                                   labelWidgetClass,
130                                   thismacrobox,
131                                   XtNlabel, macroslabel,
132                                   XtNborderWidth, 0, NULL);
133     Widget addbutton = XtVaCreateManagedWidget("add button",
134                                                commandWidgetClass,
135                                                thismacrobox,
136                                                XtNlabel, addlabel, NULL);
137     XtAddCallback(addbutton, XtNcallback, callCallback,
138                   event_handler->createCallback(&EventHandler::add_cb, 0));
139     deletebutton = XtVaCreateWidget(
140         /* not managed! */
141         "delete button",
142         commandWidgetClass,
143         thismacrobox,
144         XtNlabel, deletelabel, NULL);
145     XtAddCallback(deletebutton, XtNcallback, callCallback,
146                   event_handler->createCallback(&EventHandler::delete_cb, 0));
147     int fast_automoves = preferences.getBoolProperty(M4D_FAST_AUTOMOVES);
148     fast_toggle = XtVaCreateManagedWidget("fast",
149                                           toggleWidgetClass,
150                                           thismacrobox,
151                                           XtNlabel, "fast",
152                                           XtNstate, fast_automoves,
153                                           NULL);
154     XtAddCallback(fast_toggle, XtNcallback, callCallback,
155                   event_handler->createCallback(&EventHandler::toggleFast_cb, 0));
156     this->macrocontrols = thismacrobox;
157 
158     if (fast_automoves)
159     {
160         this->event_handler->toggleFast_cb(0);
161     }
162 }
163 
164 
165 /*
166  * Note: this is to be called from machine_init, NOT main!
167  */
WidgetsX(Preferences & p,EventHandler * event_handler,Widget toplevel,Widget & drawingwindow)168 WidgetsX::WidgetsX(Preferences& p, EventHandler* event_handler,
169                    Widget toplevel, Widget& drawingwindow) :
170     Widgets(p),
171     event_handler(event_handler),
172     buttonbox(0),
173     macrosform(0),
174     toplevel(toplevel),
175     bigform(0),
176     drawingwindow(0),
177     deletebutton(0),
178     macrocontrols(0),
179     fast_toggle(0),
180     cur_transientshell(-1)
181 {
182     int i;
183     for (i = 0; i < MAX_DIALOGS; ++i)
184     {
185         transientshells[i] = 0;
186         dialog_callbacks[i] = 0;
187     }
188 
189     Widget toplevelform;
190 
191     /*
192      * Toplevelform is a "buffer" between toplevel and bigform.
193      * Its purpose is to allow bigform to always take on its preferred size
194      * (since toplevel denies resize requests).
195      * Then when we know what that size is, we can resize toplevel
196      * explicitly by calling resize_toplevel_to_match_bigform().
197      */
198     toplevelform = XtVaCreateManagedWidget("toplevelform",
199                                            formWidgetClass,
200                                            toplevel,
201                                            XtNborderWidth, 0,
202                                            XtNdefaultDistance, 0, NULL);
203     /*
204      * Create the big form in which to put everything
205      */
206     bigform = XtVaCreateManagedWidget("bigform",
207                                       formWidgetClass,
208                                       toplevelform,
209                                       XtNborderWidth, 0,
210                                       XtNresizable, TRUE,
211                                       XtNtop, XtChainTop,
212                                       XtNbottom, XtChainBottom,
213                                       XtNleft, XtChainLeft,
214                                       XtNright, XtChainRight, NULL);
215 
216     /*
217      * Make the drawing window a square window in the upper left
218      */
219     drawingwindow = XtVaCreateManagedWidget("drawingwindow",
220                                             coreWidgetClass,
221                                             bigform,
222                                             XtNtop, XtChainTop,
223                                             XtNbottom, XtChainBottom,
224                                             XtNleft, XtChainLeft,
225                                             XtNright, XtChainRight, NULL);
226     this->drawingwindow = drawingwindow;
227 
228     if (preferences.getBoolProperty(M4D_NO_BUTTONS))
229     {
230         return;
231     }
232 
233     /*
234      * Create the main button box below the drawing window
235      */
236     buttonbox = XtVaCreateManagedWidget("buttonbox",
237                                         boxWidgetClass,
238                                         bigform,
239                                         XtNorientation, XtorientHorizontal,
240                                         XtNborderWidth, 0,
241                                         XtNresizable, TRUE,
242                                         XtNhorizDistance, 0,
243                                         XtNvertDistance, 0,
244                                         XtNfromVert, drawingwindow,
245                                         /*
246                                          * Chain it to the bottom left
247                                          * of the form, so it doesn't
248                                          * change size with the form
249                                          */
250                                         XtNtop, XtChainBottom,
251                                         XtNbottom, XtChainBottom,
252                                         XtNleft, XtChainLeft,
253                                         XtNright, XtChainLeft, NULL);
254     /*
255      * Buttons will be added to buttonbox by using widgets_add_button().
256      */
257 
258     createMacrosForm();
259 }
260 
~WidgetsX()261 WidgetsX::~WidgetsX()
262 {
263     // event_handler is externally controlled
264     int i;
265     for (i = 0; i < MAX_DIALOGS; ++i)
266     {
267         delete [] dialog_callbacks[i];
268     }
269 }
270 
271 extern void
addMenuButton(char * name,int nbuttons,ButtonData button_data[])272 WidgetsX::addMenuButton(char *name,
273                         int nbuttons,
274                         ButtonData button_data[])
275 {
276     if (preferences.getBoolProperty(M4D_NO_BUTTONS))
277     {
278         return;
279     }
280 
281     char        namebuf[80];    // bounds checking is performed
282     Widget      menu, entry;
283 
284     /*
285      * Often the label ends in "...", which confuses
286      * the menu-finding mechanism.  Delete that part when naming the menu.
287      */
288     namebuf[sizeof(namebuf) - 1] = '\0';
289     strncpy(namebuf, name, sizeof(namebuf) - 1);
290     while (*namebuf && namebuf[strlen(namebuf) - 1] == '.')
291         namebuf[strlen(namebuf) - 1] = '\0';
292 
293     /*
294      * Create the menu
295      */
296     menu = XtVaCreatePopupShell(namebuf,    /* without the "..." */
297                                 simpleMenuWidgetClass, toplevel, NULL);
298     /*
299      * Create the menu entries
300      */
301     int i;
302     for (i = 0; i < nbuttons; ++i)
303     {
304         if (button_data[i].label)
305         {
306             entry = XtVaCreateManagedWidget(button_data[i].label,
307                                             smeBSBObjectClass, menu, NULL);
308             XtAddCallback(entry, XtNcallback, callCallback,
309                           event_handler->createCallback(
310                               button_data[i].callback, button_data[i].cb_arg));
311         }
312     }
313 
314     /*
315      * Create the menu button and add it to the main button box
316      */
317     (void)XtVaCreateManagedWidget(
318         "menu button",
319         menuButtonWidgetClass, buttonbox, XtNlabel, name,
320         /* maybe with "..."  */
321         XtNmenuName,
322         preferences.getBoolProperty(M4D_NO_STRDUP_FIX) ? namebuf :
323         strdup(namebuf),
324         /*
325          * I don't know why the hell I needed to do that,
326          * but if I just use namebuf, I get "Can't find menu named ."
327          * when the menu button is hit.
328          * FIX THIS-- make sure it is a widget bug and not mine.
329          */
330         NULL);
331 }
332 
333 void
addButton(ButtonData button_data)334 WidgetsX::addButton(ButtonData button_data)
335 {
336     if (preferences.getBoolProperty(M4D_NO_BUTTONS))
337     {
338         return;
339     }
340 
341     Widget      thebutton;
342 
343     thebutton = XtVaCreateManagedWidget("button",
344                                         commandWidgetClass,
345                                         buttonbox, XtNlabel,
346                                         button_data.label, NULL);
347     XtAddCallback(thebutton, XtNcallback, callCallback,
348                   event_handler->createCallback(
349                       button_data.callback, button_data.cb_arg));
350 }
351 
352 
353 
354 
355 void
resizeToplevelToMatchBigform()356 WidgetsX::resizeToplevelToMatchBigform()
357 {
358 #if 0
359     Dimension   width, height;
360     XtVaGetValues(bigform, XtNwidth, &width, XtNheight, &height, NULL);
361     /*
362      * Chain bigform to top left of toplevelform so it doesn't move or
363      * resize
364      */
365     XtVaSetValues(bigform,
366                   XtNtop, XtChainTop,
367                   XtNbottom, XtChainTop,
368                   XtNleft, XtChainLeft, XtNright, XtChainLeft, NULL);
369     XtVaSetValues(toplevel, XtNwidth, width, XtNheight, height, NULL);
370     /*
371      * Chain bigform back again so that it will resize if toplevel
372      * resizes later
373      */
374     XtVaSetValues(bigform,
375                   XtNtop, XtChainTop,
376                   XtNbottom, XtChainBottom,
377                   XtNleft, XtChainLeft, XtNright, XtChainRight, NULL);
378 #endif
379 }
380 
381 /*
382  * Use this function to get the size
383  * of a widget that's not managed yet.
384  */
385 void
XtForceDimensionsOfUnmanagedWidget(Widget w)386 WidgetsX::XtForceDimensionsOfUnmanagedWidget(Widget w)
387 {
388     Arg         args[2];
389     int         n;
390 
391     n = 0;
392     XtSetArg(args[n], XtNmappedWhenManaged, False);
393     n++;
394     XtSetValues(w, args, n);
395 
396     XtManageChild(w);
397     XtUnmanageChild(w);
398 
399     n = 0;
400     XtSetArg(args[n], XtNmappedWhenManaged, True);
401     n++;
402     XtSetValues(w, args, n);
403 }
404 
405 void
XtGetLowerRight(Widget w,Position * x,Position * y)406 WidgetsX::XtGetLowerRight(Widget w, Position *x, Position *y)
407 {
408     Dimension   width, height;
409 
410     XtVaGetValues(w, XtNwidth, &width, XtNheight, &height, NULL);
411 
412     XtTranslateCoords(w, width, height, x, y);
413 }
414 
415 void
XtSetLowerRight(Widget w,Position x,Position y)416 WidgetsX::XtSetLowerRight(Widget w, Position x, Position y)
417 {
418     Dimension   width, height;
419 
420     XtVaGetValues(w, XtNwidth, &width, XtNheight, &height, NULL);
421 
422     XtVaSetValues(w, XtNx, x - width, XtNy, y - height, NULL);
423 }
424 
425 
426 void
XtGetCenter(Widget w,Position * x,Position * y)427 WidgetsX::XtGetCenter(Widget w, Position *x, Position *y)
428 {
429     Dimension   width, height;
430 
431     XtVaGetValues(w, XtNwidth, &width, XtNheight, &height, NULL);
432 
433     XtTranslateCoords(w, width / 2, height / 2, x, y);
434 }
435 
436 void
XtSetCenter(Widget w,Position x,Position y)437 WidgetsX::XtSetCenter(Widget w, Position x, Position y)
438 {
439     Dimension   width, height;
440 
441     XtVaGetValues(w, XtNwidth, &width, XtNheight, &height, NULL);
442 
443     XtVaSetValues(w, XtNx, x - width / 2, XtNy, y - height / 2, NULL);
444 }
445 
446 char*
getMacroName(int i)447 WidgetsX::getMacroName(int i)
448 {
449     if (macrosform == 0)
450     {
451         return 0;
452     }
453 
454     Cardinal    numchildren;
455     WidgetList  children;
456     String      str;            // "string" may conflict with STL...
457 
458     XtVaGetValues(macrosform,
459                   XtNchildren, &children, XtNnumChildren, &numchildren, NULL);
460 
461     if (!INRANGE(0 <=, i, <(int)numchildren - 1))
462     {
463         fprintf(stderr,
464                 "widgets_get_macro_name: tried to get name %d out of %d\n",
465                 i, numchildren);
466         return 0;
467     }
468 
469 
470     /*
471      * We are interested in child number 2 of the macro box.
472      */
473     XtVaGetValues(children[i + 1], XtNchildren, &children, NULL);
474     XtVaGetValues(children[2], XtNstring, &str, NULL);
475     return str;
476     /* maybe should use XawAsciiSourceFreeString? Nahhh. */
477 }
478 
479 void*
addMacro(char * name,void * prev_ui_data)480 WidgetsX::addMacro(char *name, void* prev_ui_data)
481 {
482     if (macrosform == 0)
483     {
484         // ignore macro display in no-buttons mode
485         return 0;
486     }
487 
488     Widget      thismacrobox, callbutton, callinvbutton, macroname;
489     MacroUIData* ui_data = (MacroUIData*) prev_ui_data;
490     Widget prev = (ui_data ? ui_data->box : this->macrocontrols);
491 
492     thismacrobox = XtVaCreateWidget("thismacrobox",
493                                     boxWidgetClass,
494                                     macrosform,
495                                     XtNorientation, XtorientHorizontal,
496                                     XtNborderWidth, 0,
497                                     XtNfromVert, prev,
498                                     XtNresizable, FALSE, NULL);
499 
500     callbutton = XtVaCreateManagedWidget("call a macro",
501                                          commandWidgetClass,
502                                          thismacrobox,
503                                          XtNlabel, "Apply", NULL);
504     XtAddCallback(callbutton, XtNcallback, macroApply_cb,
505                   (void*) event_handler);
506 
507     callinvbutton = XtVaCreateManagedWidget("call inverse of a macro",
508                                             commandWidgetClass,
509                                             thismacrobox,
510                                             XtNlabel, "Inverse", NULL);
511     XtAddCallback(callinvbutton, XtNcallback, macroInvert_cb,
512                   (void*) event_handler);
513 
514     ui_data = new MacroUIData(thismacrobox, callbutton, callinvbutton, ui_data);
515     if (ui_data->prev)
516     {
517         ui_data->prev->next = ui_data;
518     }
519     this->apply_to_ui_data[callbutton] = ui_data;
520     this->invert_to_ui_data[callinvbutton] = ui_data;
521 
522     macroname = XtVaCreateManagedWidget("name of a macro",
523                                         asciiTextWidgetClass,
524                                         thismacrobox,
525                                         XtNstring, name,
526                                         XtNinsertPosition, strlen(name),
527                                         XtNeditType, XawtextEdit,
528                                         XtNresize, XawtextResizeBoth,
529                                         XtNresizable, FALSE,
530                                         /* tell parent it's OK */
531                                         NULL);
532 
533     /*
534      * (The following is partially stolen from xgc and xedit)
535      */
536 
537     /*
538      * Disable keys which would cause the cursor to go off the single
539      * line that we want to display.
540      * Also disable the "@" key because that's the delimiter in the log file.
541      * Also set ^U and ^W to do what I like, because it's my program.
542      */
543 
544     XtOverrideTranslations(macroname, XtParseTranslationTable("\
545     Ctrl<Key>J:    end-of-line()\n\
546     Ctrl<Key>M:    end-of-line()\n\
547     <Key>Linefeed: end-of-line()\n\
548     <Key>Return:   end-of-line()\n\
549     Ctrl<Key>O:    end-of-line()\n\
550     Meta<Key>I:    end-of-line()\n\
551     Ctrl<Key>N:    end-of-line()\n\
552     Ctrl<Key>P:    end-of-line()\n\
553     Ctrl<Key>Z:    end-of-line()\n\
554     Meta<Key>Z:    end-of-line()\n\
555     Ctrl<Key>V:    end-of-line()\n\
556     Meta<Key>V:    end-of-line()\n\
557     Shift<Key>@:   no-op()\n\
558     Ctrl<Key>U:    beginning-of-line() kill-to-end-of-line()\n\
559     Ctrl<Key>W:    backward-kill-word()\n\
560     "));
561     /*
562      * A quirk of the text widget makes it so that the "resize" resource
563      * doesn't take effect until something about the widget is changed.
564      * Need to figure out how to trigger it immediately.
565      * The following didn't do it. I don't know how to do it.
566      */
567     /* XawTextSetInsertionPoint(macroname, (XawTextPosition)strlen(name)); */
568     /* XtSetValues(macroname, XtNstring, name, NULL); */
569     /* XtForceDimensionsOfUnmanagedWidget(thismacrobox); */
570 
571 ///    {
572 ///        WidgetList  children;
573 ///        Cardinal    nchildren;
574 ///        XtVaGetValues(this->macrosform,
575 ///                      XtNchildren, &children, XtNnumChildren, &nchildren, NULL);
576 ///        XtUnmanageChildren(children, nchildren);
577 ///        XtManageChildren(children, nchildren);
578 ///    }
579 
580     XtManageChild(deletebutton);
581     XtManageChild(thismacrobox);
582     resizeToplevelToMatchBigform();
583 
584     return (void*) ui_data;
585 }
586 
587 void
removeMacro(void * ui_data_v)588 WidgetsX::removeMacro(void* ui_data_v)
589 {
590     MacroUIData* ui_data = (MacroUIData*) ui_data_v;
591 
592     if (ui_data->next)
593     {
594         ui_data->next->prev = ui_data->prev;
595     }
596     if (ui_data->prev)
597     {
598         ui_data->prev->next = ui_data->next;
599     }
600 
601     Cardinal numchildren;
602     XtVaGetValues(macrosform,
603                   XtNnumChildren, &numchildren, NULL);
604 
605     // Actually need to unmanage the child as well as destroy it,
606     // Since destroying doesn't do anything until the callbacks
607     // are completed, and we need the big form to redo its layout
608     // right now.
609     XawFormDoLayout(bigform, False);
610     XawFormDoLayout(macrosform, False);
611     XtUnmanageChild(ui_data->box);
612     if (numchildren == 2)   /* if it was 2 */
613         XtUnmanageChild(deletebutton);
614 
615     if (ui_data->next)
616     {
617         if (ui_data->prev)
618         {
619             XtVaSetValues(ui_data->next->box,
620                           XtNfromVert, ui_data->prev->box, NULL);
621         }
622         else
623         {
624             XtVaSetValues(ui_data->next->box,
625                           XtNfromVert, this->macrocontrols, NULL);
626         }
627     }
628 
629     XawFormDoLayout(macrosform, True);
630     XawFormDoLayout(bigform, True);
631     resizeToplevelToMatchBigform();
632 
633     XtDestroyWidget(ui_data->box);
634     this->apply_to_ui_data.erase(ui_data->apply);
635     this->invert_to_ui_data.erase(ui_data->invert);
636     delete ui_data;
637 }
638 
639 void
updateFastButton(int fast_automoves)640 WidgetsX::updateFastButton(int fast_automoves)
641 {
642     XtVaSetValues(this->fast_toggle, XtNstate, fast_automoves, NULL);
643 }
644 
645 void
createDialog(char * s,int nbuttons,ButtonData * button_data)646 WidgetsX::createDialog(char *s, int nbuttons, ButtonData* button_data)
647 {
648     if (cur_transientshell == (MAX_DIALOGS - 1))
649     {
650         // FIX THIS if it's worth it
651         fprintf(stderr, "need to increase MAX_DIALOGS in WidgetsX.cpp\n");
652         return;
653     }
654 
655     Position    centerx, centery;
656     Widget      dialog;
657 
658     Widget      transientshell = XtVaCreatePopupShell(
659         "",
660         /* (gasp) this string actually appears! */
661         transientShellWidgetClass,
662         toplevel,
663         NULL);
664 
665     dialog = XtVaCreateManagedWidget("dialog",
666                                      dialogWidgetClass,
667                                      transientshell,
668                                      XtNlabel, s, XtNborderWidth, 0,
669                                      XtRGravity, XtESouthEast,
670                                      NULL);
671     ++cur_transientshell;
672     dialog_callbacks[cur_transientshell] =
673         new EventHandler::Callback*[nbuttons];
674     int i;
675     for (i = 0; i < nbuttons; ++i)
676     {
677         dialog_callbacks[cur_transientshell][i] =
678             event_handler->createCallback(
679                 button_data[i].callback, button_data[i].cb_arg);
680         XawDialogAddButton(dialog,
681                            button_data[i].label,
682                            callCallback,
683                            dialog_callbacks[cur_transientshell][i]);
684     }
685 
686     XtForceDimensionsOfUnmanagedWidget(transientshell);
687     XtGetLowerRight(toplevel, &centerx, &centery);
688 
689     // FIX THIS: forcibly setting coordinates here disregards window
690     // manager decorations.  The attempt to use XtRGravity above
691     // didn't help.  We'll just kludge around it by substracting some
692     // safe number of pixels.
693     XtSetLowerRight(transientshell, centerx - 30, centery - 30);
694 
695     XtPopup(transientshell, XtGrabNone);
696 
697     transientshells[cur_transientshell] = transientshell;
698 }
699 
700 
701 void
destroyDialog()702 WidgetsX::destroyDialog()
703 {
704     if (cur_transientshell >= 0)
705     {
706         if (cur_transientshell < MAX_DIALOGS)
707         {
708             Widget transientshell = transientshells[cur_transientshell];
709             if (transientshell)
710             {
711                 XtUnmapWidget(transientshell);
712                 XtDestroyWidget(transientshell);
713                 transientshells[cur_transientshell] = 0;
714                 delete dialog_callbacks[cur_transientshell];
715                 dialog_callbacks[cur_transientshell] = 0;
716             }
717         }
718         --cur_transientshell;
719     }
720 }
721 
722 void
debuggingHack(MacroManager * macromgr)723 WidgetsX::debuggingHack(MacroManager* macromgr)
724 {
725     static int i = 0;
726 
727     WidgetList  children;
728     Cardinal    nchildren;
729     if (this->macrosform)
730     {
731         XtVaGetValues(this->macrosform,
732                       XtNchildren, &children, XtNnumChildren, &nchildren, NULL);
733     }
734 
735     void* prev_ui_data = 0;
736     for (int i = 0; i < macromgr->getNMacros(); ++i)
737     {
738         void* ui_data = this->addMacro(
739             macromgr->getMacroName(i), prev_ui_data);
740         macromgr->setUIData(i, ui_data);
741         prev_ui_data = ui_data;
742     }
743 
744     i = (1 + i) % 4;
745 }
746 
747 #ifdef hpux
748 #warning "This stuff shouldn't be ifdef hpux"
749 /*
750  * Stubs for things used by libXaw.a on certain hp machines
751  * but not defined anywhere.
752  * Hopefully they are never called...
753  */
754 Bool
XShapeQueryExtension(Display * dpy,int * event_basep,int * error_basep)755 XShapeQueryExtension(Display * dpy, int *event_basep, int *error_basep)
756 {
757     fprintf(stderr, "In XShapeQueryExtension stub\n");
758     return False;               /* don't know what I'm doing */
759 }
760 void
XShapeCombineMask()761 XShapeCombineMask()
762 {
763     fprintf(stderr, "In XShapeCombineMask stub\n");
764 }
765 #endif /* hpux */
766 
767 // Local Variables:
768 // c-basic-offset: 4
769 // c-comment-only-line-offset: 0
770 // c-file-offsets: ((defun-block-intro . +) (block-open . 0) (substatement-open . 0) (statement-cont . +) (statement-case-open . +4) (arglist-intro . +) (arglist-close . +) (inline-open . 0))
771 // indent-tabs-mode: nil
772 // End:
773