dtwm: basic multihead(xinerama only) support
[oweals/cde.git] / cde / programs / dtfile / Encaps.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: Encaps.c /main/10 1996/10/30 11:10:16 drk $ */
24 /************************************<+>*************************************
25  ****************************************************************************
26  *
27  *   FILE:           Encaps.c
28  *
29  *   COMPONENT_NAME: Desktop File Manager (dtfile)
30  *
31  *   Description:    Source file for the dialog encapsulation functions.
32  *
33  *   FUNCTIONS: DataChangeCallback
34  *              DataCloseCallback
35  *              DialogStructureNotifyHandler
36  *              IntDialogGetResources
37  *              IntDialogPutResources
38  *              SetIconifyState
39  *              TimerEvent
40  *              _DtBooleanToString
41  *              _DtBuildDialog
42  *              _DtChildPosition
43  *              _DtDialogGetResources
44  *              _DtDialogPutResources
45  *              _DtDimensionToString
46  *              _DtEncapSetWorkSpaceHints
47  *              _DtFreeDialogData
48  *              _DtGetDefaultDialogData
49  *              _DtGetDialogData
50  *              _DtGetDialogInstance
51  *              _DtGetDialogShell
52  *              _DtGetInstanceData
53  *              _DtGetResourceDialogData
54  *              _DtHideDialog
55  *              _DtInitializeEncapsulation
56  *              _DtInstallDialog
57  *              _DtIntToString
58  *              _DtIsDialogShowing
59  *              _DtPositionToString
60  *              _DtShortToString
61  *              _DtShowBuiltDialog
62  *              _DtShowDialog
63  *              _DtStringToString
64  *              _DtWriteDialogData
65  *              _DtXmStringTableToString
66  *              _DtXmStringToString
67  *              _DtmapCB
68  *              _DtChangeTo
69  *
70  *   (c) Copyright 1993, 1994, 1995 Hewlett-Packard Company
71  *   (c) Copyright 1993, 1994, 1995 International Business Machines Corp.
72  *   (c) Copyright 1993, 1994, 1995 Sun Microsystems, Inc.
73  *   (c) Copyright 1993, 1994, 1995 Novell, Inc.
74  *
75  ****************************************************************************
76  ************************************<+>*************************************/
77
78
79 #include <string.h>
80 #include <Xm/XmP.h>
81 #include <Xm/Xm.h>
82 #include <Xm/BulletinB.h>
83 #include <Xm/AtomMgr.h>
84 #include <Xm/MwmUtil.h>
85 #include <Xm/VendorSEP.h>
86 #include <Xm/XmPrivate.h> /* _XmStringUngenerate, _XmGetWidgetExtData */
87 #include <X11/ShellP.h>
88 #include <X11/Shell.h>
89 #include <X11/Xutil.h>
90 #include <X11/Xatom.h>
91 #include <X11/Intrinsic.h>
92
93 #include <Dt/Wsm.h>
94 #include <Dt/DtNlUtils.h>
95
96 #include "Encaps.h"
97 #include "Desktop.h"
98 #include "Filter.h"
99 #include "FileMgr.h"
100 #include "Main.h"
101 #include "ModAttr.h"
102
103
104 #define MAX_NAME_LIST_SIZE      25
105 #define MAX_RESOURCE_LENGTH     256
106
107
108 /*  Cache array handling defines, structure, and global statics  */
109
110 #define INCREMENT_SIZE  10
111
112
113 typedef struct _Dialog
114 {
115    Boolean                 in_use;
116    Widget                  dialog_widget;
117    XtPointer               dialog;
118    DialogData            * dialog_data;
119    DialogChangedProc       change;
120    XtPointer               change_client_data;
121    DialogClosedProc        close;
122    XtPointer               close_client_data;
123    struct _Dialog        * next;
124 } Dialog;
125
126
127 typedef struct
128 {
129    DialogClass * class;
130    Dialog      * dialog_list;
131    Boolean       cache;
132    Boolean       destroyPopups;
133 } ClassSet;
134
135 extern int filter_dialog,mod_attr_dialog;
136
137 static ClassSet * class_set = NULL;
138 static int class_set_size = 0;
139 static int num_classes = 0;
140 static int NumberOfDialogMapped = 0;
141
142 static char * resourceBuf = NULL;
143 static int commonResourceCount = 5;
144 static DialogResource commonResources[] =
145 {
146    { "displayed", XmRBoolean, sizeof(Boolean),
147      XtOffset(DialogInstanceDataPtr, displayed),
148      (caddr_t) False, _DtBooleanToString },
149
150    { "x", XmRPosition, sizeof(Position),
151      XtOffset(DialogInstanceDataPtr, x),
152      (caddr_t) 0, _DtPositionToString},
153
154    { "y", XmRPosition, sizeof(Position),
155       XtOffset(DialogInstanceDataPtr, y),
156       (caddr_t) 0, _DtPositionToString },
157
158    { "width", XmRHorizontalDimension, sizeof(Dimension),
159      XtOffset(DialogInstanceDataPtr, width),
160      (caddr_t) 0, _DtDimensionToString },
161
162    { "height", XmRVerticalDimension, sizeof(Dimension),
163       XtOffset(DialogInstanceDataPtr, height),
164       (caddr_t) 0, _DtDimensionToString },
165 };
166
167 static Widget encap_parent_shell;
168
169 extern int file_mgr_dialog;
170
171 /*  Timer globals */
172 /*
173  * initialTimeoutLength is used to specify how long to wait before initially
174  *    kicking of the building of the dialog cache.
175  * activeTimeoutLength is used to specify how long to wait after adding
176  *    a dialog to the cache, before adding the next dialog.
177  * idleTimeoutLength is used to specify how long to wait after all dialogs
178  *    have been built, and the cache is full.
179  */
180 int initialTimeoutLength = 180000;      /* 3 minutes, in milliseconds */
181 int activeTimeoutLength = 30000;        /* 30 seconds, in milliseconds */
182 int idleTimeoutLength = 900000;         /* 15 minutes, in milliseconds */
183
184 #define TIMER_STARTUP_STATE  0
185 #define TIMER_ACTIVE_STATE   1
186 #define TIMER_IDLE_STATE     2
187
188 static int timerState = TIMER_STARTUP_STATE;
189 static XtIntervalId timerId = 0;
190
191
192 /*
193  * This global is used when positioning a dialog ABOVE (not below) its
194  * parent window.  The 'y' position is defined to be the 'y' position
195  * of the parent, minus the 'height' of the dialog, minus the value
196  * assigned to 'topPositionOffset'; this allows the application to control
197  * how much, if any, of the parent's title bar is covered.
198  */
199 int topPositionOffset = 20;
200
201
202 /********    Static Function Declarations    ********/
203
204 static void DialogStructureNotifyHandler(
205                         Widget w,
206                         XtPointer client_data,
207                         XEvent *event );
208 static void SetIconifyState(
209                         Widget shell,
210                         Boolean iconify) ;
211 static void DataChangeCallback(
212                         Widget widget,
213                         XtPointer client_data,
214                         XtPointer call_data) ;
215 static void DataCloseCallback(
216                         Widget widget,
217                         XtPointer client_data,
218                         XtPointer call_data) ;
219 static void TimerEvent(
220                         Widget widget,
221                         XtIntervalId *id) ;
222 static void IntDialogGetResources(
223                         XrmDatabase database,
224                         char *base,
225                         DialogResource *resource,
226                         XrmName *xrmName,
227                         int nameCount,
228                         XrmQuark stringQuark) ;
229 static void IntDialogPutResources(
230                         int fd,
231                         char **nameList,
232                         char *dialogName,
233                         char *base,
234                         DialogResource *resource) ;
235
236 /********    End Static Function Declarations    ********/
237
238
239
240 /************************************************************************
241  *
242  *  _DtInitializeEncapsulation
243  *      This function is used to initialize the dialog encapsulation.
244  *
245  ************************************************************************/
246
247 void
248 _DtInitializeEncapsulation(
249         Display *display,
250         char *name,
251         char *class )
252
253 {
254    Arg args[5];
255
256    /*  Create an application shell that will never be    */
257    /*  displayed that is used as a parent of all of the  */
258    /*  dialog created.                                   */
259
260    encap_parent_shell = XtAppCreateShell (name, class,
261                                     applicationShellWidgetClass,
262                                     display, NULL, 0);
263
264    /* Supposedly required to be ICCCM complient */
265    XtSetArg(args[0], XmNmappedWhenManaged, False);
266    XtSetArg(args[1], XmNwidth, 1);
267    XtSetArg(args[2], XmNheight, 1);
268    XtSetValues(encap_parent_shell, args, 3);
269    XtRealizeWidget(encap_parent_shell);
270
271    /*  Get a timer going that is used for auto creation of dialogs.  */
272
273    timerState = TIMER_STARTUP_STATE;
274    timerId = XtAppAddTimeOut(XtWidgetToApplicationContext(encap_parent_shell),
275                              initialTimeoutLength, (XtTimerCallbackProc)
276                              TimerEvent, (caddr_t) encap_parent_shell);
277
278    /* Allocate a buffer for writing out resource values */
279    resourceBuf = XtMalloc(20);
280 }
281
282
283
284
285 /************************************************************************
286  *
287  *  _DtInstallDialog
288  *      This function is used to register a dialog class with the
289  *      encapsulation functions.
290  *
291  ************************************************************************/
292
293 int
294 _DtInstallDialog(
295         DialogClass *dialog_class,
296         Boolean cache,
297         Boolean destroyPopups )
298
299 {
300    /*  Allocate additional dialog cache space if needed  */
301
302    if (num_classes == class_set_size)
303    {
304       class_set_size += INCREMENT_SIZE;
305       class_set =
306          (ClassSet *) XtRealloc ((char *)class_set,
307                                  sizeof (ClassSet) * class_set_size);
308    }
309
310    class_set[num_classes].class = dialog_class;
311    class_set[num_classes].dialog_list = NULL;
312    class_set[num_classes].cache = cache;
313    class_set[num_classes].destroyPopups = destroyPopups;
314
315    num_classes++;
316
317    return (num_classes - 1);
318 }
319
320
321
322
323 /************************************************************************
324  *
325  *  _DtGetDialogData
326  *      This function is used to get a structure containing the
327  *      current dialog data for a particular dialog instance.
328  *
329  ************************************************************************/
330
331 DialogData *
332 _DtGetDialogData(
333         DialogData *dialog_data )
334
335 {
336    Dialog * dialog;
337    DialogData * new_data;
338
339    dialog = class_set[dialog_data->type].dialog_list;
340
341    while (dialog != NULL)
342    {
343       if (dialog->dialog_data == dialog_data)
344       {
345          new_data = (DialogData *) XtMalloc (sizeof (DialogData));
346
347          new_data->type = dialog->dialog_data->type;
348          new_data->data = NULL;
349          if (class_set[new_data->type].class->get_values)
350          {
351             new_data->data =
352               (*(class_set[new_data->type].class->get_values)) (dialog->dialog);
353          }
354
355          return (new_data);
356       }
357
358       dialog = dialog->next;
359    }
360
361    return (NULL);
362 }
363
364
365
366
367 /************************************************************************
368  *
369  *  _DtGetDefaultDialogData
370  *      This function is used to get a structure containing the
371  *      default data for a particular dialog type.
372  *
373  ************************************************************************/
374
375 DialogData *
376 _DtGetDefaultDialogData(
377         int dialog_type )
378
379
380 {
381    DialogData * dialog_data;
382
383    dialog_data = (DialogData *) XtMalloc (sizeof (DialogData));
384
385    dialog_data->type = dialog_type;
386    dialog_data->data = (*(class_set[dialog_type].class->get_default_values))();
387
388    return (dialog_data);
389 }
390
391
392
393
394 /************************************************************************
395  *
396  *  _DtGetResourceDialogData
397  *      This function is used to get a structure containing the
398  *      data for a particular dialog type from a resource data base.
399  *
400  ************************************************************************/
401
402 DialogData *
403 _DtGetResourceDialogData(
404         int dialog_type,
405         XrmDatabase data_base,
406         char **name_list )
407
408 {
409    DialogData * dialog_data;
410
411    dialog_data = (DialogData *) XtMalloc (sizeof (DialogData));
412
413    dialog_data->type = dialog_type;
414    dialog_data->data = (*(class_set[dialog_type].class->get_resource_values))
415                           (data_base, name_list);
416
417    return (dialog_data);
418 }
419
420
421
422
423 /************************************************************************
424  *
425  *  _DtShowDialog
426  *      This functions is used to display an instance of a dialog with
427  *      the provided data.  The functions and data to be set back to
428  *      the application upon change or close of the dialog is also
429  *      provided as parameters.
430  *
431  ************************************************************************/
432 void
433 _DtShowDialog(
434         Widget parent,
435         Widget map_parent,
436         XtPointer top_rec,
437         DialogData *dialog_data,
438         DialogChangedProc change_proc,
439         XtPointer change_data,
440         DialogClosedProc close_proc,
441         XtPointer close_data,
442         char *workspaces,
443         Boolean iconify_state,
444         Boolean ignoreCache,
445         char * title,
446         XClassHint * classHints )
447
448 {
449    Dialog * dialog;
450    int dialog_type, n;
451    DialogInstanceData * instance_data;
452    char geometry[40];
453    Arg args[5];
454    Boolean doCenter = False;
455    Boolean doParentRelativePositioning = False;
456    int availableDialogCount;
457
458
459    /*  See if there is a cached, unused dialog of the correct type.  */
460
461    dialog_type = dialog_data->type;
462    dialog = NULL;
463
464    if (!ignoreCache)
465    {
466       Dialog * availableDialog;
467
468       availableDialog = class_set[dialog_type].dialog_list;
469       availableDialogCount = 0;
470
471       /*
472        * In addition to looking for an available dialog in the cache to use,
473        * we also want to count up the number of unused dialogs in the cache.
474        * This lets us know it we need to restart the timer, to again build
475        * up the cache.
476        */
477       while (availableDialog != NULL)
478       {
479          if (availableDialog->in_use == False)
480          {
481             if (dialog == NULL)
482                dialog = availableDialog;
483             else
484                availableDialogCount++;
485          }
486          availableDialog = availableDialog->next;
487       }
488    }
489
490    if (dialog == NULL)
491    {
492       dialog = (Dialog *) XtMalloc (sizeof (Dialog));
493
494       (*(class_set[dialog_type].class->create))
495          (XtDisplay (encap_parent_shell), encap_parent_shell,
496          &(dialog->dialog_widget), &dialog->dialog);
497
498       /* if this is a File Manager view we want to update the headers
499        * (i.e icon_path, current_directory, status_line), now so that they
500        * don't get managed up front.  This is to make the Application
501        * Manager (toolbox) happy.
502        */
503       if(dialog_type == file_mgr_dialog)
504          UpdateHeaders(dialog->dialog, dialog_data->data, False);
505
506       /*  Add the change and close callbacks into the dialog  */
507
508       if (class_set[dialog_type].class->install_change_callback)
509          (*(class_set[dialog_type].class->install_change_callback))
510             (dialog->dialog, DataChangeCallback, (XtPointer)dialog);
511
512       if (class_set[dialog_type].class->install_close_callback)
513          (*(class_set[dialog_type].class->install_close_callback))
514             (dialog->dialog, DataCloseCallback, (XtPointer)dialog);
515
516       dialog->next = class_set[dialog_type].dialog_list;
517       class_set[dialog_type].dialog_list = dialog;
518    }
519    else
520    {
521       if(dialog_type == mod_attr_dialog)
522       {
523         ModAttrRec *mr = (ModAttrRec *)dialog->dialog;
524         ResetFlag(NULL,mr->ok);
525         ResetFlag(NULL,mr->cancel);
526       }
527       else if(dialog_type == filter_dialog)
528       {
529         FilterRec *fr = (FilterRec *)dialog->dialog;
530         ResetFlag(NULL,fr->ok);
531         ResetFlag(NULL,fr->close);
532       }
533    }
534
535    if ((!ignoreCache) && (class_set[dialog_type].cache) &&
536        (availableDialogCount < 1) && (timerState == TIMER_IDLE_STATE))
537    {
538       /*
539        * We need to reset the cache building timer, so that it gets kicked
540        * off quickly, instead of after the longer idle delay.
541        */
542       if (timerId)
543         XtRemoveTimeOut(timerId);
544       timerState = TIMER_ACTIVE_STATE;
545       timerId = XtAppAddTimeOut(
546                  XtWidgetToApplicationContext(encap_parent_shell),
547                  activeTimeoutLength, (XtTimerCallbackProc) TimerEvent,
548                  (XtPointer) encap_parent_shell);
549    }
550
551    /*
552     * Set pointer to top dialog data in child of the shell.
553     * This is needed to get help to work.
554     */
555    if (top_rec == NULL)
556       top_rec = dialog->dialog;
557    XtSetArg(args[0], XmNuserData, top_rec);
558    XtSetValues(dialog->dialog_widget, args, 1);
559
560    /* Need to add the map callback in relation to the parent */
561    if (class_set[dialog_type].class->map)
562    {
563       /*
564        * The map_parent parameter gives us the ability to position
565        * the dialog relative to a window which is not the transientFor
566        * parent.  This is used for the audio preview dialog.
567        */
568       if (map_parent == NULL)
569          map_parent = parent;
570
571       (*(class_set[dialog_type].class->map)) (map_parent, dialog->dialog);
572    }
573
574
575    /*  Set the dialog structure fields to the parameter data.  */
576
577    dialog->in_use = True;
578    dialog->dialog_data = dialog_data;
579    dialog->change = change_proc;
580    dialog->change_client_data = change_data;
581    dialog->close = close_proc;
582    dialog->close_client_data = close_data;
583
584
585    instance_data = (DialogInstanceData *) dialog_data->data;
586
587    /* If a special title has been specified, we need to set it now */
588    if (title)
589    {
590       XtSetArg(args[0], XmNtitle, title);
591       XtSetValues(XtParent(dialog->dialog_widget), args, 1);
592    }
593
594    /*  If this is a top level shell, get it realized  */
595
596    if (XtIsSubclass (XtParent (dialog->dialog_widget),
597                      applicationShellWidgetClass))
598    {
599       if (XtIsRealized (XtParent (dialog->dialog_widget)) == False)
600       {
601          if (instance_data->displayed == True)
602          {
603             (void) sprintf (geometry, "=%dx%d+%d+%d",
604                             instance_data->width, instance_data->height,
605                             instance_data->x, instance_data->y);
606
607             XtSetArg (args[0], XmNgeometry, geometry);
608             XtSetValues (XtParent (dialog->dialog_widget), args, 1);
609          }
610          else if ((instance_data->width != 0) && (instance_data->height != 0))
611          {
612             n=0;
613             XtSetArg (args[n], XmNwidth, instance_data->width); n++;
614             XtSetArg (args[n], XmNheight, instance_data->height); n++;
615             XtSetValues (XtParent (dialog->dialog_widget), args, n);
616          }
617
618          /* Toggle mappedWhenManaged to false */
619          XtSetMappedWhenManaged(XtParent (dialog->dialog_widget), False);
620          XtRealizeWidget (XtParent(dialog->dialog_widget));
621
622          /* Set the proper workspaces if needed */
623          _DtEncapSetWorkSpaceHints(XtParent(dialog->dialog_widget), workspaces);
624
625          /* Set any application-specified class hints for the window */
626          if (classHints)
627          {
628             XSetClassHint(XtDisplay(dialog->dialog_widget),
629                           XtWindow(XtParent(dialog->dialog_widget)),
630                           classHints);
631          }
632
633          /* Set the iconify state */
634          SetIconifyState(XtParent(dialog->dialog_widget), iconify_state);
635
636          /* Map the window */
637          XtSetMappedWhenManaged(XtParent (dialog->dialog_widget), True);
638          XtPopup (XtParent (dialog->dialog_widget), XtGrabNone);
639          XSync(XtDisplay(dialog->dialog_widget), False);
640
641       }
642       else
643       {
644          if (instance_data->displayed == True)
645          {
646             WMShellWidget wm = (WMShellWidget)XtParent(dialog->dialog_widget);
647
648             wm->wm.size_hints.flags |= USPosition;
649             XtSetArg (args[0], XmNx, instance_data->x);
650             XtSetArg (args[1], XmNy, instance_data->y);
651             XtSetArg (args[2], XmNwidth, instance_data->width);
652             XtSetArg (args[3], XmNheight, instance_data->height);
653             XtSetValues (XtParent (dialog->dialog_widget), args, 4);
654          }
655          else if ((instance_data->width != 0) && (instance_data->height != 0))
656          {
657             n=0;
658             XtSetArg (args[n], XmNwidth, instance_data->width); n++;
659             XtSetArg (args[n], XmNheight, instance_data->height); n++;
660             XtSetValues (XtParent (dialog->dialog_widget), args, n);
661          }
662
663          /* Set the proper workspaces if needed */
664          _DtEncapSetWorkSpaceHints(XtParent(dialog->dialog_widget), workspaces);
665
666          /* Set any application-specified class hints for the window */
667          if (classHints)
668          {
669             XSetClassHint(XtDisplay(dialog->dialog_widget),
670                           XtWindow(XtParent(dialog->dialog_widget)),
671                           classHints);
672          }
673
674          /* Set the iconify state */
675          SetIconifyState(XtParent(dialog->dialog_widget), iconify_state);
676
677          /* Map the window */
678          XtPopup (XtParent (dialog->dialog_widget), XtGrabNone);
679       }
680    }
681    else
682    {
683       if (instance_data->displayed == True)
684       {
685          XtSetArg (args[0], XmNx, instance_data->x);
686          XtSetArg (args[1], XmNy, instance_data->y);
687          XtSetArg (args[2], XmNwidth, instance_data->width);
688          XtSetArg (args[3], XmNheight, instance_data->height);
689          XtSetArg (args[4], XmNdefaultPosition, False);
690          XtSetValues (dialog->dialog_widget, args, 5);
691          XtRealizeWidget (dialog->dialog_widget);
692       }
693       else
694       {
695          XtSetArg (args[0], XmNdefaultPosition, False);
696          XtSetValues (dialog->dialog_widget, args, 1);
697
698          XtRealizeWidget (dialog->dialog_widget);
699
700          if (parent)
701          {
702             /* Position relative to the parent dialog */
703             /*
704              * Must be done after the set_values call, since the dialog
705              * may get forced to a different size.
706              */
707             doParentRelativePositioning = True;
708          }
709          else
710          {
711             /* Center in the display */
712             /*
713              * Must be done after the set_values call, since the dialog
714              * may get forced to a different size.
715              */
716             doCenter = True;
717          }
718       }
719
720       /*
721        * Dialogs with no controlling parent window, need to have their
722        * own workspace perperty set, if some workspaces have been requested.
723        */
724       if ((parent == NULL) && workspaces)
725          _DtEncapSetWorkSpaceHints(XtParent(dialog->dialog_widget), workspaces);
726    }
727
728
729    /*  Set Values onto the dialog to set it to the correct data.  */
730
731    (*(class_set[dialog_data->type].class->set_values))
732       (dialog->dialog, dialog_data->data);
733
734    /*
735     * These two adjustments MUST be done AFTER the dialog's SetValues()
736     * procedure is called.  This is due to the fact that the setvalues
737     * may cause the dialog size to change, and since both of the following
738     * positioning algorithms are dependent upon the dialog size, we want
739     * to make sure that the correct size is used.
740     */
741    if (doCenter)
742    {
743       XtSetArg (args[0], XmNx,
744           (Dimension)(WidthOfScreen(XtScreen(dialog->dialog_widget)) -
745            dialog->dialog_widget->core.width) / (Dimension)2);
746       XtSetArg (args[1], XmNy,
747           (Dimension)(HeightOfScreen(XtScreen(dialog->dialog_widget)) -
748            dialog->dialog_widget->core.height) / (Dimension)2);
749       XtSetValues (dialog->dialog_widget, args, 2);
750    }
751    else if (doParentRelativePositioning)
752    {
753       XtSetArg (args[0], XmNx,
754           parent->core.x +
755           (Dimension)(parent->core.width - dialog->dialog_widget->core.width) / (Dimension)2);
756       XtSetArg (args[1], XmNy,
757           parent->core.y +
758           (Dimension)(parent->core.height - dialog->dialog_widget->core.height) / (Dimension)2);
759       XtSetValues (XtParent(dialog->dialog_widget), args, 2);
760    }
761
762
763    /*  Fix up the transient-for windowing information so that  */
764    /*  the window manager will shuffle and iconify as a group  */
765
766    if (parent != NULL)
767    {
768       if (XtIsRealized(parent))
769       {
770          XSetTransientForHint (XtDisplay (parent),
771                             XtWindow (XtParent (dialog->dialog_widget)),
772                             XtWindow (parent));
773       }
774    }
775    else
776    {
777       if (!XtIsSubclass (XtParent (dialog->dialog_widget),
778                                      applicationShellWidgetClass))
779       {
780          XSetTransientForHint (XtDisplay (encap_parent_shell),
781                             XtWindow (XtParent (dialog->dialog_widget)),
782                             XtWindow (encap_parent_shell));
783       }
784    }
785
786
787    /*  Display the dialogs, application shells are displayed above.  */
788
789    if (!(XtIsSubclass (XtParent (dialog->dialog_widget),
790                        applicationShellWidgetClass)))
791    {
792       XtManageChild (dialog->dialog_widget);
793    }
794
795
796    /*  Set the dialog instance data to indicate that the dialog  */
797    /*  is displayed.                                             */
798
799    ((DialogInstanceData *) (dialog_data->data))->displayed = True;
800
801
802    /* Give the dialog a chance to set its focus widget, if necessary */
803
804    if (class_set[dialog_data->type].class->set_focus)
805    {
806       (*(class_set[dialog_data->type].class->set_focus))
807          (dialog->dialog, dialog_data->data);
808    }
809
810
811
812    XtAddEventHandler( XtParent( dialog->dialog_widget ),
813                       StructureNotifyMask,
814                       False,
815                       (XtEventHandler)DialogStructureNotifyHandler,
816                       NULL );
817 }
818
819
820
821
822 /************************************************************************
823  *
824  *  _DtHideDialog
825  *      This function is used to undisplay a dialog.
826  *
827  ************************************************************************/
828
829 void
830 _DtHideDialog(
831         DialogData *dialog_data,
832         Boolean call_callbacks )
833
834 {
835    Dialog * dialog;
836    DialogData * new_data;
837    CorePart * core;
838    register int i;
839
840
841    /*  Find the dialog and then hide it.  */
842
843    dialog = class_set[dialog_data->type].dialog_list;
844
845    while (dialog != NULL)
846    {
847        if ((dialog->dialog_data &&
848             dialog->dialog_data == dialog_data) && dialog->in_use == True)
849
850       {
851
852          /*  Free up any dialogs attached to the dialog widget  */
853
854          if(class_set[dialog_data->type].destroyPopups)
855          {
856             core = (CorePart *) (XtParent (dialog->dialog_widget));
857
858             for (i = core->num_popups - 1; i >= 0; i--)
859                XtDestroyWidget (core->popup_list[i]);
860          }
861
862
863          /*  Get the dialog down, invoke the close callbacks, and  */
864          /*  take it out of use.                                   */
865
866          if (XtIsSubclass (XtParent (dialog->dialog_widget),
867                            applicationShellWidgetClass))
868          {
869             ShellWidget shell_widget;
870
871             /*
872              * If we had been iconified, then our popped_up flag will
873              * have been cleared by the vendor shell.  When we call
874              * XtPopdown(), it will see that we are no longer popped
875              * up, and will not notify the window manager that our
876              * icon should be removed; this can cause a subsequent
877              * core dump if the user later tries to deiconify the window.
878              * This fix should not be necessary once the toolkit is
879              * fixed to properly track the shell's state.
880              */
881             shell_widget = (ShellWidget) XtParent(dialog->dialog_widget);
882             shell_widget->shell.popped_up = True;
883
884             XtPopdown ((Widget)shell_widget);
885          }
886          else
887          {
888             /*
889              * The following is for the condition described above.  However,
890              * for a dialog shell, what happens it that the 'managed' flag
891              * was set to 'False' when the windows were iconified (apparently
892              * by the dialog shell), and when we tell the intrinsics to
893              * really unmanage the child, it thinks it already has, so
894              * nothing happens; as a result, the dialog shell is left with
895              * its 'popped_up' flag set to 'True'.  The next time we try
896              * to post this dialog, the intrinsics think that it is already
897              * up, so it does nothing.
898              */
899             dialog->dialog_widget->core.managed = True;
900             XtUnmanageChild (dialog->dialog_widget);
901          }
902
903
904          /*  Set the dialog data to hidden  */
905
906          ((DialogInstanceData *) (dialog->dialog_data->data))->displayed = False;
907
908
909          if (call_callbacks && dialog->close)
910          {
911             new_data = (DialogData *) XtMalloc (sizeof (DialogData));
912
913             new_data->type = dialog->dialog_data->type;
914             new_data->data = NULL;
915             if (class_set[new_data->type].class->get_values)
916             {
917                new_data->data =
918                (*(class_set[new_data->type].class->get_values))(dialog->dialog);
919             }
920
921             dialog->in_use = False;
922             if (new_data->data)
923                ((DialogInstanceData *) (new_data->data))->displayed = False;
924
925             (*(dialog->close))
926                   (dialog->close_client_data, dialog->dialog_data, new_data);
927          }
928          else
929          {
930             dialog->in_use = False;
931             ((DialogInstanceData *) (dialog->dialog_data->data))->displayed = False;
932          }
933
934          break;
935       }
936
937       dialog = dialog->next;
938    }
939 }
940
941
942
943
944 /************************************************************************
945  *
946  *  _DtGetDialogShell
947  *      This function is used return the shell widget of a dialog that
948  *      is currently displayed.
949  *
950  ************************************************************************/
951
952 Widget
953 _DtGetDialogShell(
954         DialogData *dialog_data )
955
956 {
957    Dialog * dialog;
958
959
960    /*  Find the dialog and then return the shell.  */
961
962    dialog = class_set[dialog_data->type].dialog_list;
963
964    while (dialog != NULL)
965    {
966       if (dialog->dialog_data == dialog_data)
967          return (dialog->dialog_widget);
968       else
969          dialog = dialog->next;
970    }
971
972    return (NULL);
973 }
974
975
976
977
978 /************************************************************************
979  *
980  *  _DtGetDialogInstance
981  *      This function is used return the dialog instance structure
982  *      of a currently in use dialog.
983  *
984  ************************************************************************/
985
986 XtPointer
987 _DtGetDialogInstance(
988         DialogData *dialog_data )
989
990 {
991    Dialog * dialog;
992
993
994    /*  Find the dialog and then return the instance  */
995
996    dialog = class_set[dialog_data->type].dialog_list;
997
998    while (dialog != NULL)
999    {
1000       if (dialog->dialog_data && dialog->dialog_data == dialog_data)
1001          return (dialog->dialog);
1002       else
1003          dialog = dialog->next;
1004    }
1005
1006    return (NULL);
1007 }
1008
1009
1010
1011
1012 /************************************************************************
1013  *
1014  *  _DtGetInstanceData
1015  *      This function is used return the dialog data structure contained
1016  *      within the cache structure referenced by instance.
1017  *
1018  ************************************************************************/
1019
1020 DialogData *
1021 _DtGetInstanceData(
1022         XtPointer instance )
1023
1024 {
1025    int i;
1026    Dialog * dialog;
1027
1028
1029    /*  Find the dialog and then return the instance  */
1030
1031    for (i = 0; i < num_classes; i++)
1032    {
1033       dialog = class_set[i].dialog_list;
1034
1035       while (dialog != NULL)
1036       {
1037          if (dialog->dialog == instance && dialog->in_use == True)
1038             return (dialog->dialog_data);
1039          else
1040             dialog = dialog->next;
1041       }
1042    }
1043
1044    return (NULL);
1045 }
1046
1047
1048
1049
1050 /************************************************************************
1051  *
1052  *  _DtIsDialogShowing
1053  *      This function is used return a boolean indicating whether the
1054  *      a dialog is displayed which contains the dialog data.
1055  *      of a currently in use dialog.
1056  *
1057  ************************************************************************/
1058
1059 Boolean
1060 _DtIsDialogShowing(
1061         DialogData *dialog_data )
1062
1063 {
1064    Dialog * dialog;
1065
1066
1067    /*  Find the dialog and then return the instance  */
1068
1069    dialog = class_set[dialog_data->type].dialog_list;
1070
1071    while (dialog != NULL)
1072    {
1073       if (dialog->in_use && dialog->dialog_data == dialog_data)
1074          return (True);
1075       else
1076          dialog = dialog->next;
1077    }
1078
1079    return (False);
1080 }
1081
1082
1083
1084
1085 /************************************************************************
1086  *
1087  *  _DtWriteDialogData
1088  *      This function is used to write, as resources, the data
1089  *      for a dialog contained in dialog_data to the open file fd.
1090  *
1091  ************************************************************************/
1092
1093 void
1094 _DtWriteDialogData(
1095         DialogData *dialog_data,
1096         int fd,
1097         char **name_list )
1098
1099 {
1100    if (dialog_data != NULL)
1101       (*(class_set[dialog_data->type].class->write_resource_values))
1102          (dialog_data, fd, name_list);
1103 }
1104
1105
1106
1107
1108 /************************************************************************
1109  *
1110  *  _DtFreeDialogData
1111  *      This function is used to free up the data space allocated
1112  *      by a dialog.
1113  *
1114  ************************************************************************/
1115
1116 void
1117 _DtFreeDialogData(
1118         DialogData *dialog_data )
1119
1120 {
1121    if (dialog_data != NULL)
1122    {
1123       (*(class_set[dialog_data->type].class->free_values)) (dialog_data->data);
1124       XtFree ((char *) dialog_data);
1125        dialog_data = NULL;
1126    }
1127 }
1128
1129
1130
1131
1132 /************************************************************************
1133  *
1134  *  _DtDialogGetResources
1135  *      This function accesses data_base to extract the resource set
1136  *      described by the resoruces array.  Resources values are
1137  *      converted to the proper type and defaults are used if not
1138  *      data is found in the resource data base.
1139  *
1140  ************************************************************************/
1141
1142 void
1143 _DtDialogGetResources(
1144         XrmDatabase database,
1145         char **name_list,
1146         char *dialog_name,
1147         char *base,
1148         DialogResource *resources,
1149         int resource_count )
1150
1151 {
1152    XrmName xrmName[MAX_NAME_LIST_SIZE];
1153    XrmQuark stringQuark;
1154    int nameCount;
1155    int i;
1156
1157    /*  Build the quarkified name list from name_list and dialog_name  */
1158    /*  provided by the calling procedure.                             */
1159
1160    nameCount = 0;
1161    if (name_list != NULL)
1162    {
1163       while (name_list[nameCount] != NULL)
1164       {
1165          xrmName[nameCount] =  XrmStringToQuark (name_list[nameCount]);
1166          nameCount++;
1167       }
1168    }
1169
1170    if (dialog_name)
1171       xrmName[nameCount] = XrmStringToQuark (dialog_name);
1172    else
1173       nameCount--;
1174
1175    xrmName[nameCount + 2] = 0;
1176    stringQuark = XrmStringToQuark (XmRString);
1177
1178
1179    /* Load the common dialog size/position resources */
1180    for (i = 0; i < resource_count; i++)
1181    {
1182       IntDialogGetResources(database, base, resources + i, xrmName, nameCount,
1183                             stringQuark);
1184    }
1185
1186    /*
1187     * Load the dialog specific resources. If no value found, use the default.
1188     */
1189    for (i = 0; i < commonResourceCount; i++)
1190    {
1191       IntDialogGetResources(database, base, commonResources + i, xrmName,
1192                             nameCount, stringQuark);
1193    }
1194 }
1195
1196
1197 /*
1198  * This internal function does the real work of loading a single resource
1199  * value.  If the value is not found in the resource database, then the
1200  * specified default value is used.
1201  */
1202
1203 static void
1204 IntDialogGetResources(
1205         XrmDatabase database,
1206         char *base,
1207         DialogResource *resource,
1208         XrmName *xrmName,
1209         int nameCount,
1210         XrmQuark stringQuark )
1211
1212 {
1213    XrmRepresentation repType;
1214    XrmValue value;
1215    XrmValue convertedValue;
1216    char  charVal;
1217    short shortVal;
1218    int   intVal;
1219    long  longVal;
1220
1221    {
1222       xrmName[nameCount + 1] = XrmStringToQuark (resource->name);
1223
1224       if (XrmQGetResource (database, xrmName, xrmName, &repType, &value))
1225       {
1226          if (repType == stringQuark)
1227             if (strcmp (resource->type, XmRString) != 0)
1228             {
1229                XtConvert (encap_parent_shell, XmRString, &value,
1230                                       resource->type, &convertedValue);
1231             }
1232             else
1233             {
1234                *((char **)(base + resource->offset)) = (char *)value.addr;
1235                return;
1236             }
1237          else
1238             convertedValue.addr = NULL;
1239
1240       }
1241       else
1242          convertedValue.addr = NULL;
1243
1244
1245       /*  Set the converted value address pointer and value to  */
1246       /*  the proper default value if the addr is NULL.         */
1247
1248       if (convertedValue.addr == NULL)
1249       {
1250          if (resource->size == sizeof(char))
1251          {
1252             charVal = (char)(XtArgVal)resource->default_value;
1253             convertedValue.addr = (caddr_t) &charVal;
1254          }
1255          else if (resource->size == sizeof(short))
1256          {
1257             shortVal = (short)(XtArgVal)resource->default_value;
1258             convertedValue.addr = (caddr_t) &shortVal;
1259          }
1260          else if (resource->size == sizeof(int))
1261          {
1262             intVal = (int)(XtArgVal)resource->default_value;
1263             convertedValue.addr = (caddr_t) &intVal;
1264          }
1265          else
1266          {
1267             longVal = (long)(XtArgVal)resource->default_value;
1268             convertedValue.addr = (caddr_t) &longVal;
1269          }
1270       }
1271
1272
1273       /*  Stuff the converted value into the calling functions   */
1274       /*  structure according to the size of the piece of data.  */
1275
1276       if (resource->size == sizeof(char))
1277          *((char *)(base + resource->offset)) = *((char *)convertedValue.addr);
1278       else if (resource->size == sizeof(short))
1279          *((short *)(base + resource->offset))= *((short *)convertedValue.addr);
1280       else if (resource->size == sizeof(int))
1281          *((int *)(base + resource->offset))= *((int *)convertedValue.addr);
1282       else
1283          *((long *)(base + resource->offset)) = *((long *)convertedValue.addr);
1284    }
1285 }
1286
1287
1288
1289 /************************************************************************
1290  *
1291  *  _DtDialogPutResources
1292  *      This function writes a resource set to a file.
1293  *
1294  ************************************************************************/
1295
1296 void
1297 _DtDialogPutResources(
1298         int fd,
1299         char **nameList,
1300         char *dialogName,
1301         char *base,
1302         DialogResource *resources,
1303         int resourceCount )
1304
1305 {
1306    int i;
1307    DialogInstanceData * dialogInstanceData;
1308
1309    /*
1310     * Write out the common dialog size/position resources, only if the
1311     * dialog is currently displayed.
1312     */
1313    dialogInstanceData = (DialogInstanceData *)base;
1314    if (dialogInstanceData->displayed)
1315    {
1316       for (i = 0; i < commonResourceCount; i++)
1317       {
1318          IntDialogPutResources(fd, nameList, dialogName, base,
1319                                commonResources + i);
1320       }
1321    }
1322
1323    /*
1324     *  Loop through the dialog specific resources, write the name list and
1325     *  resource name.
1326     */
1327    for (i = 0; i < resourceCount; i++)
1328       IntDialogPutResources( fd, nameList, dialogName, base, resources + i);
1329 }
1330
1331
1332 /*
1333  * This internal function does the real work involved in writing a single
1334  * resource out to a session file.
1335  */
1336
1337 static void
1338 IntDialogPutResources(
1339         int fd,
1340         char **nameList,
1341         char *dialogName,
1342         char *base,
1343         DialogResource *resource )
1344
1345 {
1346    static char outBuf[MAX_RESOURCE_LENGTH];
1347    int nameCount;
1348
1349    outBuf[0] = '\0';
1350
1351    (void) strcat (outBuf, "*");
1352
1353    nameCount = 0;
1354    if (nameList != NULL)
1355    {
1356       while (nameList[nameCount] != NULL)
1357       {
1358          (void) strcat (outBuf, nameList[nameCount]);
1359          (void) strcat (outBuf, ".");
1360          nameCount++;
1361       }
1362    }
1363
1364    if (dialogName != NULL)
1365    {
1366       (void) strcat (outBuf, dialogName);
1367       (void) strcat (outBuf, ".");
1368    }
1369
1370    (void) strcat (outBuf, resource->name);
1371    (void) strcat (outBuf, ":    ");
1372
1373    (*(resource->write_resource))
1374       (fd, (XtPointer) (base + resource->offset), outBuf);
1375 }
1376
1377
1378
1379 /************************************************************************
1380  ************************************************************************
1381  *
1382  *      Internal functions
1383  *
1384  ************************************************************************
1385  ************************************************************************/
1386
1387
1388 /************************************************************************
1389  *
1390  *  _DtEncapSetWorkSpaceHints
1391  *      This function sets a given shell to a given set(s) of
1392  *   workspaces.
1393  *
1394  ************************************************************************/
1395 void
1396 _DtEncapSetWorkSpaceHints(
1397         Widget shell,
1398         char *workspaces )
1399
1400 {
1401    char * ptr;
1402    Atom * workspace_atoms = NULL;
1403    int num_workspaces=0;
1404
1405    if (workspaces)
1406    {
1407       do
1408       {
1409          ptr = DtStrchr (workspaces, '*');
1410
1411          if (ptr != NULL) *ptr = '\0';
1412
1413          workspace_atoms = (Atom *) XtRealloc ((char *)workspace_atoms,
1414                            sizeof (Atom) * (num_workspaces + 1));
1415
1416          workspace_atoms[num_workspaces] =
1417                            XmInternAtom (XtDisplay(shell), workspaces, True);
1418
1419          num_workspaces++;
1420
1421          if (ptr != NULL)
1422          {
1423             *ptr = '*';
1424             workspaces = ptr + 1;
1425          }
1426       } while (ptr != NULL);
1427
1428       DtWsmSetWorkspacesOccupied (XtDisplay(shell), XtWindow (shell), workspace_atoms,
1429                            num_workspaces);
1430
1431       XtFree ((char *) workspace_atoms);
1432       workspace_atoms = NULL;
1433    }
1434    else
1435    {
1436       Window   rootWindow;
1437       Atom     pCurrent;
1438       Screen   *currentScreen;
1439       int      screen;
1440       char     *workspace_name;
1441
1442       /*
1443        * Since no specific workspaces were specified, we will force the
1444        * dialog to the current workspace.
1445        */
1446       screen = XDefaultScreen(XtDisplay(shell));
1447       currentScreen = XScreenOfDisplay(XtDisplay(shell), screen);
1448       rootWindow = RootWindowOfScreen(currentScreen);
1449
1450       if(DtWsmGetCurrentWorkspace(XtDisplay(shell), rootWindow, &pCurrent) ==
1451                                Success)
1452       {
1453          DtWsmSetWorkspacesOccupied(XtDisplay(shell), XtWindow (shell), &pCurrent, 1);
1454       }
1455    }
1456 }
1457
1458 /************************************************************************
1459  *
1460  *  SetIconifyState
1461  *      This function sets a given shell to a given iconify state.
1462  *  (e.g. Mapped or iconified)
1463  *
1464  ************************************************************************/
1465 static void
1466 SetIconifyState(
1467         Widget shell,
1468         Boolean iconify )
1469
1470 {
1471    Arg       args[1];
1472    XWMHints   *wmhints;
1473
1474    if (iconify)
1475    {
1476      /* add the iconify hint to the current shell */
1477      XtSetArg(args[0], XmNinitialState, IconicState);
1478      XtSetValues(shell, args, 1);
1479    }
1480    else
1481    {
1482      /* Remove the iconify hint from the current shell */
1483      wmhints = XGetWMHints(XtDisplay(shell), XtWindow(shell));
1484      wmhints->flags |= IconWindowHint;
1485      wmhints->initial_state = NormalState;
1486      XSetWMHints(XtDisplay(shell), XtWindow(shell), wmhints);
1487      XFree(wmhints);
1488    }
1489
1490 }
1491 /************************************************************************
1492  *
1493  *  DataChangeCallback
1494  *      This callback is invoked from a dialog upon an action on the
1495  *      dialog that means that the data within the dialog has been
1496  *      changed.
1497  *
1498  ************************************************************************/
1499
1500 /*ARGSUSED*/
1501 static void
1502 DataChangeCallback(
1503         Widget widget,
1504         XtPointer client_data,
1505         XtPointer call_data )
1506
1507 {
1508    Dialog * dialog = (Dialog *) client_data;
1509    DialogData * new_data;
1510
1511    new_data = (DialogData *) XtMalloc (sizeof (DialogData));
1512
1513    new_data->type = dialog->dialog_data->type;
1514    new_data->data = NULL;
1515    if (class_set[new_data->type].class->get_values)
1516    {
1517       new_data->data = (*(class_set[new_data->type].class->get_values))
1518                           (dialog->dialog);
1519    }
1520
1521    if (dialog->change)
1522       (*(dialog->change))
1523          (dialog->change_client_data, dialog->dialog_data, new_data, call_data);
1524 }
1525
1526
1527
1528
1529 /************************************************************************
1530  *
1531  *  DataCloseCallback
1532  *      This callback is invoked from a dialog upon an action on the
1533  *      dialog that means the dialog has been closed.
1534  *
1535  ************************************************************************/
1536
1537 /*ARGSUSED*/
1538 static void
1539 DataCloseCallback(
1540         Widget widget,
1541         XtPointer client_data,
1542         XtPointer call_data )
1543
1544
1545 {
1546    Dialog * dialog = (Dialog *) client_data;
1547
1548    if(RecheckFlag(NULL,widget)) /* cancel flag already set, just return */
1549        return;
1550    _DtHideDialog (dialog->dialog_data, True);
1551 }
1552
1553
1554
1555
1556 /************************************************************************
1557  *
1558  *  TimerEvent
1559  *      This action function is called upon the encapsulations
1560  *      timeout going off.  Its function is to precreate and destroy
1561  *      extra dialogs.
1562  *
1563  ************************************************************************/
1564
1565 /* ARGSUSED */
1566 static void
1567 TimerEvent(
1568         Widget widget,
1569         XtIntervalId *id )
1570
1571 {
1572    register int i;
1573    Dialog * dialog;
1574    Dialog * prev_dialog;
1575    int count;
1576
1577
1578    /*  First pass through the dialog set to see if any  */
1579    /*  need to be created.  This is based on having 0   */
1580    /*  not in use dialogs of each type.                 */
1581
1582    for (i = 0; i < num_classes; i++)
1583    {
1584       dialog = class_set[i].dialog_list;
1585
1586       /* Only attempt to cache dialogs requesting this feature */
1587       if (!class_set[i].cache)
1588          continue;
1589
1590       while (dialog != NULL)
1591          if (dialog->in_use == False)
1592             break;
1593          else
1594             dialog = dialog->next;
1595
1596       if (dialog == NULL)
1597       {
1598          dialog = (Dialog *) XtMalloc (sizeof (Dialog));
1599
1600          (*(class_set[i].class->create))
1601             (XtDisplay (encap_parent_shell), encap_parent_shell,
1602             &(dialog->dialog_widget), &dialog->dialog);
1603
1604
1605          /*  Add the change and close callbacks into the dialog  */
1606
1607          if (class_set[i].class->install_change_callback)
1608             (*(class_set[i].class->install_change_callback))
1609                (dialog->dialog, DataChangeCallback, (XtPointer)dialog);
1610
1611          if (class_set[i].class->install_close_callback)
1612             (*(class_set[i].class->install_close_callback))
1613                (dialog->dialog, DataCloseCallback, (XtPointer)dialog);
1614
1615
1616          dialog->next = class_set[i].dialog_list;
1617          class_set[i].dialog_list = dialog;
1618
1619          dialog->in_use = False;
1620
1621          timerState = TIMER_ACTIVE_STATE;
1622          timerId = XtAppAddTimeOut(XtWidgetToApplicationContext(widget),
1623                                    activeTimeoutLength,
1624                                    (XtTimerCallbackProc) TimerEvent,
1625                                    (XtPointer) widget);
1626
1627          return;
1628       }
1629    }
1630
1631
1632    /*  Pass through the dialog set to see if any need to be destroyed    */
1633    /*  This is based on having more than 1 not in use dialog of a type.  */
1634
1635    for (i = 0; i < num_classes; i++)
1636    {
1637       dialog = class_set[i].dialog_list;
1638       count = 0;
1639
1640       while (dialog != NULL)
1641       {
1642          if (dialog->in_use == False)
1643             count++;
1644
1645          dialog = dialog->next;
1646       }
1647
1648       if (count > 1)
1649       {
1650          dialog = class_set[i].dialog_list;
1651
1652          if (dialog->in_use == False)
1653             class_set[i].dialog_list = dialog->next;
1654          else
1655          {
1656             prev_dialog = class_set[i].dialog_list;
1657             dialog = dialog->next;
1658
1659             while (dialog->in_use == True)
1660             {
1661               prev_dialog = dialog;
1662               dialog = dialog->next;
1663             }
1664
1665             prev_dialog->next = dialog->next;
1666          }
1667
1668          (*(class_set[i].class->destroy)) (dialog->dialog);
1669          XtFree ((char *) dialog);
1670           dialog = NULL;
1671
1672          break;
1673       }
1674    }
1675
1676    timerState = TIMER_IDLE_STATE;
1677    timerId = XtAppAddTimeOut(XtWidgetToApplicationContext(widget),
1678                              idleTimeoutLength,
1679                              (XtTimerCallbackProc)TimerEvent,
1680                              (XtPointer)widget);
1681 }
1682
1683
1684
1685
1686 /************************************************************************
1687  ************************************************************************
1688  *
1689  *  Externed Type to String Converters and writers
1690  *
1691  ************************************************************************
1692  ************************************************************************/
1693
1694 void
1695 _DtIntToString(
1696         int fd,
1697         int *value,
1698         char *out_buf )
1699
1700 {
1701    (void) sprintf (resourceBuf, "%d", *value);
1702    _DtStringToString( fd, &resourceBuf, out_buf );
1703 }
1704
1705
1706 void
1707 _DtShortToString(
1708         int fd,
1709         short *value,
1710         char *out_buf )
1711
1712
1713 {
1714    (void) sprintf (resourceBuf, "%d", *value);
1715    _DtStringToString( fd, &resourceBuf, out_buf );
1716 }
1717
1718
1719
1720 void
1721 _DtPositionToString(
1722         int fd,
1723         Position *value,
1724         char *out_buf )
1725
1726 {
1727    (void) sprintf (resourceBuf, "%d", *value);
1728    _DtStringToString( fd, &resourceBuf, out_buf );
1729 }
1730
1731
1732
1733 void
1734 _DtDimensionToString(
1735         int fd,
1736         Dimension *value,
1737         char *out_buf )
1738
1739 {
1740    (void) sprintf (resourceBuf, "%d", *value);
1741    _DtStringToString( fd, &resourceBuf, out_buf );
1742 }
1743
1744
1745
1746 void
1747 _DtBooleanToString(
1748         int fd,
1749         Boolean *value,
1750         char *out_buf )
1751
1752 {
1753    char * buf;
1754
1755    if (*value == True)
1756       buf = "True";
1757    else
1758       buf = "False";
1759    _DtStringToString( fd, (char **)&buf, out_buf );
1760 }
1761
1762
1763 void
1764 _DtXmStringToString(
1765         int fd,
1766         XmString *value,
1767         char *out_buf )
1768
1769 {
1770    char *out_value = NULL;
1771
1772    if (*value != NULL)
1773    {
1774        out_value = (char *) _XmStringUngenerate(*value, XmFONTLIST_DEFAULT_TAG,
1775                                                 XmCHARSET_TEXT, XmCHARSET_TEXT);
1776        if ( out_value != NULL)
1777        {
1778            if (strlen (out_value) != 0)
1779            {
1780                (void) write (fd, out_value, strlen (out_value));
1781                _DtStringToString( fd, &out_value, out_buf );
1782
1783                XtFree ((char *) out_value);
1784            }
1785        }
1786    }
1787 }
1788
1789
1790 void
1791 _DtXmStringTableToString(
1792         int fd,
1793         XmStringTable *value,
1794         char *out_buf )
1795
1796 {
1797    int i;
1798    char *out_value = NULL;
1799    Boolean first = True;
1800
1801    if ((value != NULL) && (*value != NULL))
1802    {
1803       i = 0;
1804       while ((*value)[i] != NULL)
1805       {
1806           out_value = (char *)_XmStringUngenerate((*value)[i],
1807                                                   XmFONTLIST_DEFAULT_TAG,
1808                                                   XmCHARSET_TEXT, XmCHARSET_TEXT);
1809           if ( out_value != NULL)
1810           {
1811               if (first)
1812               {
1813                   (void) write (fd, out_buf, strlen (out_buf));
1814                   first = False;
1815               }
1816               else
1817                   (void) write (fd, ", ", strlen (", "));
1818
1819               (void) write (fd, out_value, strlen (out_value));
1820
1821               XtFree ((char *) out_value);
1822               out_value = NULL;
1823           }
1824
1825           i++;
1826       }
1827
1828       if (first == False)
1829           (void) write (fd, "\n", strlen ("\n"));
1830    }
1831 }
1832
1833
1834 void
1835 _DtStringToString(
1836         int fd,
1837         char **value,
1838         char *out_buf )
1839
1840 {
1841    if (*value == NULL || strlen (*value) == 0)
1842       ;
1843    else
1844    {
1845       (void) write (fd, out_buf, strlen (out_buf));
1846       (void) write (fd, *value, strlen (*value));
1847       (void) write (fd, "\n", strlen ("\n"));
1848    }
1849 }
1850
1851
1852 /*
1853  * _DtChildPosition:
1854  *   Choose a position for a popup window ("child") so that the main
1855  *   window ("parent") is not obscured.  The child will be positioned
1856  *   to the right, below, left, or above the parent, depending on where
1857  *   there is the most space.
1858  */
1859
1860 void
1861 _DtChildPosition(
1862          Widget w,
1863          Widget parent,
1864          Position *newX,
1865          Position *newY)
1866 {
1867    Position pY, pX;
1868    XmVendorShellExtObject vendorExt;
1869    XmWidgetExtData        extData;
1870    int xOffset, yOffset;
1871    int pHeight, myHeight, sHeight;
1872    int pWidth, myWidth, sWidth;
1873    enum { posRight, posBelow, posLeft, posAbove } pos;
1874    int space;
1875
1876    /* get x, y offsets for the parent's window frame */
1877    extData = _XmGetWidgetExtData(parent, XmSHELL_EXTENSION);
1878    if (extData)
1879    {
1880      vendorExt = (XmVendorShellExtObject)extData->widget;
1881      xOffset = vendorExt->vendor.xOffset;
1882      yOffset = vendorExt->vendor.yOffset;
1883    }
1884    else
1885      xOffset = yOffset = 0;
1886
1887    /* get size/position of screen, parent, and widget */
1888    sHeight = HeightOfScreen(XtScreen(parent));;
1889    sWidth = WidthOfScreen(XtScreen(parent));
1890    pX = XtX(parent) - xOffset;
1891    pY = XtY(parent) - yOffset;
1892    pHeight = XtHeight(parent) + yOffset + xOffset;
1893    pWidth = XtWidth(parent) + 2*xOffset;
1894    myHeight = XtHeight(w) + yOffset + xOffset;
1895    myWidth = XtWidth(w) + 2*xOffset;
1896
1897    /*
1898     * Determine how much space would be left if the child was positioned
1899     * to the right, below, left, or above the parent.  Choose the child
1900     * positioning so that the maximum space is left.
1901     */
1902    pos = posRight;
1903    space = sWidth - (pX + pWidth + myWidth);
1904
1905    if (sHeight - (pY + pHeight + myHeight) > space)
1906    {
1907       pos = posBelow;
1908       space = sHeight - (pY + pHeight + myHeight);
1909    }
1910
1911    if (pX - myWidth > space)
1912    {
1913       pos = posLeft;
1914       space = pX - myWidth;
1915    }
1916
1917    if (pY - myHeight > space)
1918    {
1919       pos = posAbove;
1920       space = pY - myHeight;
1921    }
1922
1923    /* Given relative positioning, determine x, y coordinates for the child */
1924
1925    switch (pos)
1926    {
1927      case posRight:
1928        *newX = pX + pWidth + 5;
1929        *newY = pY + (pHeight - myHeight)/2;
1930        break;
1931
1932      case posBelow:
1933        *newX = pX + (pWidth - myWidth)/2;
1934        *newY = pY + pHeight + 5;
1935        break;
1936
1937      case posLeft:
1938        *newX = pX - myWidth - 5;
1939        *newY = pY + (pHeight - myHeight)/2;
1940        break;
1941
1942      case posAbove:
1943        *newX = pX + (pWidth - myWidth)/2;
1944        *newY = pY - myHeight - 5;
1945        break;
1946    }
1947
1948    /*
1949     * The above calculations may put the dialog offscreen so one
1950     * last check must be made.  One way this can happen is if the
1951     * parent has been resized to fill almost the entire screen.
1952     * This can also happen if the parent has been maximized
1953     * and the window manager has its 'positionOnScreen' resource
1954     * set to False.
1955     */
1956    if ((*newX >= (sWidth -  10)) || (*newX < 0))
1957       *newX = sWidth - myWidth + 5;
1958    if ((*newY >= (sHeight - 10)) || (*newY < 0))
1959       *newY = (sHeight - myHeight) / 2;
1960
1961 }
1962
1963
1964 /* ARGSUSED */
1965 void
1966 _DtmapCB(
1967          Widget w,
1968          XtPointer client_data,
1969          XtPointer call_data )
1970 {
1971    Arg         args[2];
1972    Widget      parent;
1973    Position newX, newY;
1974
1975    parent = (Widget)client_data;
1976
1977    if (parent)
1978    {
1979       _DtChildPosition(w, parent, &newX, &newY);
1980       XtSetArg(args[0], XmNx, newX);
1981       XtSetArg(args[1], XmNy, newY);
1982       XtSetValues(w, args, 2);
1983    }
1984 }
1985
1986
1987 /************************************************************************
1988  *
1989  *  _DtBuildDialog
1990  *      This functions is used to build an instance of a dialog with
1991  *      the provided data but not display it.  The functions and data
1992  *      to be set back to the application upon change or close of the
1993  *      dialog is also provided as parameters.
1994  *
1995  ************************************************************************/
1996
1997 void
1998 _DtBuildDialog(
1999         Widget parent,
2000         Widget map_parent,
2001         XtPointer top_rec,
2002         DialogData *dialog_data,
2003         DialogChangedProc change_proc,
2004         XtPointer change_data,
2005         DialogClosedProc close_proc,
2006         XtPointer close_data,
2007         char *workspaces,
2008         Boolean iconify_state,
2009         Boolean ignoreCache,
2010         char * title,
2011         XClassHint * classHints )
2012
2013 {
2014    Dialog * dialog;
2015    int dialog_type, n;
2016    DialogInstanceData * instance_data;
2017    char geometry[40];
2018    Arg args[5];
2019    Boolean doCenter = False;
2020    Boolean doParentRelativePositioning = False;
2021    int availableDialogCount;
2022
2023
2024    /*  See if there is a cached, unused dialog of the correct type.  */
2025
2026    dialog_type = dialog_data->type;
2027    dialog = NULL;
2028
2029    if (!ignoreCache)
2030    {
2031       Dialog * availableDialog;
2032
2033       availableDialog = class_set[dialog_type].dialog_list;
2034       availableDialogCount = 0;
2035
2036       /*
2037        * In addition to looking for an available dialog in the cache to use,
2038        * we also want to count up the number of unused dialogs in the cache.
2039        * This lets us know it we need to restart the timer, to again build
2040        * up the cache.
2041        */
2042       while (availableDialog != NULL)
2043       {
2044          if (availableDialog->in_use == False)
2045          {
2046             if (dialog == NULL)
2047                dialog = availableDialog;
2048             else
2049                availableDialogCount++;
2050          }
2051          availableDialog = availableDialog->next;
2052       }
2053    }
2054
2055    if (dialog == NULL)
2056    {
2057       dialog = (Dialog *) XtMalloc (sizeof (Dialog));
2058
2059       (*(class_set[dialog_type].class->create))
2060          (XtDisplay (encap_parent_shell), encap_parent_shell,
2061          &(dialog->dialog_widget), &dialog->dialog);
2062
2063       /*  Add the change and close callbacks into the dialog  */
2064
2065       if (class_set[dialog_type].class->install_change_callback)
2066          (*(class_set[dialog_type].class->install_change_callback))
2067             (dialog->dialog, DataChangeCallback, (XtPointer)dialog);
2068
2069       if (class_set[dialog_type].class->install_close_callback)
2070          (*(class_set[dialog_type].class->install_close_callback))
2071             (dialog->dialog, DataCloseCallback, (XtPointer)dialog);
2072
2073       dialog->next = class_set[dialog_type].dialog_list;
2074       class_set[dialog_type].dialog_list = dialog;
2075    }
2076
2077    /*
2078     * Set pointer to top dialog data in child of the shell.
2079     * This is needed to get help to work.
2080     */
2081    if (top_rec == NULL)
2082       top_rec = dialog->dialog;
2083    XtSetArg(args[0], XmNuserData, top_rec);
2084    XtSetValues(dialog->dialog_widget, args, 1);
2085
2086    /*  Set the dialog structure fields to the parameter data.  */
2087
2088    dialog->in_use = True;
2089    dialog->dialog_data = dialog_data;
2090    dialog->change = change_proc;
2091    dialog->change_client_data = change_data;
2092    dialog->close = close_proc;
2093    dialog->close_client_data = close_data;
2094
2095    /* If a special title has been specified, we need to set it now */
2096    if (title)
2097    {
2098       XtSetArg(args[0], XmNtitle, title);
2099       XtSetValues(XtParent(dialog->dialog_widget), args, 1);
2100    }
2101 }
2102
2103
2104 /************************************************************************
2105  *
2106  *  _DtShowBuiltDialog
2107  *      This functions is used to display an instance of a dialog which
2108  *      has already been built with _DtBuildDialog.
2109  *
2110  ************************************************************************/
2111
2112 void
2113 _DtShowBuiltDialog(
2114         Widget parent,
2115         Widget map_parent,
2116         DialogData *dialog_data,
2117         char *workspaces,
2118         Boolean iconify_state,
2119         XClassHint * classHints )
2120
2121 {
2122    Dialog * dialog;
2123    int dialog_type, n;
2124    DialogInstanceData * instance_data;
2125    char geometry[40];
2126    Arg args[5];
2127    Boolean doCenter = False;
2128    Boolean doParentRelativePositioning = False;
2129    int availableDialogCount;
2130
2131
2132    dialog_type = dialog_data->type;
2133
2134    /*  Find the dialog */
2135    dialog = class_set[dialog_data->type].dialog_list;
2136    while (dialog != NULL)
2137    {
2138       if (dialog->dialog_data == dialog_data)
2139          break;
2140       else
2141          dialog = dialog->next;
2142    }
2143
2144    /* Need to add the map callback in relation to the parent */
2145    if (class_set[dialog_type].class->map)
2146    {
2147       /*
2148        * The map_parent parameter gives us the ability to position
2149        * the dialog relative to a window which is not the transientFor
2150        * parent.  This is used for the audio preview dialog.
2151        */
2152       if (map_parent == NULL)
2153          map_parent = parent;
2154
2155       (*(class_set[dialog_type].class->map)) (map_parent, dialog->dialog);
2156    }
2157
2158    instance_data = (DialogInstanceData *) dialog_data->data;
2159
2160    /*  If this is a top level shell, get it realized  */
2161    if (XtIsSubclass (XtParent (dialog->dialog_widget),
2162                      applicationShellWidgetClass))
2163    {
2164       if (XtIsRealized (XtParent (dialog->dialog_widget)) == False)
2165       {
2166          if (instance_data->displayed == True)
2167          {
2168             (void) sprintf (geometry, "=%dx%d+%d+%d",
2169                             instance_data->width, instance_data->height,
2170                             instance_data->x, instance_data->y);
2171
2172             XtSetArg (args[0], XmNgeometry, geometry);
2173             XtSetValues (XtParent (dialog->dialog_widget), args, 1);
2174          }
2175          else if ((instance_data->width != 0) && (instance_data->height != 0))
2176          {
2177             n=0;
2178             XtSetArg (args[n], XmNwidth, instance_data->width); n++;
2179             XtSetArg (args[n], XmNheight, instance_data->height); n++;
2180             XtSetValues (XtParent (dialog->dialog_widget), args, n);
2181          }
2182
2183          /* Toggle mappedWhenManaged to false */
2184          XtSetMappedWhenManaged(XtParent (dialog->dialog_widget), False);
2185          XtRealizeWidget (XtParent(dialog->dialog_widget));
2186
2187          /* Set the proper workspaces if needed */
2188          _DtEncapSetWorkSpaceHints(XtParent(dialog->dialog_widget), workspaces);
2189
2190          /* Set any application-specified class hints for the window */
2191          if (classHints)
2192          {
2193             XSetClassHint(XtDisplay(dialog->dialog_widget),
2194                           XtWindow(XtParent(dialog->dialog_widget)),
2195                           classHints);
2196          }
2197
2198          /* Set the iconify state */
2199          SetIconifyState(XtParent(dialog->dialog_widget), iconify_state);
2200
2201          /* Map the window */
2202          XtSetMappedWhenManaged(XtParent (dialog->dialog_widget), True);
2203          XtPopup (XtParent (dialog->dialog_widget), XtGrabNone);
2204          XSync(XtDisplay(dialog->dialog_widget), False);
2205
2206       }
2207       else
2208       {
2209          if (instance_data->displayed == True)
2210          {
2211             WMShellWidget wm = (WMShellWidget)XtParent(dialog->dialog_widget);
2212
2213             wm->wm.size_hints.flags |= USPosition;
2214             XtSetArg (args[0], XmNx, instance_data->x);
2215             XtSetArg (args[1], XmNy, instance_data->y);
2216             XtSetArg (args[2], XmNwidth, instance_data->width);
2217             XtSetArg (args[3], XmNheight, instance_data->height);
2218             XtSetValues (XtParent (dialog->dialog_widget), args, 4);
2219          }
2220          else if ((instance_data->width != 0) && (instance_data->height != 0))
2221          {
2222             n=0;
2223             XtSetArg (args[n], XmNwidth, instance_data->width); n++;
2224             XtSetArg (args[n], XmNheight, instance_data->height); n++;
2225             XtSetValues (XtParent (dialog->dialog_widget), args, n);
2226          }
2227
2228          /* Set the proper workspaces if needed */
2229          _DtEncapSetWorkSpaceHints(XtParent(dialog->dialog_widget), workspaces);
2230
2231          /* Set any application-specified class hints for the window */
2232          if (classHints)
2233          {
2234             XSetClassHint(XtDisplay(dialog->dialog_widget),
2235                           XtWindow(XtParent(dialog->dialog_widget)),
2236                           classHints);
2237          }
2238
2239          /* Set the iconify state */
2240          SetIconifyState(XtParent(dialog->dialog_widget), iconify_state);
2241
2242          /* Map the window */
2243          XtPopup (XtParent (dialog->dialog_widget), XtGrabNone);
2244       }
2245    }
2246    else
2247    {
2248       if (instance_data->displayed == True)
2249       {
2250          XtSetArg (args[0], XmNx, instance_data->x);
2251          XtSetArg (args[1], XmNy, instance_data->y);
2252          XtSetArg (args[2], XmNwidth, instance_data->width);
2253          XtSetArg (args[3], XmNheight, instance_data->height);
2254          XtSetArg (args[4], XmNdefaultPosition, False);
2255          XtSetValues (dialog->dialog_widget, args, 5);
2256          XtRealizeWidget (dialog->dialog_widget);
2257       }
2258       else
2259       {
2260          XtSetArg (args[0], XmNdefaultPosition, False);
2261          XtSetValues (dialog->dialog_widget, args, 1);
2262
2263          XtRealizeWidget (dialog->dialog_widget);
2264
2265          if (parent)
2266          {
2267             /* Position relative to the parent dialog */
2268             /*
2269              * Must be done after the set_values call, since the dialog
2270              * may get forced to a different size.
2271              */
2272             doParentRelativePositioning = True;
2273          }
2274          else
2275          {
2276             /* Center in the display */
2277             /*
2278              * Must be done after the set_values call, since the dialog
2279              * may get forced to a different size.
2280              */
2281             doCenter = True;
2282          }
2283       }
2284
2285       /*
2286        * Dialogs with no controlling parent window, need to have their
2287        * own workspace perperty set, if some workspaces have been requested.
2288        */
2289       if ((parent == NULL) && workspaces)
2290          _DtEncapSetWorkSpaceHints(XtParent(dialog->dialog_widget), workspaces);
2291    }
2292
2293
2294    /*  Set Values onto the dialog to set it to the correct data.  */
2295
2296    (*(class_set[dialog_data->type].class->set_values))
2297       (dialog->dialog, dialog_data->data);
2298
2299    /*
2300     * These two adjustments MUST be done AFTER the dialog's SetValues()
2301     * procedure is called.  This is due to the fact that the setvalues
2302     * may cause the dialog size to change, and since both of the following
2303     * positioning algorithms are dependent upon the dialog size, we want
2304     * to make sure that the correct size is used.
2305     */
2306    if (doCenter)
2307    {
2308       XtSetArg (args[0], XmNx,
2309           (Dimension)(WidthOfScreen(XtScreen(dialog->dialog_widget)) -
2310            dialog->dialog_widget->core.width) / (Dimension)2);
2311       XtSetArg (args[1], XmNy,
2312           (Dimension)(HeightOfScreen(XtScreen(dialog->dialog_widget)) -
2313            dialog->dialog_widget->core.height) / (Dimension)2);
2314       XtSetValues (dialog->dialog_widget, args, 2);
2315    }
2316    else if (doParentRelativePositioning)
2317    {
2318       XtSetArg (args[0], XmNx,
2319           parent->core.x +
2320           (Dimension)(parent->core.width - dialog->dialog_widget->core.width) / (Dimension)2);
2321       XtSetArg (args[1], XmNy,
2322           parent->core.y +
2323           (Dimension)(parent->core.height - dialog->dialog_widget->core.height) / (Dimension)2);
2324       XtSetValues (XtParent(dialog->dialog_widget), args, 2);
2325    }
2326
2327
2328    /*  Fix up the transient-for windowing information so that  */
2329    /*  the window manager will shuffle and iconify as a group  */
2330
2331    if (parent != NULL)
2332    {
2333       if (XtIsRealized(parent))
2334       {
2335          XSetTransientForHint (XtDisplay (parent),
2336                             XtWindow (XtParent (dialog->dialog_widget)),
2337                             XtWindow (parent));
2338       }
2339    }
2340    else
2341    {
2342       if (!XtIsSubclass (XtParent (dialog->dialog_widget),
2343                                      applicationShellWidgetClass))
2344       {
2345          XSetTransientForHint (XtDisplay (encap_parent_shell),
2346                             XtWindow (XtParent (dialog->dialog_widget)),
2347                             XtWindow (encap_parent_shell));
2348       }
2349    }
2350
2351
2352    /*  Display the dialogs, application shells are displayed above.  */
2353
2354    if (!(XtIsSubclass (XtParent (dialog->dialog_widget),
2355                        applicationShellWidgetClass)))
2356    {
2357       XtManageChild (dialog->dialog_widget);
2358    }
2359
2360
2361    /*  Set the dialog instance data to indicate that the dialog  */
2362    /*  is displayed.                                             */
2363
2364    ((DialogInstanceData *) (dialog_data->data))->displayed = True;
2365
2366
2367    /* Give the dialog a chance to set its focus widget, if necessary */
2368
2369    if (class_set[dialog_data->type].class->set_focus)
2370    {
2371       (*(class_set[dialog_data->type].class->set_focus))
2372          (dialog->dialog, dialog_data->data);
2373    }
2374 }
2375
2376
2377
2378 static void
2379 DialogStructureNotifyHandler(
2380        Widget w,
2381        XtPointer client_data,
2382        XEvent *event )
2383 {
2384   if( event->type == MapNotify )
2385   {
2386     if( NumberOfDialogMapped == 0 )
2387     {
2388       int timeOut;
2389
2390       if( timerState == TIMER_STARTUP_STATE )
2391         timeOut = initialTimeoutLength;
2392       else if( timerState == TIMER_ACTIVE_STATE )
2393         timeOut = activeTimeoutLength;
2394       else if( timerState == TIMER_IDLE_STATE )
2395         timeOut = idleTimeoutLength;
2396       else
2397         timeOut = 0;
2398
2399       if( timeOut )
2400       {
2401         if( timerId )
2402           XtRemoveTimeOut( timerId );
2403
2404         timerId = XtAppAddTimeOut( XtWidgetToApplicationContext( w ),
2405                                    timeOut,
2406                                    (XtTimerCallbackProc)TimerEvent,
2407                                    (XtPointer)w );
2408       }
2409     }
2410     ++NumberOfDialogMapped;
2411   }
2412   else if( event->type == UnmapNotify )
2413   {
2414     if( NumberOfDialogMapped )
2415       --NumberOfDialogMapped;
2416
2417     if( NumberOfDialogMapped == 0 )
2418     {
2419       if( timerId )
2420       {
2421         XtRemoveTimeOut( timerId );
2422         timerId = 0;
2423       }
2424     }
2425   }
2426 }
2427
2428
2429 void
2430 _DtChangeTo(
2431          XtPointer client_data,
2432          char  *directory)
2433 {
2434    Dialog * dialog = (Dialog *) client_data;
2435
2436    ChangeDirectoryToParent(dialog->change_client_data, directory);
2437 }
2438
2439 void
2440 _DtFreeDialog(
2441          DialogData  *dialog_data)
2442 {
2443    Dialog *dialog,**headptr;
2444    headptr = &class_set[dialog_data->type].dialog_list;
2445    dialog = *headptr;
2446
2447    while (dialog != NULL)
2448    {
2449       if (dialog->dialog_data == dialog_data)
2450       {
2451         *headptr = dialog->next;
2452         XtFree((char *) dialog);
2453         break;
2454       }
2455       headptr = &(dialog->next);
2456       dialog = *headptr;
2457    }
2458 }
2459