2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
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)
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
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
23 /* $TOG: Session.c /main/5 1997/05/20 08:20:18 samborn $ */
24 /************************************************************************
30 * Description: This file contains the session management code for the
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.
38 ************************************************************************/
42 #include <Dt/Control.h>
43 #include <Dt/ControlP.h>
45 #include "DataBaseLoad.h"
55 extern void ToggleDefaultControl(ControlData *, SubpanelData *, ControlData *);
56 extern Boolean CheckOtherMonitorsOn(SubpanelData *);
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. */
63 static char * SESSION_FILE = "/.dt/sessions/dtwmfp.session";
64 static char * TYPES_DIR = "/.dt/types/fp_dynamic/";
67 extern String unpost_arrow_image;
68 extern String unpost_monitor_arrow_image;
73 /************************************************************************
76 * Generate the name of the session file to be used to read and
77 * write the front panel session information.
79 ************************************************************************/
88 struct passwd * pw_info;
91 /* Get the home directory used to build the path to the session file. */
93 if ((home_dir = (char *)getenv("HOME")) != NULL || strlen (home_dir) == 0)
95 pw_info = getpwuid (getuid());
96 home_dir = pw_info->pw_dir;
99 file_name = XtMalloc (strlen (home_dir) + strlen (SESSION_FILE) + 1);
100 sprintf (file_name, "%s%s", home_dir, SESSION_FILE);
108 /************************************************************************
111 * This function reads the front panels session file and applies
112 * the data to the already created front panel.
114 ************************************************************************/
117 SessionRestoreData ()
126 ControlData * control_data;
128 SubpanelData ** subpanel_data = NULL;
129 int subpanel_count = 0;
130 int max_subpanel_count = 0;
132 int subpanel_posted_count = 0;
133 int subpanel_default_count = 0;
135 char name_buffer1[256];
136 char name_buffer2[256];
137 char name_buffer3[256];
139 struct stat stat_info;
141 int parent_component_type;
146 int dynamic_data_count;
166 session_file = SessionFileGetName ();
169 if ((fd = fopen (session_file, "r")) != NULL)
171 /* Get the full list of subpanels */
173 for (i = 0; i < panel.box_data_count; i++)
175 box_data = panel.box_data[i];
177 for (j = 0; j < box_data->control_data_count; j++)
179 control_data = box_data->control_data[j];
181 if (control_data->subpanel_data != NULL)
183 if (subpanel_count == max_subpanel_count)
185 max_subpanel_count += 10;
186 subpanel_data = (SubpanelData **)
187 XtRealloc ((char *) subpanel_data,
188 sizeof (SubpanelData **) * max_subpanel_count);
191 subpanel_data[subpanel_count] = control_data->subpanel_data;
198 /* Get the count of the number of subpanels to be posted. */
200 fscanf (fd, "%d", &subpanel_posted_count);
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. */
207 for (i = 0; i < subpanel_posted_count; i++)
209 fscanf (fd, "%s%d%d%d",
210 name_buffer1, &subpanel_x, &subpanel_y, &subpanel_torn);
212 for (j = 0; j < subpanel_count; j++)
214 if (strcmp (name_buffer1,
216 element_values[SUBPANEL_NAME].parsed_value) == 0)
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. */
222 if (subpanel_torn != 0)
224 subpanel_data[j]->torn = True;
227 DtWM_HINTS_BEHAVIORS | DtWM_HINTS_ATTACH_WINDOW;
229 DtWM_BEHAVIOR_PANEL | DtWM_BEHAVIOR_SUBPANEL |
230 DtWM_BEHAVIOR_SUB_RESTORED;
231 vHints.attachWindow = XtWindow (panel.shell);
233 _DtWsmSetDtWmHints (XtDisplay (panel.shell),
234 XtWindow (subpanel_data[j]->shell),
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. */
243 XtSetMappedWhenManaged (subpanel_data[j]->shell, False);
244 XtManageChild (subpanel_data[j]->form);
246 XtSetArg (al[0], XmNx, subpanel_x);
247 XtSetArg (al[1], XmNy, subpanel_y);
248 XtSetValues (subpanel_data[j]->form, al, 2);
250 XtManageChild (subpanel_data[j]->shell);
251 XtSetMappedWhenManaged (subpanel_data[j]->shell, True);
253 if (!CheckOtherMonitorsOn(subpanel_data[j]))
254 XtSetArg (al[0], XmNimageName, unpost_arrow_image);
256 XtSetArg (al[0], XmNimageName, unpost_monitor_arrow_image);
257 XtSetValues(subpanel_data[j]->parent_control_data->arrow, al, 1);
263 /* Get the count of the number of subpanel controls to be */
264 /* toggled into the main panel. */
266 fscanf (fd, "%d", &subpanel_default_count);
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. */
273 for (i = 0; i < subpanel_default_count; i++)
275 fscanf (fd, "%s%s", name_buffer1, name_buffer2);
277 for (j = 0; j < subpanel_count; j++)
279 if (strcmp (name_buffer1,
281 element_values[SUBPANEL_NAME].parsed_value) == 0)
283 for (k = 0; k < subpanel_data[j]->control_data_count; k++)
285 if (strcmp (name_buffer2,
286 subpanel_data[j]->control_data[k]->
287 element_values[CONTROL_NAME].parsed_value) == 0)
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. */
293 width = XtWidth(subpanel_data[j]->parent_control_data->icon);
295 ToggleDefaultControl(subpanel_data[j]->parent_control_data,
297 subpanel_data[j]->control_data[k]);
299 new_width = XtWidth (subpanel_data[j]->parent_control_data->icon);
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);
311 /* Read in the count of the number of dynamic component records */
313 fscanf (fd, "%d", &panel.dynamic_data_count);
314 panel.max_dynamic_data_count = panel.dynamic_data_count;
316 if (panel.dynamic_data_count > 0) {
317 panel.dynamic_data_list = (DynamicComponent **)
318 XtMalloc (sizeof (DynamicComponent **) * panel.max_dynamic_data_count);
321 dynamic_data_count = 0;
324 /* Loop through and read all of the records */
326 for (i = 0; i < panel.dynamic_data_count; i++)
328 fscanf(fd, "%s%s%d%s%d%d", name_buffer1, name_buffer2, &component_type,
329 name_buffer3, &parent_component_type, &delete_value);
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. */
337 if (lstat (name_buffer1, &stat_info) != 0)
342 if (delete_value == 1) delete = True;
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. */
349 for (j = 0; j < subpanel_count; j++)
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. */
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,
375 if (parent_component_type == SUBPANEL)
377 for (k = 0; k < subpanel_count; k++)
379 if (strcmp (subpanel_data[k]->
380 element_values[SUBPANEL_NAME].parsed_value,
383 for (l = 0; l < subpanel_data[k]->control_data_count; l++)
385 if (strcmp (subpanel_data[k]->control_data[l]->
386 element_values[CONTROL_NAME].parsed_value,
399 else if (parent_component_type == BOX)
401 for (k = 0; k < panel.box_data_count; k++)
403 if (strcmp (panel.box_data[k]->
404 element_values[BOX_NAME].parsed_value,
407 for (l = 0; l < panel.box_data[k]->control_data_count; l++)
409 if (strcmp (panel.box_data[k]->control_data[l]->
410 element_values[CONTROL_NAME].parsed_value,
427 panel.dynamic_data_list[dynamic_data_count] =
428 (DynamicComponent *) XtMalloc (sizeof (DynamicComponent));
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;
437 dynamic_data_count++;
444 panel.dynamic_data_count = dynamic_data_count;
447 /* Read whether the front panel is iconic or not and set the */
448 /* hints on the shell appropriately. */
450 if (fscanf (fd, "%d", &mapped) == 1)
453 XIconifyWindow (XtDisplay(panel.shell), XtWindow(panel.shell),
454 XScreenNumberOfScreen (XtScreen (panel.shell)));
462 XtFree ((char *) subpanel_data);
464 XtFree (session_file);
471 /************************************************************************
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.
478 ************************************************************************/
481 WmFrontPanelSessionSaveData ()
488 Boolean written = False;
491 ControlData * control_data;
493 SubpanelData ** subpanel_data = NULL;
494 int subpanel_count = 0;
495 int max_subpanel_count = 0;
497 int subpanel_posted_count = 0;
498 int subpanel_default_count = 0;
500 XWindowAttributes window_attributes;
507 /* Set the session file name and open the file */
509 session_file = SessionFileGetName ();
511 if ((fd = fopen (session_file, "w")) != NULL)
514 /* Get the full list of subpanels */
516 for (i = 0; i < panel.box_data_count; i++)
518 box_data = panel.box_data[i];
520 for (j = 0; j < box_data->control_data_count; j++)
522 control_data = box_data->control_data[j];
524 if (control_data->subpanel_data != NULL)
526 if (subpanel_count == max_subpanel_count)
528 max_subpanel_count += 10;
529 subpanel_data = (SubpanelData **)
530 XtRealloc ((char *) subpanel_data,
531 sizeof (SubpanelData **) * max_subpanel_count);
534 subpanel_data[subpanel_count] = control_data->subpanel_data;
536 if (XtIsManaged (subpanel_data[subpanel_count]->shell))
537 subpanel_posted_count++;
539 if (subpanel_data[subpanel_count]->default_control !=
540 subpanel_data[subpanel_count]->parent_control_data)
541 subpanel_default_count++;
549 /* Save off the list of subpanels that are posted */
551 fprintf (fd, "%d\n", subpanel_posted_count);
553 if (subpanel_posted_count > 0)
555 for (i = 0; i < subpanel_count; i++)
557 if (XtIsManaged (subpanel_data[i]->shell))
558 fprintf (fd, "%s %d %d %d\n",
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);
568 /* Save off the controls that have been toggled from the */
569 /* subpanel into the main panel. */
571 fprintf (fd, "%d\n", subpanel_default_count);
573 if (subpanel_default_count > 0)
575 for (i = 0; i < subpanel_count; i++)
577 if (subpanel_data[i]->default_control !=
578 subpanel_data[i]->parent_control_data)
580 fprintf (fd, "%s %s\n",
582 element_values[SUBPANEL_NAME].parsed_value,
583 subpanel_data[i]->default_control->
584 element_values[CONTROL_NAME].parsed_value);
591 /* Save off the dynamic component information */
593 fprintf (fd, "%d\n", panel.dynamic_data_count);
595 for (i = 0; i < panel.dynamic_data_count; i++)
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);
607 /* Save off whether the front panel is iconfied or not. */
609 XGetWindowAttributes (XtDisplay (panel.shell), XtWindow (panel.shell),
612 if (window_attributes.map_state == IsUnmapped)
613 fprintf (fd, "%d\n", 0);
615 fprintf (fd, "%d\n", 1);
623 XtFree ((char *) subpanel_data);
625 XtFree (session_file);
631 /************************************************************************
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.
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.
646 ************************************************************************/
649 SessionAddFileData (char * file_name,
650 char * component_name,
658 int count = panel.dynamic_data_count;
660 if (count == panel.max_dynamic_data_count)
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);
668 panel.dynamic_data_list[count] =
669 (DynamicComponent *) XtMalloc (sizeof (DynamicComponent));
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++;
683 /************************************************************************
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.
690 * Inputs: file_name - The name of the file containing the component
691 * definition. This is used to look up in the session list.
693 ************************************************************************/
696 SessionDeleteFileData (char * file_name)
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. */
707 for (i = 0; i < panel.dynamic_data_count; i++)
709 if (strcmp (file_name, panel.dynamic_data_list[i]->file_name) == 0)
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]);
716 for (j = i; j < panel.dynamic_data_count - 1; j++)
717 panel.dynamic_data_list[j] = panel.dynamic_data_list[j + 1];
719 panel.dynamic_data_count--;
729 /************************************************************************
731 * SessionFileNameLookup
732 * This function locates and returns the name of a dynamic component
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.
740 * Outputs: The file name of the dynamic component file or NULL if not found.
742 ************************************************************************/
745 SessionFileNameLookup (char * component_name,
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. */
759 for (i = 0; i < panel.dynamic_data_count; i++)
761 if (strcmp (component_name,
762 panel.dynamic_data_list[i]->component_name) == 0 &&
763 component_type == panel.dynamic_data_list[i]->component_type &&
765 panel.dynamic_data_list[i]->parent_name) == 0 &&
766 parent_type == panel.dynamic_data_list[i]->parent_type)
768 return (panel.dynamic_data_list[i]->file_name);
772 return ((char *) NULL);
775 /************************************************************************
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.
784 ************************************************************************/
787 SessionDeleteAll(void)
790 struct dirent *entry; /* directory entry */
791 char srcname[MAX_PATH];
795 struct passwd * pw_info;
799 /* Get the home directory used to build the path to the session file. */
801 if ((home_dir = (char *)getenv("HOME")) != NULL || strlen (home_dir) == 0)
803 pw_info = getpwuid (getuid());
804 home_dir = pw_info->pw_dir;
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);
812 /* Open the fp_dynamic directory */
813 dir = opendir(fp_dir);
818 /* prepare source name */
819 strcpy(srcname, fp_dir);
820 srclen = strlen(fp_dir);
821 if (srcname[srclen - 1] != '/')
822 srcname[srclen++] = '/';
824 /* Loop through all the files in the fp_dyamic directory and
828 while ((entry = readdir(dir)) != NULL)
830 if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
832 strcpy(srcname + srclen, entry->d_name);