dtcm: Coverity 88353
[oweals/cde.git] / cde / programs / dtwm / PopupMenu.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 libraries 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 /*****************************************************************************
24  *****************************************************************************
25  **
26  **   File:         PopupMenu.c
27  **
28  **   Project:      CDE
29  **
30  **   Description:  This file contains the functions for creating and managing
31  **                 the main panel and subpanel popup menus.
32  **
33  **
34  ****************************************************************************
35  *****************************************************************************/
36
37
38 #include <Xm/XmP.h>
39 #include <Xm/ManagerP.h>
40 #include <Xm/RowColumn.h>
41 #include <Xm/LabelG.h>
42 #include <Xm/PushBG.h>
43 #include <Xm/SeparatoG.h>
44
45 #include <Dt/SharedProcs.h>
46
47 #include "DataBaseLoad.h"
48 #include "WmGlobal.h"
49 #include "UI.h"
50
51 #define POPUP_CHILDREN 7
52
53
54 extern void ToggleDefaultControl (ControlData *, SubpanelData *, ControlData *);
55 extern void SwitchRenameLabel (Widget, BoxData *);
56 extern Boolean CheckControlTypeFile (ControlData *);
57
58
59
60
61
62
63
64 /************************************************************************
65  *
66  *  ActionCB
67  *
68  ************************************************************************/
69  
70 void
71 ActionCB (Widget    w,
72           XtPointer client_data,
73           XtPointer call_data)
74
75
76 {
77    ControlData * control_data;
78    long           control_type;
79
80    long indx = (long) client_data;
81    Arg args[1];
82
83
84    XtSetArg (args[0], XmNuserData, &control_data);
85    XtGetValues(w, args, 1);
86
87    if (CheckControlTypeFile (control_data) == False)
88       return;
89
90    control_type = (long) (control_data->element_values[CONTROL_TYPE].parsed_value);
91
92    if (control_type == CONTROL_FILE && !control_data->is_action)
93    {
94       DtActionArg * aap;
95
96       aap = (DtActionArg *) XtCalloc(1,sizeof(DtActionArg));
97
98       aap->argClass = DtACTION_FILE;
99
100       aap->u.file.name = (char *)
101                control_data->element_values[CONTROL_FILE_NAME].parsed_value;
102
103       DtActionInvoke (control_data->icon,
104                       control_data->actions[indx]->action_name,
105                       aap, 1, NULL, NULL, NULL, 1, NULL, NULL);
106
107       XtFree ((char *) aap);
108    }
109    else
110    {
111       DtActionInvoke (control_data->icon,
112                       control_data->actions[indx]->action_name,
113                       control_data->actions[indx]->aap,
114                       control_data->actions[indx]->count,
115                       NULL, NULL, NULL, 1, NULL, NULL);
116    }
117 }
118
119
120 /************************************************************************
121  *
122  *  DeleteWorkspaceCB
123  *      The callback function is called off of a menu pick to delete
124  *      a specific workspace.  The function identifies the index of the
125  *      workspace and calls the workspace manager API to perform the delete.
126  *      All frontpanel UI processing is performed through a notification 
127  *      callback issued by the workspace manager after a successful delete.
128  *
129  ************************************************************************/
130
131 void
132 DeleteWorkspaceCB (Widget    w,
133                    XtPointer client_data,
134                    XtPointer call_data)
135
136
137 {
138    long delete_workspace = (long) client_data;
139    SwitchData * switch_data = NULL;
140    int i;
141    
142
143    /*  Look up the switch data to get the atom name of the workspace  */
144    /*  to delete.                                                     */
145    
146    for (i = 0; i < panel.box_data_count; i++)
147    {
148       if (panel.box_data[i]->switch_data != NULL)
149       {
150          switch_data = panel.box_data[i]->switch_data;
151          break;
152       }
153    }
154
155    if(switch_data)
156    {
157       _DtWsmDeleteWorkspace (panel.shell, 
158                              switch_data->atom_names[delete_workspace]);
159    }
160 }
161
162
163
164
165 /************************************************************************
166  *
167  *  RenameWorkspaceCB
168  *      The callback function is called off of a menu pick to rename
169  *      a specific workspace.  The function identifies the index of the
170  *      workspace and calls SwitchRenameLabel() function to change the switch.
171  *      button to a text widget for typing the new workspace name and setting.
172  *      up the callback to accept the new name upon activation.
173  *
174  ************************************************************************/
175
176 void
177 RenameWorkspaceCB (Widget    w,
178                    XtPointer client_data,
179                    XtPointer call_data)
180
181
182 {
183    long rename_ws = (long) client_data;
184    SwitchData * switch_data = NULL;
185    int i;
186    
187
188    /*  Look up the switch data to get the atom name of the workspace  */
189    /*  to delete.                                                     */
190    
191    for (i = 0; i < panel.box_data_count; i++)
192    {
193       if (panel.box_data[i]->switch_data != NULL)
194       {
195          switch_data = panel.box_data[i]->switch_data;
196          break;
197       }
198    }
199    
200    if(switch_data) {
201       SwitchRenameLabel (switch_data->buttons[rename_ws], panel.box_data[i]);
202    }
203 }
204
205
206
207
208
209 /************************************************************************
210  *
211  *  AddWorkspaceCB
212  *      The callback function is called off of a menu pick.  It generates
213  *      a new workspace name and calls the workspace manager API to 
214  *      create the new workspace.  All frontpanel UI processing is 
215  *      performed through a notification callback issued by the workspace
216  *      manager after a successful add.
217  *
218  ************************************************************************/
219  
220 void
221 AddWorkspaceCB (Widget    w,
222                 XtPointer client_data,
223                 XtPointer call_data)
224
225
226 {
227    SwitchData * switch_data = NULL;
228    char * switch_name;
229    char * temp_name;
230
231    int append;
232    int i;
233    int slen;
234
235    /*  Get the beginning part of the new name  */
236    
237    temp_name = FPGETMESSAGE (82, 35, "New");
238    slen = strlen (temp_name) + 5 + 1;
239    switch_name = XtCalloc(1, slen);
240    strcpy (switch_name, temp_name);
241
242
243    /*  Look up the switch data to get the atom name of the workspace  */
244    /*  to delete.                                                     */
245    
246    for (i = 0; i < panel.box_data_count; i++)
247    {
248       if (panel.box_data[i]->switch_data != NULL)
249       {
250          switch_data = panel.box_data[i]->switch_data;
251          break;
252       }
253    }
254    
255
256    /*  Generate a new title for the workspace.  It should be unique  */
257    /*  from the existing title.                                      */
258
259    append = 0;
260
261    while (1)
262    {
263       Boolean good_name;
264       
265       good_name = True;
266       append++;      
267
268       for (i = 0; i < switch_data->switch_count; i++)
269       {
270          if (strcmp (switch_name, switch_data->switch_names[i]) == 0)
271          {
272             good_name = False;
273             snprintf (switch_name, slen - 1, "%s_%d", temp_name, append);
274             continue;
275          }
276       }
277
278       if (good_name)
279       {
280          _DtWsmCreateWorkspace (panel.shell, switch_name);
281          break;
282       }
283    }
284
285    XtFree(switch_name);
286 }
287
288
289 /************************************************************************
290  *
291  *  DeleteCancelCB
292  *
293  ************************************************************************/
294
295 static void
296 DeleteCancelCB(
297         Widget w,
298         XtPointer client_data,
299         XtPointer call_data )
300 {
301    XtUnmanageChild((Widget)client_data);
302    XmUpdateDisplay((Widget)client_data);
303    XtDestroyWidget((Widget)client_data);
304 }
305
306
307
308
309 /************************************************************************
310  *
311  *  DeleteControlOkCB
312  *      Called from the Ok button on the confimation dialog when a 
313  *      control deletion is seleted from the popup menu.
314  *
315  ************************************************************************/
316
317
318 static void
319 DeleteControlOkCB (Widget    w,
320                    XtPointer client_data,
321                    XtPointer call_data)
322
323
324 {
325    ControlData  * control_data;
326    SubpanelData * subpanel_data;
327    Arg args[1];
328
329
330    /*  Extract the control data from the user data field of the  */
331    /*  widget pointed to by client data.                         */
332    
333    XtSetArg (args[0], XmNuserData, &control_data);
334    XtGetValues((Widget) client_data, args, 1);
335
336
337    /*  Get the subpanel data for the control.  Check to see if the  */
338    /*  control is a real subpanel control or the main panel copy.   */
339    
340    if (control_data->parent_type == SUBPANEL)
341       subpanel_data = (SubpanelData *) control_data->parent_data;
342    else
343       subpanel_data = (SubpanelData *) control_data->subpanel_data;
344
345
346    /*  Get rid of the dialog and call the funtion to delete the control  */
347
348    XtUnmanageChild ((Widget) client_data);
349    XmUpdateDisplay ((Widget) client_data);
350
351    DeleteSubpanelControl (subpanel_data, control_data);
352
353    XtDestroyWidget ((Widget) client_data);
354 }
355
356
357
358
359 /************************************************************************
360  *
361  *  DeleteSubpanelOkCB
362  *
363  ************************************************************************/
364
365 static void
366 DeleteSubpanelOkCB(
367         Widget w,
368         XtPointer client_data,
369         XtPointer call_data )
370 {
371    ControlData * control_data;
372    Arg args[1];
373
374    XtSetArg (args[0], XmNuserData, &control_data);
375    XtGetValues((Widget)client_data, args, 1);
376
377    XtUnmanageChild((Widget)client_data);
378    XmUpdateDisplay((Widget)client_data);
379
380    DeleteSubpanel(control_data);
381
382    XtDestroyWidget((Widget)client_data);
383 }
384
385
386 /************************************************************************
387  *
388  *  DeleteControlCB
389  *
390  ************************************************************************/
391
392 void
393 DeleteControlCB (Widget    w,
394                  XtPointer client_data,
395                  XtPointer call_data)
396
397
398 {
399     ControlData * control_data;
400 #ifndef IBM_163763
401     SubpanelData *subpanel_data;
402 #endif
403     Widget dialog;
404     String title, del_ctrl, ctrl_name, ctrl_label, del_msg, message;
405     long indx = (long) client_data;
406     Arg args[2];
407
408     XtSetArg (args[0], XmNuserData, &control_data);
409     XtGetValues (w, args, 1);
410
411     del_ctrl = FPGETMESSAGE(82, 31, "Delete Control:");
412     del_ctrl = XtNewString (del_ctrl);
413
414     ctrl_label = (char *)
415                 control_data->element_values[CONTROL_LABEL].parsed_value;
416     ctrl_name = (char *)
417                    control_data->element_values[CONTROL_NAME].parsed_value;
418
419     if (ctrl_label == NULL)
420        ctrl_label = ctrl_name;
421
422     if (control_data->element_values[CONTROL_LOCKED].parsed_value)
423     {
424        title = FPGETMESSAGE(82,1, "Workspace Manager - Delete Locked Control Error");
425        title = XtNewString (title);
426
427        del_msg = FPGETMESSAGE(82,5, "This control cannot be deleted because it is locked.");
428        del_msg = XtNewString (del_msg);
429
430        message = XtMalloc (sizeof(char) *
431                            (strlen(del_ctrl) + strlen(ctrl_label) +
432                             strlen(del_msg) + 4));
433
434        sprintf(message, "%s %s\n\n%s", del_ctrl, ctrl_label, del_msg);
435
436        _DtMessage (XtParent(w), title, message, NULL, NULL);
437
438        XtFree (title);
439        XtFree (del_ctrl);
440        XtFree (del_msg);
441        XtFree (message);
442     }
443     else
444     {
445        title = FPGETMESSAGE(82,2, "Workspace Manager - Delete Control");
446        title = XtNewString (title);
447
448        if (SessionFileNameLookup (ctrl_name, CONTROL, (char *) control_data->element_values[CONTROL_CONTAINER_NAME].parsed_value, SUBPANEL) == NULL)
449           del_msg = FPGETMESSAGE(82,32, "If you delete this control, you cannot restore it using\nthe \"Install Icon\" drop zone.\n\nYou can use \"RestorePanel\" in the Application Manager\nto put back this control at a later time.\n\nAre you sure you want to delete this control?");
450        else
451           del_msg = FPGETMESSAGE(82,6, "Are you sure you want to delete this control?");
452
453        del_msg = XtNewString (del_msg);
454
455        message = XtMalloc (sizeof(char) *
456                            (strlen(del_ctrl) + strlen(ctrl_label) +
457                             strlen(del_msg) + 4));
458
459        sprintf(message, "%s %s\n\n%s", del_ctrl, ctrl_label, del_msg);
460
461 #ifndef IBM_163763
462        /*  Get the subpanel data for the control.  Check to see if the  */
463        /*  control is a real subpanel control or the main panel copy.   */
464
465        if (control_data->parent_type == SUBPANEL)
466           subpanel_data = (SubpanelData *) control_data->parent_data;
467        else
468           subpanel_data = (SubpanelData *) control_data->subpanel_data;
469
470        dialog = _DtMessageDialog(subpanel_data->shell,title,message,NULL,TRUE,
471 #else
472        dialog = _DtMessageDialog(panel.shell, title, message, NULL, TRUE,
473 #endif
474                            DeleteCancelCB, DeleteControlOkCB, NULL, NULL, False,
475                            QUESTION_DIALOG);
476
477        XtSetArg (args[0], XmNuserData, control_data);
478        XtSetArg (args[1], XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL);
479        XtSetValues (dialog, args, 2);
480
481        XtFree (title);
482        XtFree (del_ctrl);
483        XtFree (del_msg);
484        XtFree (message);
485     }
486
487 }
488
489
490
491
492 /************************************************************************
493  *
494  *  ToggleControlCB
495  *      This callback initiates a subpanel control being toggled into
496  *      the main panel.
497  *
498  ************************************************************************/
499
500 void
501 ToggleControlCB (Widget    w,
502                  XtPointer client_data,
503                  XtPointer call_data)
504
505
506 {
507     SubpanelData * subpanel_data = (SubpanelData *) client_data;
508     ControlData * control_data;
509     long indx = (long) client_data;
510     Arg args[1];
511
512     XtSetArg (args[0], XmNuserData, &control_data);
513     XtGetValues(w, args, 1);
514
515     ToggleDefaultControl (subpanel_data->parent_control_data,
516                           subpanel_data, control_data);
517 }
518
519
520
521
522 /************************************************************************
523  *
524  *  AddSubpanelCB
525  *
526  ************************************************************************/
527
528 void
529 AddSubpanelCB (Widget w,
530                XtPointer client_data,
531                XtPointer call_data)
532
533
534 {
535     ControlData * control_data;
536     long indx = (long) client_data;
537     Arg args[1];
538
539     XtSetArg (args[0], XmNuserData, &control_data);
540     XtGetValues(w, args, 1);
541
542     AddSubpanel(control_data);
543 }
544
545
546
547
548 /************************************************************************
549  *
550  *  DeleteSubpanelCB
551  *
552  ************************************************************************/
553  
554 void
555 DeleteSubpanelCB (Widget    w,
556                   XtPointer client_data,
557                   XtPointer call_data)
558
559
560 {
561     ControlData * control_data;
562     SubpanelData * subpanel_data;
563     Widget dialog;
564     String title, message, del_spanel, spanel_name, del_msg;
565     Arg args[2];
566
567     XtSetArg (args[0], XmNuserData, &control_data);
568     XtGetValues(w, args, 1);
569
570     subpanel_data = (SubpanelData *) control_data->subpanel_data;
571     if (!subpanel_data)
572         subpanel_data = (SubpanelData *) control_data->parent_data;
573
574     del_spanel = FPGETMESSAGE(82, 33, "Delete Subpanel:");
575     del_spanel = XtNewString (del_spanel);
576
577     spanel_name = (char *)
578                   subpanel_data->element_values[SUBPANEL_NAME].parsed_value;
579
580     if (subpanel_data->element_values[SUBPANEL_LOCKED].parsed_value)
581     {
582        title = FPGETMESSAGE(82,3, "Workspace Manager - Delete Locked Subpanel Error");
583        title = XtNewString (title);
584
585        del_msg = FPGETMESSAGE(82,7, "This subpanel cannot be deleted because it is locked.");
586        del_msg = XtNewString (del_msg);
587
588        message = XtMalloc (sizeof(char) *
589                            (strlen(del_spanel) + strlen(spanel_name) +
590                             strlen(del_msg) + 4));
591
592        sprintf(message, "%s %s\n\n%s", del_spanel, spanel_name, del_msg);
593
594        _DtMessage (XtParent(w), title, message, NULL, NULL);
595
596        XtFree (title);
597        XtFree (del_spanel);
598        XtFree (del_msg);
599        XtFree (message);
600     }
601     else
602     {
603        title = FPGETMESSAGE(82,4, "Workspace Manager - Delete Subpanel");
604        title = XtNewString (title);
605
606        if (subpanel_data->control_data_count > 0)
607        {
608          if (SessionFileNameLookup (spanel_name, SUBPANEL, (char *)
609             subpanel_data->element_values[SUBPANEL_CONTAINER_NAME].parsed_value,
610             CONTROL) == NULL)
611              del_msg = FPGETMESSAGE(82,34,
612 "If you delete this subpanel, you cannot restore all\nof the controls contained in the subpanel using the\n\"Install Icon\" drop zone.\n\nYou can use \"RestorePanel\" in the Application Manager\nto put back this subpanel and its controls at a later time.\n\nAre you sure you want to delete this subpanel?");
613          else
614              del_msg = FPGETMESSAGE(82,8, "This subpanel contains more than one control.\n\nAre you sure you want to delete this subpanel?");
615        }
616        else
617           del_msg = FPGETMESSAGE(82,9, "Are you sure you want to delete this subpanel?");
618
619        del_msg = XtNewString (del_msg);
620
621        message = XtMalloc (sizeof(char) *
622                            (strlen(del_spanel) + strlen(spanel_name) +
623                             strlen(del_msg) + 4));
624
625        sprintf(message, "%s %s\n\n%s", del_spanel, spanel_name, del_msg);
626
627 #ifndef IBM_163763
628        dialog = _DtMessageDialog(subpanel_data->shell,title,message,NULL,TRUE,
629 #else
630        dialog = _DtMessageDialog(panel.shell, title, message, NULL, TRUE,
631 #endif
632                           DeleteCancelCB, DeleteSubpanelOkCB, NULL, NULL, False,
633                           QUESTION_DIALOG);
634
635        XtSetArg (args[0], XmNuserData, control_data);
636        XtSetArg (args[1], XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL);
637        XtSetValues(dialog, args, 2);
638
639        XtFree (title);
640        XtFree (del_spanel);
641        XtFree (del_msg);
642        XtFree (message);
643     }
644 }
645
646
647
648
649
650 /************************************************************************
651  *
652  *  PostWorkspacePopupMenu
653  *
654  ************************************************************************/
655  
656
657 void
658 PostWorkspacePopupMenu (Widget      w,
659                         XtPointer   client_data,
660                         XEvent    * event)
661
662
663 {
664    int i;
665    BoxData * box_data;
666    SwitchData * switch_data = NULL;
667    XButtonEvent * b_event = (XButtonEvent *) event;
668
669    /* only use BMENU press events */
670
671    if (b_event->button != wmGD.bMenuButton) return;
672
673    for (i = 0; i < panel.box_data_count; i++)
674    {
675       box_data = panel.box_data[i];
676
677       if (box_data->switch_data != NULL)
678          switch_data = box_data->switch_data;
679    }
680
681    if (switch_data != NULL)
682       XtManageChild(switch_data->popup_data->popup);
683 }
684
685
686
687
688 /************************************************************************
689  *
690  *  PostPopupMenu
691  *
692  ************************************************************************/
693  
694 void
695 PostPopupMenu (Widget      w,
696                XtPointer   client_data,
697                XEvent    * event)
698
699
700 {
701    XButtonEvent * b_event = (XButtonEvent *) event;
702
703    /* only use BMENU press events */
704
705    if (b_event->button != wmGD.bMenuButton) return;
706
707    XtManageChild(panel.popup_data->popup);
708 }
709
710
711
712
713 /************************************************************************
714  *
715  *  GetBoxDataFromForm
716  *
717  ************************************************************************/
718  
719 static void
720 GetBoxDataFromForm (Widget     form,
721                     BoxData ** box_data_rtn)
722
723
724 {
725    BoxData * box_data;
726    int i;
727
728    for (i = 0; i < panel.box_data_count; i++)
729    {
730       box_data = panel.box_data[i];
731
732       if (box_data == *box_data_rtn) continue;
733
734       if (box_data->left_control_form == form ||
735          box_data->right_control_form == form)
736       {
737          *box_data_rtn = box_data;
738          break;
739       }
740    }
741 }
742
743
744
745
746 /************************************************************************
747  *
748  *  GetSubpanelDataFromForm
749  *
750  ************************************************************************/
751  
752 static void
753 GetSubpanelDataFromForm (Widget          form,
754                          SubpanelData ** subpanel_data_rtn)
755
756
757 {
758    BoxData * box_data;
759    ControlData * control_data;
760    SubpanelData * subpanel_data;
761    int i, j;
762
763    for (i = 0; i < panel.box_data_count; i++)
764    {
765       box_data = panel.box_data[i];
766
767       for (j = 0; j < box_data->control_data_count; j++)
768       {
769          control_data = box_data->control_data[j];
770
771          if (control_data->subpanel_data != NULL)
772          {
773             subpanel_data = control_data->subpanel_data;
774
775             if (subpanel_data == *subpanel_data_rtn) continue;
776
777             if (subpanel_data->form == form)
778             {
779                *subpanel_data_rtn = subpanel_data;
780                break;
781             }
782          }
783       }
784    }
785 }
786
787
788
789
790
791 /************************************************************************
792  *
793  *  KeyMenuPosition
794  *
795  ************************************************************************/
796  
797 static void
798 KeyMenuPosition (Widget popup, Widget focus_widget)
799
800
801 {
802    XButtonPressedEvent bevent;  /* synthetic button press event */
803    Widget parent;
804    Position root_x, root_y;
805    Position x, y;
806    Arg args[2];
807
808
809    /* get the gadget's x and y */
810
811    XtSetArg (args[0], XmNx, &x);
812    XtSetArg (args[1], XmNy, &y);
813    XtGetValues (focus_widget, args, 2);
814
815
816    /* get the focus widget's parent since the focus widget is a gadget */
817
818    parent = XtParent (focus_widget);
819
820
821    /* get the root coordinates of the gadget */
822
823    XtTranslateCoords (parent, x, y, &root_x, &root_y);
824
825
826    /*  XmMenuPosition() only uses the root_x and root_y  */
827    /*  of the event for positioning                      */
828
829    bevent.x_root = root_x;
830    bevent.y_root = root_y;
831
832
833    /* set the menu positioning */
834
835    XmMenuPosition (popup, &bevent);
836 }
837
838
839
840
841
842 /************************************************************************
843  *
844  *  GetMainControlData
845  *
846  ************************************************************************/
847  
848 static ControlData *
849 GetMainControlData (BoxData * box_data,
850                     Widget    focus_widget)
851
852
853 {
854    int i;
855    ControlData * control_data;
856    Boolean found = False;
857
858    for (i = 0; i < box_data->control_data_count; i++)
859    {
860       control_data = box_data->control_data[i];
861
862       if (control_data->icon == focus_widget)
863       {
864          found = True;
865          break;
866       }
867    }
868
869    if (!found) return NULL;
870
871    return (control_data);
872 }
873
874
875
876
877 /************************************************************************
878  *
879  *  GetSubpanelControlData
880  *
881  ************************************************************************/
882  
883 static ControlData *
884 GetSubpanelControlData (SubpanelData * subpanel_data,
885                         Widget         focus_widget)
886
887
888 {
889    int i;
890    ControlData * control_data;
891    Boolean found = False;
892
893    if ( subpanel_data->dropzone == focus_widget )
894       return NULL;
895
896    if (subpanel_data->main_panel_icon_copy == focus_widget ||
897        subpanel_data->parent_control_data->indicator == focus_widget)
898    {
899       return (subpanel_data->parent_control_data);
900    }
901
902
903    for (i = 0; i < subpanel_data->control_data_count; i++)
904    {
905       control_data = subpanel_data->control_data[i];
906       if (control_data->icon == focus_widget ||
907           control_data->indicator == focus_widget)
908       {
909          found = True;
910          break;
911       }
912    }
913
914    if (!found) return NULL;
915
916    return (control_data);
917 }
918
919
920
921
922 /************************************************************************
923  *
924  *  SetupActionMenuItems
925  *      Set up the action list for display in the popup menu for a 
926  *      control.  This may require creating additional menu items is
927  *      the action list for this control is greater that previously
928  *      encountered or it may require umanaging menu item is there are
929  *      less actions.
930  *
931  *      Inputs:
932  *         w: The parent of the menu items.
933  *         control_data: The control the menu is being set up for.
934  *         action_item: A pointer to the array of menu items for the actions.
935  *         action_count: A pointer to the total number of action items.
936  *
937  ************************************************************************/
938
939
940 static void
941 SetupActionMenuItems (Widget        w,
942                       ControlData * control_data,
943                       PopupData  * popup_data,
944                       Widget      * action_item,
945                       long        * action_count)
946
947
948 {
949    XmString label_string;
950    long i;
951    long num_actions = 0;
952    long action_index = *action_count;
953    Arg args[5];
954    
955
956    /*  Count the action list for the control in order to adjust  */
957    /*  the number of action menu items within the menu.          */
958
959    if (control_data != NULL)
960       while (control_data->actions[num_actions] != NULL)
961          num_actions++;
962
963    if (num_actions > *action_count )
964    {
965       action_item = (Widget *) XtRealloc((char *) action_item,
966                                          sizeof(Widget) * num_actions);
967
968       for (i = 0; i < num_actions - *action_count; i++)
969       {    
970           action_item[action_index] = 
971              XmCreatePushButtonGadget (w, "action_button", args, 0);
972
973           (*action_count)++;
974
975           XtManageChild (action_item[action_index]);
976           XtAddCallback (action_item[action_index], XmNactivateCallback,
977                          ActionCB, (XtPointer)action_index);
978           action_index++;
979       }
980       
981    }
982    else
983    {
984       for (i = 0; i < *action_count; i++)
985          XtUnmanageChild (action_item[i]);
986    }
987
988    for (i = 0; i < num_actions ; i++)
989    {
990       XtSetArg (args[0], XmNuserData, control_data);
991       XtSetValues (action_item[i], args, 1);
992    }
993
994    for (i = 0; i < num_actions; i++)
995    {
996       if (control_data->actions[i]->action_label != NULL)
997          label_string = 
998                XmStringCreateLocalized (control_data->actions[i]->action_label);
999       else
1000          label_string = 
1001                XmStringCreateLocalized (control_data->actions[i]->action_name);
1002
1003       XtSetArg (args[0], XmNlabelString, label_string);
1004       XtSetArg (args[1], XmNuserData, control_data);
1005       XtSetValues (action_item[i], args, 2);
1006       XmStringFree (label_string);
1007    }
1008
1009    for (i = 0; i < num_actions; i++)
1010    {
1011       if (!XtIsManaged (action_item[i]))
1012          XtManageChild (action_item[i]);
1013    }
1014
1015    if (num_actions > 0)
1016       XtManageChild(popup_data->separator1);
1017    else
1018       XtUnmanageChild(popup_data->separator1);
1019 }
1020
1021
1022
1023
1024
1025 /************************************************************************
1026  *
1027  *  UpdateMainControlMenu
1028  *      Set up the label and the add/delete subpanel menu item for the
1029  *      popup menu.
1030  *
1031  *      Inputs:
1032  *         control_data: The control overwhich the menu is being posted.
1033  *
1034  ************************************************************************/
1035  
1036
1037 static void
1038 UpdateMainControlMenu (ControlData * control_data)
1039
1040
1041 {
1042    XmString   label_string;
1043    char     * mnemonic;
1044    char     * control_label;
1045
1046    long control_type;
1047    Arg args[5];
1048
1049    ElementValue * old_element_values;
1050
1051    /*  Save element values of control then load values of default control */
1052
1053    if (control_data->subpanel_data != NULL && 
1054         control_data != control_data->subpanel_data->default_control)
1055    {
1056         old_element_values = control_data->element_values;
1057         control_data->element_values = 
1058                 control_data->subpanel_data->default_control->element_values;
1059    }
1060
1061    /*  Set the title of the menu  */
1062    
1063    control_label =
1064          (char *) control_data->element_values[CONTROL_LABEL].parsed_value;
1065
1066    if (control_label == NULL)
1067       control_label = 
1068                (char *) control_data->element_values[CONTROL_NAME].parsed_value;
1069
1070    label_string = XmStringCreateLocalized (control_label);
1071    XtSetArg (args[0], XmNlabelString, label_string);
1072    XtSetValues (panel.popup_data->popup_title, args, 1);
1073    XmStringFree (label_string);
1074
1075
1076    /*  If the control is blank, remove the add/delete subpanel item.    */
1077    /*  Otherwise, if there is a subpanel, activate the delete subpanel  */
1078    /*  item.  Else activate the add subpanel item.                      */
1079
1080    control_type = (long)control_data->element_values[CONTROL_TYPE].parsed_value;
1081
1082    if (control_type != CONTROL_BLANK)
1083    {
1084       XtManageChild (panel.popup_data->modify_subpanel_item);
1085
1086       if (control_data->subpanel_data == NULL)
1087       {
1088          if (panel.popup_data->subpanel_add_state != True)
1089          {
1090             label_string = 
1091                XmStringCreateLocalized ((FPGETMESSAGE(82, 10, "Add Subpanel")));
1092             XtSetArg (args[0], XmNlabelString, label_string);
1093             mnemonic = ((char *)FPGETMESSAGE(82, 11, "A"));
1094             XtSetArg (args[1], XmNmnemonic, mnemonic[0]);
1095             XtSetArg (args[2], XmNuserData, control_data);
1096             XtSetValues (panel.popup_data->modify_subpanel_item, args, 3);
1097
1098             XmStringFree (label_string);
1099
1100             XtRemoveCallback (panel.popup_data->modify_subpanel_item,
1101                               XmNactivateCallback, DeleteSubpanelCB, NULL);
1102             XtAddCallback (panel.popup_data->modify_subpanel_item,
1103                            XmNactivateCallback, AddSubpanelCB, NULL);
1104
1105             panel.popup_data->subpanel_add_state = True;
1106          }
1107          else
1108          {
1109             XtSetArg (args[0], XmNuserData, control_data);
1110             XtSetValues (panel.popup_data->modify_subpanel_item, args, 1);
1111          }
1112       }
1113       else
1114       {
1115          if (panel.popup_data->subpanel_add_state == True)
1116          {
1117             label_string = 
1118               XmStringCreateLocalized ((FPGETMESSAGE(82, 12, "Delete Subpanel")));
1119             XtSetArg (args[0], XmNlabelString, label_string);
1120             mnemonic = ((char *)FPGETMESSAGE(82, 13, "D"));
1121             XtSetArg (args[1], XmNmnemonic, mnemonic[0]);
1122             XtSetArg (args[2], XmNuserData, control_data);
1123             XtSetValues (panel.popup_data->modify_subpanel_item, args, 3);
1124
1125             XmStringFree (label_string);
1126
1127             XtRemoveCallback (panel.popup_data->modify_subpanel_item,
1128                               XmNactivateCallback, AddSubpanelCB, NULL);
1129             XtAddCallback (panel.popup_data->modify_subpanel_item,
1130                            XmNactivateCallback, DeleteSubpanelCB, NULL);
1131
1132             panel.popup_data->subpanel_add_state = False;
1133          }
1134          else
1135          {
1136             XtSetArg (args[0], XmNuserData, control_data);
1137             XtSetValues (panel.popup_data->modify_subpanel_item, args, 1);
1138          }
1139       }
1140    }
1141    else
1142    {
1143       XtUnmanageChild (panel.popup_data->modify_subpanel_item);
1144    }
1145
1146    XtRemoveAllCallbacks (panel.popup_data->help_item, XmNactivateCallback);
1147
1148    XtAddCallback(panel.popup_data->help_item, XmNactivateCallback,
1149                  ControlTopicHelpCB, (XtPointer)control_data);
1150
1151    XtUnmanageChild (panel.popup_data->deinstall_item);
1152    XtUnmanageChild (panel.popup_data->toggle_item);
1153
1154    /* Restore element values to control. */
1155
1156    if (control_data->subpanel_data != NULL && 
1157         control_data != control_data->subpanel_data->default_control)
1158    {
1159         control_data->element_values = old_element_values;
1160    }
1161 }
1162
1163
1164
1165
1166
1167 /************************************************************************
1168  *
1169  *  UpdateSubpanelControlMenu
1170  *      Set the elements of the popup menu for a subpanel control
1171  *      item to its proper values before it is made visible.
1172  *
1173  *      Inputs: 
1174  *        subpanel_data:  The subpanel in which the menu is to be
1175  *                        posted.
1176  *
1177  *        control_data:  The control that the menu is being brought up for.
1178  *
1179  ************************************************************************/
1180  
1181
1182 static void
1183 UpdateSubpanelControlMenu (SubpanelData * subpanel_data,
1184                            ControlData  * control_data)
1185
1186
1187 {
1188    XmString label_string;
1189    Arg args[5];
1190    char     * control_label = NULL;
1191
1192    /*  Set the title of the menu  */
1193    
1194    if (control_data)
1195    {
1196       control_label =
1197          (char *) control_data->element_values[CONTROL_LABEL].parsed_value;
1198
1199       if (control_label == NULL)
1200          control_label = 
1201                (char *) control_data->element_values[CONTROL_NAME].parsed_value;
1202    } 
1203    else
1204    {
1205       control_label = FPGETMESSAGE(82, 36, "Install Icon");
1206    }
1207
1208    label_string = XmStringCreateLocalized (control_label);
1209    XtSetArg (args[0], XmNlabelString, label_string);
1210    XtSetValues (panel.popup_data->popup_title, args, 1);
1211    XmStringFree (label_string);
1212
1213
1214    /*  Set the sensitivity of the control deinstall and toggle menu item  */
1215    
1216    if (control_data == NULL)
1217    {
1218       XtSetSensitive (panel.popup_data->deinstall_item, False);
1219       XtSetSensitive (panel.popup_data->toggle_item, False);
1220
1221       XtRemoveAllCallbacks (panel.popup_data->help_item, XmNactivateCallback);
1222
1223       XtAddCallback(panel.popup_data->help_item, XmNactivateCallback,
1224                     GeneralTopicHelpCB, (XtPointer)INSTALL_ZONE);
1225    }
1226    else
1227    {
1228       XtSetSensitive (panel.popup_data->deinstall_item, True);
1229       XtSetArg (args[0], XmNuserData, control_data);
1230       XtSetValues(panel.popup_data->deinstall_item, args, 1);
1231
1232       XtRemoveAllCallbacks (panel.popup_data->deinstall_item, 
1233                             XmNactivateCallback);
1234
1235       XtAddCallback (panel.popup_data->deinstall_item, XmNactivateCallback,
1236                      DeleteControlCB, (XtPointer) NULL);
1237
1238       if ( control_data ==  subpanel_data->default_control)
1239          XtSetSensitive (panel.popup_data->toggle_item, False);
1240       else
1241          XtSetSensitive (panel.popup_data->toggle_item, True);
1242
1243       XtSetArg (args[0], XmNuserData, control_data);
1244       XtSetValues(panel.popup_data->toggle_item, args, 1);
1245
1246       XtRemoveAllCallbacks (panel.popup_data->toggle_item,
1247                             XmNactivateCallback);
1248
1249       XtAddCallback (panel.popup_data->toggle_item, XmNactivateCallback,
1250                      ToggleControlCB, (XtPointer) subpanel_data);
1251
1252       XtRemoveAllCallbacks (panel.popup_data->help_item, XmNactivateCallback);
1253
1254       XtAddCallback(panel.popup_data->help_item, XmNactivateCallback,
1255                     ControlTopicHelpCB, (XtPointer)control_data);
1256    }
1257
1258    XtManageChild (panel.popup_data->deinstall_item);
1259
1260    if (! (subpanel_data->parent_control_data->
1261                   element_values[CONTROL_LOCKED].parsed_value))
1262       XtManageChild (panel.popup_data->toggle_item);
1263    else
1264       XtUnmanageChild (panel.popup_data->toggle_item);
1265    
1266    XtUnmanageChild (panel.popup_data->modify_subpanel_item);
1267 }
1268
1269
1270
1271
1272 /************************************************************************
1273  *
1274  *  PopupMenu
1275  *      Callback function which updates the popup menu for main panel
1276  *      and subpanel controls before the menu is posted.
1277  *
1278  ************************************************************************/
1279
1280
1281 static void
1282 PopupMenu (Widget    w,
1283            XtPointer client_data,
1284            XtPointer call_data)
1285
1286
1287 {
1288    XmAnyCallbackStruct * callback;
1289    XEvent * event;
1290    Widget form, focus_widget;
1291    XmManagerWidget mgr;
1292    SubpanelData * subpanel_data = NULL;
1293    ControlData * control_data;
1294    BoxData * box_data = NULL;
1295    XmString label_string;
1296    Arg args[5];
1297    long control_type, action_count = panel.popup_data->action_count;
1298
1299    callback = (XmAnyCallbackStruct *) call_data;
1300    event = (XEvent *) callback->event;
1301
1302
1303    /*  Get the form where the menu was posted from.  */
1304
1305    form = XmGetPostedFromWidget(w);
1306
1307    XtSetArg (args[0], XmNuserData, &control_type);
1308    XtGetValues (form, args, 1);
1309
1310    if (control_type == CONTROL)
1311    {
1312       GetBoxDataFromForm (form, &box_data);
1313       subpanel_data = NULL;
1314    }
1315    else if (control_type == SUBPANEL)
1316    {
1317       GetSubpanelDataFromForm (form, &subpanel_data);
1318       box_data = NULL;
1319    }
1320
1321    if (event->type == ButtonPress)
1322    {
1323       /* Change to use new Xme function when porting to Motif 2.0 */
1324       /* Get gadget at x, y position */
1325
1326       focus_widget = (Widget) XmObjectAtPoint (form, event->xbutton.x,
1327                                                event->xbutton.y);
1328       if (focus_widget == NULL)
1329          return;
1330
1331       /* set the menu positioning */
1332
1333       XmMenuPosition (panel.popup_data->popup, (XButtonPressedEvent *)event);
1334    }
1335    else
1336    {
1337       /* get the widget that has the traversal focus */
1338
1339       focus_widget = XmGetFocusWidget (form);
1340
1341
1342       /* set the menu positioning for non button events */
1343
1344       KeyMenuPosition (panel.popup_data->popup, focus_widget);
1345    }
1346
1347    if (control_type == CONTROL)
1348    {
1349       control_data = GetMainControlData (box_data, focus_widget);
1350
1351       /* Find the right subpanel data if main control is not default */
1352       /* control.                                                    */
1353
1354       UpdateMainControlMenu (control_data);
1355
1356       if (control_data->subpanel_data != NULL &&                        
1357           control_data != control_data->subpanel_data->default_control)
1358       {
1359          subpanel_data = control_data->subpanel_data;
1360          control_data = control_data->subpanel_data->default_control;
1361          control_data->subpanel_data = subpanel_data;
1362          UpdateMainControlMenu (control_data);
1363       }
1364
1365       SetupActionMenuItems (w, control_data, panel.popup_data,
1366                             panel.popup_data->action_item, &action_count);
1367
1368    }
1369    else if (control_type == SUBPANEL)
1370    {
1371       control_data = GetSubpanelControlData (subpanel_data, focus_widget);
1372
1373       UpdateSubpanelControlMenu (subpanel_data, control_data);
1374
1375       SetupActionMenuItems (w, control_data, panel.popup_data,
1376                             panel.popup_data->action_item, &action_count);
1377    }
1378
1379    panel.popup_data->action_count = action_count;
1380 }
1381
1382
1383
1384
1385 /************************************************************************
1386  *
1387  *  CreatePopupMenu
1388  *
1389  ************************************************************************/
1390
1391
1392 void
1393 CreatePopupMenu (Widget w)
1394
1395
1396 {
1397    Widget children[20];
1398    char * mnemonic;
1399    Arg args[5];
1400    PopupData * popup_data;
1401    long i, child_num = 0;
1402    XmString label_string;
1403
1404    popup_data = panel.popup_data = (PopupData *) XtMalloc(sizeof(PopupData));
1405
1406    i = 0;
1407    XtSetArg (args[i], XmNwhichButton, wmGD.bMenuButton); i++;
1408
1409    popup_data->popup = XmCreatePopupMenu(w, "FPPopup", args, i);
1410
1411    popup_data->add_ws_item = NULL;
1412
1413    XtAddCallback (popup_data->popup, XmNmapCallback, PopupMenu,
1414                   (XtPointer) NULL);
1415
1416    popup_data->popup_title = children[child_num++] =
1417                  XmCreateLabelGadget(popup_data->popup, "title", NULL, 0);
1418
1419    children[child_num++] = XmCreateSeparatorGadget(popup_data->popup,
1420                                                    "sep1", NULL, 0);
1421    children[child_num++] = XmCreateSeparatorGadget(popup_data->popup,
1422                                                    "sep2", NULL, 0);
1423
1424    popup_data->action_item = (Widget *) XtMalloc(sizeof(Widget) * 5);
1425    popup_data->action_count = 0;
1426
1427    for (i = 0; i < 5; i++)
1428    {    
1429       children[child_num] = popup_data->action_item[i] =
1430          XmCreatePushButtonGadget(popup_data->popup, "action_button", args, 0);
1431       popup_data->action_count++;
1432
1433       XtManageChild (popup_data->action_item[i]);
1434       XtAddCallback (children[child_num++], XmNactivateCallback,
1435                      ActionCB, (XtPointer) i);
1436    }
1437
1438    popup_data->separator1 = children[child_num++] =
1439                 XmCreateSeparatorGadget (popup_data->popup, "sep3", NULL, 0);
1440
1441    label_string =
1442            XmStringCreateLocalized((FPGETMESSAGE(82, 14, "Copy To Main Panel")));
1443    XtSetArg (args[0], XmNlabelString, label_string);
1444    mnemonic = ((char *)FPGETMESSAGE(82, 15, "C"));
1445    XtSetArg (args[1], XmNmnemonic, mnemonic[0]);
1446    popup_data->toggle_item = children[child_num] =
1447       XmCreatePushButtonGadget (popup_data->popup, "Toggle_Control", args, 2);
1448    XmStringFree (label_string);
1449
1450    label_string = XmStringCreateLocalized((FPGETMESSAGE(82, 16, "Delete")));
1451    XtSetArg (args[0], XmNlabelString, label_string);
1452    mnemonic = ((char *)FPGETMESSAGE(82, 17, "D"));
1453    XtSetArg (args[1], XmNmnemonic, mnemonic[0]);
1454    popup_data->deinstall_item = children[child_num] =
1455          XmCreatePushButtonGadget(popup_data->popup, "Delete_Control",
1456                                   args, 2);
1457    XmStringFree (label_string);
1458
1459    label_string =
1460               XmStringCreateLocalized ((FPGETMESSAGE(82, 10, "Add Subpanel")));
1461    XtSetArg (args[0], XmNlabelString, label_string);
1462    mnemonic = ((char *)FPGETMESSAGE(82, 11, "A"));
1463    XtSetArg (args[1], XmNmnemonic, mnemonic[0]);
1464    popup_data->modify_subpanel_item = children[child_num] =
1465          XmCreatePushButtonGadget (popup_data->popup, "Add_Subpanel", args, 2);
1466    XmStringFree (label_string);
1467
1468    XtAddCallback(children[child_num++], XmNactivateCallback, AddSubpanelCB,
1469                         (XtPointer)NULL);
1470    popup_data->subpanel_add_state = True;
1471
1472    popup_data->separator2 = children[child_num++] =
1473                 XmCreateSeparatorGadget(popup_data->popup, "sep4", NULL, 0);
1474
1475    label_string = XmStringCreateLocalized ((FPGETMESSAGE(82, 18, "Help")));
1476    XtSetArg (args[0], XmNlabelString, label_string);
1477    mnemonic = ((char *)FPGETMESSAGE(82, 19, "H"));
1478    XtSetArg (args[1], XmNmnemonic, mnemonic[0]);
1479    popup_data->help_item = children[child_num++] =
1480                 XmCreatePushButtonGadget (popup_data->popup, "Help", args, 2);
1481    XmStringFree (label_string);
1482
1483    XtManageChildren(children, child_num);
1484 }
1485
1486
1487
1488
1489 /************************************************************************
1490  *
1491  *  CreateActionButtons
1492  *     Show the the action menu items and hide workspace menu items since
1493  *     we are over a control.
1494  *
1495  *
1496  ************************************************************************/
1497  
1498
1499 static void
1500 CreateActionButtons (Widget        w,
1501                      SwitchData  * switch_data,
1502                      ControlData * control_data)
1503
1504
1505 {
1506     PopupData * popup_data = switch_data->popup_data;
1507     long action_count = popup_data->action_count;
1508     Arg args[1];
1509     XmString label_string;
1510     char     * control_label;
1511
1512    /*  Set the title of the menu  */
1513    
1514     control_label =
1515           (char *) control_data->element_values[CONTROL_LABEL].parsed_value;
1516
1517     if (control_label == NULL)
1518        control_label = 
1519                (char *) control_data->element_values[CONTROL_NAME].parsed_value;
1520
1521     label_string = XmStringCreateLocalized (control_label);
1522     XtSetArg (args[0], XmNlabelString, label_string);
1523     XtSetValues (popup_data->popup_title, args, 1);
1524     XmStringFree (label_string);
1525
1526    /* show actions items */
1527     SetupActionMenuItems(w, control_data, popup_data,
1528                          popup_data->action_item, &action_count);
1529     popup_data->action_count = action_count;
1530
1531    /* hide add and delete workspace items */
1532     XtUnmanageChild(popup_data->add_ws_item);
1533     XtUnmanageChild(popup_data->delete_ws_item);
1534     XtUnmanageChild(popup_data->rename_ws_item);
1535
1536    /* reset the help callback to reflect switch control help */
1537     XtRemoveAllCallbacks (popup_data->help_item, XmNactivateCallback);
1538     XtAddCallback(popup_data->help_item, XmNactivateCallback,
1539                   ControlTopicHelpCB, control_data);
1540 }
1541
1542
1543
1544
1545
1546 /************************************************************************
1547  *
1548  *  ShowWorkspaceItems
1549  *     Don't show the the action menu items since we are not over a control.
1550  *     Reset the activate callbacks with the latest data.
1551  *
1552  ************************************************************************/
1553  
1554
1555 static void
1556 ShowWorkspaceItems (SwitchData * switch_data,
1557                            Widget       focus_widget)
1558
1559
1560 {
1561    PopupData * popup_data = switch_data->popup_data;
1562    long i;
1563    Arg args[1];
1564    XmString label_string;
1565    char     * control_label;
1566    char     * ws;
1567    char     * ws_name;
1568    char     * format;
1569
1570
1571    /* hide actions items */
1572
1573    for (i = 0; i < popup_data->action_count; i++)
1574        XtUnmanageChild (popup_data->action_item[i]);
1575
1576
1577    /* show add and delete workspace items */
1578
1579    XtManageChild (popup_data->add_ws_item);
1580    XtManageChild (popup_data->delete_ws_item);
1581    XtManageChild (popup_data->rename_ws_item);
1582
1583
1584    /* reset the activate callback to reflect current button index */
1585
1586    XtRemoveAllCallbacks (popup_data->delete_ws_item, XmNactivateCallback);
1587    for (i = 0; i < switch_data->switch_count &&
1588                switch_data->buttons[i] != NULL; i++)
1589    {
1590       if (switch_data->buttons[i] == focus_widget) break;
1591    }
1592
1593
1594    /*  If we didn't find the switch button to post the menu for, it   */
1595    /*  must be in edit mode so the correct menu is the active switch  */
1596
1597    if (i >= switch_data->switch_count)
1598       i = switch_data->active_switch;
1599
1600
1601    /*  Set the title of the menu  */
1602    
1603    format = strdup (FPGETMESSAGE(82, 20, "%1$s %2$s"));
1604    ws = strdup (FPGETMESSAGE(82, 21, "Workspace"));
1605    ws_name = switch_data->switch_names[i];
1606
1607    control_label = XtMalloc (sizeof(char) * (strlen(ws) + strlen(ws_name) + 4));
1608
1609    sprintf (control_label, format, ws, ws_name);
1610    free (format);
1611    free (ws);
1612
1613    label_string = XmStringCreateLocalized (control_label);
1614    XtSetArg (args[0], XmNlabelString, label_string);
1615    XtSetValues (popup_data->popup_title, args, 1);
1616    XmStringFree (label_string);
1617    XtFree(control_label);
1618
1619    XtAddCallback (popup_data->delete_ws_item, XmNactivateCallback,
1620                   DeleteWorkspaceCB, (XtPointer) i);
1621
1622    /* reset the activate callback to reflect current button index */
1623    XtRemoveAllCallbacks (popup_data->rename_ws_item, XmNactivateCallback);
1624    XtAddCallback (popup_data->rename_ws_item, XmNactivateCallback,
1625                   RenameWorkspaceCB, (XtPointer) i);
1626
1627    /* reset the help callback to reflect switch button help */
1628    XtRemoveAllCallbacks (popup_data->help_item, XmNactivateCallback);
1629    XtAddCallback(popup_data->help_item, XmNactivateCallback,
1630                  GeneralTopicHelpCB, (XtPointer) SWITCH_BUTTON);
1631
1632    XtManageChild(popup_data->separator1);
1633 }
1634
1635
1636
1637
1638 /************************************************************************
1639  *
1640  *  ShowPartialWorkspaceItems
1641  *     Don't show the delete workspace item since we are not over
1642  *     a workspace button and don't show the action menu items since we are
1643  *     not over a control.  Reset the activate callback with the latest data.
1644  *
1645  ************************************************************************/
1646  
1647 static void
1648 ShowPartialWorkspaceItems(SwitchData * switch_data)
1649
1650
1651 {
1652    PopupData * popup_data = switch_data->popup_data;
1653    int i;
1654    Arg args[1];
1655    XmString label_string;
1656
1657    label_string = XmStringCreateLocalized((FPGETMESSAGE(82, 22, "Switch Area")));
1658    XtSetArg (args[0], XmNlabelString, label_string);
1659    XtSetValues (popup_data->popup_title, args, 1);
1660    XmStringFree (label_string);
1661
1662    /* hide actions items */
1663    for (i = 0; i < popup_data->action_count; i++)
1664        XtUnmanageChild (popup_data->action_item[i]);
1665
1666    /* show add workspace item */
1667    XtManageChild (popup_data->add_ws_item);
1668
1669    /* hide delete and rename workspace items */
1670    XtUnmanageChild (popup_data->delete_ws_item);
1671    XtUnmanageChild (popup_data->rename_ws_item);
1672
1673    /* reset the help callback to reflect switch area help */
1674    XtRemoveAllCallbacks (popup_data->help_item, XmNactivateCallback);
1675    XtAddCallback(popup_data->help_item, XmNactivateCallback,
1676                  SwitchTopicHelpCB, (XtPointer)switch_data);
1677
1678    XtManageChild(popup_data->separator1);
1679 }
1680
1681
1682
1683
1684
1685 /************************************************************************
1686  *
1687  *  GetSwitchDataFromForm
1688  *
1689  ************************************************************************/
1690  
1691
1692
1693 static void
1694 GetSwitchDataFromForm (Widget        form,
1695                        SwitchData ** switch_data_rtn)
1696
1697
1698 {
1699    BoxData * box_data;
1700    int i;
1701
1702    for (i = 0; i < panel.box_data_count; i++)
1703    {
1704       box_data = panel.box_data[i];
1705
1706       if (box_data->switch_form == form)
1707       {
1708          *switch_data_rtn = box_data->switch_data;
1709          break;
1710       }
1711    }
1712 }
1713
1714
1715
1716
1717 /************************************************************************
1718  *
1719  *  GetSwtichControlData
1720  *
1721  ************************************************************************/
1722  
1723
1724 static ControlData *
1725 GetSwitchControlData (SwitchData * switch_data,
1726                       Widget       focus_widget)
1727
1728
1729 {
1730    int i;
1731    ControlData * control_data;
1732    Boolean found = False;
1733
1734    for (i = 0; i < switch_data->control_data_count; i++)
1735    {
1736       control_data = switch_data->control_data[i];
1737
1738       if (control_data->icon == focus_widget)
1739       {
1740          found = True;
1741          break;
1742       }
1743    }
1744
1745    if (!found) return NULL;
1746
1747    return (control_data);
1748 }
1749
1750
1751
1752
1753
1754 /************************************************************************
1755  *
1756  *  WSPopupMenu
1757  *
1758  ************************************************************************/
1759  
1760 static void
1761 WSPopupMenu (Widget     w,
1762              XtPointer client_data,
1763              XtPointer call_data)
1764
1765
1766 {
1767    XmManagerWidget mgr = (XmManagerWidget) w;
1768    int num_children = mgr->composite.num_children;
1769    XmAnyCallbackStruct * callback;
1770    XEvent * event;
1771    Widget form, focus_widget;
1772    SwitchData * switch_data;
1773    ControlData * control_data = NULL;
1774    Boolean is_button = False;
1775    Position x, y;
1776    Arg args[2];
1777    long control_type;
1778
1779    callback = (XmAnyCallbackStruct *) call_data;
1780    event = (XEvent *) callback->event;
1781
1782
1783    /* get the form where the menu was posted from */
1784
1785    form = XmGetPostedFromWidget (w);
1786
1787    GetSwitchDataFromForm (form, &switch_data);
1788
1789
1790    if (event->type == ButtonPress)
1791    {
1792
1793      /*  Change to use new Xme function when porting to Motif 2.0  */
1794      /*  Get gadget at x, y position                               */
1795
1796      focus_widget = (Widget) XmObjectAtPoint (form, event->xbutton.x,
1797                                               event->xbutton.y);
1798
1799      if (focus_widget == NULL)
1800      {
1801         XtSetArg (args[0], XmNx, &x);
1802         XtSetArg (args[1], XmNy, &y);
1803         XtGetValues(switch_data->rc, args, 2);
1804
1805         focus_widget = (Widget) XmObjectAtPoint (switch_data->rc,
1806                                                  event->xbutton.x - x,
1807                                                  event->xbutton.y - y);
1808         is_button = True;
1809      }
1810      else
1811         control_data = GetSwitchControlData (switch_data, focus_widget);
1812
1813
1814      /* set the menu positioning */
1815
1816      XmMenuPosition (switch_data->popup_data->popup,
1817                      (XButtonPressedEvent *) event);
1818    }
1819    else
1820    {
1821  
1822       /* get the widget that has the traversal focus */
1823   
1824       focus_widget = XmGetFocusWidget (form);
1825
1826       control_data = GetSwitchControlData (switch_data, focus_widget);
1827
1828       if (control_data == NULL)
1829          is_button = True;
1830
1831       /* set the menu positioning for non button events */
1832
1833       KeyMenuPosition (switch_data->popup_data->popup, focus_widget);
1834    }
1835
1836    if (focus_widget != NULL)
1837    {
1838       if (is_button)
1839         /* The mouse is over a button in the switch area */
1840          ShowWorkspaceItems (switch_data, focus_widget);
1841       else
1842       {
1843          if (control_data != NULL)
1844          {
1845             control_type =
1846                  (long) control_data->element_values[CONTROL_TYPE].parsed_value;
1847
1848             if (control_type != CONTROL_BLANK)
1849               /* The mouse is over a control in the switch area */
1850                CreateActionButtons (w, switch_data, control_data);
1851             else
1852               /* The mouse is over a blank control in the switch area */
1853                ShowPartialWorkspaceItems (switch_data);
1854          }
1855          else
1856          {
1857               /*
1858                * The mouse is over area other than the buttons and control
1859                * in the switch area
1860                */
1861                ShowPartialWorkspaceItems (switch_data);
1862          }
1863       }
1864    } 
1865    else
1866       /*
1867        * The mouse is over area other than the buttons and control
1868        * in the switch area
1869        */
1870       ShowPartialWorkspaceItems (switch_data);
1871 }
1872
1873
1874
1875
1876 /************************************************************************
1877  *
1878  *  CreateWorkspacePopupMenu
1879  *
1880  ************************************************************************/
1881  
1882  
1883 void
1884 CreateWorkspacePopupMenu (Widget       w,
1885                           SwitchData * switch_data)
1886
1887
1888 {
1889    Widget children[20];
1890    XmString label_string;
1891    char * mnemonic;
1892    Arg args[5];
1893    long i, child_num = 0;
1894    PopupData * popup_data;
1895
1896    popup_data = (PopupData *) XtMalloc(sizeof(PopupData));
1897
1898    i = 0;
1899    XtSetArg (args[i], XmNwhichButton, wmGD.bMenuButton); i++;
1900
1901    popup_data->popup = XmCreatePopupMenu(w, "WSPopup", args, i);
1902
1903    popup_data->deinstall_item = NULL;
1904    popup_data->toggle_item = NULL;
1905    popup_data->modify_subpanel_item = NULL;
1906    popup_data->subpanel_add_state = True;
1907
1908    XtAddCallback(popup_data->popup, XmNmapCallback, WSPopupMenu,
1909                  (XtPointer) switch_data);
1910
1911    label_string = XmStringCreateLocalized((FPGETMESSAGE(82, 22, "Switch Area")));
1912    XtSetArg (args[0], XmNlabelString, label_string);
1913    popup_data->popup_title = children[child_num++] =
1914                 XmCreateLabelGadget (popup_data->popup, "title", args, 1);
1915    XmStringFree (label_string);
1916
1917    children[child_num++] = XmCreateSeparatorGadget (popup_data->popup, "sep1",
1918                                                     NULL, 0);
1919    children[child_num++] = XmCreateSeparatorGadget (popup_data->popup, "sep2",
1920                                                     NULL, 0);
1921
1922    popup_data->action_item = (Widget *) XtMalloc(sizeof(Widget) * 5);
1923    popup_data->action_count = 0;
1924
1925    for (i = 0; i < 5; i++)
1926    {    
1927       children[child_num] = popup_data->action_item[i] =
1928          XmCreatePushButtonGadget (popup_data->popup, "action_button", args, 0);
1929       popup_data->action_count++;
1930
1931       XtManageChild (popup_data->action_item[i]);
1932       XtAddCallback (children[child_num++], XmNactivateCallback,
1933                      ActionCB, (XtPointer) i);
1934    }
1935
1936    label_string =
1937           XmStringCreateLocalized ((FPGETMESSAGE(82, 23, "Add Workspace")));
1938    XtSetArg (args[0], XmNlabelString, label_string);
1939    mnemonic = ((char *)FPGETMESSAGE(82, 24, "A"));
1940    XtSetArg (args[1], XmNmnemonic, mnemonic[0]);
1941    popup_data->add_ws_item = children[child_num] =
1942          XmCreatePushButtonGadget (popup_data->popup, "Add_Workspace", args, 2);
1943    XmStringFree (label_string);
1944
1945    XtAddCallback(children[child_num++], XmNactivateCallback, AddWorkspaceCB,
1946                         (XtPointer)NULL);
1947
1948    label_string = XmStringCreateLocalized((FPGETMESSAGE(82, 25, "Delete")));
1949    XtSetArg (args[0], XmNlabelString, label_string);
1950    mnemonic = ((char *)FPGETMESSAGE(82, 26, "D"));
1951    XtSetArg (args[1], XmNmnemonic, mnemonic[0]);
1952    popup_data->delete_ws_item = children[child_num] = 
1953                         XmCreatePushButtonGadget (popup_data->popup,
1954                                                   "Delete_Workspace", args, 2);
1955    XmStringFree (label_string);
1956
1957    XtAddCallback(children[child_num++], XmNactivateCallback,
1958                  DeleteWorkspaceCB, (XtPointer) 0);
1959
1960    label_string = XmStringCreateLocalized((FPGETMESSAGE(82, 27, "Rename")));
1961    XtSetArg (args[0], XmNlabelString, label_string);
1962    mnemonic = ((char *)FPGETMESSAGE(82, 28, "R"));
1963    XtSetArg (args[1], XmNmnemonic, mnemonic[0]);
1964    popup_data->rename_ws_item = children[child_num] = 
1965                         XmCreatePushButtonGadget (popup_data->popup,
1966                                                   "Rename_Workspace", args, 2);
1967    XmStringFree (label_string);
1968
1969    XtAddCallback(children[child_num++], XmNactivateCallback,
1970                  RenameWorkspaceCB, (XtPointer) 0);
1971
1972    popup_data->separator1 = children[child_num++] =
1973       XmCreateSeparatorGadget (popup_data->popup, "sep3", NULL, 0);
1974
1975    popup_data->separator2 = NULL;
1976
1977    label_string = XmStringCreateLocalized((FPGETMESSAGE(82, 29, "Help")));
1978    XtSetArg (args[0], XmNlabelString, label_string);
1979    mnemonic = ((char *)FPGETMESSAGE(82, 30, "H"));
1980    XtSetArg (args[1], XmNmnemonic, mnemonic[0]);
1981    popup_data->help_item = children[child_num++] =
1982                 XmCreatePushButtonGadget (popup_data->popup, "Help", args, 2);
1983    XmStringFree (label_string);
1984
1985    XtManageChildren(children, child_num);
1986
1987    switch_data->popup_data = popup_data;
1988 }
1989
1990
1991