Initial import of the CDE 2.1.30 sources from the Open Group.
[oweals/cde.git] / cde / programs / dtmail / MotifApp / MenuBar.C
1 /* $TOG: MenuBar.C /main/6 1997/06/03 16:12:28 mgreess $ */
2 /*
3  *+SNOTICE
4  *
5  *      RESTRICTED CONFIDENTIAL INFORMATION:
6  *      
7  *      The information in this document is subject to special
8  *      restrictions in a confidential disclosure agreement bertween
9  *      HP, IBM, Sun, USL, SCO and Univel.  Do not distribute this
10  *      document outside HP, IBM, Sun, USL, SCO, or Univel wihtout
11  *      Sun's specific written approval.  This documment and all copies
12  *      and derivative works thereof must be returned or destroyed at
13  *      Sun's request.
14  *
15  *      Copyright 1993, 1994, 1995 Sun Microsystems, Inc.  All rights reserved.
16  *
17  *+ENOTICE
18  */
19 ///////////////////////////////////////////////////////////////////////////////
20 //////////////////////////////////////////////////////////////////////////////
21 //         This example code is from the book:
22 //
23 //           Object-Oriented Programming with C++ and OSF/Motif
24 //         by
25 //           Douglas Young
26 //           Prentice Hall, 1992
27 //           ISBN 0-13-630252-1 
28 //
29 //         Copyright 1991 by Prentice Hall
30 //         All Rights Reserved
31 //
32 //  Permission to use, copy, modify, and distribute this software for 
33 //  any purpose except publication and without fee is hereby granted, provided 
34 //  that the above copyright notice appear in all copies of the software.
35 ///////////////////////////////////////////////////////////////////////////////
36 //////////////////////////////////////////////////////////////////////////////
37
38
39 //////////////////////////////////////////////////////////
40 // MenuBar.C: A menu bar whose panes support items
41 //            that execute Cmd's
42 //////////////////////////////////////////////////////////
43
44 ////////////////////////////////////////////////////////////
45 // MODIFIED TO SUPPORT SUBMENUS - not described in Book
46 ///////////////////////////////////////////////////////////
47
48
49 #include "Application.h"
50 #include "MenuBar.h"
51 #include "Cmd.h"
52 #include "CmdList.h"
53 #include "ToggleButtonInterface.h"
54 #include "ButtonInterface.h"
55 #include "Help.hh"
56 #include <Xm/RowColumn.h>
57 #include <Xm/CascadeB.h>
58 #include <Xm/Separator.h>
59 #include <Xm/PushB.h>
60 #include <Xm/Label.h>
61
62
63 extern "C" {
64 extern XtPointer _XmStringUngenerate (
65                                 XmString string,
66                                 XmStringTag tag,
67                                 XmTextType tag_type,
68                                 XmTextType output_type);
69 }
70
71 MenuBar::MenuBar ( Widget parent, char *name, unsigned char type ) 
72 : UIComponent ( name )
73 {
74     // Base widget is a Motif menu bar widget
75     
76     if(parent == NULL)
77         return;
78
79     if( type == XmMENU_POPUP) {
80         Arg args[1];
81         int i = 0;
82
83         XtSetArg(args[i], XmNwhichButton, theApplication->bMenuButton()); i++;
84         _w = XmCreatePopupMenu( parent, _name, args, i );
85 //        XtVaSetValues(_w, XmNwhichButton, theApplication->bMenuButton(), NULL);
86     } else {
87         type = XmMENU_BAR; // Force it to menu bar
88         _w = XmCreateMenuBar ( parent, _name, NULL, 0 );
89     }
90
91     printHelpId("_w", _w);
92     /* install callback */
93     // XtAddCallback(_w, XmNhelpCallback, HelpCB, helpId);
94     
95     installDestroyHandler();
96 }
97 Widget MenuBar::addCommands ( Widget *menuBarCascade, CmdList *list, Boolean help, unsigned char type )
98 {
99     return( createPulldown ( _w, list, menuBarCascade, help, type ) );
100 }
101
102 Widget MenuBar::addCommands ( CmdList *list, Boolean help, unsigned char type )
103 {
104     return( createPulldown ( _w, list, help, type ) );
105 }
106
107 Widget 
108 MenuBar::createPulldown ( 
109         Widget parent, 
110         CmdList *list, 
111         Widget *cascade, 
112         Boolean help ,
113         unsigned char type)
114 {
115     int    i;
116     Widget pulldown;
117     Arg  args2[2];
118     char * helpId;
119     XmString label_str;
120
121     if(type != XmMENU_POPUP)
122         type = XmMENU_BAR;
123     
124     // Create a pulldown menu pane for this list of commands
125     
126     if( type == XmMENU_BAR) {
127                 pulldown = XmCreatePulldownMenu( parent,
128                                 (char *) list->name(), NULL, 0 );
129                 label_str = XmStringCreateLocalized(list->getLabel());
130                 XtVaSetValues(pulldown,
131                               XmNlabelString, label_str,
132                               NULL);
133                 printHelpId("pulldown", pulldown);
134                 /* install callback */
135                 // XtAddCallback(pulldown, XmNhelpCallback, HelpCB, helpId);
136
137                 
138                 // Each entry in the menu bar must have a cascade button
139                 // from which the user can pull down the pane
140
141                 if (cascade != NULL && *cascade != NULL)
142                         XtVaSetValues (*cascade, XmNsubMenuId, pulldown, 
143                                        XmNlabelString, label_str,
144                                        NULL);
145                 else {
146
147                         XtSetArg(args2[0], XmNsubMenuId, pulldown);
148                         *cascade = XtCreateWidget ( list->name(), 
149                                        xmCascadeButtonWidgetClass,
150                                        parent, 
151                                        args2, 1);
152                         XtVaSetValues(*cascade,
153                                       XmNlabelString, label_str,
154                                       NULL);
155                         if (help) {
156                                 XtSetArg (args2[0], XmNmenuHelpWidget, *cascade);
157                                 XtSetValues (parent, args2, 1);
158                         }
159                         
160                         XtManageChild ( *cascade );
161                         printHelpId("cascade", *cascade);
162                         /* install callback */
163
164
165                         // Install callbacks for each of the 
166                         // pulldown menus so we can get
167                         // On Item help for them.
168
169                         helpId = XtName(*cascade);
170                         if (helpId == "Mailbox") {
171                                 XtAddCallback(*cascade, XmNhelpCallback, 
172                                 HelpCB, DTMAILCONTAINERMENUID);
173                         } else if (helpId == "Edit") {
174                                 XtAddCallback(*cascade, XmNhelpCallback, 
175                                         HelpCB, DTMAILEDITMENUID);
176                         } else if (helpId == "Message") {
177                                 XtAddCallback(*cascade, XmNhelpCallback, 
178                                         HelpCB, DTMAILMESSAGEMENUID);
179                         } else if (helpId == "Attachments") {
180                                 XtAddCallback(*cascade, XmNhelpCallback, 
181                                         HelpCB, DTMAILATTACHMENUID);
182                         } else if (helpId == "View") {
183                                 XtAddCallback(*cascade, XmNhelpCallback, 
184                                         HelpCB, DTMAILVIEWMENUID);
185                         } else if (helpId == "Compose") {
186                                 XtAddCallback(*cascade, XmNhelpCallback, 
187                                         HelpCB, DTMAILCOMPOSEMENUID);
188                         }
189                 }
190      } else
191                 pulldown = _w;
192         
193         
194     
195     // Loop through the cmdList, creating a menu 
196     // entry for each command. 
197     Widget *head_wl, *wl;
198     Cardinal num_wl = 0;
199     head_wl = wl = new Widget[ list->size() ];
200     
201     for ( i = 0; i < list->size(); i++)
202     {
203
204         if(!strcmp((*list)[i]->className(), "CmdList")) {
205             Widget pane = createPulldown(pulldown, 
206                 (CmdList*) (*list)[i], FALSE, XmMENU_BAR);
207             ((CmdList *)(*list)[i])->setPaneWidget(pane);
208             label_str = XmStringCreateLocalized(((CmdList *)(*list)[i])->getLabel());
209             XtVaSetValues(pane, 
210                           XmNlabelString, label_str,
211                           NULL);
212         } else {
213             if ( !strcmp((*list)[i]->className(),"SeparatorCmd")) {
214                 *(wl++) = XtCreateWidget ( (*list)[i]->name(),
215                                           xmSeparatorWidgetClass,
216                                           pulldown,
217                                           NULL, 0);
218             } else if (!strcmp((*list)[i]->className(),"ToggleButtonCmd")) {
219                 CmdInterface *ci;
220                 ci = new ToggleButtonInterface(pulldown, (*list)[i] );
221                 *(wl++) = ci->baseWidget();
222             } else if(!strcmp((*list)[i]->className(),"LabelCmd")) {
223                 label_str = XmStringCreateLocalized((*list)[i]->getLabel());
224
225                 *(wl++) = XtVaCreateWidget ( (*list)[i]->name(),
226                                         xmLabelWidgetClass,
227                                         pulldown,
228                                         XmNlabelString, label_str,
229                                         NULL);
230             } else {
231                 CmdInterface *ci;
232                 ci  = new ButtonInterface ( pulldown, (*list)[i] );
233                 *(wl++) = ci->baseWidget();
234             }
235
236             num_wl++;
237         }
238     }
239
240     XtManageChildren ( head_wl, num_wl );
241     delete head_wl;
242
243     return(pulldown);
244 }
245
246 Widget 
247 MenuBar::createPulldown ( 
248         Widget parent, 
249         CmdList *list, 
250         Boolean help ,
251         unsigned char type)
252 {
253     int    i;
254     Widget pulldown, cascade;
255     Arg  args2[2];
256     char * helpId;
257     XmString label_str;
258
259     if(type != XmMENU_POPUP)
260         type = XmMENU_BAR;
261     
262     // Create a pulldown menu pane for this list of commands
263     
264     if( type == XmMENU_BAR) {
265                 pulldown = XmCreatePulldownMenu( parent,
266                                 (char *) list->name(), NULL, 0 );
267                 label_str = XmStringCreateLocalized(list->getLabel());
268                 XtVaSetValues(pulldown,
269                               XmNlabelString, label_str,
270                               NULL);
271                 printHelpId("pulldown", pulldown);
272                 /* install callback */
273                 // XtAddCallback(pulldown, XmNhelpCallback, HelpCB, helpId);
274
275                 
276                 // Each entry in the menu bar must have a cascade button
277                 // from which the user can pull down the pane
278
279                 XtSetArg(args2[0], XmNsubMenuId, pulldown);
280                 cascade = XtCreateWidget ( list->name(), 
281                                xmCascadeButtonWidgetClass,
282                                parent, 
283                                args2, 1);
284                 XtVaSetValues(cascade,
285                               XmNlabelString, label_str,
286                               NULL);
287                 if (help) {
288                         XtSetArg (args2[0], XmNmenuHelpWidget, cascade);
289                         XtSetValues (parent, args2, 1);
290                 }
291                 
292                 XtManageChild ( cascade );
293                 printHelpId("cascade", cascade);
294                 /* install callback */
295
296
297                 // Install callbacks for each of the 
298                 // pulldown menus so we can get
299                 // On Item help for them.
300
301                 helpId = XtName(cascade);
302                 if (helpId == "Mailbox") {
303                         XtAddCallback(cascade, XmNhelpCallback, 
304                                 HelpCB, DTMAILCONTAINERMENUID);
305                 } else if (helpId == "Edit") {
306                         XtAddCallback(cascade, XmNhelpCallback, 
307                                 HelpCB, DTMAILEDITMENUID);
308                 } else if (helpId == "Message") {
309                         XtAddCallback(cascade, XmNhelpCallback, 
310                                 HelpCB, DTMAILMESSAGEMENUID);
311                 } else if (helpId == "Attachments") {
312                         XtAddCallback(cascade, XmNhelpCallback, 
313                                 HelpCB, DTMAILATTACHMENUID);
314                 } else if (helpId == "View") {
315                         XtAddCallback(cascade, XmNhelpCallback, 
316                                 HelpCB, DTMAILVIEWMENUID);
317                 } else if (helpId == "Compose") {
318                         XtAddCallback(cascade, XmNhelpCallback, 
319                                 HelpCB, DTMAILCOMPOSEMENUID);
320                 }
321      } else
322                 pulldown = _w;
323         
324         
325     
326     // Loop through the cmdList, creating a menu 
327     // entry for each command. 
328     
329     for ( i = 0; i < list->size(); i++)
330     {
331
332         if(!strcmp((*list)[i]->className(), "CmdList")) {
333             Widget pane = createPulldown(pulldown, 
334                         (CmdList*) (*list)[i], FALSE, XmMENU_BAR);
335             ((CmdList *)(*list)[i])->setPaneWidget(pane);
336             label_str = XmStringCreateLocalized((*list)[i]->getLabel());
337             XtVaSetValues(pane, 
338                           XmNlabelString, label_str,
339                           NULL);
340         } else {
341             if ( !strcmp((*list)[i]->className(),"SeparatorCmd")) {
342                 XtCreateManagedWidget ( (*list)[i]->name(),
343                                           xmSeparatorWidgetClass,
344                                           pulldown,
345                                           NULL, 0);
346             } else if (!strcmp((*list)[i]->className(),"ToggleButtonCmd")) {
347                 CmdInterface *ci;
348                 ci = new ToggleButtonInterface(pulldown, (*list)[i]);
349                 ci->manage();
350             } else if(!strcmp((*list)[i]->className(),"LabelCmd")) {
351                 Widget  _i18n;
352                 Arg _args[1];
353                 XmString xms;
354                 
355                 _i18n = XtCreateManagedWidget(
356                                         (*list)[i]->name(),
357                                         xmLabelWidgetClass,
358                                         pulldown,
359                                         NULL, 0
360                                         );
361
362                 xms = XmStringCreateLocalized((char*) (*list)[i]->getLabel());
363                 XtSetArg( _args[0], XmNlabelString, xms );
364                 XtSetValues( _i18n, _args, 1 );
365                 XmStringFree(xms);
366             } else {
367                 CmdInterface *ci;
368                 ci  = new ButtonInterface ( pulldown, (*list)[i] );
369                 ci->manage();
370             }
371         }
372     }
373     return(pulldown);
374 }
375
376 // SR - Added to handle dynamic menus
377
378 Widget
379 MenuBar::addCommands(
380     Widget pulldown,
381     CmdList *new_list
382 )
383 {
384     // if(isValidMenuPane(pulldown) == FALSE)
385     //  return NULL;
386
387     int    i, num_children;
388     WidgetList children;
389     Boolean haveNoSeparator;
390     int newItemIndex, numPBUnmanaged, tmpPBUnmanaged;
391
392     XtVaGetValues(pulldown,
393         XmNnumChildren, &num_children,
394         NULL);
395     
396     children = (WidgetList)XtMalloc(sizeof(Widget) * num_children);
397     
398     XtVaGetValues(pulldown,
399         XmNchildren, &children,
400         NULL);
401
402     // Handle the creation or management of the Separator.
403
404     haveNoSeparator = TRUE;
405     numPBUnmanaged = 0;
406     
407     for (i=0; (i < num_children); i++) {
408         Widget wid = (Widget) children[i];
409         if (XtIsSubclass(wid, xmSeparatorWidgetClass)) {
410             XtManageChild(wid);
411             haveNoSeparator = FALSE;
412         }
413         else if (XtIsSubclass(wid, xmPushButtonWidgetClass)) {
414             if (!XtIsManaged(wid)) { // If widget is unmanaged
415                 numPBUnmanaged++;
416             }
417         }
418     }
419     if (haveNoSeparator) {
420         XtCreateManagedWidget ("Separator",
421                 xmSeparatorWidgetClass,
422                 pulldown,
423                 NULL, 0);
424         haveNoSeparator = FALSE;
425     }
426     
427     // Now handle the pushButton case
428
429     newItemIndex = 0;
430     tmpPBUnmanaged = 0;
431
432     // Loop through the cmdList, creating a menu 
433     // entry for each command. 
434         
435     for (newItemIndex = 0; newItemIndex < new_list->size(); newItemIndex++) {
436
437         tmpPBUnmanaged = numPBUnmanaged;
438
439         if (numPBUnmanaged > 0) { // If there exists unmanaged PBs
440             for (i = 0; 
441                  (i < num_children) && 
442                  (tmpPBUnmanaged == numPBUnmanaged); 
443                  i++) {
444
445                 Widget wid = (Widget) children[i];
446                 
447                 if (XtIsSubclass(wid, xmPushButtonWidgetClass)) {
448                     if (!XtIsManaged(wid)) { 
449                         // If widget is unmanaged
450                         // Set its label to be the newItemIndex widget's.
451                         // Manage it.
452                         // Bump up newItemIndex
453                         XtVaSetValues(wid,
454                             XmNlabelString, XmStringCreateLocalized(
455                                 (char *) (*new_list)[newItemIndex]->getLabel()),
456                             NULL);
457                         XtManageChild(wid);
458                         numPBUnmanaged--;
459                     }
460                 }
461             }
462         }
463         else {          // No unmanaged push buttons available
464             CmdInterface *ci;
465             ci  = new ButtonInterface ( 
466                 pulldown, (*new_list)[newItemIndex] 
467             );
468             ci->manage();
469         }
470     }
471
472     return(pulldown);
473 }
474
475 void
476 MenuBar::removeOnlyCommands(
477     Widget pulldown,
478     CmdList *redundant_list
479 )
480 {
481     // if(isValidMenuPane(pulldown) == FALSE)
482     //  return;
483
484     int    i, j, num_children;
485     WidgetList children;
486     
487     XtVaGetValues(pulldown,
488         XmNnumChildren, &num_children,
489         NULL);
490     
491     children = (WidgetList)XtMalloc(sizeof(Widget) * num_children);
492     
493     XtVaGetValues(pulldown,
494         XmNchildren, &children,
495         NULL);
496      
497     // Loop through widget list.  Destroy those widgets that map to those
498     // in the redundant list.
499
500     for (i=0; i<num_children; i++) {
501
502         Widget wid = (Widget) children[i];
503
504         if (XtIsSubclass(wid, xmPushButtonWidgetClass)) {
505
506             for (j=0; j<redundant_list->size(); j++) {
507                 char name[200];
508                 ButtonInterface::mapName((*redundant_list)[j]->name(), name);
509                 if (strcmp(XtName(wid), name) == 0) {
510                     // The redundant item has been found.
511                     XtUnmanageChild(wid);
512                 }
513             }
514         }
515     }
516 }
517 void
518 MenuBar::removeCommands(
519     Widget pulldown,
520     CmdList *redundant_list
521 )
522 {
523     // if(isValidMenuPane(pulldown) == FALSE)
524     //  return;
525
526     int    i, j, num_children;
527     WidgetList children;
528     
529     XtVaGetValues(pulldown,
530         XmNnumChildren, &num_children,
531         NULL);
532     
533     children = (WidgetList)XtMalloc(sizeof(Widget) * num_children);
534     
535     XtVaGetValues(pulldown,
536         XmNchildren, &children,
537         NULL);
538      
539     // Loop through widget list.  Destroy those widgets that map to those
540     // in the redundant list.
541
542     for (i=0; i<num_children; i++) {
543
544         Widget wid = (Widget) children[i];
545
546         if (XtIsSubclass(wid, xmSeparatorWidgetClass)) {
547             XtUnmanageChild(wid);
548         }
549         else if (XtIsSubclass(wid, xmPushButtonWidgetClass)) {
550
551             for (j=0; j<redundant_list->size(); j++) {
552                 XmString str=NULL;
553                 String label=NULL;
554                 XtVaGetValues(wid, XmNlabelString, &str, NULL);
555                 if (str == NULL) continue;
556                 label = NULL;
557                 label = (char *) _XmStringUngenerate(
558                                         str, NULL,
559                                         XmMULTIBYTE_TEXT, XmMULTIBYTE_TEXT);
560                 XmStringFree(str);
561                 if (label == NULL) continue;
562                 if (strcmp(label, (*redundant_list)[j]->getLabel()) == 0) {
563                     // The redundant item has been found.
564                     XtUnmanageChild(wid);
565                 }
566                 XtFree(label);
567             }
568         }
569     }
570 }
571
572 void
573 MenuBar::addCommand(
574     Widget pulldown,
575     Cmd *cmd
576 )
577 {
578     // if(isValidMenuPane(pulldown) == FALSE)
579     //  return;
580
581     CmdInterface *ci;
582     ci  = new ButtonInterface ( pulldown, cmd);
583     ci->manage();
584 }
585
586 void
587 MenuBar::changeLabel(
588     Widget pulldown,
589     int index,
590     char * name
591 )
592 {
593     // if(isValidMenuPane(pulldown) == FALSE)
594     //  return;
595
596     int managed_widgets, i, num_children;
597     WidgetList children;
598     XmString label;
599     Widget wid;
600
601     XtVaGetValues(pulldown,
602         XmNnumChildren, &num_children,
603         NULL);
604
605     children = (WidgetList)XtMalloc(sizeof(Widget) * num_children);
606
607     XtVaGetValues(pulldown,
608         XmNchildren, &children,
609         NULL);
610     
611     // Some widgets may be unmanaged, so find the real index
612     for (managed_widgets=0, i=0; 
613                 managed_widgets <= index && i < num_children; i++) {
614         wid = (Widget) children[i];
615         if (XtIsManaged(wid)) managed_widgets++;
616     }
617     if (--i >= num_children) return;
618
619     wid = (Widget) children[i];
620
621     label = XmStringCreateLocalized(name);
622
623     XtVaSetValues(wid,
624         XmNlabelString, label,
625         NULL);
626     XmStringFree(label);
627 }
628
629 void
630 MenuBar::changeLabel(Widget pulldown,
631                      const char * button_name,
632                      const char * label)
633 {
634     // if(isValidMenuPane(pulldown) == FALSE)
635     //  return;
636
637     // Locate the appropriate widget in the list.
638     //
639     int num_children;
640     char wid_name[200];
641     XmString label_string = XmStringCreateLocalized((char *)label);
642
643     ButtonInterface::mapName(button_name, wid_name);
644
645     XtVaGetValues(pulldown,
646                   XmNnumChildren, &num_children,
647                   NULL);
648
649     Widget * children = new Widget[num_children];
650     XtVaGetValues(pulldown,
651                   XmNchildren, &children,
652                   NULL);
653
654     for (int wid = 0; wid < num_children; wid++) {
655         if (strcmp(XtName(children[wid]), wid_name) == 0) {
656             if (XtIsManaged(children[wid]))
657                  XtVaSetValues(children[wid],
658                           XmNlabelString, label_string,
659                           NULL);
660         }
661     }
662
663     XmStringFree(label_string);
664 }
665     
666 void
667 MenuBar::rotateLabels(
668     Widget pulldown,
669     int startindex,
670     int endindex
671 )
672 {
673     // if(isValidMenuPane(pulldown) == FALSE)
674     //  return;
675
676     int    num_managed_wids=0, i, j, num_children, num_to_change;
677     WidgetList children;
678     XmString label, endlabel;
679     Widget prevwid, wid;
680
681     if (startindex < 0 || endindex < 0)
682         return;
683
684     XtVaGetValues(pulldown,
685         XmNnumChildren, &num_children,
686         NULL);
687
688     if (startindex >= num_children || endindex >= num_children)
689         return;
690     
691     num_to_change = endindex - startindex;
692     if (num_children < num_to_change || num_to_change == 0) 
693         return;
694
695     children = (WidgetList)XtMalloc(sizeof(Widget) * num_children);
696
697     XtVaGetValues(pulldown,
698         XmNchildren, &children,
699         NULL);
700
701     // Some of the widgets may be unmanaged: find the first managed widget
702     for (i = startindex; i < num_children; i++) {
703         if (XtIsManaged(children[i]))
704                 break;
705         startindex++;
706     }
707
708     if (startindex == num_children) 
709         return;
710
711     // Find the real endindex
712     endindex = startindex+1;
713     while (endindex < num_children) {
714         if (XtIsManaged(children[endindex])) 
715                 num_managed_wids++;
716         if (num_managed_wids == num_to_change)
717                 // We have found the endindex at this point
718                 break;
719         endindex++;
720     } 
721  
722     if (endindex == num_children) 
723         return;
724
725     wid = (Widget) children[endindex];
726     XtVaGetValues(wid,
727         XmNlabelString, &label,
728         NULL);
729     endlabel = XmStringCopy(label);
730
731     j = i = endindex; 
732     while (i > startindex) {
733
734         do {
735                 if (--j < startindex) break;
736                 prevwid = (Widget) children[j];
737         } while (!XtIsManaged(prevwid));
738
739         XtVaGetValues(prevwid,
740                 XmNlabelString, &label,
741                 NULL);
742
743         XtVaSetValues(wid,
744                 XmNlabelString, label,
745                 NULL);
746
747         i = j;
748
749         wid = (Widget) children[i];
750     }
751
752     wid = (Widget) children[startindex];
753     XtVaSetValues(wid,
754         XmNlabelString, endlabel,
755         NULL);
756     
757     XmStringFree(endlabel);
758 }
759
760 #ifdef DEAD_WOOD
761 Boolean
762 MenuBar::isValidMenuPane(Widget w)
763 {
764         Boolean retval = FALSE;
765         Widget parent = w;
766
767         while(parent && parent != _w)
768                 parent = XtParent(parent);
769
770         if(parent == _w)
771                 retval = TRUE;
772
773         return retval;
774 }
775 #endif /* DEAD_WOOD */
776
777 void
778 MenuBar::removeCommand(
779     Widget pulldown,
780     int index
781 )
782 {
783     //if(isValidMenuPane(pulldown) == FALSE)
784     //   return;
785
786     int   managed_widgets, i, num_children;
787     WidgetList children;
788
789     XtVaGetValues(pulldown,
790         XmNnumChildren, &num_children,
791         NULL);
792
793     children = (WidgetList)XtMalloc(sizeof(Widget) * num_children);
794
795     XtVaGetValues(pulldown,
796         XmNchildren, &children,
797         NULL);
798
799     // Some widgets may be unmanaged, so find the real index
800     for (managed_widgets=0, i=0;
801                 managed_widgets <= index && i < num_children; i++) {
802         Widget wid = (Widget) children[i];
803         if (XtIsManaged(wid)) managed_widgets++;
804     }
805
806     if (--i < num_children)
807         XtUnmanageChild(children[i]);
808 }