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