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 /*****************************************************************************
25 * File: DataBaseLoad.c
29 * Description: This file contains the functions which load and parse
30 * the front panel databases.
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.
38 ****************************************************************************/
41 #include <X11/Xresource.h> /* XrmQuark */
42 #include <Dt/DtP.h> /* required for DtDirPaths type */
43 #include <Dt/DbReader.h> /* required for DtDbPathId type */
44 #include <Dt/Connect.h> /* required for DtDbPathId type */
46 #include <Dt/Utility.h>
47 #include <Dt/IconFile.h>
49 #include <Dt/UserMsg.h>
53 #include "DataBaseLoad.h"
63 /************************************************************************
65 * panel is the global top of the panel tree structure.
67 * switch is a local that is held until the hierary is built.
69 ************************************************************************/
72 static SwitchData * switch1;
73 static ElementValue * control_element_values = NULL;
74 static Boolean control_element_value_found = False;
78 #define ANY_CONTAINER_TYPE 99
80 static char * TYPES_DIR = "/.dt/types/fp_dynamic/";
81 static char * TYPES_DIR_NO_SLASH = "/.dt/types/fp_dynamic";
82 static char * HOME_DIR = NULL;
83 static char * RM = "/bin/rm";
86 typedef Boolean (*FieldParse)(char *, void **);
87 typedef void (*FieldFree)(void **);
91 FieldParse parse_function;
93 FieldFree free_function;
99 /************************************************************************
101 * Definitions and structure initializations for PANEL record type.
103 ************************************************************************/
105 static char * panel_keywords[] =
114 "DISPLAY_CONTROL_LABELS",
122 static ParseFunction panel_parse_functions[] =
124 { StringToString, NULL, FreeString}, /* Name */
125 { StringToString, NULL, FreeString}, /* Panel Geometry */
126 { StringToBoolean, (void *) True, NULL}, /* Display Handles */
127 { StringToBoolean, (void *) True, NULL}, /* Display Menu */
128 { StringToBoolean, (void *) True, NULL}, /* Display Minimize */
129 { StringToResolution, (void *) 3, NULL}, /* Resolution */
130 { StringToControlBehavior, (void *) 0, NULL}, /* Control Behavior */
131 { StringToBoolean, (void *) False, NULL}, /* Display Control Labels */
132 { StringToBoolean, (void *) True, NULL}, /* Subpanel Unpost */
133 { StringToBoolean, (void *) False, NULL}, /* Locked */
134 { StringToString, NULL, FreeString}, /* Help String */
135 { StringToString, NULL, FreeString}, /* Help Volume */
136 { StringToString, NULL, FreeString}, /* Help Topic */
140 /************************************************************************
142 * Definitions and structure initializations for BOX record type.
144 ************************************************************************/
146 static char * box_keywords[] =
158 static ParseFunction box_parse_functions[] =
160 {StringToString, NULL, FreeString}, /* Name */
161 {StringToString, NULL, FreeString}, /* Container Name */
162 {StringToPositionHints, (void *) 0, NULL}, /* Position Hints */
163 {StringToBoolean, (void *) False, NULL}, /* Locked */
164 {StringToBoolean, (void *) False, NULL}, /* Delete */
165 {StringToString, NULL, FreeString}, /* Help String */
166 {StringToString, NULL, FreeString}, /* Help Volume */
167 {StringToString, NULL, FreeString}, /* Help Topic */
171 /************************************************************************
173 * Definitions and structure initializations for SUBPANEL record type.
175 ************************************************************************/
177 static char * subpanel_keywords[] =
190 static ParseFunction subpanel_parse_functions[] =
192 { StringToString, NULL, FreeString}, /* Name */
193 { StringToString, NULL, FreeString}, /* Container Name */
194 { StringToBoolean, (void *) True, NULL}, /* Control Install */
195 { StringToString, NULL, FreeString}, /* Title */
196 { StringToBoolean, (void *) False, NULL}, /* Locked */
197 { StringToBoolean, (void *) False, NULL}, /* Delete */
198 { StringToString, NULL, FreeString}, /* Help String */
199 { StringToString, NULL, FreeString}, /* Help Volume */
200 { StringToString, NULL, FreeString}, /* Help Topic */
204 /************************************************************************
206 * Definitions and structure initializations for SWITCH record type.
208 ************************************************************************/
210 static char * switch_keywords[] =
224 static ParseFunction switch_parse_functions[] =
226 { StringToString, NULL, FreeString}, /* Name */
227 { StringToString, NULL, FreeString}, /* Container Name */
228 { StringToPositionHints, (void *) 0, NULL}, /* Position Hints */
229 { StringToInt, (void *) 2, NULL}, /* Number of Rows */
230 { StringToBoolean, (void *) False, NULL}, /* Locked */
231 { StringToBoolean, (void *) False, NULL}, /* Delete */
232 { StringToString, NULL, FreeString}, /* Help String */
233 { StringToString, NULL, FreeString}, /* Help Volume */
234 { StringToString, NULL, FreeString}, /* Help Topic */
238 /************************************************************************
240 * Definitions and structure initializations for CONTROL record type.
242 ************************************************************************/
244 static char * control_keywords[] =
271 static ParseFunction control_parse_functions[] =
273 {StringToString, NULL, FreeString}, /* Name */
274 {StringToControlType, (void *)CONTROL_ICON, NULL}, /* Type */
275 {StringToControlContainerType, NULL, NULL}, /* Container Type */
276 {StringToString, NULL, FreeString}, /* Container Name */
277 {StringToPositionHints,(void *) 0, NULL}, /* Position Hints */
278 {StringToString, NULL, FreeString}, /* Image */
279 {StringToString, NULL, FreeString}, /* Altername Image */
280 {StringToString, NULL, FreeString}, /* Label */
281 {StringToAction, NULL, FreeAction}, /* Push Action */
282 {StringToString, NULL, FreeString}, /* Push Animation */
283 {StringToAction, NULL, FreeAction}, /* Drop Action */
284 {StringToString, NULL, FreeString}, /* Drop Animation */
285 {StringToBoolean, (void *) False, NULL}, /* Push Recall */
286 {StringToMonitorType, (void *) MONITOR_NONE,NULL}, /* Monitor Type */
287 {StringToString, NULL, FreeString}, /* Client Name */
288 {StringToGeometry, NULL, FreeGeometry}, /* Client Geometry */
289 {StringToFileName, NULL, FreeString}, /* File Name */
290 {StringToString, NULL, FreeString}, /* Date Format */
291 {StringToBoolean, (void *) False, NULL}, /* Locked */
292 {StringToBoolean, (void *) False, NULL}, /* Delete */
293 {StringToString, NULL, FreeString}, /* Help String */
294 {StringToString, NULL, FreeString}, /* Help Volume */
295 {StringToString, NULL, FreeString}, /* Help Topic */
300 /************************************************************************
302 * Structure definition and initialization for the front panel
305 ************************************************************************/
307 char * entry_types[] =
316 char * control_types[] =
328 char * resolution_types[] =
336 char * monitor_types[] =
343 #define ANIMATION "ANIMATION"
347 char * record_keyword;
349 char ** field_keywords;
350 ParseFunction * parse_functions;
354 static RecordKeywords record_keywords[] =
356 { "PANEL", PANEL_KEYWORD_COUNT,
357 panel_keywords, panel_parse_functions },
359 { "BOX", BOX_KEYWORD_COUNT,
360 box_keywords, box_parse_functions },
362 { "SUBPANEL", SUBPANEL_KEYWORD_COUNT,
363 subpanel_keywords, subpanel_parse_functions },
365 { "SWITCH", SWITCH_KEYWORD_COUNT,
366 switch_keywords, switch_parse_functions },
368 { "CONTROL", CONTROL_KEYWORD_COUNT,
369 control_keywords, control_parse_functions },
373 /************************************************************************
375 * Static and external function definitions
377 ************************************************************************/
380 extern void WmFrontPanelSetBusy (Boolean);
381 extern char * _DtDbGetDataBaseEnv (void);
383 static Boolean PanelParseCB (DtDtsDbField *, DtDbPathId, char *, Boolean);
384 static Boolean BoxParseCB (DtDtsDbField *, DtDbPathId, char *, Boolean);
385 static Boolean SubpanelParseCB (DtDtsDbField *, DtDbPathId, char *, Boolean);
386 static Boolean SwitchParseCB (DtDtsDbField *, DtDbPathId, char *, Boolean);
387 static Boolean ControlParseCB (DtDtsDbField *, DtDbPathId, char *, Boolean);
388 static Boolean AnimationParseCB (DtDtsDbField *, DtDbPathId, char *, Boolean);
389 static Boolean ControlSingleParseCB(DtDtsDbField *, DtDbPathId, char *, Boolean);
390 static void ProcessRecord (DtDtsDbField *, ElementValue *);
391 static void AllocateRecordData (RecordData **, int, int *, int *);
392 static void ReorderByContainerType(RecordData *, int , int);
393 static void ReorderByContainerName(RecordData *, int , int, int);
394 static void ReorderByName(RecordData *, int , int, int);
395 static void ReorderByPosition(RecordData *, int , int, int, int);
396 static void OrderRecord (RecordData *, int, int);
397 static char ** GetNameList (RecordData *, int, int, int, int);
398 static void EliminateUnused (RecordData *, int *, char **, int, int, int, int);
399 static void EliminateDeleted (RecordData *, int *, int, int, int, int, int);
400 static void ResolveDuplicates (RecordData *, int *, int, int, int, int, int);
401 static void InitializeField (ElementValue *, int, ParseFunction *);
402 static void ProcessBox (BoxData *);
403 static int ProcessBoxControl (ControlData *);
404 static void ProcessSubpanel (SubpanelData *);
405 static void ProcessSwitch (SwitchData *);
406 static void ProcessControl (XtPointer, char, ControlData ***, int *, ElementValue *);
407 static void InitializePrimaryControlFields (ElementValue *);
408 static void InitializeSecondaryControlFields (ElementValue *);
409 static void InitializeFileControlFields (ElementValue *, char *);
413 /************************************************************************
415 * Variable and record declarations and initializations to keep track
416 * of the data base info as it is read and to be used as storage for
417 * subsequent parsing and reprocessing.
419 ************************************************************************/
421 static int panel_count = 0;
422 static int panel_data_count = 0;
423 static RecordData * panel_data = NULL;
425 static int box_count = 0;
426 static int box_data_count = 0;
427 static RecordData * box_data = NULL;
429 static int subpanel_count = 0;
430 static int subpanel_data_count = 0;
431 static RecordData * subpanel_data = NULL;
433 static int switch_count = 0;
434 static int switch_data_count = 0;
435 static RecordData * switch_data = NULL;
437 static int control_count = 0;
438 static int control_data_count = 0;
439 static RecordData * control_data = NULL;
443 static DtDbConverter panel_converter[] = { (DtDbConverter) PanelParseCB,
445 static DtDbConverter box_converter[] = { (DtDbConverter) BoxParseCB,
447 static DtDbConverter subpanel_converter[] = { (DtDbConverter) SubpanelParseCB,
449 static DtDbConverter switch_converter[] = { (DtDbConverter) SwitchParseCB,
451 static DtDbConverter control_converter[] = { (DtDbConverter) ControlParseCB,
453 static DtDbConverter animation_converter[] ={ (DtDbConverter) AnimationParseCB,
456 static DtDbRecordDesc record_descriptor[] =
458 { "PANEL", PANEL_KEYWORD_COUNT, panel_converter },
459 { "BOX", BOX_KEYWORD_COUNT, box_converter },
460 { "SUBPANEL", SUBPANEL_KEYWORD_COUNT, subpanel_converter },
461 { "SWITCH", SWITCH_KEYWORD_COUNT, switch_converter },
462 { "CONTROL", CONTROL_KEYWORD_COUNT, control_converter },
463 { "ANIMATION", DTUNLIMITEDFIELDS, animation_converter }
466 static DtDbConverter control_single_converter[] =
467 { (DtDbConverter) ControlSingleParseCB, NULL};
469 static DtDbRecordDesc control_record_descriptor[] =
471 { "CONTROL", CONTROL_KEYWORD_COUNT, control_single_converter },
472 { "ANIMATION", DTUNLIMITEDFIELDS, animation_converter }
479 /************************************************************************
481 * FrontPanelReadDatabases
482 * Read in the front panel database, parse out each line, build
483 * the internal data structures that are then used to create the
484 * visual representation.
486 * Processing occurs in a series of steps:
488 * 1. Read in all of the database records and copy the unparsed
489 * string information into a structure.
490 * a. Group the records according to type.
491 * b. Group the records according to container.
492 * c. Ensure the original read order is maintained to process
495 * This step occurs out of the callback for each of the component
498 * 2. Eliminate the unused component definitions by working top-down
499 * throught the lists. Select the PANEL and SWITCH definition
500 * to be used at this time.
502 * 3. Eliminate overridden components by either selecting the first
503 * locked definition or if none are locked, selecting the last
506 * 4. Reorder the component groups according to the position hints
508 * 5. Build hierarchical data structure from record sets, top-down.
509 * Fully parse each record as the structure is built.
514 ************************************************************************/
517 FrontPanelReadDatabases (void)
522 char * new_search_paths;
523 struct passwd * pw_info;
526 struct stat stat_info;
533 DtDirPaths * dir_paths;
536 panel.animation_data = NULL;
537 panel.animation_count = 0;
541 /* Before reading the databases, add the front panel dynamic */
542 /* directory to the search path. */
544 search_paths = _DtDbGetDataBaseEnv();
546 if ((HOME_DIR = (char *) getenv ("HOME")) == NULL)
548 pw_info = getpwuid (getuid());
549 HOME_DIR = pw_info->pw_dir;
552 HOME_DIR = XtNewString (HOME_DIR);
555 XtMalloc (strlen ("DTDATABASESEARCHPATH") + strlen (HOME_DIR) +
556 strlen (TYPES_DIR_NO_SLASH) + strlen (search_paths) + 3);
557 sprintf (new_search_paths, "%s=%s%s,%s",
558 "DTDATABASESEARCHPATH", HOME_DIR, TYPES_DIR_NO_SLASH, search_paths);
559 putenv (new_search_paths);
561 XtFree (search_paths);
564 /* See if the fp_dynamic directory exists. If not, create it */
566 dynamic_dir = XtMalloc (strlen (HOME_DIR) + strlen (TYPES_DIR) + 3);
567 sprintf (dynamic_dir, "%s%s", HOME_DIR, TYPES_DIR);
569 if (lstat (dynamic_dir, &stat_info) != 0)
570 if ((fd=mkdir (dynamic_dir, S_IRWXU | S_IRGRP | S_IROTH |
571 S_IXGRP | S_IXOTH)) != 0)
576 XtFree ((char *) dynamic_dir);
579 /* Read the database and do the initial set of processing on */
580 /* the file based information. This work occurs within the */
581 /* callback function referenced in the data read call. */
583 dir_paths = _DtGetDatabaseDirPaths();
585 #ifdef DT_PERFORMANCE
586 _DtPerfChkpntMsgSend("Begin Front panel database read");
589 _DtDbRead (dir_paths, FILE_TYPE_SUFFIX, record_descriptor, 6);
591 #ifdef DT_PERFORMANCE
592 _DtPerfChkpntMsgSend("End Front panel database read");
595 if (panel_count == 0)
597 _DtFreeDatabaseDirPaths (dir_paths);
601 /* Once all of the PANEL records have been read in, select the panel */
602 /* record that is to be used to build the front panel. */
604 /* This selection is done by first scanning the list to find a LOCKED */
605 /* panel. The first one found is selected. If none are found, the */
606 /* last panel read is selectd. */
608 for (i = panel_count - 1; i > 0; i--)
610 if ((intptr_t)(panel_data[i].element_values[PANEL_LOCKED].parsed_value))
614 panel.element_values = panel_data[i].element_values;
617 /* Parse out additional panel element values */
619 InitializeField (panel.element_values, PANEL_GEOMETRY, panel_parse_functions);
620 InitializeField (panel.element_values, PANEL_DISPLAY_HANDLES, panel_parse_functions);
621 InitializeField (panel.element_values, PANEL_DISPLAY_MENU, panel_parse_functions);
622 InitializeField (panel.element_values, PANEL_DISPLAY_MINIMIZE, panel_parse_functions);
623 InitializeField (panel.element_values, PANEL_RESOLUTION, panel_parse_functions);
624 InitializeField (panel.element_values, PANEL_CONTROL_BEHAVIOR, panel_parse_functions);
625 InitializeField (panel.element_values, PANEL_DISPLAY_CONTROL_LABELS, panel_parse_functions);
626 InitializeField (panel.element_values, PANEL_SUBPANEL_UNPOST, panel_parse_functions);
627 InitializeField (panel.element_values, PANEL_HELP_STRING, panel_parse_functions);
628 InitializeField (panel.element_values, PANEL_HELP_TOPIC, panel_parse_functions);
629 InitializeField (panel.element_values, PANEL_HELP_VOLUME, panel_parse_functions);
631 XtFree ((char *) panel_data);
634 /* Eliminate the records within the other component types that */
635 /* are not part of this selected panel. */
637 /* This elimination occurs top down because boxes have to be */
638 /* removed before controls can be removed... */
640 name_list = (char **) XtMalloc (sizeof (char **) * 2);
641 name_list[0] = panel.element_values[PANEL_NAME].parsed_value;
643 EliminateUnused (box_data, &box_count, name_list, BOX_CONTAINER_NAME,
644 ANY_CONTAINER_TYPE, PANEL, BOX);
645 XtFree ((char *) name_list);
647 /* Remove entries that have the deleted keyword set to True unless */
648 /* it is a locked file. */
649 EliminateDeleted (box_data, &box_count, BOX_CONTAINER_NAME,
650 BOX_NAME, BOX, BOX_DELETE, BOX_LOCKED);
651 EliminateDeleted (switch_data, &switch_count, SWITCH_CONTAINER_NAME,
652 SWITCH_NAME, SWITCH, SWITCH_DELETE, SWITCH_LOCKED);
653 EliminateDeleted (subpanel_data, &subpanel_count, SUBPANEL_CONTAINER_NAME,
654 SUBPANEL_NAME, SUBPANEL, SUBPANEL_DELETE, SUBPANEL_LOCKED);
655 EliminateDeleted (control_data, &control_count, CONTROL_CONTAINER_NAME,
656 CONTROL_NAME, CONTROL, CONTROL_DELETE, CONTROL_LOCKED);
658 name_list = GetNameList (box_data, box_count,
659 BOX_NAME, ANY_CONTAINER_TYPE, 0);
661 EliminateUnused(switch_data, &switch_count, name_list,
662 SWITCH_CONTAINER_NAME, ANY_CONTAINER_TYPE,
665 EliminateUnused(control_data, &control_count, name_list,
666 CONTROL_CONTAINER_NAME, CONTROL_CONTAINER_TYPE,
669 XtFree ((char *) name_list);
672 /* Once the elimination of superfluous switch definitions is complete, */
673 /* make the selection of the single Switch. This makes the elimination */
674 /* of the switch based controls efficient. */
676 /* This selection is done by first scanning the list to find a LOCKED */
677 /* switch. The first one found is selected. If none are found, the */
678 /* last switch read is selected. */
680 if (switch_count != 0) {
681 for (i = switch_count - 1; i > 0; i--)
683 if ((intptr_t)(switch_data[i].element_values[SWITCH_LOCKED].parsed_value))
687 switch1 = (SwitchData *) XtMalloc (sizeof (SwitchData));
688 switch1->element_values = switch_data[i].element_values;
689 switch1->control_data = NULL;
690 switch1->control_data_count = 0;
692 switch1->buttons = NULL;
693 switch1->atom_names = NULL;
694 switch1->switch_names = NULL;
695 switch1->switch_count = 0;
696 switch1->active_switch = 0;
697 switch1->popup_data = NULL;
700 /* Parse the remaining database values for the switch */
702 InitializeField (switch1->element_values, SWITCH_POSITION_HINTS, switch_parse_functions);
703 InitializeField (switch1->element_values, SWITCH_NUMBER_OF_ROWS, switch_parse_functions);
704 InitializeField (switch1->element_values, SWITCH_HELP_STRING, switch_parse_functions);
705 InitializeField (switch1->element_values, SWITCH_HELP_TOPIC, switch_parse_functions);
706 InitializeField (switch1->element_values, SWITCH_HELP_STRING, switch_parse_functions);
709 XtFree ((char *) switch_data);
712 /* Continue the elimination of unused records */
714 name_list = (char **) XtMalloc (sizeof (char *) * 2);
715 if (switch_count != 0)
716 name_list[0] = switch1->element_values[SWITCH_NAME].parsed_value;
720 EliminateUnused (control_data, &control_count, name_list,
721 CONTROL_CONTAINER_NAME, CONTROL_CONTAINER_TYPE,
723 XtFree ((char *)name_list);
725 name_list = GetNameList (control_data, control_count,
726 CONTROL_NAME, CONTROL_CONTAINER_TYPE, BOX);
728 EliminateUnused (subpanel_data, &subpanel_count, name_list,
729 SUBPANEL_CONTAINER_NAME, ANY_CONTAINER_TYPE,
731 XtFree ((char *)name_list);
733 name_list = GetNameList (subpanel_data, subpanel_count,
734 SUBPANEL_NAME, ANY_CONTAINER_TYPE, SUBPANEL);
736 EliminateUnused (control_data, &control_count, name_list,
737 CONTROL_CONTAINER_NAME, CONTROL_CONTAINER_TYPE,
740 XtFree ((char *)name_list);
743 /* The record types of CONTROL, SUBPANEL and BOX still have need */
744 /* several steps of processing. */
746 ReorderByContainerType(control_data, control_count, CONTROL_CONTAINER_TYPE);
748 ReorderByContainerName(control_data, control_count, CONTROL_CONTAINER_NAME,
749 CONTROL_CONTAINER_TYPE);
751 ReorderByName(box_data, box_count, BOX_NAME, BOX_CONTAINER_NAME);
753 ReorderByName(control_data, control_count, CONTROL_NAME,
754 CONTROL_CONTAINER_NAME);
757 for (i = 0; i < control_count; i++) {
758 printf("control %s, %d, %s\n",
759 control_data[i].element_values[CONTROL_CONTAINER_NAME].parsed_value,
760 control_data[i].element_values[CONTROL_CONTAINER_TYPE].parsed_value,
761 control_data[i].element_values[CONTROL_NAME].parsed_value);
766 /* Reprocess each of these groups to eliminate overridden */
767 /* components. If a component is locked, use the first lock */
768 /* encountered. Otherwise, use the last component read. */
770 ResolveDuplicates (box_data, &box_count, BOX_NAME,
771 ANY_CONTAINER_TYPE, BOX_CONTAINER_NAME,
773 ResolveDuplicates (subpanel_data, &subpanel_count, SUBPANEL_NAME,
774 ANY_CONTAINER_TYPE, SUBPANEL_CONTAINER_NAME,
775 SUBPANEL_LOCKED, SUBPANEL);
776 ResolveDuplicates (control_data, &control_count, CONTROL_NAME,
777 CONTROL_CONTAINER_TYPE, CONTROL_CONTAINER_NAME,
778 CONTROL_LOCKED, CONTROL);
780 /* Now that the elimination has been completed, initialize the */
781 /* remaining values for each of the components. */
783 for (i = 0; i < box_count; i++)
785 InitializeField (box_data[i].element_values,
786 BOX_POSITION_HINTS, box_parse_functions);
787 InitializeField (box_data[i].element_values,
788 BOX_HELP_STRING, box_parse_functions);
789 InitializeField (box_data[i].element_values,
790 BOX_HELP_TOPIC, box_parse_functions);
791 InitializeField (box_data[i].element_values,
792 BOX_HELP_VOLUME, box_parse_functions);
795 for (i = 0; i < subpanel_count; i++)
797 InitializeField (subpanel_data[i].element_values,
798 SUBPANEL_CONTROL_INSTALL, subpanel_parse_functions);
799 InitializeField (subpanel_data[i].element_values,
800 SUBPANEL_TITLE, subpanel_parse_functions);
801 InitializeField (subpanel_data[i].element_values,
802 SUBPANEL_HELP_STRING, subpanel_parse_functions);
803 InitializeField (subpanel_data[i].element_values,
804 SUBPANEL_HELP_TOPIC, subpanel_parse_functions);
805 InitializeField (subpanel_data[i].element_values,
806 SUBPANEL_HELP_VOLUME, subpanel_parse_functions);
809 for (i = 0; i < control_count; i++)
811 InitializeSecondaryControlFields (control_data[i].element_values);
812 InitializeFileControlFields (control_data[i].element_values, NULL);
816 for (i = 0; i < box_count; i++) {
817 printf("box %d = %s\n",
818 box_data[i].element_values[BOX_POSITION_HINTS].parsed_value,
819 box_data[i].element_values[BOX_NAME].parsed_value);
822 for (i = 0; i < subpanel_count; i++) {
823 printf("subpanel = %s\n",
824 subpanel_data[i].element_values[SUBPANEL_NAME].parsed_value);
827 for (i = 0; i < control_count; i++) {
828 printf("control %d = %s\n",
829 control_data[i].element_values[CONTROL_POSITION_HINTS].parsed_value,
830 control_data[i].element_values[CONTROL_NAME].parsed_value);
834 /* Reorder subgroups according to position hints. */
836 ReorderByPosition (box_data, box_count, BOX_POSITION_HINTS,
837 ANY_CONTAINER_TYPE, BOX_CONTAINER_NAME);
838 ReorderByPosition (control_data, control_count, CONTROL_POSITION_HINTS,
839 CONTROL_CONTAINER_TYPE, CONTROL_CONTAINER_NAME);
842 printf("**************************************************************\n\n");
844 for (i = 0; i < box_count; i++) {
845 printf("box %d = %s\n", (int)
846 box_data[i].element_values[BOX_POSITION_HINTS].parsed_value,
847 box_data[i].element_values[BOX_NAME].parsed_value);
850 for (i = 0; i < control_count; i++) {
851 printf("control %d = %s\n", (int)
852 control_data[i].element_values[CONTROL_POSITION_HINTS].parsed_value,
853 control_data[i].element_values[CONTROL_NAME].parsed_value);
858 /* Build hierarchical data structure from record sets, top-down. */
859 /* Fully parse each record as the structure is built. */
861 panel.box_data = (BoxData **) XtMalloc (sizeof (BoxData *) * box_count);
862 panel.box_data_count = box_count;
864 for (i = 0; i < box_count; i++)
868 panel.box_data[i] = (BoxData *) XtMalloc (sizeof (BoxData));
869 box = panel.box_data[i];
871 box->element_values = box_data[i].element_values;
872 box->control_data = NULL;
873 box->control_data_count = 0;
875 box->left_arrow_form = NULL;
876 box->left_control_form = NULL;
877 box->right_arrow_form = NULL;
878 box->right_control_form = NULL;
879 box->switch_data = NULL;
880 box->switch_form = NULL;
881 box->switch_edit = NULL;
882 box->subpanel_count = 0;
885 if (switch_count != 0 &&
886 strcmp ((char *) box->element_values[BOX_NAME].parsed_value,
887 (char *) switch1->element_values[SWITCH_CONTAINER_NAME].parsed_value) == 0)
889 box->switch_data = switch1;
890 switch1->box_data = box;
891 ProcessSwitch (box->switch_data);
895 /* Call a function to process each box, allocating the control */
896 /* data structures needed for them and calling functions to */
897 /* further process each control. */
902 XtFree ((char *) box_data);
903 _DtFreeDatabaseDirPaths (dir_paths);
911 /************************************************************************
914 * Allocate a structure to contain the Panel record returned by
915 * the database read code and copy the record information into the
918 ************************************************************************/
921 PanelParseCB (DtDtsDbField * fields,
927 AllocateRecordData (&panel_data,
928 sizeof (ElementValue) * PANEL_KEYWORD_COUNT,
929 &panel_data_count, &panel_count);
931 ProcessRecord (fields, (ElementValue *)
932 panel_data[panel_count - 1].element_values);
934 InitializeField (panel_data[panel_count - 1].element_values,
935 PANEL_NAME, panel_parse_functions);
936 InitializeField (panel_data[panel_count - 1].element_values,
937 PANEL_LOCKED, panel_parse_functions);
945 /************************************************************************
948 * Allocate a structure to contain the Box record returned by
949 * the database read code and copy the record information into the
952 ************************************************************************/
955 BoxParseCB (DtDtsDbField * fields,
962 AllocateRecordData (&box_data,
963 sizeof (ElementValue) * BOX_KEYWORD_COUNT,
964 &box_data_count, &box_count);
966 ProcessRecord (fields, box_data[box_count - 1].element_values);
968 InitializeField (box_data[box_count - 1].element_values,
969 BOX_NAME, box_parse_functions);
970 InitializeField (box_data[box_count - 1].element_values,
971 BOX_CONTAINER_NAME, box_parse_functions);
972 InitializeField (box_data[box_count - 1].element_values,
973 BOX_LOCKED, box_parse_functions);
974 InitializeField (box_data[box_count - 1].element_values,
975 BOX_DELETE, box_parse_functions);
977 OrderRecord (box_data, box_count, BOX_CONTAINER_NAME);
985 /************************************************************************
988 * Allocate a structure to contain the Subpanel record returned by
989 * the database read code and copy the record information into the
992 ************************************************************************/
995 SubpanelParseCB (DtDtsDbField * fields,
1001 AllocateRecordData (&subpanel_data,
1002 sizeof (ElementValue) * SUBPANEL_KEYWORD_COUNT,
1003 &subpanel_data_count, &subpanel_count);
1005 ProcessRecord (fields, subpanel_data[subpanel_count - 1].element_values);
1007 InitializeField (subpanel_data[subpanel_count - 1].element_values,
1008 SUBPANEL_NAME, subpanel_parse_functions);
1009 InitializeField (subpanel_data[subpanel_count - 1].element_values,
1010 SUBPANEL_CONTAINER_NAME, subpanel_parse_functions);
1011 InitializeField (subpanel_data[subpanel_count - 1].element_values,
1012 SUBPANEL_LOCKED, subpanel_parse_functions);
1013 InitializeField (subpanel_data[subpanel_count - 1].element_values,
1014 SUBPANEL_DELETE, subpanel_parse_functions);
1016 OrderRecord (subpanel_data, subpanel_count, SUBPANEL_CONTAINER_NAME);
1024 /************************************************************************
1027 * Allocate a structure to contain the Switch record returned by
1028 * the database read code and copy the record information into the
1031 ************************************************************************/
1034 SwitchParseCB (DtDtsDbField * fields,
1040 AllocateRecordData (&switch_data,
1041 sizeof (ElementValue) * SWITCH_KEYWORD_COUNT,
1042 &switch_data_count, &switch_count);
1044 ProcessRecord (fields, switch_data[switch_count - 1].element_values);
1046 InitializeField (switch_data[switch_count - 1].element_values,
1047 SWITCH_NAME, switch_parse_functions);
1048 InitializeField (switch_data[switch_count - 1].element_values,
1049 SWITCH_CONTAINER_NAME, switch_parse_functions);
1050 InitializeField (switch_data[switch_count - 1].element_values,
1051 SWITCH_LOCKED, switch_parse_functions);
1052 InitializeField (switch_data[switch_count - 1].element_values,
1053 SWITCH_DELETE, switch_parse_functions);
1055 OrderRecord (switch_data, switch_count, SWITCH_CONTAINER_NAME);
1062 /************************************************************************
1065 * Allocate a structure to contain the Control record returned by
1066 * the database read code and copy the record information into the
1069 ************************************************************************/
1072 ControlParseCB (DtDtsDbField * fields,
1078 AllocateRecordData (&control_data,
1079 sizeof (ElementValue) * CONTROL_KEYWORD_COUNT,
1080 &control_data_count, &control_count);
1082 ProcessRecord (fields, control_data[control_count - 1].element_values);
1084 InitializePrimaryControlFields
1085 (control_data[control_count - 1].element_values);
1087 OrderRecord (control_data, control_count, CONTROL_CONTAINER_NAME);
1095 /************************************************************************
1098 * Allocate a structure to contain the Animation records returned by
1099 * the database read code and copy the record information into the
1102 ************************************************************************/
1105 AnimationParseCB (DtDtsDbField * fields,
1111 unsigned char *string, *source, *head_ptr;
1114 int count = panel.animation_count;
1115 int field_count = 0;
1118 XrmQuark animation_quark = XrmStringToQuark(ANIMATION);
1120 panel.animation_data = (AnimationData *)
1121 XtRealloc ((char *) panel.animation_data,
1122 sizeof (AnimationData) * (count + 1));
1124 panel.animation_data[count].name = strdup(fields[0].fieldValue);
1127 for (i = 1; fields[i].fieldName != NULLQUARK; i++)
1129 if (fields[i].fieldName == animation_quark)
1133 panel.animation_data[count].item_count = field_count;
1135 panel.animation_data[count].items = (AnimationItem *)
1136 XtMalloc(sizeof(AnimationItem) * field_count);
1138 for (i = 0; i < field_count; i++)
1140 if (fields[i+1].fieldName == animation_quark)
1143 (unsigned char *) strdup((char *)fields[i+1].fieldValue);
1145 if ((string = _DtWmParseNextTokenC(&source, False)) != NULL)
1147 panel.animation_data[count].items[i].image_name =
1148 strdup((char *) string);
1149 if ((string = _DtWmParseNextTokenC(&source, False)) != NULL)
1151 StringToInt((char *)string, &val_rtn);
1152 panel.animation_data[count].items[i].delay = (int) (intptr_t) val_rtn;
1156 panel.animation_data[count].items[i].delay = 0;
1160 free((char *)head_ptr);
1164 panel.animation_count++;
1171 /************************************************************************
1173 * ControlSingleParseCB
1174 * Allocate a structure to contain the Control record returned by
1175 * the database read code and copy the record information into the
1178 ************************************************************************/
1181 ControlSingleParseCB (DtDtsDbField * fields,
1187 if (control_element_value_found) {
1191 control_element_values = (ElementValue *) XtMalloc (sizeof(ElementValue) *
1192 CONTROL_KEYWORD_COUNT);
1193 control_element_value_found = True;
1195 ProcessRecord (fields, control_element_values);
1197 InitializeControlFields(control_element_values, NULL);
1205 /************************************************************************
1208 * Extract the fields of a returned record and put them into an
1209 * allocated structure for latter processing.
1211 ************************************************************************/
1214 ProcessRecord (DtDtsDbField * fields,
1215 ElementValue * element_values)
1221 int keyword_count = 0;
1222 char ** field_keywords;
1225 /* Find the position in the record structure for the value of */
1226 /* the entry keyword contained in the first position of the */
1229 for (entry = 0; entry < TOTAL_ENTRY_COUNT; entry++)
1231 if (fields[0].fieldName == XrmStringToQuark(record_keywords[entry].record_keyword))
1233 keyword_count = record_keywords[entry].keyword_count;
1234 field_keywords = record_keywords[entry].field_keywords;
1240 /* Initialize the element_values array */
1242 for (i = 0; i < keyword_count; i++)
1244 (element_values + i)->use_default = True;
1245 (element_values + i)->string_value = NULL;
1246 (element_values + i)->parsed_value = NULL;
1250 /* Loop through each read in keyword value pair, comparing it */
1251 /* to the keywords for this record type and when found, enter */
1252 /* it into the element values array for the component. */
1254 for (i = 0; fields[i].fieldName != NULLQUARK; i++)
1256 XrmQuark field1 = fields[i].fieldName;
1257 char * field2 = fields[i].fieldValue;
1260 /* Search the field_keywords list and when the keyword is found */
1261 /* make a copy of field2 and place in its position. */
1263 for (j = 0; j < keyword_count; j++)
1265 if (field1 == XrmStringToQuark(field_keywords[j]))
1267 (element_values + j)->use_default = False;
1268 (element_values + j)->string_value = strdup (field2);
1273 if (j == keyword_count)
1274 _DtSimpleError (panel.app_name, DtWarning, NULL,
1275 "Invalid keyword -- %s", XrmQuarkToString(field1));
1282 /************************************************************************
1284 * AllocateRecordData
1285 * Allocate a structure to contain the values for a data base record
1286 * and stuff it in an array for latter processing. Do all of this
1287 * by indirection so that multiple record types can be handled.
1289 ************************************************************************/
1292 AllocateRecordData (RecordData ** record_data,
1294 int * record_data_count,
1298 if (*record_count >= *record_data_count)
1300 *record_data_count += 10;
1301 *record_data = (RecordData *)
1302 XtRealloc ((char *) *record_data,
1303 sizeof (RecordData) * (*record_data_count));
1306 (*record_data)[*record_count].element_values =
1307 (ElementValue *) XtMalloc (record_size);
1315 /************************************************************************
1318 * Compare the value in the last element values struture referenced
1319 * by value_define to previous element values. Move the element
1320 * value structure to a new position defined by the comparison
1321 * value being equal or greater the previous position and less
1322 * than the next position
1324 * The function works on string data.
1326 ************************************************************************/
1329 OrderRecord (RecordData * record_data,
1337 char * position_value;
1338 char * compare_value;
1339 ElementValue * element_values;
1342 /* If this is the first record, it is already in position */
1344 if (record_count == 1)
1348 /* Extract the comparison value and loop backward through the */
1349 /* record_data to find the correct */
1351 element_values = record_data[record_count - 1].element_values;
1352 position_value = element_values[value_define].parsed_value;
1354 for (new_loc = record_count - 2; new_loc >= 0; new_loc--)
1357 record_data[new_loc].element_values[value_define].parsed_value;
1359 if (strcmp (position_value, compare_value) >= 0)
1362 record_data[new_loc + 1].element_values =
1363 record_data[new_loc].element_values;
1368 /* If any values have been moved, place the position value into */
1369 /* the vacated spot. */
1371 if (new_loc != record_count - 2)
1372 record_data[new_loc + 1].element_values = element_values;
1378 /************************************************************************
1381 * Swap element value records based on positions.
1383 ************************************************************************/
1386 SwapEntries (RecordData * rec_data,
1392 ElementValue * temp_value;
1394 temp_value = rec_data[i].element_values;
1395 rec_data[i].element_values = rec_data[j].element_values;
1396 rec_data[j].element_values = temp_value;
1402 /************************************************************************
1405 * Reorder the records according to element index. This routine
1406 * performs a quick sort. Positions that are equal will retain current
1409 ************************************************************************/
1413 QuickSort(RecordData * rec_data,
1424 SwapEntries(rec_data, left, (left + right)/2);
1428 if (container == BOX && elem_index == BOX_POSITION_HINTS ||
1429 (container == CONTROL && elem_index == CONTROL_POSITION_HINTS))
1431 for (i = left + 1; i <= right; i++)
1432 if (rec_data[i].element_values[elem_index].parsed_value <
1433 rec_data[left].element_values[elem_index].parsed_value)
1434 SwapEntries(rec_data, ++last, i);
1438 for (i = left + 1; i <= right; i++)
1439 if (strcmp(rec_data[i].element_values[elem_index].parsed_value,
1440 rec_data[left].element_values[elem_index].parsed_value) < 0)
1441 SwapEntries(rec_data, ++last, i);
1444 SwapEntries(rec_data, left, last);
1446 QuickSort(rec_data, left, last - 1, elem_index, container);
1447 QuickSort(rec_data, last + 1, right, elem_index, container);
1449 #endif /* NOT_DEF */
1454 /************************************************************************
1457 * Reorder the records according to element index. This routine
1458 * performs a bubble sort. Positions that are equal will retain current
1461 ************************************************************************/
1464 BubbleSort (RecordData * rec_data,
1472 Boolean is_string = False;
1477 if (elem_index == CONTROL_CONTAINER_NAME ||
1478 elem_index == CONTROL_NAME)
1484 for (j = start; j < bound; j++)
1488 str1 = (char *)rec_data[j].element_values[elem_index].parsed_value;
1489 str2 = (char *)rec_data[j+1].element_values[elem_index].parsed_value;
1490 if (strcmp(str1, str2) > 0)
1492 SwapEntries(rec_data, j, j+1);
1498 if ((intptr_t) rec_data[j].element_values[elem_index].parsed_value >
1499 (intptr_t) rec_data[j+1].element_values[elem_index].parsed_value)
1501 SwapEntries(rec_data, j, j+1);
1513 /************************************************************************
1516 * Reverse order of the records. This routine reverses the order of
1517 * the records so that user records that have the same positioning
1518 * will get a higher presidence.
1521 ************************************************************************/
1524 ReversePositions (RecordData * rec_data,
1532 for (i = start, j = end; i < j; i++, j--)
1534 SwapEntries(rec_data, i, j);
1541 /************************************************************************
1543 * ReorderByContainerName
1544 * Reorder the records according to container name. This will be done
1545 * using a quick sort. Container type order must be retained. Matchinng
1546 * names will retain current ordering.
1548 *************************************************************************/
1551 ReorderByContainerName (RecordData * rec_data,
1557 int i = 0, start = 0;
1560 while (i < rec_count)
1562 cont_type = (int) (intptr_t)
1563 (rec_data[start].element_values[elem_type].parsed_value);
1564 while ((intptr_t)(rec_data[i].element_values[elem_type].parsed_value) ==
1568 if (rec_count == i) break;
1571 BubbleSort(rec_data, start, i - 1, name);
1579 /************************************************************************
1582 * Reorder the records according to names. This will be done
1583 * using a quick sort. Container name order must be retained.
1584 * Matching names will retain current order.
1586 *************************************************************************/
1589 ReorderByName (RecordData * rec_data,
1595 int i = 0, start = 0;
1598 while (i < rec_count)
1600 cont_name = (char *)
1601 (rec_data[start].element_values[elem_type].parsed_value);
1602 while (strcmp((char *)rec_data[i].element_values[elem_type].parsed_value,
1606 if (rec_count == i) break;
1609 BubbleSort(rec_data, start, i - 1, name);
1617 /************************************************************************
1620 * Reorder the records according to position_hints. This will be done
1621 * using a quick sort. Positions that are equal will retain current
1623 *************************************************************************/
1626 ReorderByPosition(RecordData *rec_data,
1633 int i = 0, start = 0;
1635 char *container_name;
1637 ReversePositions(rec_data, 0, rec_count - 1);
1639 while (i < rec_count)
1641 container_name = (char *)
1642 (rec_data[start].element_values[cont_name].parsed_value);
1644 if (cont_type == ANY_CONTAINER_TYPE)
1646 while (strcmp((char *)
1647 rec_data[i].element_values[cont_name].parsed_value,
1648 container_name) == 0)
1651 if (rec_count == i) break;
1656 container_type = (int) (intptr_t)
1657 (rec_data[start].element_values[cont_type].parsed_value);
1658 while (((intptr_t)rec_data[i].element_values[cont_type].parsed_value ==
1661 rec_data[i].element_values[cont_name].parsed_value,
1662 container_name) == 0))
1665 if (rec_count == i) break;
1669 BubbleSort(rec_data, start, i - 1, pos_hints);
1678 /************************************************************************
1680 * ReorderByContainerType
1681 * Reorder the records according to container type. This will be done
1682 * using a bubble sort. Container types that are match must retain
1683 * current positioning.
1685 *************************************************************************/
1688 ReorderByContainerType (RecordData * rec_data,
1693 BubbleSort(rec_data, 0, rec_count - 1, container_type);
1699 /************************************************************************
1703 ************************************************************************/
1706 RemoveEntry (RecordData * record_data,
1713 for (i = 0; i < record_descriptor[record_type].maxFields; i++)
1715 if (record_keywords[record_type].parse_functions[i].free_function
1717 record_data->element_values[i].parsed_value != NULL &&
1718 record_data->element_values[i].use_default == False)
1720 (*(record_keywords[record_type].parse_functions[i].free_function))
1721 (&(record_data->element_values[i].parsed_value));
1724 if (record_data->element_values[i].use_default == False &&
1725 record_data->element_values[i].string_value != NULL)
1726 free(record_data->element_values[i].string_value);
1729 XtFree((char *)record_data->element_values);
1735 /************************************************************************
1738 * Given a container type and the indicies of the records to be deleted,
1739 * delete any components which are within the specified container type
1742 ************************************************************************/
1745 EliminateEntries (RecordData * record_data,
1756 if (start > end) return;
1758 for (j = start; j <= end; j++)
1760 RemoveEntry(&(record_data[j]), record_type);
1763 if (end + 1 < *record_count)
1765 memmove((void *) &record_data[start], (void *) &record_data[end+1],
1766 (size_t) ((*record_count - end) * sizeof(RecordData)));
1770 *i += (end - start) + 1;
1771 *count = *record_count -= (end - start) + 1;
1777 /************************************************************************
1780 * Reprocess each group to eliminate overridden components.
1781 * If a component is locked, use the first lock encountered.
1782 * Otherwise, use the last component read.
1784 ************************************************************************/
1787 ResolveDuplicates (RecordData * record_data,
1796 int i, start_index, lock_index, last_index;
1797 ElementValue * element_values;
1799 char *cont_name, *record_name;
1800 int count = *record_count;
1805 /* Go through the array of records */
1809 element_values = record_data[i].element_values;
1810 if (ANY_CONTAINER_TYPE != container_type)
1812 cont_type = (int) (intptr_t) (element_values[container_type].parsed_value);
1813 cont_name = (char *) (element_values[container_name].parsed_value);
1815 record_name = (char *) (element_values[name_type].parsed_value);
1817 locked = (Boolean) (intptr_t) (element_values[lock_type].parsed_value);
1822 start_index = last_index = i;
1823 element_values = record_data[i].element_values;
1824 if (ANY_CONTAINER_TYPE == container_type)
1826 while ((strcmp((char *) (element_values[name_type].parsed_value),
1832 element_values = record_data[i].element_values;
1837 while (((intptr_t)(element_values[container_type].parsed_value)
1839 (strcmp((char *)(element_values[container_name].parsed_value),
1841 (strcmp((char *)(element_values[name_type].parsed_value),
1847 element_values = record_data[i].element_values;
1850 if (start_index != last_index)
1851 EliminateEntries(record_data, record_count, last_index,
1852 start_index - 1, &i, &count, record_type);
1858 start_index = lock_index = last_index = i;
1860 if (i < 0) continue;
1861 element_values = record_data[i].element_values;
1862 if (ANY_CONTAINER_TYPE == container_type)
1864 while ((strcmp((char *) (element_values[name_type].parsed_value),
1867 locked = (Boolean) (intptr_t) (element_values[lock_type].parsed_value);
1868 if (locked && start_index == lock_index)
1873 element_values = record_data[i].element_values;
1878 while (((intptr_t)(element_values[container_type].parsed_value)
1880 (strcmp((char *)(element_values[container_name].parsed_value),
1882 (strcmp((char *)(element_values[name_type].parsed_value),
1885 locked = (Boolean) (intptr_t) (element_values[lock_type].parsed_value);
1886 if (locked && start_index == lock_index)
1891 element_values = record_data[i].element_values;
1894 if (start_index != last_index)
1896 if (start_index == lock_index)
1897 EliminateEntries(record_data, record_count, last_index + 1,
1898 start_index, &i, &count, record_type);
1901 int diff = start_index - lock_index;
1902 EliminateEntries(record_data, record_count, lock_index + 1,
1903 start_index, &i, &count, record_type);
1906 if (lock_index != last_index)
1907 EliminateEntries(record_data, record_count, last_index,
1908 lock_index - 1, &i, &count, record_type);
1919 /************************************************************************
1922 * Given a record_data array and a particular container type,
1923 * allocate an array of pointers to strings and set to the component
1924 * names of each component which matches the above criteria.
1926 ************************************************************************/
1929 GetNameList (RecordData * record_data,
1938 char ** name_list = NULL;
1939 int name_list_count = 0;
1940 int found_count = 0;
1942 for (i = 0; i < record_count; i++)
1944 if (ANY_CONTAINER_TYPE == container_type ||
1945 (intptr_t)(record_data[i].element_values[container_type].parsed_value) ==
1948 if (found_count >= name_list_count)
1950 name_list_count += 10;
1952 (char **) XtRealloc ((char *) name_list,
1953 sizeof (char *) * (name_list_count + 1));
1955 name_list [found_count] =
1956 record_data[i].element_values[name_type].parsed_value;
1961 if (name_list != NULL)
1962 name_list [found_count] = NULL;
1971 /************************************************************************
1974 * Given a record_data array, container name list and container type,
1975 * delete any components which are within the specified container type
1976 * but do not contain the container name.
1978 ************************************************************************/
1981 EliminateUnused (RecordData * record_data,
1983 char ** cont_name_list,
1990 int i, j, dummy = 0;
1991 char * container_name;
1992 int count = *record_count;
1993 Boolean name_found = False;
1994 ElementValue * element_values;
2000 element_values = record_data[i].element_values;
2001 if (cont_type == ANY_CONTAINER_TYPE ||
2002 (intptr_t)(element_values[cont_type].parsed_value) == container)
2004 if (cont_name_list != NULL)
2006 for (j = 0; cont_name_list[j] != NULL; j++)
2008 container_name = cont_name_list[j];
2009 if (strcmp((char *)element_values[cont_name].parsed_value,
2010 container_name) == 0)
2020 printf("Entry Eliminated - %s\n",
2021 (char *)element_values[cont_name].parsed_value);
2023 EliminateEntries(record_data, record_count, i, i, &dummy, &count,
2039 /************************************************************************
2042 * Given a record_data array, delete any components which have the
2043 * DELETE keyword set to True. Also delete any duplicates that match
2044 * the container name, container type, record name, and record type
2045 * but do not have the LOCKED keyword set to True.
2047 ************************************************************************/
2050 EliminateDeleted (RecordData * record_data,
2059 int i, j, start, dummy = 0;
2061 ElementValue * element_values, * other_element_values;
2062 char * container_name, * rec_name;
2063 int container_type, rec_type;
2065 count = *record_count;
2071 element_values = record_data[i].element_values;
2072 if ((intptr_t)element_values[delete_type].parsed_value)
2074 Boolean delete_rest = False;
2076 if (record_type == CONTROL)
2078 rec_type = (intptr_t)element_values[CONTROL_TYPE].parsed_value;
2080 (intptr_t)element_values[CONTROL_CONTAINER_TYPE].parsed_value;
2083 XtNewString ((char *)element_values[cont_name].parsed_value);
2085 XtNewString ((char *)element_values[record_name].parsed_value);
2087 for (j = count - 1; j >= 0; j--)
2089 other_element_values = record_data[j].element_values;
2090 if ((record_type != CONTROL ||
2091 ((intptr_t)other_element_values[CONTROL_CONTAINER_TYPE].parsed_value
2092 == container_type &&
2093 (intptr_t) other_element_values[CONTROL_TYPE].parsed_value
2095 strcmp((char *)other_element_values[cont_name].parsed_value,
2096 container_name) == 0 &&
2097 strcmp((char *)other_element_values[record_name].parsed_value,
2100 if ((intptr_t)other_element_values[lock_type].parsed_value)
2102 if ((intptr_t)other_element_values[delete_type].parsed_value)
2104 EliminateEntries(record_data, record_count, j, j, &dummy,
2105 &count, record_type);
2108 else if (delete_rest)
2110 EliminateEntries(record_data, record_count, j, j, &dummy,
2111 &count, record_type);
2115 EliminateEntries(record_data, record_count, j, j, &dummy,
2116 &count, record_type);
2120 XtFree(container_name);
2131 /************************************************************************
2134 * Given an ElementValues array, a particular keyword that references
2135 * a single element and the parse function array for the record
2136 * type: if the element has a value string, parse it otherwise
2137 * set the parsed value to the default.
2139 ************************************************************************/
2142 InitializeField (ElementValue * element_values,
2144 ParseFunction * parse_functions)
2147 if (element_values[keyword].string_value != NULL)
2149 element_values[keyword].use_default = False;
2151 if (!parse_functions[keyword].parse_function (
2152 element_values[keyword].string_value,
2153 &(element_values[keyword].parsed_value)))
2155 XtFree(element_values[keyword].string_value);
2156 element_values[keyword].string_value = NULL;
2158 element_values[keyword].use_default = True;
2159 element_values[keyword].parsed_value =
2160 parse_functions[keyword].default_value;
2165 element_values[keyword].use_default = True;
2166 element_values[keyword].parsed_value =
2167 parse_functions[keyword].default_value;
2173 /************************************************************************
2176 * Given a record_data array, a container name and container type
2177 * count how many records match and return the value.
2179 ************************************************************************/
2182 CountElements (RecordData * record_data,
2184 char * container_name,
2192 static int found_count = 0;
2194 for (i = 0; i < record_count; i++)
2196 if (ANY_CONTAINER_TYPE == container_type ||
2197 (intptr_t)(record_data[i].element_values[container_type].parsed_value) ==
2200 if (strcmp (container_name,
2201 record_data[i].element_values[name_type].parsed_value) ==0)
2206 return (found_count);
2212 /************************************************************************
2214 * DeleteControlActionList
2216 ************************************************************************/
2220 DeleteControlActionList (ControlData * control_data)
2226 if (control_data->move_action != NULL)
2227 free(control_data->move_action);
2228 if (control_data->copy_action != NULL)
2229 free(control_data->copy_action);
2230 if (control_data->link_action != NULL)
2231 free(control_data->link_action);
2233 if (control_data->actions != NULL)
2235 for (i = 0; control_data->actions[i] != NULL; i++)
2237 free (control_data->actions[i]->action_name);
2238 if (control_data->actions[i]->action_label != NULL)
2239 free (control_data->actions[i]->action_label);
2240 XtFree ((char *) control_data->actions[i]);
2243 XtFree((char *)control_data->actions);
2250 /************************************************************************
2252 * AddControlActionList
2254 ************************************************************************/
2258 AddControlActionList (ControlData * control_data)
2262 char * data_type = NULL;
2263 char * act_list = NULL;
2264 char * file_name = NULL;
2266 char ** action_list = NULL;
2267 int num_actions = 0;
2270 Boolean is_file_control = False;
2271 PanelActionData * drop_action;
2276 if ((intptr_t)control_data->element_values[CONTROL_TYPE].parsed_value ==
2279 file_name = (char *)
2280 control_data->element_values[CONTROL_FILE_NAME].parsed_value;
2282 data_type = DtDtsFileToDataType (file_name);
2283 is_file_control = True;
2286 if (data_type != NULL)
2288 DtDtsAttribute ** attr_list;
2291 attr_list = DtDtsDataTypeToAttributeList (data_type, file_name);
2294 /* The attribute list is ordered alphabetically by name so */
2295 /* do a linear search of the atr_list array and get the values */
2296 /* as use run into them. Use the following array to get the */
2297 /* values for these attributes. */
2299 attr[0] = DtDTS_DA_ACTION_LIST;
2300 attr[1] = DtDTS_DA_COPY_TO_ACTION;
2301 attr[2] = DtDTS_DA_LINK_TO_ACTION;
2302 attr[3] = DtDTS_DA_MOVE_TO_ACTION;
2304 if (attr_list != NULL)
2306 for (i = 0; attr_list[i] != NULL; i++)
2308 for (j = 0; j < 4; j++)
2309 if (strcmp (attr_list[i]->name, attr[j]) == 0)
2313 /* If we have found a match, find the appropriate attr */
2314 /* and assign the value. */
2318 /* DtDTS_DA_ACTION_LIST */
2320 free(act_list); /* Remove any previous loop run through */
2321 act_list = (char *) strdup(attr_list[i]->value);
2324 /* DtDTS_DA_COPY_TO_ACTION */
2326 control_data->copy_action =
2327 (char *) strdup(attr_list[i]->value);
2330 /* DtDTS_DA_LINK_TO_ACTION */
2332 control_data->link_action =
2333 (char *) strdup(attr_list[i]->value);
2336 /* DtDTS_DA_MOVE_TO_ACTION */
2338 control_data->move_action =
2339 (char *) strdup(attr_list[i]->value);
2351 action_list = _DtVectorizeInPlace (act_list, ',');
2352 for (i = 0; action_list[i] != NULL; i++)
2356 if (DtDtsDataTypeIsAction(data_type) && is_file_control)
2357 control_data->is_action = True;
2359 if (attr_list != NULL)
2360 DtDtsFreeAttributeList(attr_list);
2363 if (action_list == NULL)
2365 if (control_data->element_values[CONTROL_PUSH_ACTION].string_value != NULL)
2367 action_list = (char **) XtMalloc(sizeof(char *) * 2);
2370 control_data->element_values[CONTROL_PUSH_ACTION].string_value;
2371 action_list[1] = NULL;
2378 control_data->actions = (PanelActionData **)
2379 XtMalloc(sizeof(PanelActionData *) *
2382 for (i = 0, j = 0; j < num_actions; i++, j++)
2384 /* Remove the OpenInPlace action from the list of actions */
2385 if (strcmp(action_list[j],"OpenInPlace") == 0)
2391 control_data->actions[i] = (PanelActionData *)
2392 XtMalloc(sizeof(PanelActionData));
2394 control_data->actions[i]->action_name = strdup(action_list[j]);
2396 control_data->actions[i]->aap = NULL;
2397 control_data->actions[i]->count = 0;
2399 label = DtActionLabel (action_list[j]);
2402 control_data->actions[i]->action_label = label;
2404 control_data->actions[i]->action_label = strdup (action_list[j]);
2409 control_data->actions[i] = NULL;
2415 XtFree ((char *) action_list);
2417 if ((data_type != NULL) && is_file_control)
2418 DtDtsFreeDataType (data_type);
2424 /************************************************************************
2427 * For a box structure, find the control set that is to be contained
2428 * by it, allocate a ControlData array and reassign the element
2429 * values pointers. Further process each control.
2431 * Inputs: box_data - a pointer the BoxData structure to be initialized.
2433 ************************************************************************/
2436 ProcessBox (BoxData * box_data)
2440 ElementValue * element_values;
2442 int box_control_count = 0;
2446 /* Loop the control array and check each control to see if it belongs */
2447 /* in this box. If so, call a function to add it and then see if the */
2448 /* control has a subpanel to process. */
2450 for (i = 0; i < control_count; i++)
2452 element_values = control_data[i].element_values;
2454 if ((intptr_t) element_values[CONTROL_CONTAINER_TYPE].parsed_value == BOX &&
2455 strcmp ((char *) box_data->element_values[BOX_NAME].parsed_value,
2456 (char *) element_values[CONTROL_CONTAINER_NAME].parsed_value) == 0)
2458 ProcessControl ((XtPointer) box_data, BOX, &(box_data->control_data),
2459 &box_control_count, element_values);
2461 box_data->subpanel_count +=
2462 ProcessBoxControl (box_data->control_data[box_control_count - 1]);
2466 box_data->control_data_count = box_control_count;
2472 /************************************************************************
2475 * For each control that is created, reallocate the array of
2476 * pointer that hold the control and allocate a control structure.
2477 * Initialize the control fields. This is called for BOX, SUBPANEL
2478 * and SWITCH controls.
2480 * Inputs: parent - a pointer to the head of the structure that is to
2481 * contain this control.
2482 * parent_type - the type of parent of the control.
2483 * control_data_ptr - a pointer to the array of control pointers.
2484 * control_count - the current count of controls within the array.
2485 * element_values - the new controls database values.
2487 ************************************************************************/
2491 ProcessControl (XtPointer parent,
2493 ControlData *** control_data_ptr,
2494 int * control_count,
2495 ElementValue * element_values)
2499 ControlData * control;
2502 (ControlData **) XtRealloc ((char *) *control_data_ptr,
2503 sizeof (ControlData *) * (*control_count + 1));
2504 (*control_data_ptr)[*control_count] =
2505 (ControlData *) XtMalloc (sizeof (ControlData));
2507 control = (*control_data_ptr)[*control_count];
2509 control->element_values = element_values;
2510 control->parent_data = parent;
2511 control->parent_type = parent_type;
2512 control->subpanel_data = NULL;
2513 control->icon = NULL;
2514 control->arrow = NULL;
2515 control->arrow_separator = NULL;
2516 control->indicator = NULL;
2517 control->actions = NULL;
2518 control->is_action = False;
2519 control->move_action = NULL;
2520 control->copy_action = NULL;
2521 control->link_action = NULL;
2522 control->operation = 0;
2524 AddControlActionList (control);
2526 *control_count = *control_count + 1;
2532 /************************************************************************
2535 * For a control structure within a box, see if there is a subpanel
2536 * attached to it and if so, process the subpanel and its controls.
2537 * Return the subpanel count to be stored as part of the box data.
2539 * Inputs: control_data - a pointer to the control to be processed
2541 ************************************************************************/
2544 ProcessBoxControl (ControlData * control_data)
2549 ElementValue * element_values;
2550 int box_subpanel_count = 0;
2551 SubpanelData * subpanel;
2554 /* Loop through the subpanel data and find one that is attached */
2555 /* to the provided control. */
2557 for (i = 0; i < subpanel_count; i++)
2559 element_values = subpanel_data[i].element_values;
2561 if (strcmp ((char *) control_data->element_values[CONTROL_NAME].parsed_value,
2562 (char *) element_values[SUBPANEL_CONTAINER_NAME].parsed_value) == 0)
2564 box_subpanel_count = 1;
2566 control_data->subpanel_data =
2567 (SubpanelData *) XtMalloc (sizeof (SubpanelData));
2569 subpanel = control_data->subpanel_data;
2570 subpanel->element_values = element_values;
2571 subpanel->control_data = NULL;
2572 subpanel->control_data_count = 0;
2573 subpanel->parent_control_data = control_data;
2574 subpanel->default_control = NULL;
2575 subpanel->shell = NULL;
2576 subpanel->form = NULL;
2577 subpanel->dropzone = NULL;
2578 subpanel->separator = NULL;
2579 subpanel->main_panel_icon_copy = NULL;
2580 subpanel->torn = False;
2582 ProcessSubpanel (subpanel);
2587 return (box_subpanel_count);
2593 /************************************************************************
2596 * For a Subpanel, find all of the controls within it an allocate
2597 * a ControlData array and move the element values for the controls.
2599 * Inputs: subpanel_data - A pointer the the subpanel structure to be
2602 ************************************************************************/
2605 ProcessSubpanel (SubpanelData * subpanel_data)
2609 ElementValue * element_values;
2611 int subpanel_control_count = 0;
2616 /* Loop the control array and check each control to see if it belongs */
2617 /* in this subpanel. If so, call a function to add it. */
2619 for (i = 0; i < control_count; i++)
2621 element_values = control_data[i].element_values;
2623 if ((intptr_t) element_values[CONTROL_CONTAINER_TYPE].parsed_value == SUBPANEL &&
2624 strcmp ((char *) subpanel_data->element_values[SUBPANEL_NAME].parsed_value,
2625 (char *) element_values[CONTROL_CONTAINER_NAME].parsed_value) == 0)
2627 ProcessControl ((XtPointer) subpanel_data, SUBPANEL,
2628 &(subpanel_data->control_data),
2629 &subpanel_control_count, element_values);
2633 subpanel_data->control_data_count = subpanel_control_count;
2639 /************************************************************************
2642 * For a Switch, find all of the controls within it an allocate
2643 * a ControlData array and move the element values for the controls.
2645 * Inputs: switch_data - a pointer to the switch data structure to be
2648 ************************************************************************/
2651 ProcessSwitch (SwitchData * switch_data)
2655 ElementValue * element_values;
2657 int switch_control_count = 0;
2661 /* Count the number of controls that are to go into this switch */
2662 /* and allocate a ControlData array to hold the controls. */
2664 for (i = 0; i < control_count; i++)
2666 element_values = control_data[i].element_values;
2668 if ((intptr_t) element_values[CONTROL_CONTAINER_TYPE].parsed_value == SWITCH &&
2669 strcmp ((char *) switch_data->element_values[SWITCH_NAME].parsed_value,
2670 (char *) element_values[CONTROL_CONTAINER_NAME].parsed_value) == 0)
2672 ProcessControl ((XtPointer) switch_data, SWITCH,
2673 &(switch_data->control_data),
2674 &switch_control_count, element_values);
2678 switch_data->control_data_count = switch_control_count;
2684 /************************************************************************
2686 * CreateComponentFileName
2687 * Create a file name in which to store a component file. This is
2688 * accomplished by using the components name with an integer value
2691 * Inputs: record_data - a pointer to the struture that contains the
2692 * components name, as well as other values.
2694 ************************************************************************/
2698 CreateComponentFileName (RecordData * record_data)
2703 char * component_name;
2704 struct stat stat_info;
2708 component_name = XtMalloc(9);
2709 strncpy (component_name, record_data->element_values[0].string_value, 8);
2710 component_name[8] = '\0';
2712 file_name = XtMalloc (strlen (HOME_DIR) + strlen (TYPES_DIR) + 14);
2714 for (i = 1; i < 1000; i++)
2716 sprintf(file_name, "%s%s%s%d.fp", HOME_DIR, TYPES_DIR, component_name, i);
2718 if (lstat (file_name, &stat_info) != 0)
2722 XtFree(component_name);
2730 /************************************************************************
2732 * WriteComponentToFile
2733 * Write a component (contained within record_data) to a .fp file.
2735 * Inputs: record_data - a pointer to the data for the component,
2736 * including its element values.
2737 * record_type - the type of component (CONTROL, SUBPANEL, ...)
2738 * keywords - the ordered array of keywords for the component
2739 * type, used to reference into the element values array.
2740 * container_name - the parent of the component.
2741 * container_type - the type of parent of the component.
2742 * delete - whether the component is be added or deleted.
2744 ************************************************************************/
2748 WriteComponentToFile (RecordData * record_data,
2751 char * container_name,
2758 char * file_name = CreateComponentFileName (record_data);
2761 if ((fd = fopen(file_name, "w")) != NULL)
2763 fprintf (fd, "%s %s\n{\n", keywords[0],
2764 record_data->element_values[0].string_value);
2768 if (record_type == CONTROL)
2770 fprintf(fd, " TYPE %s\n",
2771 record_data->element_values[CONTROL_TYPE].string_value);
2772 fprintf(fd, " CONTAINER_TYPE %s\n",
2773 record_data->element_values[CONTROL_CONTAINER_TYPE].string_value);
2776 fprintf(fd, " CONTAINER_NAME %s\n", container_name);
2777 fprintf(fd, " DELETE True\n");
2782 for (k = 1; k < record_descriptor[record_type].maxFields; k++)
2784 if (record_data->element_values[k].string_value != NULL &&
2785 record_data->element_values[k].use_default == False)
2787 if (record_type == CONTROL &&
2788 (intptr_t) record_data->element_values[CONTROL_TYPE].parsed_value == CONTROL_FILE &&
2789 (k == CONTROL_PUSH_ACTION ||
2790 k == CONTROL_LABEL || k == CONTROL_DROP_ACTION))
2793 fprintf (fd, " %s %s\n", keywords[k],
2794 record_data->element_values[k].string_value);
2804 if (record_type == CONTROL)
2805 SessionAddFileData(file_name,
2806 record_data->element_values[CONTROL_NAME].string_value,
2808 container_name, container_type, delete);
2810 SessionAddFileData(file_name,
2811 record_data->element_values[0].string_value,
2812 record_type, container_name, container_type,delete);
2815 WmFrontPanelSessionSaveData ();
2823 /************************************************************************
2825 * RemoveComponentFile
2826 * Find the dynamic .fp file name of a file in the session data and
2827 * unlink the file to remove the component. If no file name is
2828 * found or the unlink fails, Call a function to write a .fp for
2829 * the file which will have the DELETE keyword set to True.
2831 ************************************************************************/
2835 RemoveComponentFile (RecordData * record_data,
2838 char * container_name,
2846 SessionFileNameLookup (record_data->element_values[0].string_value,
2847 record_type, container_name, container_type);
2849 if (file_name == NULL || unlink (file_name) < 0)
2850 WriteComponentToFile (record_data, record_type, keywords,
2851 container_name, container_type, True);
2854 SessionDeleteFileData (file_name);
2855 WmFrontPanelSessionSaveData ();
2862 /************************************************************************
2864 * WriteControlComponentFile
2865 * Set up the parameters to call a function which will write out
2866 * to a .fp file a control description.
2868 * Inputs: control_data - a pointer to the control to be written.
2870 ************************************************************************/
2874 WriteControlComponentFile (ControlData * control_data)
2878 ElementValue * element_values;
2880 element_values = control_data->element_values;
2882 WriteComponentToFile ((RecordData *) control_data, CONTROL, control_keywords,
2883 (char *) element_values[CONTROL_CONTAINER_NAME].parsed_value,
2884 (int) (intptr_t) element_values[CONTROL_CONTAINER_TYPE].parsed_value,
2891 /************************************************************************
2893 * WriteSubpanelComponentFile
2894 * Set up the parameters to call a function which will write out
2895 * to a .fp file a subpanel description.
2897 * Inputs: subpanel_data - a pointer to the subpanel to be written.
2899 ************************************************************************/
2902 WriteSubpanelComponentFile (SubpanelData * subpanel_data)
2906 ElementValue * element_values = subpanel_data->element_values;
2908 WriteComponentToFile ((RecordData *) subpanel_data, SUBPANEL, subpanel_keywords,
2909 (char *) element_values[SUBPANEL_CONTAINER_NAME].parsed_value,
2916 /************************************************************************
2918 * RemoveControlComponentFile
2919 * Set up the parameters to call a function which delete a control's
2922 * Inputs: control_data - a pointer to the control to be deleted.
2924 ************************************************************************/
2928 RemoveControlComponentFile (ControlData * control_data)
2932 ElementValue * element_values = control_data->element_values;
2934 RemoveComponentFile ((RecordData *) control_data, CONTROL, control_keywords,
2935 (char *) element_values[CONTROL_CONTAINER_NAME].parsed_value,
2936 (int) (intptr_t) element_values[CONTROL_CONTAINER_TYPE].parsed_value);
2942 /************************************************************************
2944 * RemoveSubpanelComponentFile
2945 * Set up the parameters to call a function which delete a subpanel's
2948 * Inputs: subpanel_data - a pointer to the subpanel to be deleted.
2950 ************************************************************************/
2953 RemoveSubpanelComponentFile (SubpanelData * subpanel_data)
2957 ElementValue * element_values = subpanel_data->element_values;
2959 RemoveComponentFile ((RecordData *) subpanel_data, SUBPANEL, subpanel_keywords,
2960 (char *) element_values[SUBPANEL_CONTAINER_NAME].parsed_value,
2967 /************************************************************************
2969 * _WriteControlElementValues
2970 * Set up a loop which write out all of the values that define
2971 * a control. These are written as normal keyword, value pairs.
2973 * Inputs: element_values - a pointer to the array of element value
2974 * strutures each of which contain a value for a keyword.
2976 ************************************************************************/
2980 _WriteControlElementValues (ElementValue * element_values)
2986 printf("%s %s\n{\n", control_keywords[0], element_values[0].string_value);
2988 for (k = 1; k < record_descriptor[CONTROL].maxFields; k++)
2990 if (element_values[k].string_value != NULL)
2992 control_keywords[k], element_values[k].string_value);
3002 /************************************************************************
3006 ************************************************************************/
3009 InitParse (char * file_name,
3010 ElementValue ** elem_vals)
3020 DtDirPaths * dirPath;
3023 /* create directory for dir path */
3025 tmpPath = XtMalloc (strlen(HOME_DIR) + strlen(TYPES_DIR) + 34);
3026 sprintf (tmpPath, "%s%s%s%d", HOME_DIR, TYPES_DIR, "fp", (int) getpid());
3027 mkdir (tmpPath, S_IRUSR | S_IWUSR | S_IXUSR);
3030 /* create symbolic link to file_name */
3032 tmpName = XtNewString(file_name);
3033 baseName = strrchr(tmpName, '/');
3034 tmpFile = XtMalloc(strlen(tmpPath) + strlen(baseName) + 1);
3035 sprintf(tmpFile, "%s%s", tmpPath, baseName);
3036 symlink(file_name, tmpFile);
3038 hostName = XtMalloc((Cardinal)(MAXHOSTNAMELEN + 1));
3039 DtGetShortHostname (hostName, MAXHOSTNAMELEN + 1);
3041 tmpDir = XtMalloc(strlen(hostName) + strlen(tmpPath) + 2);
3042 sprintf(tmpDir, "%s:%s", hostName, tmpPath);
3044 dirPath = (DtDirPaths *) XtMalloc(sizeof(DtDirPaths));
3045 dirPath->dirs = (char **) XtMalloc(sizeof(char *) * 2);
3046 dirPath->paths = (char **) XtMalloc(sizeof(char *) * 2);
3048 dirPath->dirs[0] = tmpDir;
3049 dirPath->dirs[1] = NULL;
3050 dirPath->paths[0] = tmpPath;
3051 dirPath->paths[1] = NULL;
3053 _DtDbRead (dirPath, FILE_TYPE_SUFFIX, control_record_descriptor, 2);
3055 control_element_value_found = False;
3057 /* remove link and directory */
3062 XtFree((char *) dirPath->dirs);
3063 XtFree((char *) dirPath->paths);
3064 XtFree((char *) dirPath);
3071 *elem_vals = control_element_values;
3077 /************************************************************************
3079 * FreeFileControlField
3081 ************************************************************************/
3085 FreeFileControlField (ElementValue * element_values,
3090 if (control_parse_functions[indx].free_function != NULL &&
3091 element_values[indx].parsed_value != NULL &&
3092 element_values[indx].use_default == False)
3094 (*(control_parse_functions[indx].free_function))
3095 (&(element_values[indx].parsed_value));
3096 element_values[indx].parsed_value = NULL;
3099 if (element_values[indx].use_default == False &&
3100 element_values[indx].string_value != NULL)
3102 free(element_values[indx].string_value);
3103 element_values[indx].string_value = NULL;
3110 /************************************************************************
3112 * InitializePrimaryControlFields
3114 ************************************************************************/
3118 InitializePrimaryControlFields (ElementValue * element_values)
3122 InitializeField (element_values,
3123 CONTROL_NAME, control_parse_functions);
3124 InitializeField (element_values,
3125 CONTROL_CONTAINER_NAME, control_parse_functions);
3126 InitializeField (element_values,
3127 CONTROL_CONTAINER_TYPE, control_parse_functions);
3128 InitializeField (element_values,
3129 CONTROL_LOCKED, control_parse_functions);
3130 InitializeField (element_values,
3131 CONTROL_DELETE, control_parse_functions);
3138 /************************************************************************
3140 * InitializeSecondaryControlFields
3142 ************************************************************************/
3146 InitializeSecondaryControlFields (ElementValue * element_values)
3150 InitializeField (element_values,
3151 CONTROL_TYPE, control_parse_functions);
3152 InitializeField (element_values,
3153 CONTROL_POSITION_HINTS, control_parse_functions);
3154 InitializeField (element_values,
3155 CONTROL_ALTERNATE_ICON, control_parse_functions);
3156 InitializeField (element_values,
3157 CONTROL_PUSH_ANIMATION, control_parse_functions);
3158 InitializeField (element_values,
3159 CONTROL_DROP_ANIMATION, control_parse_functions);
3160 InitializeField (element_values,
3161 CONTROL_PUSH_RECALL, control_parse_functions);
3162 InitializeField (element_values,
3163 CONTROL_MONITOR_TYPE, control_parse_functions);
3164 InitializeField (element_values,
3165 CONTROL_CLIENT_NAME, control_parse_functions);
3166 InitializeField (element_values,
3167 CONTROL_CLIENT_GEOMETRY, control_parse_functions);
3168 InitializeField (element_values,
3169 CONTROL_FILE_NAME, control_parse_functions);
3170 InitializeField (element_values,
3171 CONTROL_DATE_FORMAT, control_parse_functions);
3172 InitializeField (element_values,
3173 CONTROL_HELP_STRING, control_parse_functions);
3174 InitializeField (element_values,
3175 CONTROL_HELP_VOLUME, control_parse_functions);
3176 InitializeField (element_values,
3177 CONTROL_HELP_TOPIC, control_parse_functions);
3184 /************************************************************************
3186 * InitializeFileControlFields
3188 ************************************************************************/
3192 InitializeFileControlFields (ElementValue * element_values,
3197 if ((intptr_t)element_values[CONTROL_TYPE].parsed_value == CONTROL_FILE)
3199 Boolean free_data_type = False;
3201 char ** action_list = NULL;
3206 char * label = NULL;
3209 struct stat stat_info;
3210 Boolean valid_file = True;
3213 file_name = (char *) element_values[CONTROL_FILE_NAME].parsed_value;
3215 if (lstat (file_name, &stat_info) != 0)
3218 if (data_type == NULL && file_name != NULL)
3220 data_type = DtDtsFileToDataType (file_name);
3221 free_data_type = True;
3224 if (data_type != NULL)
3228 icon_name = DtDtsDataTypeToAttributeValue (data_type,
3229 DtDTS_DA_ICON, NULL);
3231 if (element_values[CONTROL_NORMAL_ICON].string_value != NULL)
3233 XtFree (element_values[CONTROL_NORMAL_ICON].string_value);
3234 element_values[CONTROL_NORMAL_ICON].string_value = NULL;
3237 element_values[CONTROL_NORMAL_ICON].string_value =
3238 XtNewString (icon_name);
3240 DtDtsFreeAttributeValue(icon_name);
3244 DtDtsDataTypeToAttributeValue(data_type, DtDTS_DA_DESCRIPTION, NULL);
3246 if (element_values[CONTROL_HELP_STRING].string_value != NULL)
3248 XtFree (element_values[CONTROL_HELP_STRING].string_value);
3249 element_values[CONTROL_HELP_STRING].string_value = NULL;
3252 element_values[CONTROL_HELP_STRING].string_value = XtNewString (description);
3253 DtDtsFreeAttributeValue (description);
3256 act_list = DtDtsDataTypeToAttributeValue (data_type,
3257 DtDTS_DA_ACTION_LIST,
3260 action_list = _DtVectorizeInPlace (act_list, ',');
3262 if (action_list && action_list[0] != NULL)
3264 element_values[CONTROL_PUSH_ACTION].string_value =
3265 strdup (action_list[0]);
3266 element_values[CONTROL_DROP_ACTION].string_value =
3267 strdup (action_list[0]);
3269 if (DtDtsDataTypeIsAction (data_type))
3270 label = DtActionLabel (action_list[0]);
3273 /* try to set it to the name of the type */
3274 if (label == NULL) {
3275 label = DtDtsDataTypeToAttributeValue (data_type,
3276 DtDTS_DA_LABEL, NULL);
3278 /* copy & correctly free the memory */
3282 label = XtNewString(t);
3284 DtDtsFreeAttributeValue(t);
3289 if (label == NULL && file_name != NULL)
3291 if ((file_str = (char *)strrchr(file_name, '/')) == NULL)
3292 file_str = file_name;
3295 label = XtNewString(file_str);
3299 element_values[CONTROL_LABEL].string_value = label;
3302 if (data_type != NULL)
3306 DtDtsFreeAttributeValue (act_list);
3307 XtFree ((char *) action_list);
3311 DtDtsFreeDataType (data_type);
3316 InitializeField (element_values,
3317 CONTROL_NORMAL_ICON, control_parse_functions);
3318 InitializeField (element_values,
3319 CONTROL_HELP_STRING, control_parse_functions);
3320 InitializeField (element_values,
3321 CONTROL_LABEL, control_parse_functions);
3322 InitializeField (element_values,
3323 CONTROL_PUSH_ACTION, control_parse_functions);
3324 InitializeField (element_values,
3325 CONTROL_DROP_ACTION, control_parse_functions);
3331 /************************************************************************
3333 * InitializeControlFields
3335 ************************************************************************/
3339 InitializeControlFields (ElementValue * element_values,
3344 InitializePrimaryControlFields (element_values);
3345 InitializeSecondaryControlFields (element_values);
3346 InitializeFileControlFields (element_values, data_type);
3352 /************************************************************************
3356 ************************************************************************/
3360 UpdateFileType (ControlData * control_data)
3365 char * control_label;
3366 XmString icon_label;
3369 FreeFileControlField (control_data->element_values, CONTROL_NORMAL_ICON);
3370 FreeFileControlField (control_data->element_values, CONTROL_PUSH_ACTION);
3371 FreeFileControlField (control_data->element_values, CONTROL_DROP_ACTION);
3372 FreeFileControlField (control_data->element_values, CONTROL_LABEL);
3373 InitializeFileControlFields (control_data->element_values, NULL);
3375 DeleteControlActionList (control_data);
3376 AddControlActionList (control_data);
3379 (char *)control_data->element_values[CONTROL_NORMAL_ICON].parsed_value;
3381 if ((intptr_t)control_data->element_values[CONTROL_CONTAINER_TYPE].parsed_value ==
3384 icon_name = GetIconName (icon_name, panel.sub_icon_size);
3388 icon_name = GetIconName (icon_name, panel.main_icon_size);
3390 if (icon_name == NULL)
3391 icon_name = GetIconName (icon_name, panel.sub_icon_size);
3394 control_label = (char *)
3395 control_data->element_values[CONTROL_LABEL].parsed_value;
3397 icon_label = XmStringCreateLocalized (control_label);
3399 XtSetArg(al[0], XmNimageName, icon_name);
3400 XtSetArg(al[1], XmNstring, icon_label);
3401 XtSetValues(control_data->icon, al, 2);
3407 /************************************************************************
3409 * UpdateFileTypeControlFields
3411 ************************************************************************/
3415 UpdateFileTypeControlFields (void)
3420 ControlData * control_data;
3421 SubpanelData * subpanel_data;
3422 SwitchData * switch_data;
3425 if (panel_count == 0) return;
3427 for (i = 0; i < panel.box_data_count; i++)
3429 box_data = panel.box_data[i];
3431 for (j = 0; j < box_data->control_data_count; j++)
3433 control_data = box_data->control_data[j];
3435 if ((intptr_t)control_data->element_values[CONTROL_TYPE].parsed_value ==
3437 UpdateFileType(control_data);
3439 if (control_data->subpanel_data != NULL)
3441 subpanel_data = control_data->subpanel_data;
3443 for (k = 0; k < subpanel_data->control_data_count; k++)
3445 control_data = subpanel_data->control_data[k];
3447 if ((intptr_t)control_data->element_values[CONTROL_TYPE].parsed_value
3449 UpdateFileType(control_data);
3454 if (box_data->switch_data != NULL)
3456 switch_data = box_data->switch_data;
3457 for (j = 0; j < switch_data->control_data_count; j++)
3459 control_data = switch_data->control_data[j];
3461 if ((intptr_t)control_data->element_values[CONTROL_TYPE].parsed_value ==
3463 UpdateFileType(control_data);
3472 /************************************************************************
3474 * InitializeSubpanelFields
3476 ************************************************************************/
3480 InitializeSubpanelFields (ElementValue * element_values)
3484 InitializeField (element_values,
3485 SUBPANEL_NAME, subpanel_parse_functions);
3486 InitializeField (element_values,
3487 SUBPANEL_CONTAINER_NAME, subpanel_parse_functions);
3488 InitializeField (element_values,
3489 SUBPANEL_LOCKED, subpanel_parse_functions);
3490 InitializeField (element_values,
3491 SUBPANEL_CONTROL_INSTALL, subpanel_parse_functions);
3492 InitializeField (element_values,
3493 SUBPANEL_TITLE, subpanel_parse_functions);
3494 InitializeField (element_values,
3495 SUBPANEL_DELETE, subpanel_parse_functions);
3496 InitializeField (element_values,
3497 SUBPANEL_HELP_STRING, subpanel_parse_functions);
3498 InitializeField (element_values,
3499 SUBPANEL_HELP_TOPIC, subpanel_parse_functions);
3500 InitializeField (element_values,
3501 SUBPANEL_HELP_VOLUME, subpanel_parse_functions);