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