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 libraries and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
23 /************************************************************************
29 * Description: This file contains the session management code for the
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.
37 ************************************************************************/
41 #include <Dt/Control.h>
42 #include <Dt/ControlP.h>
44 #include "DataBaseLoad.h"
54 extern void ToggleDefaultControl(ControlData *, SubpanelData *, ControlData *);
55 extern Boolean CheckOtherMonitorsOn(SubpanelData *);
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. */
62 static char * SESSION_FILE = "/.dt/sessions/dtwmfp.session";
63 static char * TYPES_DIR = "/.dt/types/fp_dynamic/";
66 extern String unpost_arrow_image;
67 extern String unpost_monitor_arrow_image;
72 /************************************************************************
75 * Generate the name of the session file to be used to read and
76 * write the front panel session information.
78 ************************************************************************/
81 SessionFileGetName (void)
85 struct passwd * pw_info;
88 /* Get the home directory used to build the path to the session file. */
90 if ((home_dir = (char *)getenv("HOME")) != NULL || strlen (home_dir) == 0)
92 pw_info = getpwuid (getuid());
93 home_dir = pw_info->pw_dir;
96 file_name = XtMalloc (strlen (home_dir) + strlen (SESSION_FILE) + 1);
97 sprintf (file_name, "%s%s", home_dir, SESSION_FILE);
105 /************************************************************************
108 * This function reads the front panels session file and applies
109 * the data to the already created front panel.
111 ************************************************************************/
114 SessionRestoreData (void)
121 ControlData * control_data;
123 SubpanelData ** subpanel_data = NULL;
124 int subpanel_count = 0;
125 int max_subpanel_count = 0;
127 int subpanel_posted_count = 0;
128 int subpanel_default_count = 0;
130 char name_buffer1[256];
131 char name_buffer2[256];
132 char name_buffer3[256];
134 struct stat stat_info;
136 int parent_component_type;
141 int dynamic_data_count;
161 session_file = SessionFileGetName ();
164 if ((fd = fopen (session_file, "r")) != NULL)
166 /* Get the full list of subpanels */
168 for (i = 0; i < panel.box_data_count; i++)
170 box_data = panel.box_data[i];
172 for (j = 0; j < box_data->control_data_count; j++)
174 control_data = box_data->control_data[j];
176 if (control_data->subpanel_data != NULL)
178 if (subpanel_count == max_subpanel_count)
180 max_subpanel_count += 10;
181 subpanel_data = (SubpanelData **)
182 XtRealloc ((char *) subpanel_data,
183 sizeof (SubpanelData *) * max_subpanel_count);
186 subpanel_data[subpanel_count] = control_data->subpanel_data;
193 /* Get the count of the number of subpanels to be posted. */
195 fscanf (fd, "%d", &subpanel_posted_count);
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. */
202 for (i = 0; i < subpanel_posted_count; i++)
204 fscanf (fd, "%s%d%d%d",
205 name_buffer1, &subpanel_x, &subpanel_y, &subpanel_torn);
207 for (j = 0; j < subpanel_count; j++)
209 if (strcmp (name_buffer1,
211 element_values[SUBPANEL_NAME].parsed_value) == 0)
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. */
217 if (subpanel_torn != 0)
219 subpanel_data[j]->torn = True;
222 DtWM_HINTS_BEHAVIORS | DtWM_HINTS_ATTACH_WINDOW;
224 DtWM_BEHAVIOR_PANEL | DtWM_BEHAVIOR_SUBPANEL |
225 DtWM_BEHAVIOR_SUB_RESTORED;
226 vHints.attachWindow = XtWindow (panel.shell);
228 _DtWsmSetDtWmHints (XtDisplay (panel.shell),
229 XtWindow (subpanel_data[j]->shell),
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. */
238 XtSetMappedWhenManaged (subpanel_data[j]->shell, False);
239 XtManageChild (subpanel_data[j]->form);
241 XtSetArg (al[0], XmNx, subpanel_x);
242 XtSetArg (al[1], XmNy, subpanel_y);
243 XtSetValues (subpanel_data[j]->form, al, 2);
245 XtManageChild (subpanel_data[j]->shell);
246 XtSetMappedWhenManaged (subpanel_data[j]->shell, True);
248 if (!CheckOtherMonitorsOn(subpanel_data[j]))
249 XtSetArg (al[0], XmNimageName, unpost_arrow_image);
251 XtSetArg (al[0], XmNimageName, unpost_monitor_arrow_image);
252 XtSetValues(subpanel_data[j]->parent_control_data->arrow, al, 1);
258 /* Get the count of the number of subpanel controls to be */
259 /* toggled into the main panel. */
261 fscanf (fd, "%d", &subpanel_default_count);
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. */
268 for (i = 0; i < subpanel_default_count; i++)
270 fscanf (fd, "%s%s", name_buffer1, name_buffer2);
272 for (j = 0; j < subpanel_count; j++)
274 if (strcmp (name_buffer1,
276 element_values[SUBPANEL_NAME].parsed_value) == 0)
278 for (k = 0; k < subpanel_data[j]->control_data_count; k++)
280 if (strcmp (name_buffer2,
281 subpanel_data[j]->control_data[k]->
282 element_values[CONTROL_NAME].parsed_value) == 0)
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. */
288 width = XtWidth(subpanel_data[j]->parent_control_data->icon);
290 ToggleDefaultControl(subpanel_data[j]->parent_control_data,
292 subpanel_data[j]->control_data[k]);
294 new_width = XtWidth (subpanel_data[j]->parent_control_data->icon);
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);
306 /* Read in the count of the number of dynamic component records */
308 fscanf (fd, "%d", &panel.dynamic_data_count);
309 panel.max_dynamic_data_count = panel.dynamic_data_count;
311 if (panel.dynamic_data_count > 0) {
312 panel.dynamic_data_list = (DynamicComponent **)
313 XtMalloc (sizeof (DynamicComponent *) * panel.max_dynamic_data_count);
316 dynamic_data_count = 0;
319 /* Loop through and read all of the records */
321 for (i = 0; i < panel.dynamic_data_count; i++)
323 fscanf(fd, "%s%s%d%s%d%d", name_buffer1, name_buffer2, &component_type,
324 name_buffer3, &parent_component_type, &delete_value);
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. */
332 if (lstat (name_buffer1, &stat_info) != 0)
337 if (delete_value == 1) delete = True;
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. */
344 for (j = 0; j < subpanel_count; j++)
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. */
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,
370 if (parent_component_type == SUBPANEL)
372 for (k = 0; k < subpanel_count; k++)
374 if (strcmp (subpanel_data[k]->
375 element_values[SUBPANEL_NAME].parsed_value,
378 for (l = 0; l < subpanel_data[k]->control_data_count; l++)
380 if (strcmp (subpanel_data[k]->control_data[l]->
381 element_values[CONTROL_NAME].parsed_value,
394 else if (parent_component_type == BOX)
396 for (k = 0; k < panel.box_data_count; k++)
398 if (strcmp (panel.box_data[k]->
399 element_values[BOX_NAME].parsed_value,
402 for (l = 0; l < panel.box_data[k]->control_data_count; l++)
404 if (strcmp (panel.box_data[k]->control_data[l]->
405 element_values[CONTROL_NAME].parsed_value,
422 panel.dynamic_data_list[dynamic_data_count] =
423 (DynamicComponent *) XtMalloc (sizeof (DynamicComponent));
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;
432 dynamic_data_count++;
439 panel.dynamic_data_count = dynamic_data_count;
442 /* Read whether the front panel is iconic or not and set the */
443 /* hints on the shell appropriately. */
445 if (fscanf (fd, "%d", &mapped) == 1)
448 XIconifyWindow (XtDisplay(panel.shell), XtWindow(panel.shell),
449 XScreenNumberOfScreen (XtScreen (panel.shell)));
457 XtFree ((char *) subpanel_data);
459 XtFree (session_file);
466 /************************************************************************
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.
473 ************************************************************************/
476 WmFrontPanelSessionSaveData (void)
481 Boolean written = False;
484 ControlData * control_data;
486 SubpanelData ** subpanel_data = NULL;
487 int subpanel_count = 0;
488 int max_subpanel_count = 0;
490 int subpanel_posted_count = 0;
491 int subpanel_default_count = 0;
493 XWindowAttributes window_attributes;
500 /* Set the session file name and open the file */
502 session_file = SessionFileGetName ();
504 if ((fd = fopen (session_file, "w")) != NULL)
507 /* Get the full list of subpanels */
509 for (i = 0; i < panel.box_data_count; i++)
511 box_data = panel.box_data[i];
513 for (j = 0; j < box_data->control_data_count; j++)
515 control_data = box_data->control_data[j];
517 if (control_data->subpanel_data != NULL)
519 if (subpanel_count == max_subpanel_count)
521 max_subpanel_count += 10;
522 subpanel_data = (SubpanelData **)
523 XtRealloc ((char *) subpanel_data,
524 sizeof (SubpanelData *) * max_subpanel_count);
527 subpanel_data[subpanel_count] = control_data->subpanel_data;
529 if (XtIsManaged (subpanel_data[subpanel_count]->shell))
530 subpanel_posted_count++;
532 if (subpanel_data[subpanel_count]->default_control !=
533 subpanel_data[subpanel_count]->parent_control_data)
534 subpanel_default_count++;
542 /* Save off the list of subpanels that are posted */
544 fprintf (fd, "%d\n", subpanel_posted_count);
546 if (subpanel_posted_count > 0)
548 for (i = 0; i < subpanel_count; i++)
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);
561 /* Save off the controls that have been toggled from the */
562 /* subpanel into the main panel. */
564 fprintf (fd, "%d\n", subpanel_default_count);
566 if (subpanel_default_count > 0)
568 for (i = 0; i < subpanel_count; i++)
570 if (subpanel_data[i]->default_control !=
571 subpanel_data[i]->parent_control_data)
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);
584 /* Save off the dynamic component information */
586 fprintf (fd, "%d\n", panel.dynamic_data_count);
588 for (i = 0; i < panel.dynamic_data_count; i++)
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);
600 /* Save off whether the front panel is iconfied or not. */
602 XGetWindowAttributes (XtDisplay (panel.shell), XtWindow (panel.shell),
605 if (window_attributes.map_state == IsUnmapped)
606 fprintf (fd, "%d\n", 0);
608 fprintf (fd, "%d\n", 1);
616 XtFree ((char *) subpanel_data);
618 XtFree (session_file);
624 /************************************************************************
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.
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.
639 ************************************************************************/
642 SessionAddFileData (char * file_name,
643 char * component_name,
651 int count = panel.dynamic_data_count;
653 if (count == panel.max_dynamic_data_count)
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);
661 panel.dynamic_data_list[count] =
662 (DynamicComponent *) XtMalloc (sizeof (DynamicComponent));
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++;
676 /************************************************************************
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.
683 * Inputs: file_name - The name of the file containing the component
684 * definition. This is used to look up in the session list.
686 ************************************************************************/
689 SessionDeleteFileData (char * file_name)
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. */
700 for (i = 0; i < panel.dynamic_data_count; i++)
702 if (strcmp (file_name, panel.dynamic_data_list[i]->file_name) == 0)
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]);
709 for (j = i; j < panel.dynamic_data_count - 1; j++)
710 panel.dynamic_data_list[j] = panel.dynamic_data_list[j + 1];
712 panel.dynamic_data_count--;
722 /************************************************************************
724 * SessionFileNameLookup
725 * This function locates and returns the name of a dynamic component
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.
733 * Outputs: The file name of the dynamic component file or NULL if not found.
735 ************************************************************************/
738 SessionFileNameLookup (char * component_name,
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. */
752 for (i = 0; i < panel.dynamic_data_count; i++)
754 if (strcmp (component_name,
755 panel.dynamic_data_list[i]->component_name) == 0 &&
756 component_type == panel.dynamic_data_list[i]->component_type &&
758 panel.dynamic_data_list[i]->parent_name) == 0 &&
759 parent_type == panel.dynamic_data_list[i]->parent_type)
761 return (panel.dynamic_data_list[i]->file_name);
765 return ((char *) NULL);
768 /************************************************************************
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.
777 ************************************************************************/
780 SessionDeleteAll(void)
783 struct dirent *entry; /* directory entry */
784 char srcname[MAX_PATH];
788 struct passwd * pw_info;
792 /* Get the home directory used to build the path to the session file. */
794 if ((home_dir = (char *)getenv("HOME")) != NULL || strlen (home_dir) == 0)
796 pw_info = getpwuid (getuid());
797 home_dir = pw_info->pw_dir;
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);
805 /* Open the fp_dynamic directory */
806 dir = opendir(fp_dir);
811 /* prepare source name */
812 strcpy(srcname, fp_dir);
813 srclen = strlen(fp_dir);
814 if (srcname[srclen - 1] != '/')
815 srcname[srclen++] = '/';
817 /* Loop through all the files in the fp_dyamic directory and
821 while ((entry = readdir(dir)) != NULL)
823 if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
825 strcpy(srcname + srclen, entry->d_name);