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