1 /* $TOG: Session.c /main/5 1997/05/20 08:20:18 samborn $ */
2 /************************************************************************
8 * Description: This file contains the session management code for the
11 * (c) Copyright 1993, 1994 Hewlett-Packard Company
12 * (c) Copyright 1993, 1994 International Business Machines Corp.
13 * (c) Copyright 1993, 1994 Sun Microsystems, Inc.
14 * (c) Copyright 1993, 1994 Unix System Labs, Inc., a subsidiary of Novell, Inc.
16 ************************************************************************/
20 #include <Dt/Control.h>
21 #include <Dt/ControlP.h>
23 #include "DataBaseLoad.h"
33 extern void ToggleDefaultControl(ControlData *, SubpanelData *, ControlData *);
34 extern Boolean CheckOtherMonitorsOn(SubpanelData *);
38 /* This define is used as the file name and location of the session */
39 /* file needed by the front panel to store its across session data. */
41 static char * SESSION_FILE = "/.dt/sessions/dtwmfp.session";
42 static char * TYPES_DIR = "/.dt/types/fp_dynamic/";
45 extern String unpost_arrow_image;
46 extern String unpost_monitor_arrow_image;
51 /************************************************************************
54 * Generate the name of the session file to be used to read and
55 * write the front panel session information.
57 ************************************************************************/
66 struct passwd * pw_info;
69 /* Get the home directory used to build the path to the session file. */
71 if ((home_dir = (char *)getenv("HOME")) != NULL || strlen (home_dir) == 0)
73 pw_info = getpwuid (getuid());
74 home_dir = pw_info->pw_dir;
77 file_name = XtMalloc (strlen (home_dir) + strlen (SESSION_FILE) + 1);
78 sprintf (file_name, "%s%s", home_dir, SESSION_FILE);
86 /************************************************************************
89 * This function reads the front panels session file and applies
90 * the data to the already created front panel.
92 ************************************************************************/
104 ControlData * control_data;
106 SubpanelData ** subpanel_data = NULL;
107 int subpanel_count = 0;
108 int max_subpanel_count = 0;
110 int subpanel_posted_count = 0;
111 int subpanel_default_count = 0;
113 char name_buffer1[256];
114 char name_buffer2[256];
115 char name_buffer3[256];
117 struct stat stat_info;
119 int parent_component_type;
124 int dynamic_data_count;
144 session_file = SessionFileGetName ();
147 if ((fd = fopen (session_file, "r")) != NULL)
149 /* Get the full list of subpanels */
151 for (i = 0; i < panel.box_data_count; i++)
153 box_data = panel.box_data[i];
155 for (j = 0; j < box_data->control_data_count; j++)
157 control_data = box_data->control_data[j];
159 if (control_data->subpanel_data != NULL)
161 if (subpanel_count == max_subpanel_count)
163 max_subpanel_count += 10;
164 subpanel_data = (SubpanelData **)
165 XtRealloc ((char *) subpanel_data,
166 sizeof (SubpanelData **) * max_subpanel_count);
169 subpanel_data[subpanel_count] = control_data->subpanel_data;
176 /* Get the count of the number of subpanels to be posted. */
178 fscanf (fd, "%d", &subpanel_posted_count);
181 /* If the count is greater than 0, read in the list of subpanel */
182 /* names, compare them with the list of subpanels and post the */
183 /* appropriate ones. */
185 for (i = 0; i < subpanel_posted_count; i++)
187 fscanf (fd, "%s%d%d%d",
188 name_buffer1, &subpanel_x, &subpanel_y, &subpanel_torn);
190 for (j = 0; j < subpanel_count; j++)
192 if (strcmp (name_buffer1,
194 element_values[SUBPANEL_NAME].parsed_value) == 0)
196 /* If the subpanel is torn, modify the window manager */
197 /* behavior hints so that it can be positioned properly */
198 /* and does not slide up. */
200 if (subpanel_torn != 0)
202 subpanel_data[j]->torn = True;
205 DtWM_HINTS_BEHAVIORS | DtWM_HINTS_ATTACH_WINDOW;
207 DtWM_BEHAVIOR_PANEL | DtWM_BEHAVIOR_SUBPANEL |
208 DtWM_BEHAVIOR_SUB_RESTORED;
209 vHints.attachWindow = XtWindow (panel.shell);
211 _DtWsmSetDtWmHints (XtDisplay (panel.shell),
212 XtWindow (subpanel_data[j]->shell),
217 /* Manage and position the form and shell of the subpanel */
218 /* Note: this is a close copy of the ArrowCB posting */
219 /* function logic. */
221 XtSetMappedWhenManaged (subpanel_data[j]->shell, False);
222 XtManageChild (subpanel_data[j]->form);
224 XtSetArg (al[0], XmNx, subpanel_x);
225 XtSetArg (al[1], XmNy, subpanel_y);
226 XtSetValues (subpanel_data[j]->form, al, 2);
228 XtManageChild (subpanel_data[j]->shell);
229 XtSetMappedWhenManaged (subpanel_data[j]->shell, True);
231 if (!CheckOtherMonitorsOn(subpanel_data[j]))
232 XtSetArg (al[0], XmNimageName, unpost_arrow_image);
234 XtSetArg (al[0], XmNimageName, unpost_monitor_arrow_image);
235 XtSetValues(subpanel_data[j]->parent_control_data->arrow, al, 1);
241 /* Get the count of the number of subpanel controls to be */
242 /* toggled into the main panel. */
244 fscanf (fd, "%d", &subpanel_default_count);
247 /* If the count is greater than 0, read in the list of subpanel */
248 /* names, and control_names and compare them with the list of */
249 /* subpanels and their controls. Toggle the proper control. */
251 for (i = 0; i < subpanel_default_count; i++)
253 fscanf (fd, "%s%s", name_buffer1, name_buffer2);
255 for (j = 0; j < subpanel_count; j++)
257 if (strcmp (name_buffer1,
259 element_values[SUBPANEL_NAME].parsed_value) == 0)
261 for (k = 0; k < subpanel_data[j]->control_data_count; k++)
263 if (strcmp (name_buffer2,
264 subpanel_data[j]->control_data[k]->
265 element_values[CONTROL_NAME].parsed_value) == 0)
267 /* use the difference in width of the old and new */
268 /* main controls to adjust the parent form. This */
269 /* should not be necessary but form is buggy. */
271 width = XtWidth(subpanel_data[j]->parent_control_data->icon);
273 ToggleDefaultControl(subpanel_data[j]->parent_control_data,
275 subpanel_data[j]->control_data[k]);
277 new_width = XtWidth (subpanel_data[j]->parent_control_data->icon);
279 parent = XtParent (subpanel_data[j]->parent_control_data->icon);
280 XtSetArg (al[0], XmNwidth, XtWidth (parent) + new_width - width);
281 XtSetValues (parent, al, 1);
289 /* Read in the count of the number of dynamic component records */
291 fscanf (fd, "%d", &panel.dynamic_data_count);
292 panel.max_dynamic_data_count = panel.dynamic_data_count;
294 if (panel.dynamic_data_count > 0) {
295 panel.dynamic_data_list = (DynamicComponent **)
296 XtMalloc (sizeof (DynamicComponent **) * panel.max_dynamic_data_count);
299 dynamic_data_count = 0;
302 /* Loop through and read all of the records */
304 for (i = 0; i < panel.dynamic_data_count; i++)
306 fscanf(fd, "%s%s%d%s%d%d", name_buffer1, name_buffer2, &component_type,
307 name_buffer3, &parent_component_type, &delete_value);
310 /* Stat the file name to see if it still exists. If not, */
311 /* continue at the next iteration of the loop. This has */
312 /* the effect of not putting the data into the dynamic list */
313 /* so that it will not be written on the next shutdown. */
315 if (lstat (name_buffer1, &stat_info) != 0)
320 if (delete_value == 1) delete = True;
323 /* Loop through the subpanels and verify that each of the */
324 /* records matches component within the hierarchy. If not, */
325 /* do not put the record in the list. */
327 for (j = 0; j < subpanel_count; j++)
332 /* If the data is a reference to a deleted component, put */
333 /* it in the list. If it is a subpanel, verify that there */
334 /* is a subpanel of that name and a main control parent of */
335 /* the correct name. If it is a control, reloop through */
336 /* the subpanel set a look for a control which matches the */
337 /* name and a subpanel which matches the parent name. */
341 else if (component_type == SUBPANEL &&
342 strcmp (subpanel_data[j]->
343 element_values[SUBPANEL_NAME].parsed_value,
344 name_buffer2) == 0 &&
345 strcmp (subpanel_data[j]->
346 element_values[SUBPANEL_CONTAINER_NAME].parsed_value,
353 if (parent_component_type == SUBPANEL)
355 for (k = 0; k < subpanel_count; k++)
357 if (strcmp (subpanel_data[k]->
358 element_values[SUBPANEL_NAME].parsed_value,
361 for (l = 0; l < subpanel_data[k]->control_data_count; l++)
363 if (strcmp (subpanel_data[k]->control_data[l]->
364 element_values[CONTROL_NAME].parsed_value,
377 else if (parent_component_type == BOX)
379 for (k = 0; k < panel.box_data_count; k++)
381 if (strcmp (panel.box_data[k]->
382 element_values[BOX_NAME].parsed_value,
385 for (l = 0; l < panel.box_data[k]->control_data_count; l++)
387 if (strcmp (panel.box_data[k]->control_data[l]->
388 element_values[CONTROL_NAME].parsed_value,
405 panel.dynamic_data_list[dynamic_data_count] =
406 (DynamicComponent *) XtMalloc (sizeof (DynamicComponent));
408 panel.dynamic_data_list[dynamic_data_count]->file_name = XtNewString (name_buffer1);
409 panel.dynamic_data_list[dynamic_data_count]->component_name = XtNewString (name_buffer2);
410 panel.dynamic_data_list[dynamic_data_count]->component_type = component_type;
411 panel.dynamic_data_list[dynamic_data_count]->parent_name = XtNewString (name_buffer3);
412 panel.dynamic_data_list[dynamic_data_count]->parent_type = parent_component_type;
413 panel.dynamic_data_list[dynamic_data_count]->delete = delete;
415 dynamic_data_count++;
422 panel.dynamic_data_count = dynamic_data_count;
425 /* Read whether the front panel is iconic or not and set the */
426 /* hints on the shell appropriately. */
428 if (fscanf (fd, "%d", &mapped) == 1)
431 XIconifyWindow (XtDisplay(panel.shell), XtWindow(panel.shell),
432 XScreenNumberOfScreen (XtScreen (panel.shell)));
440 XtFree ((char *) subpanel_data);
442 XtFree (session_file);
449 /************************************************************************
451 * WmFPSessionSaveData
452 * This function calculates and save the front panels session data
453 * needed for the next restart. It is called from the window manager
454 * in its SaveResources function.
456 ************************************************************************/
459 WmFrontPanelSessionSaveData ()
466 Boolean written = False;
469 ControlData * control_data;
471 SubpanelData ** subpanel_data = NULL;
472 int subpanel_count = 0;
473 int max_subpanel_count = 0;
475 int subpanel_posted_count = 0;
476 int subpanel_default_count = 0;
478 XWindowAttributes window_attributes;
485 /* Set the session file name and open the file */
487 session_file = SessionFileGetName ();
489 if ((fd = fopen (session_file, "w")) != NULL)
492 /* Get the full list of subpanels */
494 for (i = 0; i < panel.box_data_count; i++)
496 box_data = panel.box_data[i];
498 for (j = 0; j < box_data->control_data_count; j++)
500 control_data = box_data->control_data[j];
502 if (control_data->subpanel_data != NULL)
504 if (subpanel_count == max_subpanel_count)
506 max_subpanel_count += 10;
507 subpanel_data = (SubpanelData **)
508 XtRealloc ((char *) subpanel_data,
509 sizeof (SubpanelData **) * max_subpanel_count);
512 subpanel_data[subpanel_count] = control_data->subpanel_data;
514 if (XtIsManaged (subpanel_data[subpanel_count]->shell))
515 subpanel_posted_count++;
517 if (subpanel_data[subpanel_count]->default_control !=
518 subpanel_data[subpanel_count]->parent_control_data)
519 subpanel_default_count++;
527 /* Save off the list of subpanels that are posted */
529 fprintf (fd, "%d\n", subpanel_posted_count);
531 if (subpanel_posted_count > 0)
533 for (i = 0; i < subpanel_count; i++)
535 if (XtIsManaged (subpanel_data[i]->shell))
536 fprintf (fd, "%s %d %d %d\n",
538 element_values[SUBPANEL_NAME].parsed_value,
539 XtX (subpanel_data[i]->shell),
540 XtY (subpanel_data[i]->shell),
541 (int) subpanel_data[i]->torn);
546 /* Save off the controls that have been toggled from the */
547 /* subpanel into the main panel. */
549 fprintf (fd, "%d\n", subpanel_default_count);
551 if (subpanel_default_count > 0)
553 for (i = 0; i < subpanel_count; i++)
555 if (subpanel_data[i]->default_control !=
556 subpanel_data[i]->parent_control_data)
558 fprintf (fd, "%s %s\n",
560 element_values[SUBPANEL_NAME].parsed_value,
561 subpanel_data[i]->default_control->
562 element_values[CONTROL_NAME].parsed_value);
569 /* Save off the dynamic component information */
571 fprintf (fd, "%d\n", panel.dynamic_data_count);
573 for (i = 0; i < panel.dynamic_data_count; i++)
575 fprintf (fd, "%s %s %d %s %d %d\n",
576 panel.dynamic_data_list[i]->file_name,
577 panel.dynamic_data_list[i]->component_name,
578 panel.dynamic_data_list[i]->component_type,
579 panel.dynamic_data_list[i]->parent_name,
580 panel.dynamic_data_list[i]->parent_type,
581 (int) panel.dynamic_data_list[i]->delete);
585 /* Save off whether the front panel is iconfied or not. */
587 XGetWindowAttributes (XtDisplay (panel.shell), XtWindow (panel.shell),
590 if (window_attributes.map_state == IsUnmapped)
591 fprintf (fd, "%d\n", 0);
593 fprintf (fd, "%d\n", 1);
601 XtFree ((char *) subpanel_data);
603 XtFree (session_file);
609 /************************************************************************
612 * This function adds a new session file record to the list
613 * attached to panel. It is called when a new control or
614 * subpanel is dynamically added.
616 * Inputs: file_name - the name of the file the component is stored in
617 * component_name - the value of the name field of the component
618 * component_type - a value of CONTROL or SUBPANEL
619 * parent_name - the container of the component
620 * parent_type - a value of SUBPANEL or CONTROL
621 * delete - a Boolean indicating whether the component has been
622 * deleted. This requires special handling on startup.
624 ************************************************************************/
627 SessionAddFileData (char * file_name,
628 char * component_name,
636 int count = panel.dynamic_data_count;
638 if (count == panel.max_dynamic_data_count)
640 panel.max_dynamic_data_count += 10;
641 panel.dynamic_data_list = (DynamicComponent **)
642 XtRealloc ((char *) panel.dynamic_data_list,
643 sizeof (DynamicComponent **) * panel.max_dynamic_data_count);
646 panel.dynamic_data_list[count] =
647 (DynamicComponent *) XtMalloc (sizeof (DynamicComponent));
649 panel.dynamic_data_list[count]->file_name = XtNewString (file_name);
650 panel.dynamic_data_list[count]->component_name = XtNewString (component_name);
651 panel.dynamic_data_list[count]->component_type = component_type;
652 panel.dynamic_data_list[count]->parent_name = XtNewString (parent_name);
653 panel.dynamic_data_list[count]->parent_type = parent_type;
654 panel.dynamic_data_list[count]->delete = (int) delete;
655 panel.dynamic_data_count++;
661 /************************************************************************
663 * SessionDeleteFileData
664 * This function deletes a session file record from the list
665 * attached to panel. It is called when a componentent is deleted
666 * from the front panel.
668 * Inputs: file_name - The name of the file containing the component
669 * definition. This is used to look up in the session list.
671 ************************************************************************/
674 SessionDeleteFileData (char * file_name)
681 /* Loop through the dynamic data list and find the matching record */
682 /* Free the data attached to the record and the record. Then move */
683 /* the list up to fill the empty space. */
685 for (i = 0; i < panel.dynamic_data_count; i++)
687 if (strcmp (file_name, panel.dynamic_data_list[i]->file_name) == 0)
689 XtFree ((char *) panel.dynamic_data_list[i]->file_name);
690 XtFree ((char *) panel.dynamic_data_list[i]->component_name);
691 XtFree ((char *) panel.dynamic_data_list[i]->parent_name);
692 XtFree ((char *) panel.dynamic_data_list[i]);
694 for (j = i; j < panel.dynamic_data_count - 1; j++)
695 panel.dynamic_data_list[j] = panel.dynamic_data_list[j + 1];
697 panel.dynamic_data_count--;
707 /************************************************************************
709 * SessionFileNameLookup
710 * This function locates and returns the name of a dynamic component
713 * Inputs: component_name - the name of the dynamic component.
714 * component_type - the type (CONTROL, SUBPANEL) of the component.
715 * parent_name - the name of the container of the component.
716 * parent_type - the type (SUBPANEL, CONTROL) of the parent.
718 * Outputs: The file name of the dynamic component file or NULL if not found.
720 ************************************************************************/
723 SessionFileNameLookup (char * component_name,
733 /* Loop through the dynamic data list and find the matching record */
734 /* Return the file name when found or NULL if not found */
735 /* the list up to fill the empty space. */
737 for (i = 0; i < panel.dynamic_data_count; i++)
739 if (strcmp (component_name,
740 panel.dynamic_data_list[i]->component_name) == 0 &&
741 component_type == panel.dynamic_data_list[i]->component_type &&
743 panel.dynamic_data_list[i]->parent_name) == 0 &&
744 parent_type == panel.dynamic_data_list[i]->parent_type)
746 return (panel.dynamic_data_list[i]->file_name);
750 return ((char *) NULL);
753 /************************************************************************
756 * This function deletes all of the session file records from the list
757 * attached to panel. It is called when a request is made to restore
758 * the default front panel.
762 ************************************************************************/
765 SessionDeleteAll(void)
768 struct dirent *entry; /* directory entry */
769 char srcname[MAX_PATH];
773 struct passwd * pw_info;
777 /* Get the home directory used to build the path to the session file. */
779 if ((home_dir = (char *)getenv("HOME")) != NULL || strlen (home_dir) == 0)
781 pw_info = getpwuid (getuid());
782 home_dir = pw_info->pw_dir;
785 /* Add path to fp_dynamic directory */
786 fp_dir = XtMalloc (strlen(home_dir) + strlen(TYPES_DIR) + 1);
787 sprintf (fp_dir, "%s%s", home_dir, TYPES_DIR);
790 /* Open the fp_dynamic directory */
791 dir = opendir(fp_dir);
796 /* prepare source name */
797 strcpy(srcname, fp_dir);
798 srclen = strlen(fp_dir);
799 if (srcname[srclen - 1] != '/')
800 srcname[srclen++] = '/';
802 /* Loop through all the files in the fp_dyamic directory and
806 while ((entry = readdir(dir)) != NULL)
808 if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
810 strcpy(srcname + srclen, entry->d_name);