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