dtwm: Change to ANSI function definitions
[oweals/cde.git] / cde / programs / dtwm / Session.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these libraries and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /************************************************************************
24  *
25  *  File:        Session.c
26  *
27  *  Project:     CDE
28  *
29  *  Description: This file contains the session management code for the
30  *               CDE front panel.
31  *
32  * (c) Copyright 1993, 1994 Hewlett-Packard Company
33  * (c) Copyright 1993, 1994 International Business Machines Corp.
34  * (c) Copyright 1993, 1994 Sun Microsystems, Inc.
35  * (c) Copyright 1993, 1994 Unix System Labs, Inc., a subsidiary of Novell, Inc.
36  *
37  ************************************************************************/
38
39 #include <Dt/WsmP.h>
40
41 #include <Dt/Control.h>
42 #include <Dt/ControlP.h>
43
44 #include "DataBaseLoad.h"
45
46
47 #include <pwd.h>
48 #include <fcntl.h>
49 #include <sys/stat.h>
50 #include <dirent.h>
51
52
53
54 extern void ToggleDefaultControl(ControlData *, SubpanelData *, ControlData *);
55 extern Boolean CheckOtherMonitorsOn(SubpanelData *);
56
57
58
59 /*  This define is used as the file name and location of the session  */
60 /*  file needed by the front panel to store its across session data.  */
61
62 static char * SESSION_FILE = "/.dt/sessions/dtwmfp.session";
63 static char * TYPES_DIR = "/.dt/types/fp_dynamic/";
64
65
66 extern String unpost_arrow_image;
67 extern String unpost_monitor_arrow_image;
68
69 #define MAX_PATH        1024
70
71
72 /************************************************************************
73  *
74  *  SessionFileGetName
75  *      Generate the name of the session file to be used to read and
76  *      write the front panel session information.
77  *
78  ************************************************************************/
79  
80 static char *
81 SessionFileGetName (void)
82 {
83    char * home_dir;
84    char * file_name;
85    struct passwd * pw_info;
86    
87
88    /*  Get the home directory used to build the path to the session file.  */
89
90    if ((home_dir = (char *)getenv("HOME")) != NULL || strlen (home_dir) == 0)
91    {
92       pw_info = getpwuid (getuid());
93       home_dir = pw_info->pw_dir;
94    }
95
96    file_name = XtMalloc (strlen (home_dir) + strlen (SESSION_FILE) + 1);
97    sprintf (file_name, "%s%s", home_dir, SESSION_FILE);
98    
99    return (file_name);
100 }
101
102
103
104
105 /************************************************************************
106  *
107  *  SessionRestoreData
108  *      This function reads the front panels session file and applies
109  *      the data to the already created front panel.
110  *
111  ************************************************************************/
112
113 void
114 SessionRestoreData (void)
115 {
116    FILE * fd;
117
118    char * session_file;
119    
120    BoxData * box_data;
121    ControlData * control_data;
122
123    SubpanelData ** subpanel_data = NULL;
124    int subpanel_count = 0;
125    int max_subpanel_count = 0;
126    
127    int subpanel_posted_count = 0;
128    int subpanel_default_count = 0;
129
130    char name_buffer1[256];
131    char name_buffer2[256];
132    char name_buffer3[256];
133
134    struct stat stat_info;
135
136    int     parent_component_type;
137    int     component_type;
138    int     delete_value;
139    Boolean delete;
140
141    int dynamic_data_count;
142    
143    int subpanel_x;
144    int subpanel_y;
145    int subpanel_torn;
146
147    DtWmHints vHints;
148    
149    Boolean have_it;
150    
151    Dimension width;
152    Dimension new_width;
153    Widget    parent;
154    
155    int mapped;
156
157    int i, j, k, l;
158    Arg al[2];
159
160    
161    session_file = SessionFileGetName ();
162
163
164    if ((fd = fopen (session_file, "r")) != NULL)
165    {
166       /*  Get the full list of subpanels  */
167       
168       for (i = 0; i < panel.box_data_count; i++)
169       {
170          box_data = panel.box_data[i];
171          
172          for (j = 0; j < box_data->control_data_count; j++)
173          {
174             control_data = box_data->control_data[j];
175             
176             if (control_data->subpanel_data != NULL)
177             {
178                if (subpanel_count == max_subpanel_count)
179                {
180                   max_subpanel_count += 10;
181                   subpanel_data = (SubpanelData **)
182                     XtRealloc ((char *) subpanel_data, 
183                                sizeof (SubpanelData **) * max_subpanel_count);
184                }
185
186                subpanel_data[subpanel_count] = control_data->subpanel_data;
187                subpanel_count++;
188             }
189          }
190       }
191
192
193       /*  Get the count of the number of subpanels to be posted.  */
194
195       fscanf (fd, "%d", &subpanel_posted_count);         
196
197
198       /*  If the count is greater than 0, read in the list of subpanel  */
199       /*  names, compare them with the list of subpanels and post the   */
200       /*  appropriate ones.                                             */
201          
202       for (i = 0; i < subpanel_posted_count; i++)
203       {
204          fscanf (fd, "%s%d%d%d", 
205                  name_buffer1, &subpanel_x, &subpanel_y, &subpanel_torn);
206             
207          for (j = 0; j < subpanel_count; j++)
208          {
209             if (strcmp (name_buffer1,
210                         subpanel_data[j]->
211                         element_values[SUBPANEL_NAME].parsed_value) == 0)
212             {
213                /*  If the subpanel is torn, modify the window manager    */
214                /*  behavior hints so that it can be positioned properly  */
215                /*  and does not slide up.                                */
216                
217                if (subpanel_torn != 0)
218                {
219                   subpanel_data[j]->torn = True;
220
221                   vHints.flags = 
222                      DtWM_HINTS_BEHAVIORS | DtWM_HINTS_ATTACH_WINDOW;
223                   vHints.behaviors = 
224                      DtWM_BEHAVIOR_PANEL | DtWM_BEHAVIOR_SUBPANEL | 
225                                            DtWM_BEHAVIOR_SUB_RESTORED;
226                   vHints.attachWindow = XtWindow (panel.shell);
227
228                   _DtWsmSetDtWmHints (XtDisplay (panel.shell),
229                                       XtWindow (subpanel_data[j]->shell), 
230                                       &vHints);
231                }
232
233
234                /*  Manage and position the form and shell of the subpanel  */
235                /*  Note: this is a close copy of the ArrowCB posting       */
236                /*  function logic.                                         */
237                
238                XtSetMappedWhenManaged (subpanel_data[j]->shell, False);
239                XtManageChild (subpanel_data[j]->form);
240
241                XtSetArg (al[0], XmNx, subpanel_x);
242                XtSetArg (al[1], XmNy, subpanel_y);
243                XtSetValues (subpanel_data[j]->form, al, 2);
244
245                XtManageChild (subpanel_data[j]->shell);
246                XtSetMappedWhenManaged (subpanel_data[j]->shell, True);
247
248                if (!CheckOtherMonitorsOn(subpanel_data[j]))
249                   XtSetArg (al[0], XmNimageName, unpost_arrow_image);
250                else
251                   XtSetArg (al[0], XmNimageName, unpost_monitor_arrow_image);
252                XtSetValues(subpanel_data[j]->parent_control_data->arrow, al, 1);
253             }
254          }
255       }  
256
257
258       /*  Get the count of the number of subpanel controls to be  */
259       /*  toggled into the main panel.                            */
260          
261       fscanf (fd, "%d", &subpanel_default_count);
262
263
264       /*  If the count is greater than 0, read in the list of subpanel  */
265       /*  names, and control_names and compare them with the list of    */
266       /*  subpanels and their controls.  Toggle the proper control.     */
267
268       for (i = 0; i < subpanel_default_count; i++)
269       {
270          fscanf (fd, "%s%s", name_buffer1, name_buffer2);
271             
272          for (j = 0; j < subpanel_count; j++)
273          {
274             if (strcmp (name_buffer1,
275                         subpanel_data[j]->
276                         element_values[SUBPANEL_NAME].parsed_value) == 0)
277             {
278                for (k = 0; k < subpanel_data[j]->control_data_count; k++)
279                {
280                   if (strcmp (name_buffer2,
281                               subpanel_data[j]->control_data[k]->
282                               element_values[CONTROL_NAME].parsed_value) == 0)
283                   {
284                      /*  use the difference in width of the old and new  */
285                      /*  main controls to adjust the parent form.  This  */
286                      /*  should not be necessary but form is buggy.      */
287
288                      width = XtWidth(subpanel_data[j]->parent_control_data->icon);
289
290                      ToggleDefaultControl(subpanel_data[j]->parent_control_data,
291                                           subpanel_data[j],
292                                           subpanel_data[j]->control_data[k]);
293
294                      new_width = XtWidth (subpanel_data[j]->parent_control_data->icon);
295
296                      parent = XtParent (subpanel_data[j]->parent_control_data->icon);
297                      XtSetArg (al[0], XmNwidth, XtWidth (parent) + new_width - width);
298                      XtSetValues (parent, al, 1);
299                   }
300                }
301             }
302          }
303       }  
304
305    
306       /*  Read in the count of the number of dynamic component records  */
307       
308       fscanf (fd, "%d", &panel.dynamic_data_count);
309       panel.max_dynamic_data_count = panel.dynamic_data_count;
310
311       if (panel.dynamic_data_count > 0) {
312         panel.dynamic_data_list = (DynamicComponent **)
313           XtMalloc (sizeof (DynamicComponent **) * panel.max_dynamic_data_count);
314       }
315
316       dynamic_data_count = 0;
317       
318
319       /*  Loop through and read all of the records  */
320       
321       for (i = 0; i < panel.dynamic_data_count; i++)
322       {
323          fscanf(fd, "%s%s%d%s%d%d", name_buffer1, name_buffer2, &component_type,
324                 name_buffer3, &parent_component_type, &delete_value);
325
326
327          /*  Stat the file name to see if it still exists.  If not,    */
328          /*  continue at the next iteration of the loop.  This has     */
329          /*  the effect of not putting the data into the dynamic list  */
330          /*  so that it will not be written on the next shutdown.      */
331          
332          if (lstat (name_buffer1, &stat_info) != 0)
333             continue;
334
335
336          delete = False;
337          if (delete_value == 1) delete = True;
338
339
340          /*  Loop through the subpanels and verify that each of the    */
341          /*  records matches component within the hierarchy.  If not,  */
342          /*  do not put the record in the list.                        */
343       
344          for (j = 0; j < subpanel_count; j++)
345          {
346             have_it = False;
347             
348
349             /*  If the data is a reference to a deleted component, put   */
350             /*  it in the list.  If it is a subpanel, verify that there  */
351             /*  is a subpanel of that name and a main control parent of  */
352             /*  the correct name.  If it is a control, reloop through    */
353             /*  the subpanel set a look for a control which matches the  */
354             /*  name and a subpanel which matches the parent name.       */
355
356             if (delete)
357                have_it = True;
358             else if (component_type == SUBPANEL && 
359                      strcmp (subpanel_data[j]->
360                              element_values[SUBPANEL_NAME].parsed_value,
361                              name_buffer2) == 0 &&
362                      strcmp (subpanel_data[j]->
363                              element_values[SUBPANEL_CONTAINER_NAME].parsed_value,
364                              name_buffer3) == 0)
365             {
366                have_it = True;
367             }
368             else
369             {
370                if (parent_component_type == SUBPANEL)
371                {
372                   for (k = 0; k < subpanel_count; k++)
373                   {
374                      if (strcmp (subpanel_data[k]->
375                          element_values[SUBPANEL_NAME].parsed_value,
376                          name_buffer3) == 0)
377                      {
378                         for (l = 0; l < subpanel_data[k]->control_data_count; l++)
379                         {
380                            if (strcmp (subpanel_data[k]->control_data[l]->
381                                element_values[CONTROL_NAME].parsed_value,
382                                name_buffer2) == 0)
383                            {
384                               have_it = True;
385                               break;
386                            }
387                         }
388                      }
389
390                      if (have_it) 
391                         break;
392                   }
393                }
394                else if (parent_component_type == BOX)
395                {
396                   for (k = 0; k < panel.box_data_count; k++)
397                   {
398                      if (strcmp (panel.box_data[k]->
399                          element_values[BOX_NAME].parsed_value,
400                          name_buffer3) == 0)
401                      {
402                         for (l = 0; l < panel.box_data[k]->control_data_count; l++)
403                         {
404                            if (strcmp (panel.box_data[k]->control_data[l]->
405                                element_values[CONTROL_NAME].parsed_value,
406                                name_buffer2) == 0)
407                            {
408                               have_it = True;
409                               break;
410                            }
411                         }
412                      }
413
414                      if (have_it) 
415                         break;
416                   }
417                }
418             }       
419
420             if (have_it)
421             {
422                panel.dynamic_data_list[dynamic_data_count] = 
423                   (DynamicComponent *) XtMalloc (sizeof (DynamicComponent));
424
425                panel.dynamic_data_list[dynamic_data_count]->file_name = XtNewString (name_buffer1);
426                panel.dynamic_data_list[dynamic_data_count]->component_name = XtNewString (name_buffer2);
427                panel.dynamic_data_list[dynamic_data_count]->component_type = component_type;
428                panel.dynamic_data_list[dynamic_data_count]->parent_name = XtNewString (name_buffer3);
429                panel.dynamic_data_list[dynamic_data_count]->parent_type = parent_component_type;
430                panel.dynamic_data_list[dynamic_data_count]->delete = delete;
431
432                dynamic_data_count++;
433
434                break;
435             }
436          }
437       }
438
439       panel.dynamic_data_count = dynamic_data_count;
440
441    
442       /*  Read whether the front panel is iconic or not and set the  */
443       /*  hints on the shell appropriately.                          */
444       
445       if (fscanf (fd, "%d", &mapped) == 1)
446       {
447          if (mapped == 0)
448             XIconifyWindow (XtDisplay(panel.shell), XtWindow(panel.shell),
449                             XScreenNumberOfScreen (XtScreen (panel.shell)));
450       }
451
452       fclose (fd);
453    }
454
455
456    if (subpanel_data)
457       XtFree ((char *) subpanel_data); 
458
459    XtFree (session_file);
460 }
461
462
463
464
465
466 /************************************************************************
467  *
468  *  WmFPSessionSaveData
469  *      This function calculates and save the front panels session data
470  *      needed for the next restart.  It is called from the window manager
471  *      in its SaveResources function.
472  *
473  ************************************************************************/
474
475 void
476 WmFrontPanelSessionSaveData (void)
477 {
478    FILE * fd;
479
480    char * session_file;
481    Boolean written = False;
482    
483    BoxData * box_data;
484    ControlData * control_data;
485
486    SubpanelData ** subpanel_data = NULL;
487    int subpanel_count = 0;
488    int max_subpanel_count = 0;
489    
490    int subpanel_posted_count = 0;
491    int subpanel_default_count = 0;
492
493    XWindowAttributes window_attributes;
494
495    Arg al[2];
496
497    int i,j;
498
499
500    /*  Set the session file name and open the file  */
501
502    session_file = SessionFileGetName ();
503
504    if ((fd = fopen (session_file, "w")) != NULL)
505    {
506
507       /*  Get the full list of subpanels  */
508       
509       for (i = 0; i < panel.box_data_count; i++)
510       {
511          box_data = panel.box_data[i];
512          
513          for (j = 0; j < box_data->control_data_count; j++)
514          {
515             control_data = box_data->control_data[j];
516             
517             if (control_data->subpanel_data != NULL)
518             {
519                if (subpanel_count == max_subpanel_count)
520                {
521                   max_subpanel_count += 10;
522                   subpanel_data = (SubpanelData **)
523                     XtRealloc ((char *) subpanel_data, 
524                                sizeof (SubpanelData **) * max_subpanel_count);
525                }
526
527                subpanel_data[subpanel_count] = control_data->subpanel_data;
528
529                if (XtIsManaged (subpanel_data[subpanel_count]->shell))
530                   subpanel_posted_count++;
531
532                if (subpanel_data[subpanel_count]->default_control !=
533                    subpanel_data[subpanel_count]->parent_control_data)
534                   subpanel_default_count++;
535
536                subpanel_count++;
537             }
538          }
539       }
540        
541
542       /*  Save off the list of subpanels that are posted  */
543
544       fprintf (fd, "%d\n", subpanel_posted_count);
545
546       if (subpanel_posted_count > 0)
547       {
548          for (i = 0; i < subpanel_count; i++)
549          {
550             if (XtIsManaged (subpanel_data[i]->shell))
551                fprintf (fd, "%s %d %d %d\n",
552                          (char *) subpanel_data[i]->
553                          element_values[SUBPANEL_NAME].parsed_value,
554                          XtX (subpanel_data[i]->shell),
555                          XtY (subpanel_data[i]->shell),
556                          (int) subpanel_data[i]->torn);
557          }
558       }
559             
560
561       /*  Save off the controls that have been toggled from the  */
562       /*  subpanel into the main panel.                          */
563
564       fprintf (fd, "%d\n", subpanel_default_count);
565
566       if (subpanel_default_count > 0)
567       {
568          for (i = 0; i < subpanel_count; i++)
569          {
570             if (subpanel_data[i]->default_control !=
571                 subpanel_data[i]->parent_control_data)
572             {
573                fprintf (fd, "%s %s\n", 
574                           (char *) subpanel_data[i]->
575                                     element_values[SUBPANEL_NAME].parsed_value,
576                           (char *) subpanel_data[i]->default_control->
577                                     element_values[CONTROL_NAME].parsed_value);
578                
579             }
580          }
581       }
582
583    
584       /*  Save off the dynamic component information  */
585       
586       fprintf (fd, "%d\n", panel.dynamic_data_count);
587       
588       for (i = 0; i < panel.dynamic_data_count; i++)
589       {
590          fprintf (fd, "%s %s %d %s %d %d\n", 
591                   panel.dynamic_data_list[i]->file_name,
592                   panel.dynamic_data_list[i]->component_name,
593                   panel.dynamic_data_list[i]->component_type,
594                   panel.dynamic_data_list[i]->parent_name,
595                   panel.dynamic_data_list[i]->parent_type,
596                   (int) panel.dynamic_data_list[i]->delete);
597       }
598
599
600       /*  Save off whether the front panel is iconfied or not.  */
601       
602       XGetWindowAttributes (XtDisplay (panel.shell), XtWindow (panel.shell),
603                             &window_attributes);
604
605       if (window_attributes.map_state == IsUnmapped)
606          fprintf (fd, "%d\n", 0);
607       else
608          fprintf (fd, "%d\n", 1);
609
610       fflush (fd);
611       fclose (fd);
612    }
613
614
615    if (subpanel_data)
616       XtFree ((char *) subpanel_data);
617
618    XtFree (session_file);
619 }
620
621
622
623
624 /************************************************************************
625  *
626  *  SessionAddFileData
627  *      This function adds a new session file record to the list 
628  *      attached to panel.  It is called when a new control or 
629  *      subpanel is dynamically added.
630  *
631  *  Inputs: file_name - the name of the file the component is stored in
632  *          component_name - the value of the name field of the component
633  *          component_type - a value of CONTROL or SUBPANEL
634  *          parent_name - the container of the component
635  *          parent_type - a value of SUBPANEL or CONTROL
636  *          delete - a Boolean indicating whether the component has been
637  *                   deleted.  This requires special handling on startup.
638  *
639  ************************************************************************/
640
641 void
642 SessionAddFileData (char  * file_name,
643                     char  * component_name,
644                     int     component_type,
645                     char  * parent_name,
646                     int     parent_type,
647                     Boolean delete)
648
649
650 {
651    int count = panel.dynamic_data_count;
652
653    if (count == panel.max_dynamic_data_count)
654    {
655        panel.max_dynamic_data_count += 10;
656        panel.dynamic_data_list = (DynamicComponent **)
657           XtRealloc ((char *) panel.dynamic_data_list,
658              sizeof (DynamicComponent **) * panel.max_dynamic_data_count);
659    }
660
661    panel.dynamic_data_list[count] = 
662       (DynamicComponent *) XtMalloc (sizeof (DynamicComponent));
663
664    panel.dynamic_data_list[count]->file_name = XtNewString (file_name);
665    panel.dynamic_data_list[count]->component_name = XtNewString (component_name);
666    panel.dynamic_data_list[count]->component_type = component_type;
667    panel.dynamic_data_list[count]->parent_name = XtNewString (parent_name);
668    panel.dynamic_data_list[count]->parent_type = parent_type;
669    panel.dynamic_data_list[count]->delete = (int) delete;
670    panel.dynamic_data_count++;
671 }
672
673
674
675
676 /************************************************************************
677  *
678  *  SessionDeleteFileData
679  *      This function deletes a session file record from the list 
680  *      attached to panel.  It is called when a componentent is deleted
681  *      from the front panel.
682  *
683  *  Inputs: file_name - The name of the file containing the component
684  *          definition.  This is used to look up in the session list.
685  *
686  ************************************************************************/
687
688 void
689 SessionDeleteFileData (char * file_name)
690
691
692 {
693    int i, j;
694    
695
696    /*  Loop through the dynamic data list and find the matching record  */
697    /*  Free the data attached to the record and the record.  Then move  */
698    /*  the list up to fill the empty space.                             */
699    
700    for (i = 0; i < panel.dynamic_data_count; i++)
701    {
702       if (strcmp (file_name, panel.dynamic_data_list[i]->file_name) == 0)
703       {
704          XtFree ((char *) panel.dynamic_data_list[i]->file_name);
705          XtFree ((char *) panel.dynamic_data_list[i]->component_name);
706          XtFree ((char *) panel.dynamic_data_list[i]->parent_name);
707          XtFree ((char *) panel.dynamic_data_list[i]);
708          
709          for (j = i; j < panel.dynamic_data_count - 1; j++)
710             panel.dynamic_data_list[j] = panel.dynamic_data_list[j + 1];
711
712          panel.dynamic_data_count--;
713
714          break;
715       }
716    }
717 }
718
719
720
721
722 /************************************************************************
723  *
724  *  SessionFileNameLookup
725  *      This function locates and returns the name of a dynamic component
726  *      .fp file.
727  *
728  *  Inputs: component_name - the name of the dynamic component.
729  *          component_type - the type (CONTROL, SUBPANEL) of the component.
730  *          parent_name - the name of the container of the component.
731  *          parent_type - the type (SUBPANEL, CONTROL) of the parent.
732  *
733  *  Outputs: The file name of the dynamic component file or NULL if not found.
734  *
735  ************************************************************************/
736
737 char *
738 SessionFileNameLookup (char * component_name,
739                        int    component_type,
740                        char * parent_name,
741                        int    parent_type)
742
743
744 {
745    int i;
746    
747
748    /*  Loop through the dynamic data list and find the matching record  */
749    /*  Return the file name when found or NULL if not found             */
750    /*  the list up to fill the empty space.                             */
751    
752    for (i = 0; i < panel.dynamic_data_count; i++)
753    {
754       if (strcmp (component_name, 
755                   panel.dynamic_data_list[i]->component_name) == 0     &&
756           component_type == panel.dynamic_data_list[i]->component_type &&
757           strcmp (parent_name, 
758                   panel.dynamic_data_list[i]->parent_name) == 0        &&
759           parent_type == panel.dynamic_data_list[i]->parent_type)
760       {
761          return (panel.dynamic_data_list[i]->file_name);
762       }
763    }
764
765    return ((char *) NULL);
766 }
767
768 /************************************************************************
769  *
770  *  SessionDeleteAll
771  *      This function deletes all of the session file records from the list 
772  *      attached to panel.  It is called when a request is made to restore
773  *      the default front panel.
774  *
775  *  Inputs: None
776  *
777  ************************************************************************/
778
779 void
780 SessionDeleteAll(void)
781 {
782    DIR *dir;
783    struct dirent *entry;          /* directory entry */
784    char srcname[MAX_PATH];
785    int srclen;
786    char * home_dir;
787    char * fp_dir;
788    struct passwd * pw_info;
789    int i;
790
791
792    /*  Get the home directory used to build the path to the session file.  */
793
794    if ((home_dir = (char *)getenv("HOME")) != NULL || strlen (home_dir) == 0)
795    {
796       pw_info = getpwuid (getuid());
797       home_dir = pw_info->pw_dir;
798    }
799
800   /* Add path to fp_dynamic directory */
801    fp_dir = XtMalloc (strlen(home_dir) + strlen(TYPES_DIR) + 1);
802    sprintf (fp_dir, "%s%s", home_dir, TYPES_DIR);
803
804     
805   /* Open the fp_dynamic directory */
806    dir = opendir(fp_dir);
807
808    if (dir == NULL)
809      return;
810
811   /* prepare source name */
812    strcpy(srcname, fp_dir);
813    srclen = strlen(fp_dir);
814    if (srcname[srclen - 1] != '/')
815      srcname[srclen++] = '/';
816
817   /*  Loop through all the files in the fp_dyamic directory and
818    *  remove them.
819    */
820
821    while ((entry = readdir(dir)) != NULL)
822    {
823       if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
824          continue;
825       strcpy(srcname + srclen, entry->d_name);
826       remove (srcname);
827    }
828    
829    closedir(dir);
830 }
831