mirror of
git://git.code.sf.net/p/cdesktopenv/code
synced 2025-03-09 15:50:02 +00:00
3503 lines
104 KiB
C
3503 lines
104 KiB
C
/*
|
|
* CDE - Common Desktop Environment
|
|
*
|
|
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
|
|
*
|
|
* These libraries and programs are free software; you can
|
|
* redistribute them and/or modify them under the terms of the GNU
|
|
* Lesser General Public License as published by the Free Software
|
|
* Foundation; either version 2 of the License, or (at your option)
|
|
* any later version.
|
|
*
|
|
* These libraries and programs are distributed in the hope that
|
|
* they will be useful, but WITHOUT ANY WARRANTY; without even the
|
|
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
|
* PURPOSE. See the GNU Lesser General Public License for more
|
|
* details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with these librararies and programs; if not, write
|
|
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
|
|
* Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
/* $TOG: DataBaseLoad.c /main/9 1998/01/12 16:46:23 cshi $ */
|
|
/*****************************************************************************
|
|
*
|
|
* File: DataBaseLoad.c
|
|
*
|
|
* Project: CDE
|
|
*
|
|
* Description: This file contains the functions which load and parse
|
|
* the front panel databases.
|
|
*
|
|
* (c) Copyright 1993, 1994 Hewlett-Packard Company
|
|
* (c) Copyright 1993, 1994 International Business Machines Corp.
|
|
* (c) Copyright 1993, 1994 Sun Microsystems, Inc.
|
|
* (c) Copyright 1993, 1994 Unix System Labs, Inc., a subsidiary of Novell, Inc.
|
|
*
|
|
*
|
|
****************************************************************************/
|
|
|
|
#include <X11/Xlib.h>
|
|
#include <X11/Xresource.h> /* XrmQuark */
|
|
#include <Dt/DtP.h> /* required for DtDirPaths type */
|
|
#include <Dt/DbReader.h> /* required for DtDbPathId type */
|
|
#include <Dt/Connect.h> /* required for DtDbPathId type */
|
|
#include <Dt/Dts.h>
|
|
#include <Dt/Utility.h>
|
|
#include <Dt/IconFile.h>
|
|
#include <Dt/Icon.h>
|
|
#include <Dt/UserMsg.h>
|
|
|
|
#include "WmParse.h"
|
|
#include "WmPanelP.h"
|
|
#include "DataBaseLoad.h"
|
|
#include "Parse.h"
|
|
#include "UI.h"
|
|
|
|
#include <pwd.h>
|
|
#include <fcntl.h>
|
|
#include <sys/stat.h>
|
|
|
|
|
|
/************************************************************************
|
|
*
|
|
* panel is the global top of the panel tree structure.
|
|
*
|
|
* switch is a local that is held until the hierary is built.
|
|
*
|
|
************************************************************************/
|
|
|
|
PanelData panel;
|
|
static SwitchData * switch1;
|
|
static ElementValue * control_element_values = NULL;
|
|
static Boolean control_element_value_found = False;
|
|
|
|
|
|
|
|
#define ANY_CONTAINER_TYPE 99
|
|
|
|
static char * TYPES_DIR = "/.dt/types/fp_dynamic/";
|
|
static char * TYPES_DIR_NO_SLASH = "/.dt/types/fp_dynamic";
|
|
static char * HOME_DIR = NULL;
|
|
static char * RM = "/bin/rm";
|
|
|
|
|
|
typedef Boolean (*FieldParse)(char *, void **);
|
|
typedef void (*FieldFree)(void **);
|
|
|
|
typedef struct
|
|
{
|
|
FieldParse parse_function;
|
|
void * default_value;
|
|
FieldFree free_function;
|
|
} ParseFunction;
|
|
|
|
|
|
|
|
|
|
/************************************************************************
|
|
*
|
|
* Definitions and structure initializations for PANEL record type.
|
|
*
|
|
************************************************************************/
|
|
|
|
static char * panel_keywords[] =
|
|
{
|
|
"PANEL",
|
|
"PANEL_GEOMETRY",
|
|
"DISPLAY_HANDLES",
|
|
"DISPLAY_MENU",
|
|
"DISPLAY_MINIMIZE",
|
|
"RESOLUTION",
|
|
"CONTROL_BEHAVIOR",
|
|
"DISPLAY_CONTROL_LABELS",
|
|
"SUBPANEL_UNPOST",
|
|
"LOCKED",
|
|
"HELP_STRING",
|
|
"HELP_VOLUME",
|
|
"HELP_TOPIC",
|
|
};
|
|
|
|
static ParseFunction panel_parse_functions[] =
|
|
{
|
|
{ StringToString, NULL, FreeString}, /* Name */
|
|
{ StringToString, NULL, FreeString}, /* Panel Geometry */
|
|
{ StringToBoolean, (void *) True, NULL}, /* Display Handles */
|
|
{ StringToBoolean, (void *) True, NULL}, /* Display Menu */
|
|
{ StringToBoolean, (void *) True, NULL}, /* Display Minimize */
|
|
{ StringToResolution, (void *) 3, NULL}, /* Resolution */
|
|
{ StringToControlBehavior, (void *) 0, NULL}, /* Control Behavior */
|
|
{ StringToBoolean, (void *) False, NULL}, /* Display Control Labels */
|
|
{ StringToBoolean, (void *) True, NULL}, /* Subpanel Unpost */
|
|
{ StringToBoolean, (void *) False, NULL}, /* Locked */
|
|
{ StringToString, NULL, FreeString}, /* Help String */
|
|
{ StringToString, NULL, FreeString}, /* Help Volume */
|
|
{ StringToString, NULL, FreeString}, /* Help Topic */
|
|
};
|
|
|
|
|
|
/************************************************************************
|
|
*
|
|
* Definitions and structure initializations for BOX record type.
|
|
*
|
|
************************************************************************/
|
|
|
|
static char * box_keywords[] =
|
|
{
|
|
"BOX",
|
|
"CONTAINER_NAME",
|
|
"POSITION_HINTS",
|
|
"LOCKED",
|
|
"DELETE",
|
|
"HELP_STRING",
|
|
"HELP_VOLUME",
|
|
"HELP_TOPIC",
|
|
};
|
|
|
|
static ParseFunction box_parse_functions[] =
|
|
{
|
|
{StringToString, NULL, FreeString}, /* Name */
|
|
{StringToString, NULL, FreeString}, /* Container Name */
|
|
{StringToPositionHints, (void *) 0, NULL}, /* Position Hints */
|
|
{StringToBoolean, (void *) False, NULL}, /* Locked */
|
|
{StringToBoolean, (void *) False, NULL}, /* Delete */
|
|
{StringToString, NULL, FreeString}, /* Help String */
|
|
{StringToString, NULL, FreeString}, /* Help Volume */
|
|
{StringToString, NULL, FreeString}, /* Help Topic */
|
|
};
|
|
|
|
|
|
/************************************************************************
|
|
*
|
|
* Definitions and structure initializations for SUBPANEL record type.
|
|
*
|
|
************************************************************************/
|
|
|
|
static char * subpanel_keywords[] =
|
|
{
|
|
"SUBPANEL",
|
|
"CONTAINER_NAME",
|
|
"CONTROL_INSTALL",
|
|
"TITLE",
|
|
"LOCKED",
|
|
"DELETE",
|
|
"HELP_STRING",
|
|
"HELP_VOLUME",
|
|
"HELP_TOPIC",
|
|
};
|
|
|
|
static ParseFunction subpanel_parse_functions[] =
|
|
{
|
|
{ StringToString, NULL, FreeString}, /* Name */
|
|
{ StringToString, NULL, FreeString}, /* Container Name */
|
|
{ StringToBoolean, (void *) True, NULL}, /* Control Install */
|
|
{ StringToString, NULL, FreeString}, /* Title */
|
|
{ StringToBoolean, (void *) False, NULL}, /* Locked */
|
|
{ StringToBoolean, (void *) False, NULL}, /* Delete */
|
|
{ StringToString, NULL, FreeString}, /* Help String */
|
|
{ StringToString, NULL, FreeString}, /* Help Volume */
|
|
{ StringToString, NULL, FreeString}, /* Help Topic */
|
|
};
|
|
|
|
|
|
/************************************************************************
|
|
*
|
|
* Definitions and structure initializations for SWITCH record type.
|
|
*
|
|
************************************************************************/
|
|
|
|
static char * switch_keywords[] =
|
|
{
|
|
"SWITCH",
|
|
"CONTAINER_NAME",
|
|
"POSITION_HINTS",
|
|
"NUMBER_OF_ROWS",
|
|
"LOCKED",
|
|
"DELETE",
|
|
"HELP_STRING",
|
|
"HELP_VOLUME",
|
|
"HELP_TOPIC",
|
|
};
|
|
|
|
|
|
static ParseFunction switch_parse_functions[] =
|
|
{
|
|
{ StringToString, NULL, FreeString}, /* Name */
|
|
{ StringToString, NULL, FreeString}, /* Container Name */
|
|
{ StringToPositionHints, (void *) 0, NULL}, /* Position Hints */
|
|
{ StringToInt, (void *) 2, NULL}, /* Number of Rows */
|
|
{ StringToBoolean, (void *) False, NULL}, /* Locked */
|
|
{ StringToBoolean, (void *) False, NULL}, /* Delete */
|
|
{ StringToString, NULL, FreeString}, /* Help String */
|
|
{ StringToString, NULL, FreeString}, /* Help Volume */
|
|
{ StringToString, NULL, FreeString}, /* Help Topic */
|
|
};
|
|
|
|
|
|
/************************************************************************
|
|
*
|
|
* Definitions and structure initializations for CONTROL record type.
|
|
*
|
|
************************************************************************/
|
|
|
|
static char * control_keywords[] =
|
|
{
|
|
"CONTROL",
|
|
"TYPE",
|
|
"CONTAINER_TYPE",
|
|
"CONTAINER_NAME",
|
|
"POSITION_HINTS",
|
|
"ICON",
|
|
"ALTERNATE_ICON",
|
|
"LABEL",
|
|
"PUSH_ACTION",
|
|
"PUSH_ANIMATION",
|
|
"DROP_ACTION",
|
|
"DROP_ANIMATION",
|
|
"PUSH_RECALL",
|
|
"MONITOR_TYPE",
|
|
"CLIENT_NAME",
|
|
"CLIENT_GEOMETRY",
|
|
"FILE_NAME",
|
|
"DATE_FORMAT",
|
|
"LOCKED",
|
|
"DELETE",
|
|
"HELP_STRING",
|
|
"HELP_VOLUME",
|
|
"HELP_TOPIC",
|
|
};
|
|
|
|
static ParseFunction control_parse_functions[] =
|
|
{
|
|
{StringToString, NULL, FreeString}, /* Name */
|
|
{StringToControlType, (void *)CONTROL_ICON, NULL}, /* Type */
|
|
{StringToControlContainerType, NULL, NULL}, /* Container Type */
|
|
{StringToString, NULL, FreeString}, /* Container Name */
|
|
{StringToPositionHints,(void *) 0, NULL}, /* Position Hints */
|
|
{StringToString, NULL, FreeString}, /* Image */
|
|
{StringToString, NULL, FreeString}, /* Altername Image */
|
|
{StringToString, NULL, FreeString}, /* Label */
|
|
{StringToAction, NULL, FreeAction}, /* Push Action */
|
|
{StringToString, NULL, FreeString}, /* Push Animation */
|
|
{StringToAction, NULL, FreeAction}, /* Drop Action */
|
|
{StringToString, NULL, FreeString}, /* Drop Animation */
|
|
{StringToBoolean, (void *) False, NULL}, /* Push Recall */
|
|
{StringToMonitorType, (void *) MONITOR_NONE,NULL}, /* Monitor Type */
|
|
{StringToString, NULL, FreeString}, /* Client Name */
|
|
{StringToGeometry, NULL, FreeGeometry}, /* Client Geometry */
|
|
{StringToFileName, NULL, FreeString}, /* File Name */
|
|
{StringToString, NULL, FreeString}, /* Date Format */
|
|
{StringToBoolean, (void *) False, NULL}, /* Locked */
|
|
{StringToBoolean, (void *) False, NULL}, /* Delete */
|
|
{StringToString, NULL, FreeString}, /* Help String */
|
|
{StringToString, NULL, FreeString}, /* Help Volume */
|
|
{StringToString, NULL, FreeString}, /* Help Topic */
|
|
};
|
|
|
|
|
|
|
|
/************************************************************************
|
|
*
|
|
* Structure definition and initialization for the front panel
|
|
* keyword lists.
|
|
*
|
|
************************************************************************/
|
|
|
|
char * entry_types[] =
|
|
{
|
|
"PANEL",
|
|
"BOX",
|
|
"SUBPANEL",
|
|
"SWITCH",
|
|
"CONTROL"
|
|
};
|
|
|
|
char * control_types[] =
|
|
{
|
|
"blank",
|
|
"busy",
|
|
"icon",
|
|
"client",
|
|
"clock",
|
|
"date",
|
|
"file",
|
|
};
|
|
|
|
|
|
char * resolution_types[] =
|
|
{
|
|
"high",
|
|
"medium",
|
|
"low",
|
|
"match_display"
|
|
};
|
|
|
|
char * monitor_types[] =
|
|
{
|
|
"none",
|
|
"mail",
|
|
"file",
|
|
};
|
|
|
|
#define ANIMATION "ANIMATION"
|
|
|
|
typedef struct
|
|
{
|
|
char * record_keyword;
|
|
int keyword_count;
|
|
char ** field_keywords;
|
|
ParseFunction * parse_functions;
|
|
} RecordKeywords;
|
|
|
|
|
|
static RecordKeywords record_keywords[] =
|
|
{
|
|
{ "PANEL", PANEL_KEYWORD_COUNT,
|
|
panel_keywords, panel_parse_functions },
|
|
|
|
{ "BOX", BOX_KEYWORD_COUNT,
|
|
box_keywords, box_parse_functions },
|
|
|
|
{ "SUBPANEL", SUBPANEL_KEYWORD_COUNT,
|
|
subpanel_keywords, subpanel_parse_functions },
|
|
|
|
{ "SWITCH", SWITCH_KEYWORD_COUNT,
|
|
switch_keywords, switch_parse_functions },
|
|
|
|
{ "CONTROL", CONTROL_KEYWORD_COUNT,
|
|
control_keywords, control_parse_functions },
|
|
};
|
|
|
|
|
|
/************************************************************************
|
|
*
|
|
* Static and external function definitions
|
|
*
|
|
************************************************************************/
|
|
|
|
|
|
extern void WmFrontPanelSetBusy (Boolean);
|
|
extern char * _DtDbGetDataBaseEnv (void);
|
|
|
|
static Boolean PanelParseCB (DtDtsDbField *, DtDbPathId, char *, Boolean);
|
|
static Boolean BoxParseCB (DtDtsDbField *, DtDbPathId, char *, Boolean);
|
|
static Boolean SubpanelParseCB (DtDtsDbField *, DtDbPathId, char *, Boolean);
|
|
static Boolean SwitchParseCB (DtDtsDbField *, DtDbPathId, char *, Boolean);
|
|
static Boolean ControlParseCB (DtDtsDbField *, DtDbPathId, char *, Boolean);
|
|
static Boolean AnimationParseCB (DtDtsDbField *, DtDbPathId, char *, Boolean);
|
|
static Boolean ControlSingleParseCB(DtDtsDbField *, DtDbPathId, char *, Boolean);
|
|
static void ProcessRecord (DtDtsDbField *, ElementValue *);
|
|
static void AllocateRecordData (RecordData **, int, int *, int *);
|
|
static void ReorderByContainerType(RecordData *, int , int);
|
|
static void ReorderByContainerName(RecordData *, int , int, int);
|
|
static void ReorderByName(RecordData *, int , int, int);
|
|
static void ReorderByPosition(RecordData *, int , int, int, int);
|
|
static void OrderRecord (RecordData *, int, int);
|
|
static char ** GetNameList (RecordData *, int, int, int, int);
|
|
static void EliminateUnused (RecordData *, int *, char **, int, int, int, int);
|
|
static void EliminateDeleted (RecordData *, int *, int, int, int, int, int);
|
|
static void ResolveDuplicates (RecordData *, int *, int, int, int, int, int);
|
|
static void InitializeField (ElementValue *, int, ParseFunction *);
|
|
static void ProcessBox (BoxData *);
|
|
static int ProcessBoxControl (ControlData *);
|
|
static void ProcessSubpanel (SubpanelData *);
|
|
static void ProcessSwitch (SwitchData *);
|
|
static void ProcessControl (XtPointer, char, ControlData ***, int *, ElementValue *);
|
|
static void InitializePrimaryControlFields (ElementValue *);
|
|
static void InitializeSecondaryControlFields (ElementValue *);
|
|
static void InitializeFileControlFields (ElementValue *, char *);
|
|
|
|
|
|
|
|
/************************************************************************
|
|
*
|
|
* Variable and record declarations and initializations to keep track
|
|
* of the data base info as it is read and to be used as storage for
|
|
* subsequent parsing and reprocessing.
|
|
*
|
|
************************************************************************/
|
|
|
|
static int panel_count = 0;
|
|
static int panel_data_count = 0;
|
|
static RecordData * panel_data = NULL;
|
|
|
|
static int box_count = 0;
|
|
static int box_data_count = 0;
|
|
static RecordData * box_data = NULL;
|
|
|
|
static int subpanel_count = 0;
|
|
static int subpanel_data_count = 0;
|
|
static RecordData * subpanel_data = NULL;
|
|
|
|
static int switch_count = 0;
|
|
static int switch_data_count = 0;
|
|
static RecordData * switch_data = NULL;
|
|
|
|
static int control_count = 0;
|
|
static int control_data_count = 0;
|
|
static RecordData * control_data = NULL;
|
|
|
|
|
|
|
|
static DtDbConverter panel_converter[] = { (DtDbConverter) PanelParseCB,
|
|
NULL };
|
|
static DtDbConverter box_converter[] = { (DtDbConverter) BoxParseCB,
|
|
NULL };
|
|
static DtDbConverter subpanel_converter[] = { (DtDbConverter) SubpanelParseCB,
|
|
NULL };
|
|
static DtDbConverter switch_converter[] = { (DtDbConverter) SwitchParseCB,
|
|
NULL };
|
|
static DtDbConverter control_converter[] = { (DtDbConverter) ControlParseCB,
|
|
NULL };
|
|
static DtDbConverter animation_converter[] ={ (DtDbConverter) AnimationParseCB,
|
|
NULL };
|
|
|
|
static DtDbRecordDesc record_descriptor[] =
|
|
{
|
|
{ "PANEL", PANEL_KEYWORD_COUNT, panel_converter },
|
|
{ "BOX", BOX_KEYWORD_COUNT, box_converter },
|
|
{ "SUBPANEL", SUBPANEL_KEYWORD_COUNT, subpanel_converter },
|
|
{ "SWITCH", SWITCH_KEYWORD_COUNT, switch_converter },
|
|
{ "CONTROL", CONTROL_KEYWORD_COUNT, control_converter },
|
|
{ "ANIMATION", DTUNLIMITEDFIELDS, animation_converter }
|
|
};
|
|
|
|
static DtDbConverter control_single_converter[] =
|
|
{ (DtDbConverter) ControlSingleParseCB, NULL};
|
|
|
|
static DtDbRecordDesc control_record_descriptor[] =
|
|
{
|
|
{ "CONTROL", CONTROL_KEYWORD_COUNT, control_single_converter },
|
|
{ "ANIMATION", DTUNLIMITEDFIELDS, animation_converter }
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/************************************************************************
|
|
*
|
|
* FrontPanelReadDatabases
|
|
* Read in the front panel database, parse out each line, build
|
|
* the internal data structures that are then used to create the
|
|
* visual representation.
|
|
*
|
|
* Processing occurs in a series of steps:
|
|
*
|
|
* 1. Read in all of the database records and copy the unparsed
|
|
* string information into a structure.
|
|
* a. Group the records according to type.
|
|
* b. Group the records according to container.
|
|
* c. Ensure the original read order is maintained to process
|
|
* overrides.
|
|
*
|
|
* This step occurs out of the callback for each of the component
|
|
* types.
|
|
*
|
|
* 2. Eliminate the unused component definitions by working top-down
|
|
* throught the lists. Select the PANEL and SWITCH definition
|
|
* to be used at this time.
|
|
*
|
|
* 3. Eliminate overridden components by either selecting the first
|
|
* locked definition or if none are locked, selecting the last
|
|
* definition.
|
|
*
|
|
* 4. Reorder the component groups according to the position hints
|
|
*
|
|
* 5. Build hierarchical data structure from record sets, top-down.
|
|
* Fully parse each record as the structure is built.
|
|
*
|
|
*
|
|
* 6. Return.
|
|
*
|
|
************************************************************************/
|
|
|
|
Boolean
|
|
FrontPanelReadDatabases (void)
|
|
|
|
|
|
{
|
|
char * search_paths;
|
|
char * new_search_paths;
|
|
struct passwd * pw_info;
|
|
|
|
char * dynamic_dir;
|
|
struct stat stat_info;
|
|
int fd;
|
|
|
|
int i;
|
|
char * fp_database;
|
|
int num_entries;
|
|
char ** name_list;
|
|
DtDirPaths * dir_paths;
|
|
|
|
|
|
panel.animation_data = NULL;
|
|
panel.animation_count = 0;
|
|
|
|
|
|
|
|
/* Before reading the databases, add the front panel dynamic */
|
|
/* directory to the search path. */
|
|
|
|
search_paths = _DtDbGetDataBaseEnv();
|
|
|
|
if ((HOME_DIR = (char *) getenv ("HOME")) == NULL)
|
|
{
|
|
pw_info = getpwuid (getuid());
|
|
HOME_DIR = pw_info->pw_dir;
|
|
}
|
|
|
|
HOME_DIR = XtNewString (HOME_DIR);
|
|
|
|
new_search_paths =
|
|
XtMalloc (strlen ("DTDATABASESEARCHPATH") + strlen (HOME_DIR) +
|
|
strlen (TYPES_DIR_NO_SLASH) + strlen (search_paths) + 3);
|
|
sprintf (new_search_paths, "%s=%s%s,%s",
|
|
"DTDATABASESEARCHPATH", HOME_DIR, TYPES_DIR_NO_SLASH, search_paths);
|
|
putenv (new_search_paths);
|
|
|
|
XtFree (search_paths);
|
|
|
|
|
|
/* See if the fp_dynamic directory exists. If not, create it */
|
|
|
|
dynamic_dir = XtMalloc (strlen (HOME_DIR) + strlen (TYPES_DIR) + 3);
|
|
sprintf (dynamic_dir, "%s%s", HOME_DIR, TYPES_DIR);
|
|
|
|
if (lstat (dynamic_dir, &stat_info) != 0)
|
|
if ((fd=mkdir (dynamic_dir, S_IRWXU | S_IRGRP | S_IROTH |
|
|
S_IXGRP | S_IXOTH)) != 0)
|
|
{
|
|
|
|
}
|
|
|
|
XtFree ((char *) dynamic_dir);
|
|
|
|
|
|
/* Read the database and do the initial set of processing on */
|
|
/* the file based information. This work occurs within the */
|
|
/* callback function referenced in the data read call. */
|
|
|
|
dir_paths = _DtGetDatabaseDirPaths();
|
|
|
|
#ifdef DT_PERFORMANCE
|
|
_DtPerfChkpntMsgSend("Begin Front panel database read");
|
|
#endif
|
|
|
|
_DtDbRead (dir_paths, FILE_TYPE_SUFFIX, record_descriptor, 6);
|
|
|
|
#ifdef DT_PERFORMANCE
|
|
_DtPerfChkpntMsgSend("End Front panel database read");
|
|
#endif
|
|
|
|
if (panel_count == 0)
|
|
{
|
|
_DtFreeDatabaseDirPaths (dir_paths);
|
|
return False;
|
|
}
|
|
|
|
/* Once all of the PANEL records have been read in, select the panel */
|
|
/* record that is to be used to build the front panel. */
|
|
/* */
|
|
/* This selection is done by first scanning the list to find a LOCKED */
|
|
/* panel. The first one found is selected. If none are found, the */
|
|
/* last panel read is selectd. */
|
|
|
|
for (i = panel_count - 1; i > 0; i--)
|
|
{
|
|
if ((intptr_t)(panel_data[i].element_values[PANEL_LOCKED].parsed_value))
|
|
break;
|
|
}
|
|
|
|
panel.element_values = panel_data[i].element_values;
|
|
|
|
|
|
/* Parse out additional panel element values */
|
|
|
|
InitializeField (panel.element_values, PANEL_GEOMETRY, panel_parse_functions);
|
|
InitializeField (panel.element_values, PANEL_DISPLAY_HANDLES, panel_parse_functions);
|
|
InitializeField (panel.element_values, PANEL_DISPLAY_MENU, panel_parse_functions);
|
|
InitializeField (panel.element_values, PANEL_DISPLAY_MINIMIZE, panel_parse_functions);
|
|
InitializeField (panel.element_values, PANEL_RESOLUTION, panel_parse_functions);
|
|
InitializeField (panel.element_values, PANEL_CONTROL_BEHAVIOR, panel_parse_functions);
|
|
InitializeField (panel.element_values, PANEL_DISPLAY_CONTROL_LABELS, panel_parse_functions);
|
|
InitializeField (panel.element_values, PANEL_SUBPANEL_UNPOST, panel_parse_functions);
|
|
InitializeField (panel.element_values, PANEL_HELP_STRING, panel_parse_functions);
|
|
InitializeField (panel.element_values, PANEL_HELP_TOPIC, panel_parse_functions);
|
|
InitializeField (panel.element_values, PANEL_HELP_VOLUME, panel_parse_functions);
|
|
|
|
XtFree ((char *) panel_data);
|
|
|
|
|
|
/* Eliminate the records within the other component types that */
|
|
/* are not part of this selected panel. */
|
|
/* */
|
|
/* This elimination occurs top down because boxes have to be */
|
|
/* removed before controls can be removed... */
|
|
|
|
name_list = (char **) XtMalloc (sizeof (char **) * 2);
|
|
name_list[0] = panel.element_values[PANEL_NAME].parsed_value;
|
|
name_list[1] = NULL;
|
|
EliminateUnused (box_data, &box_count, name_list, BOX_CONTAINER_NAME,
|
|
ANY_CONTAINER_TYPE, PANEL, BOX);
|
|
XtFree ((char *) name_list);
|
|
|
|
/* Remove entries that have the deleted keyword set to True unless */
|
|
/* it is a locked file. */
|
|
EliminateDeleted (box_data, &box_count, BOX_CONTAINER_NAME,
|
|
BOX_NAME, BOX, BOX_DELETE, BOX_LOCKED);
|
|
EliminateDeleted (switch_data, &switch_count, SWITCH_CONTAINER_NAME,
|
|
SWITCH_NAME, SWITCH, SWITCH_DELETE, SWITCH_LOCKED);
|
|
EliminateDeleted (subpanel_data, &subpanel_count, SUBPANEL_CONTAINER_NAME,
|
|
SUBPANEL_NAME, SUBPANEL, SUBPANEL_DELETE, SUBPANEL_LOCKED);
|
|
EliminateDeleted (control_data, &control_count, CONTROL_CONTAINER_NAME,
|
|
CONTROL_NAME, CONTROL, CONTROL_DELETE, CONTROL_LOCKED);
|
|
|
|
name_list = GetNameList (box_data, box_count,
|
|
BOX_NAME, ANY_CONTAINER_TYPE, 0);
|
|
|
|
EliminateUnused(switch_data, &switch_count, name_list,
|
|
SWITCH_CONTAINER_NAME, ANY_CONTAINER_TYPE,
|
|
BOX, SWITCH);
|
|
|
|
EliminateUnused(control_data, &control_count, name_list,
|
|
CONTROL_CONTAINER_NAME, CONTROL_CONTAINER_TYPE,
|
|
BOX, CONTROL);
|
|
|
|
XtFree ((char *) name_list);
|
|
|
|
|
|
/* Once the elimination of superfluous switch definitions is complete, */
|
|
/* make the selection of the single Switch. This makes the elimination */
|
|
/* of the switch based controls efficient. */
|
|
/* */
|
|
/* This selection is done by first scanning the list to find a LOCKED */
|
|
/* switch. The first one found is selected. If none are found, the */
|
|
/* last switch read is selected. */
|
|
|
|
if (switch_count != 0) {
|
|
for (i = switch_count - 1; i > 0; i--)
|
|
{
|
|
if ((intptr_t)(switch_data[i].element_values[SWITCH_LOCKED].parsed_value))
|
|
break;
|
|
}
|
|
|
|
switch1 = (SwitchData *) XtMalloc (sizeof (SwitchData));
|
|
switch1->element_values = switch_data[i].element_values;
|
|
switch1->control_data = NULL;
|
|
switch1->control_data_count = 0;
|
|
switch1->rc = NULL;
|
|
switch1->buttons = NULL;
|
|
switch1->atom_names = NULL;
|
|
switch1->switch_names = NULL;
|
|
switch1->switch_count = 0;
|
|
switch1->active_switch = 0;
|
|
switch1->popup_data = NULL;
|
|
|
|
|
|
/* Parse the remaining database values for the switch */
|
|
|
|
InitializeField (switch1->element_values, SWITCH_POSITION_HINTS, switch_parse_functions);
|
|
InitializeField (switch1->element_values, SWITCH_NUMBER_OF_ROWS, switch_parse_functions);
|
|
InitializeField (switch1->element_values, SWITCH_HELP_STRING, switch_parse_functions);
|
|
InitializeField (switch1->element_values, SWITCH_HELP_TOPIC, switch_parse_functions);
|
|
InitializeField (switch1->element_values, SWITCH_HELP_STRING, switch_parse_functions);
|
|
}
|
|
|
|
XtFree ((char *) switch_data);
|
|
|
|
|
|
/* Continue the elimination of unused records */
|
|
|
|
name_list = (char **) XtMalloc (sizeof (char **) * 2);
|
|
if (switch_count != 0)
|
|
name_list[0] = switch1->element_values[SWITCH_NAME].parsed_value;
|
|
else
|
|
name_list[0] = NULL;
|
|
name_list[1] = NULL;
|
|
EliminateUnused (control_data, &control_count, name_list,
|
|
CONTROL_CONTAINER_NAME, CONTROL_CONTAINER_TYPE,
|
|
SWITCH, CONTROL);
|
|
XtFree ((char *)name_list);
|
|
|
|
name_list = GetNameList (control_data, control_count,
|
|
CONTROL_NAME, CONTROL_CONTAINER_TYPE, BOX);
|
|
|
|
EliminateUnused (subpanel_data, &subpanel_count, name_list,
|
|
SUBPANEL_CONTAINER_NAME, ANY_CONTAINER_TYPE,
|
|
CONTROL, SUBPANEL);
|
|
XtFree ((char *)name_list);
|
|
|
|
name_list = GetNameList (subpanel_data, subpanel_count,
|
|
SUBPANEL_NAME, ANY_CONTAINER_TYPE, SUBPANEL);
|
|
|
|
EliminateUnused (control_data, &control_count, name_list,
|
|
CONTROL_CONTAINER_NAME, CONTROL_CONTAINER_TYPE,
|
|
SUBPANEL, CONTROL);
|
|
|
|
XtFree ((char *)name_list);
|
|
|
|
|
|
/* The record types of CONTROL, SUBPANEL and BOX still have need */
|
|
/* several steps of processing. */
|
|
|
|
ReorderByContainerType(control_data, control_count, CONTROL_CONTAINER_TYPE);
|
|
|
|
ReorderByContainerName(control_data, control_count, CONTROL_CONTAINER_NAME,
|
|
CONTROL_CONTAINER_TYPE);
|
|
|
|
ReorderByName(box_data, box_count, BOX_NAME, BOX_CONTAINER_NAME);
|
|
|
|
ReorderByName(control_data, control_count, CONTROL_NAME,
|
|
CONTROL_CONTAINER_NAME);
|
|
|
|
#ifdef DEBUG
|
|
for (i = 0; i < control_count; i++) {
|
|
printf("control %s, %d, %s\n",
|
|
control_data[i].element_values[CONTROL_CONTAINER_NAME].parsed_value,
|
|
control_data[i].element_values[CONTROL_CONTAINER_TYPE].parsed_value,
|
|
control_data[i].element_values[CONTROL_NAME].parsed_value);
|
|
}
|
|
#endif
|
|
|
|
|
|
/* Reprocess each of these groups to eliminate overridden */
|
|
/* components. If a component is locked, use the first lock */
|
|
/* encountered. Otherwise, use the last component read. */
|
|
|
|
ResolveDuplicates (box_data, &box_count, BOX_NAME,
|
|
ANY_CONTAINER_TYPE, BOX_CONTAINER_NAME,
|
|
BOX_LOCKED, BOX);
|
|
ResolveDuplicates (subpanel_data, &subpanel_count, SUBPANEL_NAME,
|
|
ANY_CONTAINER_TYPE, SUBPANEL_CONTAINER_NAME,
|
|
SUBPANEL_LOCKED, SUBPANEL);
|
|
ResolveDuplicates (control_data, &control_count, CONTROL_NAME,
|
|
CONTROL_CONTAINER_TYPE, CONTROL_CONTAINER_NAME,
|
|
CONTROL_LOCKED, CONTROL);
|
|
|
|
/* Now that the elimination has been completed, initialize the */
|
|
/* remaining values for each of the components. */
|
|
|
|
for (i = 0; i < box_count; i++)
|
|
{
|
|
InitializeField (box_data[i].element_values,
|
|
BOX_POSITION_HINTS, box_parse_functions);
|
|
InitializeField (box_data[i].element_values,
|
|
BOX_HELP_STRING, box_parse_functions);
|
|
InitializeField (box_data[i].element_values,
|
|
BOX_HELP_TOPIC, box_parse_functions);
|
|
InitializeField (box_data[i].element_values,
|
|
BOX_HELP_VOLUME, box_parse_functions);
|
|
}
|
|
|
|
for (i = 0; i < subpanel_count; i++)
|
|
{
|
|
InitializeField (subpanel_data[i].element_values,
|
|
SUBPANEL_CONTROL_INSTALL, subpanel_parse_functions);
|
|
InitializeField (subpanel_data[i].element_values,
|
|
SUBPANEL_TITLE, subpanel_parse_functions);
|
|
InitializeField (subpanel_data[i].element_values,
|
|
SUBPANEL_HELP_STRING, subpanel_parse_functions);
|
|
InitializeField (subpanel_data[i].element_values,
|
|
SUBPANEL_HELP_TOPIC, subpanel_parse_functions);
|
|
InitializeField (subpanel_data[i].element_values,
|
|
SUBPANEL_HELP_VOLUME, subpanel_parse_functions);
|
|
}
|
|
|
|
for (i = 0; i < control_count; i++)
|
|
{
|
|
InitializeSecondaryControlFields (control_data[i].element_values);
|
|
InitializeFileControlFields (control_data[i].element_values, NULL);
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
for (i = 0; i < box_count; i++) {
|
|
printf("box %d = %s\n",
|
|
box_data[i].element_values[BOX_POSITION_HINTS].parsed_value,
|
|
box_data[i].element_values[BOX_NAME].parsed_value);
|
|
}
|
|
|
|
for (i = 0; i < subpanel_count; i++) {
|
|
printf("subpanel = %s\n",
|
|
subpanel_data[i].element_values[SUBPANEL_NAME].parsed_value);
|
|
}
|
|
|
|
for (i = 0; i < control_count; i++) {
|
|
printf("control %d = %s\n",
|
|
control_data[i].element_values[CONTROL_POSITION_HINTS].parsed_value,
|
|
control_data[i].element_values[CONTROL_NAME].parsed_value);
|
|
}
|
|
#endif
|
|
|
|
/* Reorder subgroups according to position hints. */
|
|
|
|
ReorderByPosition (box_data, box_count, BOX_POSITION_HINTS,
|
|
ANY_CONTAINER_TYPE, BOX_CONTAINER_NAME);
|
|
ReorderByPosition (control_data, control_count, CONTROL_POSITION_HINTS,
|
|
CONTROL_CONTAINER_TYPE, CONTROL_CONTAINER_NAME);
|
|
|
|
#ifdef DEBUG
|
|
printf("**************************************************************\n\n");
|
|
|
|
for (i = 0; i < box_count; i++) {
|
|
printf("box %d = %s\n", (int)
|
|
box_data[i].element_values[BOX_POSITION_HINTS].parsed_value,
|
|
box_data[i].element_values[BOX_NAME].parsed_value);
|
|
}
|
|
|
|
for (i = 0; i < control_count; i++) {
|
|
printf("control %d = %s\n", (int)
|
|
control_data[i].element_values[CONTROL_POSITION_HINTS].parsed_value,
|
|
control_data[i].element_values[CONTROL_NAME].parsed_value);
|
|
}
|
|
#endif
|
|
|
|
|
|
/* Build hierarchical data structure from record sets, top-down. */
|
|
/* Fully parse each record as the structure is built. */
|
|
|
|
panel.box_data = (BoxData **) XtMalloc (sizeof (BoxData *) * box_count);
|
|
panel.box_data_count = box_count;
|
|
|
|
for (i = 0; i < box_count; i++)
|
|
{
|
|
BoxData * box;
|
|
|
|
panel.box_data[i] = (BoxData *) XtMalloc (sizeof (BoxData));
|
|
box = panel.box_data[i];
|
|
|
|
box->element_values = box_data[i].element_values;
|
|
box->control_data = NULL;
|
|
box->control_data_count = 0;
|
|
box->form = NULL;
|
|
box->left_arrow_form = NULL;
|
|
box->left_control_form = NULL;
|
|
box->right_arrow_form = NULL;
|
|
box->right_control_form = NULL;
|
|
box->switch_data = NULL;
|
|
box->switch_form = NULL;
|
|
box->switch_edit = NULL;
|
|
box->subpanel_count = 0;
|
|
|
|
|
|
if (switch_count != 0 &&
|
|
strcmp ((char *) box->element_values[BOX_NAME].parsed_value,
|
|
(char *) switch1->element_values[SWITCH_CONTAINER_NAME].parsed_value) == 0)
|
|
{
|
|
box->switch_data = switch1;
|
|
switch1->box_data = box;
|
|
ProcessSwitch (box->switch_data);
|
|
}
|
|
|
|
|
|
/* Call a function to process each box, allocating the control */
|
|
/* data structures needed for them and calling functions to */
|
|
/* further process each control. */
|
|
|
|
ProcessBox (box);
|
|
}
|
|
|
|
XtFree ((char *) box_data);
|
|
_DtFreeDatabaseDirPaths (dir_paths);
|
|
|
|
return True;
|
|
}
|
|
|
|
|
|
|
|
|
|
/************************************************************************
|
|
*
|
|
* PanelParseCB
|
|
* Allocate a structure to contain the Panel record returned by
|
|
* the database read code and copy the record information into the
|
|
* structure.
|
|
*
|
|
************************************************************************/
|
|
|
|
static Boolean
|
|
PanelParseCB (DtDtsDbField * fields,
|
|
DtDbPathId path_id,
|
|
char * host_prefix,
|
|
Boolean rejection)
|
|
|
|
{
|
|
AllocateRecordData (&panel_data,
|
|
sizeof (ElementValue) * PANEL_KEYWORD_COUNT,
|
|
&panel_data_count, &panel_count);
|
|
|
|
ProcessRecord (fields, (ElementValue *)
|
|
panel_data[panel_count - 1].element_values);
|
|
|
|
InitializeField (panel_data[panel_count - 1].element_values,
|
|
PANEL_NAME, panel_parse_functions);
|
|
InitializeField (panel_data[panel_count - 1].element_values,
|
|
PANEL_LOCKED, panel_parse_functions);
|
|
|
|
return (True);
|
|
}
|
|
|
|
|
|
|
|
|
|
/************************************************************************
|
|
*
|
|
* BoxParseCB
|
|
* Allocate a structure to contain the Box record returned by
|
|
* the database read code and copy the record information into the
|
|
* structure.
|
|
*
|
|
************************************************************************/
|
|
|
|
static Boolean
|
|
BoxParseCB (DtDtsDbField * fields,
|
|
DtDbPathId path_id,
|
|
char * host_prefix,
|
|
Boolean rejection)
|
|
|
|
|
|
{
|
|
AllocateRecordData (&box_data,
|
|
sizeof (ElementValue) * BOX_KEYWORD_COUNT,
|
|
&box_data_count, &box_count);
|
|
|
|
ProcessRecord (fields, box_data[box_count - 1].element_values);
|
|
|
|
InitializeField (box_data[box_count - 1].element_values,
|
|
BOX_NAME, box_parse_functions);
|
|
InitializeField (box_data[box_count - 1].element_values,
|
|
BOX_CONTAINER_NAME, box_parse_functions);
|
|
InitializeField (box_data[box_count - 1].element_values,
|
|
BOX_LOCKED, box_parse_functions);
|
|
InitializeField (box_data[box_count - 1].element_values,
|
|
BOX_DELETE, box_parse_functions);
|
|
|
|
OrderRecord (box_data, box_count, BOX_CONTAINER_NAME);
|
|
|
|
return (True);
|
|
}
|
|
|
|
|
|
|
|
|
|
/************************************************************************
|
|
*
|
|
* SubpanelParseCB
|
|
* Allocate a structure to contain the Subpanel record returned by
|
|
* the database read code and copy the record information into the
|
|
* structure.
|
|
*
|
|
************************************************************************/
|
|
|
|
static Boolean
|
|
SubpanelParseCB (DtDtsDbField * fields,
|
|
DtDbPathId path_id,
|
|
char * host_prefix,
|
|
Boolean rejection)
|
|
|
|
{
|
|
AllocateRecordData (&subpanel_data,
|
|
sizeof (ElementValue) * SUBPANEL_KEYWORD_COUNT,
|
|
&subpanel_data_count, &subpanel_count);
|
|
|
|
ProcessRecord (fields, subpanel_data[subpanel_count - 1].element_values);
|
|
|
|
InitializeField (subpanel_data[subpanel_count - 1].element_values,
|
|
SUBPANEL_NAME, subpanel_parse_functions);
|
|
InitializeField (subpanel_data[subpanel_count - 1].element_values,
|
|
SUBPANEL_CONTAINER_NAME, subpanel_parse_functions);
|
|
InitializeField (subpanel_data[subpanel_count - 1].element_values,
|
|
SUBPANEL_LOCKED, subpanel_parse_functions);
|
|
InitializeField (subpanel_data[subpanel_count - 1].element_values,
|
|
SUBPANEL_DELETE, subpanel_parse_functions);
|
|
|
|
OrderRecord (subpanel_data, subpanel_count, SUBPANEL_CONTAINER_NAME);
|
|
|
|
return (True);
|
|
}
|
|
|
|
|
|
|
|
|
|
/************************************************************************
|
|
*
|
|
* SwitchParseCB
|
|
* Allocate a structure to contain the Switch record returned by
|
|
* the database read code and copy the record information into the
|
|
* structure.
|
|
*
|
|
************************************************************************/
|
|
|
|
static Boolean
|
|
SwitchParseCB (DtDtsDbField * fields,
|
|
DtDbPathId path_id,
|
|
char * host_prefix,
|
|
Boolean rejection)
|
|
|
|
{
|
|
AllocateRecordData (&switch_data,
|
|
sizeof (ElementValue) * SWITCH_KEYWORD_COUNT,
|
|
&switch_data_count, &switch_count);
|
|
|
|
ProcessRecord (fields, switch_data[switch_count - 1].element_values);
|
|
|
|
InitializeField (switch_data[switch_count - 1].element_values,
|
|
SWITCH_NAME, switch_parse_functions);
|
|
InitializeField (switch_data[switch_count - 1].element_values,
|
|
SWITCH_CONTAINER_NAME, switch_parse_functions);
|
|
InitializeField (switch_data[switch_count - 1].element_values,
|
|
SWITCH_LOCKED, switch_parse_functions);
|
|
InitializeField (switch_data[switch_count - 1].element_values,
|
|
SWITCH_DELETE, switch_parse_functions);
|
|
|
|
OrderRecord (switch_data, switch_count, SWITCH_CONTAINER_NAME);
|
|
|
|
return (True);
|
|
}
|
|
|
|
|
|
|
|
/************************************************************************
|
|
*
|
|
* ControlParseCB
|
|
* Allocate a structure to contain the Control record returned by
|
|
* the database read code and copy the record information into the
|
|
* structure.
|
|
*
|
|
************************************************************************/
|
|
|
|
static Boolean
|
|
ControlParseCB (DtDtsDbField * fields,
|
|
DtDbPathId path_id,
|
|
char * host_prefix,
|
|
Boolean rejection)
|
|
|
|
{
|
|
AllocateRecordData (&control_data,
|
|
sizeof (ElementValue) * CONTROL_KEYWORD_COUNT,
|
|
&control_data_count, &control_count);
|
|
|
|
ProcessRecord (fields, control_data[control_count - 1].element_values);
|
|
|
|
InitializePrimaryControlFields
|
|
(control_data[control_count - 1].element_values);
|
|
|
|
OrderRecord (control_data, control_count, CONTROL_CONTAINER_NAME);
|
|
|
|
return (True);
|
|
}
|
|
|
|
|
|
|
|
|
|
/************************************************************************
|
|
*
|
|
* AnimationParseCB
|
|
* Allocate a structure to contain the Animation records returned by
|
|
* the database read code and copy the record information into the
|
|
* structure.
|
|
*
|
|
************************************************************************/
|
|
|
|
static Boolean
|
|
AnimationParseCB (DtDtsDbField * fields,
|
|
DtDbPathId path_id,
|
|
char * host_prefix,
|
|
Boolean rejection)
|
|
|
|
{
|
|
unsigned char *string, *source, *head_ptr;
|
|
char * field1;
|
|
char * field2;
|
|
int count = panel.animation_count;
|
|
int field_count = 0;
|
|
void * val_rtn;
|
|
int i;
|
|
XrmQuark animation_quark = XrmStringToQuark(ANIMATION);
|
|
|
|
panel.animation_data = (AnimationData *)
|
|
XtRealloc ((char *) panel.animation_data,
|
|
sizeof (AnimationData) * (count + 1));
|
|
|
|
panel.animation_data[count].name = strdup(fields[0].fieldValue);
|
|
|
|
|
|
for (i = 1; fields[i].fieldName != NULLQUARK; i++)
|
|
{
|
|
if (fields[i].fieldName == animation_quark)
|
|
field_count++;
|
|
}
|
|
|
|
panel.animation_data[count].item_count = field_count;
|
|
|
|
panel.animation_data[count].items = (AnimationItem *)
|
|
XtMalloc(sizeof(AnimationItem) * field_count);
|
|
|
|
for (i = 0; i < field_count; i++)
|
|
{
|
|
if (fields[i+1].fieldName == animation_quark)
|
|
{
|
|
head_ptr = source =
|
|
(unsigned char *) strdup((char *)fields[i+1].fieldValue);
|
|
|
|
if ((string = _DtWmParseNextTokenC(&source, False)) != NULL)
|
|
{
|
|
panel.animation_data[count].items[i].image_name =
|
|
strdup((char *) string);
|
|
if ((string = _DtWmParseNextTokenC(&source, False)) != NULL)
|
|
{
|
|
StringToInt((char *)string, &val_rtn);
|
|
panel.animation_data[count].items[i].delay = (int) (intptr_t) val_rtn;
|
|
}
|
|
else
|
|
{
|
|
panel.animation_data[count].items[i].delay = 0;
|
|
}
|
|
}
|
|
|
|
free((char *)head_ptr);
|
|
}
|
|
}
|
|
|
|
panel.animation_count++;
|
|
|
|
return (True);
|
|
}
|
|
|
|
|
|
|
|
/************************************************************************
|
|
*
|
|
* ControlSingleParseCB
|
|
* Allocate a structure to contain the Control record returned by
|
|
* the database read code and copy the record information into the
|
|
* structure.
|
|
*
|
|
************************************************************************/
|
|
|
|
static Boolean
|
|
ControlSingleParseCB (DtDtsDbField * fields,
|
|
DtDbPathId path_id,
|
|
char * host_prefix,
|
|
Boolean rejection)
|
|
|
|
{
|
|
if (control_element_value_found) {
|
|
return (True);
|
|
}
|
|
|
|
control_element_values = (ElementValue *) XtMalloc (sizeof(ElementValue) *
|
|
CONTROL_KEYWORD_COUNT);
|
|
control_element_value_found = True;
|
|
|
|
ProcessRecord (fields, control_element_values);
|
|
|
|
InitializeControlFields(control_element_values, NULL);
|
|
|
|
return (True);
|
|
}
|
|
|
|
|
|
|
|
|
|
/************************************************************************
|
|
*
|
|
* ProcessRecord
|
|
* Extract the fields of a returned record and put them into an
|
|
* allocated structure for latter processing.
|
|
*
|
|
************************************************************************/
|
|
|
|
static void
|
|
ProcessRecord (DtDtsDbField * fields,
|
|
ElementValue * element_values)
|
|
|
|
{
|
|
int i, j;
|
|
int entry;
|
|
|
|
int keyword_count;
|
|
char ** field_keywords;
|
|
|
|
|
|
/* Find the position in the record structure for the value of */
|
|
/* the entry keyword contained in the first position of the */
|
|
/* fields array */
|
|
|
|
for (entry = 0; entry < TOTAL_ENTRY_COUNT; entry++)
|
|
{
|
|
if (fields[0].fieldName == XrmStringToQuark(record_keywords[entry].record_keyword))
|
|
{
|
|
keyword_count = record_keywords[entry].keyword_count;
|
|
field_keywords = record_keywords[entry].field_keywords;
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
/* Initialize the element_values array */
|
|
|
|
for (i = 0; i < keyword_count; i++)
|
|
{
|
|
(element_values + i)->use_default = True;
|
|
(element_values + i)->string_value = NULL;
|
|
(element_values + i)->parsed_value = NULL;
|
|
}
|
|
|
|
|
|
/* Loop through each read in keyword value pair, comparing it */
|
|
/* to the keywords for this record type and when found, enter */
|
|
/* it into the element values array for the component. */
|
|
|
|
for (i = 0; fields[i].fieldName != NULLQUARK; i++)
|
|
{
|
|
XrmQuark field1 = fields[i].fieldName;
|
|
char * field2 = fields[i].fieldValue;
|
|
|
|
|
|
/* Search the field_keywords list and when the keyword is found */
|
|
/* make a copy of field2 and place in its position. */
|
|
|
|
for (j = 0; j < keyword_count; j++)
|
|
{
|
|
if (field1 == XrmStringToQuark(field_keywords[j]))
|
|
{
|
|
(element_values + j)->use_default = False;
|
|
(element_values + j)->string_value = strdup (field2);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (j == keyword_count)
|
|
_DtSimpleError (panel.app_name, DtWarning, NULL,
|
|
"Invalid keyword -- %s", XrmQuarkToString(field1));
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
/************************************************************************
|
|
*
|
|
* AllocateRecordData
|
|
* Allocate a structure to contain the values for a data base record
|
|
* and stuff it in an array for latter processing. Do all of this
|
|
* by indirection so that multiple record types can be handled.
|
|
*
|
|
************************************************************************/
|
|
|
|
static void
|
|
AllocateRecordData (RecordData ** record_data,
|
|
int record_size,
|
|
int * record_data_count,
|
|
int * record_count)
|
|
|
|
{
|
|
if (*record_count >= *record_data_count)
|
|
{
|
|
*record_data_count += 10;
|
|
*record_data = (RecordData *)
|
|
XtRealloc ((char *) *record_data,
|
|
sizeof (RecordData *) * (*record_data_count));
|
|
}
|
|
|
|
(*record_data)[*record_count].element_values =
|
|
(ElementValue *) XtMalloc (record_size);
|
|
|
|
|
|
(*record_count)++;
|
|
}
|
|
|
|
|
|
|
|
/************************************************************************
|
|
*
|
|
* OrderRecord
|
|
* Compare the value in the last element values struture referenced
|
|
* by value_define to previous element values. Move the element
|
|
* value structure to a new position defined by the comparison
|
|
* value being equal or greater the previous position and less
|
|
* than the next position
|
|
*
|
|
* The function works on string data.
|
|
*
|
|
************************************************************************/
|
|
|
|
static void
|
|
OrderRecord (RecordData * record_data,
|
|
int record_count,
|
|
int value_define)
|
|
|
|
{
|
|
int i;
|
|
int new_loc;
|
|
|
|
char * position_value;
|
|
char * compare_value;
|
|
ElementValue * element_values;
|
|
|
|
|
|
/* If this is the first record, it is already in position */
|
|
|
|
if (record_count == 1)
|
|
return;
|
|
|
|
|
|
/* Extract the comparison value and loop backward through the */
|
|
/* record_data to find the correct */
|
|
|
|
element_values = record_data[record_count - 1].element_values;
|
|
position_value = element_values[value_define].parsed_value;
|
|
|
|
for (new_loc = record_count - 2; new_loc >= 0; new_loc--)
|
|
{
|
|
compare_value =
|
|
record_data[new_loc].element_values[value_define].parsed_value;
|
|
|
|
if (strcmp (position_value, compare_value) >= 0)
|
|
break;
|
|
|
|
record_data[new_loc + 1].element_values =
|
|
record_data[new_loc].element_values;
|
|
|
|
}
|
|
|
|
|
|
/* If any values have been moved, place the position value into */
|
|
/* the vacated spot. */
|
|
|
|
if (new_loc != record_count - 2)
|
|
record_data[new_loc + 1].element_values = element_values;
|
|
}
|
|
|
|
|
|
|
|
|
|
/************************************************************************
|
|
*
|
|
* SwapEntries
|
|
* Swap element value records based on positions.
|
|
*
|
|
************************************************************************/
|
|
|
|
static void
|
|
SwapEntries (RecordData * rec_data,
|
|
int i,
|
|
int j)
|
|
|
|
|
|
{
|
|
ElementValue * temp_value;
|
|
|
|
temp_value = rec_data[i].element_values;
|
|
rec_data[i].element_values = rec_data[j].element_values;
|
|
rec_data[j].element_values = temp_value;
|
|
}
|
|
|
|
|
|
|
|
|
|
/************************************************************************
|
|
*
|
|
* QuickSort
|
|
* Reorder the records according to element index. This routine
|
|
* performs a quick sort. Positions that are equal will retain current
|
|
* positioning.
|
|
*
|
|
************************************************************************/
|
|
|
|
#ifdef NOT_DEF
|
|
static void
|
|
QuickSort(RecordData * rec_data,
|
|
int left,
|
|
int right,
|
|
int elem_index,
|
|
int container)
|
|
{
|
|
int i, last;
|
|
|
|
if (left >= right)
|
|
return;
|
|
|
|
SwapEntries(rec_data, left, (left + right)/2);
|
|
|
|
last = left;
|
|
|
|
if (container == BOX && elem_index == BOX_POSITION_HINTS ||
|
|
(container == CONTROL && elem_index == CONTROL_POSITION_HINTS))
|
|
{
|
|
for (i = left + 1; i <= right; i++)
|
|
if (rec_data[i].element_values[elem_index].parsed_value <
|
|
rec_data[left].element_values[elem_index].parsed_value)
|
|
SwapEntries(rec_data, ++last, i);
|
|
}
|
|
else
|
|
{
|
|
for (i = left + 1; i <= right; i++)
|
|
if (strcmp(rec_data[i].element_values[elem_index].parsed_value,
|
|
rec_data[left].element_values[elem_index].parsed_value) < 0)
|
|
SwapEntries(rec_data, ++last, i);
|
|
}
|
|
|
|
SwapEntries(rec_data, left, last);
|
|
|
|
QuickSort(rec_data, left, last - 1, elem_index, container);
|
|
QuickSort(rec_data, last + 1, right, elem_index, container);
|
|
}
|
|
#endif /* NOT_DEF */
|
|
|
|
|
|
|
|
|
|
/************************************************************************
|
|
*
|
|
* BubbleSort
|
|
* Reorder the records according to element index. This routine
|
|
* performs a bubble sort. Positions that are equal will retain current
|
|
* positioning.
|
|
*
|
|
************************************************************************/
|
|
|
|
static void
|
|
BubbleSort (RecordData * rec_data,
|
|
int start,
|
|
int rec_count,
|
|
int elem_index)
|
|
|
|
|
|
{
|
|
int bound, t, j;
|
|
Boolean is_string = False;
|
|
char *str1, *str2;
|
|
|
|
bound = rec_count;
|
|
|
|
if (elem_index == CONTROL_CONTAINER_NAME ||
|
|
elem_index == CONTROL_NAME)
|
|
is_string = True;
|
|
|
|
while (bound != 0)
|
|
{
|
|
t = 0;
|
|
for (j = start; j < bound; j++)
|
|
{
|
|
if (is_string)
|
|
{
|
|
str1 = (char *)rec_data[j].element_values[elem_index].parsed_value;
|
|
str2 = (char *)rec_data[j+1].element_values[elem_index].parsed_value;
|
|
if (strcmp(str1, str2) > 0)
|
|
{
|
|
SwapEntries(rec_data, j, j+1);
|
|
t = j;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ((intptr_t) rec_data[j].element_values[elem_index].parsed_value >
|
|
(intptr_t) rec_data[j+1].element_values[elem_index].parsed_value)
|
|
{
|
|
SwapEntries(rec_data, j, j+1);
|
|
t = j;
|
|
}
|
|
}
|
|
}
|
|
bound = t;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
/************************************************************************
|
|
*
|
|
* ReversePositions
|
|
* Reverse order of the records. This routine reverses the order of
|
|
* the records so that user records that have the same positioning
|
|
* will get a higher presidence.
|
|
*
|
|
*
|
|
************************************************************************/
|
|
|
|
static void
|
|
ReversePositions (RecordData * rec_data,
|
|
int start,
|
|
int end)
|
|
|
|
|
|
{
|
|
int i, j;
|
|
|
|
for (i = start, j = end; i < j; i++, j--)
|
|
{
|
|
SwapEntries(rec_data, i, j);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
/************************************************************************
|
|
*
|
|
* ReorderByContainerName
|
|
* Reorder the records according to container name. This will be done
|
|
* using a quick sort. Container type order must be retained. Matchinng
|
|
* names will retain current ordering.
|
|
*
|
|
*************************************************************************/
|
|
|
|
static void
|
|
ReorderByContainerName (RecordData * rec_data,
|
|
int rec_count,
|
|
int name,
|
|
int elem_type)
|
|
|
|
{
|
|
int i = 0, start = 0;
|
|
int cont_type;
|
|
|
|
while (i < rec_count)
|
|
{
|
|
cont_type = (int) (intptr_t)
|
|
(rec_data[start].element_values[elem_type].parsed_value);
|
|
while ((intptr_t)(rec_data[i].element_values[elem_type].parsed_value) ==
|
|
cont_type)
|
|
{
|
|
i++;
|
|
if (rec_count == i) break;
|
|
}
|
|
|
|
BubbleSort(rec_data, start, i - 1, name);
|
|
start = i;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
/************************************************************************
|
|
*
|
|
* ReorderByName
|
|
* Reorder the records according to names. This will be done
|
|
* using a quick sort. Container name order must be retained.
|
|
* Matching names will retain current order.
|
|
*
|
|
*************************************************************************/
|
|
|
|
static void
|
|
ReorderByName (RecordData * rec_data,
|
|
int rec_count,
|
|
int name,
|
|
int elem_type)
|
|
|
|
{
|
|
int i = 0, start = 0;
|
|
char *cont_name;
|
|
|
|
while (i < rec_count)
|
|
{
|
|
cont_name = (char *)
|
|
(rec_data[start].element_values[elem_type].parsed_value);
|
|
while (strcmp((char *)rec_data[i].element_values[elem_type].parsed_value,
|
|
cont_name) == 0)
|
|
{
|
|
i++;
|
|
if (rec_count == i) break;
|
|
}
|
|
|
|
BubbleSort(rec_data, start, i - 1, name);
|
|
start = i;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
/************************************************************************
|
|
*
|
|
* ReorderByPosition
|
|
* Reorder the records according to position_hints. This will be done
|
|
* using a quick sort. Positions that are equal will retain current
|
|
* positioning.
|
|
*************************************************************************/
|
|
|
|
static void
|
|
ReorderByPosition(RecordData *rec_data,
|
|
int rec_count,
|
|
int pos_hints,
|
|
int cont_type,
|
|
int cont_name)
|
|
|
|
{
|
|
int i = 0, start = 0;
|
|
int container_type;
|
|
char *container_name;
|
|
|
|
ReversePositions(rec_data, 0, rec_count - 1);
|
|
|
|
while (i < rec_count)
|
|
{
|
|
container_name = (char *)
|
|
(rec_data[start].element_values[cont_name].parsed_value);
|
|
|
|
if (cont_type == ANY_CONTAINER_TYPE)
|
|
{
|
|
while (strcmp((char *)
|
|
rec_data[i].element_values[cont_name].parsed_value,
|
|
container_name) == 0)
|
|
{
|
|
i++;
|
|
if (rec_count == i) break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
container_type = (int) (intptr_t)
|
|
(rec_data[start].element_values[cont_type].parsed_value);
|
|
while (((intptr_t)rec_data[i].element_values[cont_type].parsed_value ==
|
|
container_type) &&
|
|
(strcmp((char *)
|
|
rec_data[i].element_values[cont_name].parsed_value,
|
|
container_name) == 0))
|
|
{
|
|
i++;
|
|
if (rec_count == i) break;
|
|
}
|
|
}
|
|
|
|
BubbleSort(rec_data, start, i - 1, pos_hints);
|
|
start = i;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/************************************************************************
|
|
*
|
|
* ReorderByContainerType
|
|
* Reorder the records according to container type. This will be done
|
|
* using a bubble sort. Container types that are match must retain
|
|
* current positioning.
|
|
*
|
|
*************************************************************************/
|
|
|
|
static void
|
|
ReorderByContainerType (RecordData * rec_data,
|
|
int rec_count,
|
|
int container_type)
|
|
|
|
{
|
|
BubbleSort(rec_data, 0, rec_count - 1, container_type);
|
|
}
|
|
|
|
|
|
|
|
|
|
/************************************************************************
|
|
*
|
|
* RemoveEntry
|
|
*
|
|
************************************************************************/
|
|
|
|
void
|
|
RemoveEntry (RecordData * record_data,
|
|
int record_type)
|
|
|
|
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < record_descriptor[record_type].maxFields; i++)
|
|
{
|
|
if (record_keywords[record_type].parse_functions[i].free_function
|
|
!= NULL &&
|
|
record_data->element_values[i].parsed_value != NULL &&
|
|
record_data->element_values[i].use_default == False)
|
|
{
|
|
(*(record_keywords[record_type].parse_functions[i].free_function))
|
|
(&(record_data->element_values[i].parsed_value));
|
|
}
|
|
|
|
if (record_data->element_values[i].use_default == False &&
|
|
record_data->element_values[i].string_value != NULL)
|
|
free(record_data->element_values[i].string_value);
|
|
}
|
|
|
|
XtFree((char *)record_data->element_values);
|
|
}
|
|
|
|
|
|
|
|
|
|
/************************************************************************
|
|
*
|
|
* EliminateEntries
|
|
* Given a container type and the indicies of the records to be deleted,
|
|
* delete any components which are within the specified container type
|
|
* and range.
|
|
*
|
|
************************************************************************/
|
|
|
|
static void
|
|
EliminateEntries (RecordData * record_data,
|
|
int * record_count,
|
|
int start,
|
|
int end,
|
|
int * i,
|
|
int * count,
|
|
int record_type)
|
|
|
|
{
|
|
int j, k;
|
|
|
|
if (start > end) return;
|
|
|
|
for (j = start; j <= end; j++)
|
|
{
|
|
RemoveEntry(&(record_data[j]), record_type);
|
|
}
|
|
|
|
if (end + 1 < *record_count)
|
|
{
|
|
memmove((void *) &record_data[start], (void *) &record_data[end+1],
|
|
(size_t) ((*record_count - end) * sizeof(RecordData)));
|
|
}
|
|
|
|
|
|
*i += (end - start) + 1;
|
|
*count = *record_count -= (end - start) + 1;
|
|
}
|
|
|
|
|
|
|
|
|
|
/************************************************************************
|
|
*
|
|
* ResolveDuplicates
|
|
* Reprocess each group to eliminate overridden components.
|
|
* If a component is locked, use the first lock encountered.
|
|
* Otherwise, use the last component read.
|
|
*
|
|
************************************************************************/
|
|
|
|
static void
|
|
ResolveDuplicates (RecordData * record_data,
|
|
int * record_count,
|
|
int name_type,
|
|
int container_type,
|
|
int container_name,
|
|
int lock_type,
|
|
int record_type)
|
|
|
|
{
|
|
int i, start_index, lock_index, last_index;
|
|
ElementValue * element_values;
|
|
int cont_type;
|
|
char *cont_name, *record_name;
|
|
int count = *record_count;
|
|
Boolean locked;
|
|
|
|
i = count - 1;
|
|
|
|
/* Go through the array of records */
|
|
|
|
while (i >= 0)
|
|
{
|
|
element_values = record_data[i].element_values;
|
|
if (ANY_CONTAINER_TYPE != container_type)
|
|
{
|
|
cont_type = (int) (intptr_t) (element_values[container_type].parsed_value);
|
|
cont_name = (char *) (element_values[container_name].parsed_value);
|
|
}
|
|
record_name = (char *) (element_values[name_type].parsed_value);
|
|
|
|
locked = (Boolean) (intptr_t) (element_values[lock_type].parsed_value);
|
|
if (locked)
|
|
{
|
|
i--;
|
|
if (i < 0) break;
|
|
start_index = last_index = i;
|
|
element_values = record_data[i].element_values;
|
|
if (ANY_CONTAINER_TYPE == container_type)
|
|
{
|
|
while ((strcmp((char *) (element_values[name_type].parsed_value),
|
|
cont_name) == 0))
|
|
{
|
|
last_index = i;
|
|
i--;
|
|
if (i < 0) break;
|
|
element_values = record_data[i].element_values;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
while (((intptr_t)(element_values[container_type].parsed_value)
|
|
== cont_type) &&
|
|
(strcmp((char *)(element_values[container_name].parsed_value),
|
|
cont_name) == 0) &&
|
|
(strcmp((char *)(element_values[name_type].parsed_value),
|
|
record_name) == 0))
|
|
{
|
|
last_index = i;
|
|
i--;
|
|
if (i < 0) break;
|
|
element_values = record_data[i].element_values;
|
|
}
|
|
}
|
|
if (start_index != last_index)
|
|
EliminateEntries(record_data, record_count, last_index,
|
|
start_index - 1, &i, &count, record_type);
|
|
|
|
if (i < 0) break;
|
|
}
|
|
else
|
|
{
|
|
start_index = lock_index = last_index = i;
|
|
i--;
|
|
if (i < 0) continue;
|
|
element_values = record_data[i].element_values;
|
|
if (ANY_CONTAINER_TYPE == container_type)
|
|
{
|
|
while ((strcmp((char *) (element_values[name_type].parsed_value),
|
|
record_name) == 0))
|
|
{
|
|
locked = (Boolean) (intptr_t) (element_values[lock_type].parsed_value);
|
|
if (locked && start_index == lock_index)
|
|
lock_index = i;
|
|
last_index = i;
|
|
i--;
|
|
if (i < 0) break;
|
|
element_values = record_data[i].element_values;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
while (((intptr_t)(element_values[container_type].parsed_value)
|
|
== cont_type) &&
|
|
(strcmp((char *)(element_values[container_name].parsed_value),
|
|
cont_name) == 0) &&
|
|
(strcmp((char *)(element_values[name_type].parsed_value),
|
|
record_name) == 0))
|
|
{
|
|
locked = (Boolean) (intptr_t) (element_values[lock_type].parsed_value);
|
|
if (locked && start_index == lock_index)
|
|
lock_index = i;
|
|
last_index = i;
|
|
i--;
|
|
if (i < 0) break;
|
|
element_values = record_data[i].element_values;
|
|
}
|
|
}
|
|
if (start_index != last_index)
|
|
{
|
|
if (start_index == lock_index)
|
|
EliminateEntries(record_data, record_count, last_index + 1,
|
|
start_index, &i, &count, record_type);
|
|
else
|
|
{
|
|
int diff = start_index - lock_index;
|
|
EliminateEntries(record_data, record_count, lock_index + 1,
|
|
start_index, &i, &count, record_type);
|
|
lock_index += diff;
|
|
last_index += diff;
|
|
if (lock_index != last_index)
|
|
EliminateEntries(record_data, record_count, last_index,
|
|
lock_index - 1, &i, &count, record_type);
|
|
}
|
|
}
|
|
if (i < 0) break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
/************************************************************************
|
|
*
|
|
* GetNameList
|
|
* Given a record_data array and a particular container type,
|
|
* allocate an array of pointers to strings and set to the component
|
|
* names of each component which matches the above criteria.
|
|
*
|
|
************************************************************************/
|
|
|
|
static char **
|
|
GetNameList (RecordData * record_data,
|
|
int record_count,
|
|
int name_type,
|
|
int container_type,
|
|
int container)
|
|
|
|
{
|
|
int i;
|
|
|
|
char ** name_list = NULL;
|
|
int name_list_count = 0;
|
|
int found_count = 0;
|
|
|
|
for (i = 0; i < record_count; i++)
|
|
{
|
|
if (ANY_CONTAINER_TYPE == container_type ||
|
|
(intptr_t)(record_data[i].element_values[container_type].parsed_value) ==
|
|
container)
|
|
{
|
|
if (found_count >= name_list_count)
|
|
{
|
|
name_list_count += 10;
|
|
name_list =
|
|
(char **) XtRealloc ((char *) name_list,
|
|
sizeof (char **) * (name_list_count + 1));
|
|
}
|
|
name_list [found_count] =
|
|
record_data[i].element_values[name_type].parsed_value;
|
|
found_count++;
|
|
}
|
|
}
|
|
|
|
if (name_list != NULL)
|
|
name_list [found_count] = NULL;
|
|
|
|
return (name_list);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/************************************************************************
|
|
*
|
|
* EliminateUnused
|
|
* Given a record_data array, container name list and container type,
|
|
* delete any components which are within the specified container type
|
|
* but do not contain the container name.
|
|
*
|
|
************************************************************************/
|
|
|
|
static void
|
|
EliminateUnused (RecordData * record_data,
|
|
int * record_count,
|
|
char ** cont_name_list,
|
|
int cont_name,
|
|
int cont_type,
|
|
int container,
|
|
int record_type)
|
|
|
|
{
|
|
int i, j, dummy = 0;
|
|
char * container_name;
|
|
int count = *record_count;
|
|
Boolean name_found = False;
|
|
ElementValue * element_values;
|
|
|
|
i = 0;
|
|
|
|
while (i < count)
|
|
{
|
|
element_values = record_data[i].element_values;
|
|
if (cont_type == ANY_CONTAINER_TYPE ||
|
|
(intptr_t)(element_values[cont_type].parsed_value) == container)
|
|
{
|
|
if (cont_name_list != NULL)
|
|
{
|
|
for (j = 0; cont_name_list[j] != NULL; j++)
|
|
{
|
|
container_name = cont_name_list[j];
|
|
if (strcmp((char *)element_values[cont_name].parsed_value,
|
|
container_name) == 0)
|
|
{
|
|
name_found = True;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (!name_found)
|
|
{
|
|
#ifdef DEBUG
|
|
printf("Entry Eliminated - %s\n",
|
|
(char *)element_values[cont_name].parsed_value);
|
|
#endif
|
|
EliminateEntries(record_data, record_count, i, i, &dummy, &count,
|
|
record_type);
|
|
}
|
|
else
|
|
{
|
|
name_found = False;
|
|
i++;
|
|
}
|
|
}
|
|
else
|
|
i++;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/************************************************************************
|
|
*
|
|
* EliminateDeleted
|
|
* Given a record_data array, delete any components which have the
|
|
* DELETE keyword set to True. Also delete any duplicates that match
|
|
* the container name, container type, record name, and record type
|
|
* but do not have the LOCKED keyword set to True.
|
|
*
|
|
************************************************************************/
|
|
|
|
static void
|
|
EliminateDeleted (RecordData * record_data,
|
|
int * record_count,
|
|
int cont_name,
|
|
int record_name,
|
|
int record_type,
|
|
int delete_type,
|
|
int lock_type)
|
|
|
|
{
|
|
int i, j, start, dummy = 0;
|
|
int count;
|
|
ElementValue * element_values, * other_element_values;
|
|
char * container_name, * rec_name;
|
|
int container_type, rec_type;
|
|
|
|
count = *record_count;
|
|
i = 0;
|
|
|
|
while (i < count)
|
|
{
|
|
start = i;
|
|
element_values = record_data[i].element_values;
|
|
if ((intptr_t)element_values[delete_type].parsed_value)
|
|
{
|
|
Boolean delete_rest = False;
|
|
|
|
if (record_type == CONTROL)
|
|
{
|
|
rec_type = (intptr_t)element_values[CONTROL_TYPE].parsed_value;
|
|
container_type =
|
|
(intptr_t)element_values[CONTROL_CONTAINER_TYPE].parsed_value;
|
|
}
|
|
container_name =
|
|
XtNewString ((char *)element_values[cont_name].parsed_value);
|
|
rec_name =
|
|
XtNewString ((char *)element_values[record_name].parsed_value);
|
|
|
|
for (j = count - 1; j >= 0; j--)
|
|
{
|
|
other_element_values = record_data[j].element_values;
|
|
if ((record_type != CONTROL ||
|
|
((intptr_t)other_element_values[CONTROL_CONTAINER_TYPE].parsed_value
|
|
== container_type &&
|
|
(intptr_t) other_element_values[CONTROL_TYPE].parsed_value
|
|
== rec_type)) &&
|
|
strcmp((char *)other_element_values[cont_name].parsed_value,
|
|
container_name) == 0 &&
|
|
strcmp((char *)other_element_values[record_name].parsed_value,
|
|
rec_name) == 0)
|
|
{
|
|
if ((intptr_t)other_element_values[lock_type].parsed_value)
|
|
{
|
|
if ((intptr_t)other_element_values[delete_type].parsed_value)
|
|
{
|
|
EliminateEntries(record_data, record_count, j, j, &dummy,
|
|
&count, record_type);
|
|
delete_rest = True;
|
|
}
|
|
else if (delete_rest)
|
|
{
|
|
EliminateEntries(record_data, record_count, j, j, &dummy,
|
|
&count, record_type);
|
|
}
|
|
}
|
|
else
|
|
EliminateEntries(record_data, record_count, j, j, &dummy,
|
|
&count, record_type);
|
|
}
|
|
}
|
|
|
|
XtFree(container_name);
|
|
XtFree(rec_name);
|
|
}
|
|
else
|
|
i++;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
/************************************************************************
|
|
*
|
|
* InitializeField
|
|
* Given an ElementValues array, a particular keyword that references
|
|
* a single element and the parse function array for the record
|
|
* type: if the element has a value string, parse it otherwise
|
|
* set the parsed value to the default.
|
|
*
|
|
************************************************************************/
|
|
|
|
static void
|
|
InitializeField (ElementValue * element_values,
|
|
int keyword,
|
|
ParseFunction * parse_functions)
|
|
|
|
{
|
|
if (element_values[keyword].string_value != NULL)
|
|
{
|
|
element_values[keyword].use_default = False;
|
|
|
|
if (!parse_functions[keyword].parse_function (
|
|
element_values[keyword].string_value,
|
|
&(element_values[keyword].parsed_value)))
|
|
{
|
|
XtFree(element_values[keyword].string_value);
|
|
element_values[keyword].string_value = NULL;
|
|
|
|
element_values[keyword].use_default = True;
|
|
element_values[keyword].parsed_value =
|
|
parse_functions[keyword].default_value;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
element_values[keyword].use_default = True;
|
|
element_values[keyword].parsed_value =
|
|
parse_functions[keyword].default_value;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/************************************************************************
|
|
*
|
|
* CountElements
|
|
* Given a record_data array, a container name and container type
|
|
* count how many records match and return the value.
|
|
*
|
|
************************************************************************/
|
|
|
|
static int
|
|
CountElements (RecordData * record_data,
|
|
int record_count,
|
|
char * container_name,
|
|
int name_type,
|
|
int container_type,
|
|
int container)
|
|
|
|
|
|
{
|
|
int i;
|
|
static int found_count = 0;
|
|
|
|
for (i = 0; i < record_count; i++)
|
|
{
|
|
if (ANY_CONTAINER_TYPE == container_type ||
|
|
(intptr_t)(record_data[i].element_values[container_type].parsed_value) ==
|
|
container)
|
|
{
|
|
if (strcmp (container_name,
|
|
record_data[i].element_values[name_type].parsed_value) ==0)
|
|
found_count++;
|
|
}
|
|
}
|
|
|
|
return (found_count);
|
|
}
|
|
|
|
|
|
|
|
|
|
/************************************************************************
|
|
*
|
|
* DeleteControlActionList
|
|
*
|
|
************************************************************************/
|
|
|
|
|
|
void
|
|
DeleteControlActionList (ControlData * control_data)
|
|
|
|
|
|
{
|
|
int i;
|
|
|
|
if (control_data->move_action != NULL)
|
|
free(control_data->move_action);
|
|
if (control_data->copy_action != NULL)
|
|
free(control_data->copy_action);
|
|
if (control_data->link_action != NULL)
|
|
free(control_data->link_action);
|
|
|
|
if (control_data->actions != NULL)
|
|
{
|
|
for (i = 0; control_data->actions[i] != NULL; i++)
|
|
{
|
|
free (control_data->actions[i]->action_name);
|
|
if (control_data->actions[i]->action_label != NULL)
|
|
free (control_data->actions[i]->action_label);
|
|
XtFree ((char *) control_data->actions[i]);
|
|
}
|
|
|
|
XtFree((char *)control_data->actions);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
/************************************************************************
|
|
*
|
|
* AddControlActionList
|
|
*
|
|
************************************************************************/
|
|
|
|
|
|
void
|
|
AddControlActionList (ControlData * control_data)
|
|
|
|
|
|
{
|
|
char * data_type = NULL;
|
|
char * act_list = NULL;
|
|
char * file_name = NULL;
|
|
char * file_str;
|
|
char ** action_list = NULL;
|
|
int num_actions = 0;
|
|
int i = 0;
|
|
int result;
|
|
Boolean is_file_control = False;
|
|
PanelActionData * drop_action;
|
|
char * label;
|
|
int j = 0;
|
|
|
|
|
|
if ((intptr_t)control_data->element_values[CONTROL_TYPE].parsed_value ==
|
|
CONTROL_FILE)
|
|
{
|
|
file_name = (char *)
|
|
control_data->element_values[CONTROL_FILE_NAME].parsed_value;
|
|
|
|
data_type = DtDtsFileToDataType (file_name);
|
|
is_file_control = True;
|
|
}
|
|
|
|
if (data_type != NULL)
|
|
{
|
|
DtDtsAttribute ** attr_list;
|
|
char * attr[5];
|
|
|
|
attr_list = DtDtsDataTypeToAttributeList (data_type, file_name);
|
|
|
|
|
|
/* The attribute list is ordered alphabetically by name so */
|
|
/* do a linear search of the atr_list array and get the values */
|
|
/* as use run into them. Use the following array to get the */
|
|
/* values for these attributes. */
|
|
|
|
attr[0] = DtDTS_DA_ACTION_LIST;
|
|
attr[1] = DtDTS_DA_COPY_TO_ACTION;
|
|
attr[2] = DtDTS_DA_LINK_TO_ACTION;
|
|
attr[3] = DtDTS_DA_MOVE_TO_ACTION;
|
|
|
|
if (attr_list != NULL)
|
|
{
|
|
for (i = 0; attr_list[i] != NULL; i++)
|
|
{
|
|
for (j = 0; j < 4; j++)
|
|
if (strcmp (attr_list[i]->name, attr[j]) == 0)
|
|
break;
|
|
|
|
|
|
/* If we have found a match, find the appropriate attr */
|
|
/* and assign the value. */
|
|
|
|
switch (j)
|
|
{
|
|
/* DtDTS_DA_ACTION_LIST */
|
|
case 0:
|
|
act_list = (char *) strdup(attr_list[i]->value);
|
|
break;
|
|
|
|
/* DtDTS_DA_COPY_TO_ACTION */
|
|
case 1:
|
|
control_data->copy_action =
|
|
(char *) strdup(attr_list[i]->value);
|
|
break;
|
|
|
|
/* DtDTS_DA_LINK_TO_ACTION */
|
|
case 2:
|
|
control_data->link_action =
|
|
(char *) strdup(attr_list[i]->value);
|
|
break;
|
|
|
|
/* DtDTS_DA_MOVE_TO_ACTION */
|
|
case 3:
|
|
control_data->move_action =
|
|
(char *) strdup(attr_list[i]->value);
|
|
break;
|
|
|
|
/* No Match */
|
|
case 4:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (act_list)
|
|
{
|
|
action_list = _DtVectorizeInPlace (act_list, ',');
|
|
for (i = 0; action_list[i] != NULL; i++)
|
|
num_actions++;
|
|
}
|
|
|
|
if (DtDtsDataTypeIsAction(data_type) && is_file_control)
|
|
control_data->is_action = True;
|
|
|
|
if (attr_list != NULL)
|
|
DtDtsFreeAttributeList(attr_list);
|
|
}
|
|
|
|
if (action_list == NULL)
|
|
{
|
|
if (control_data->element_values[CONTROL_PUSH_ACTION].string_value != NULL)
|
|
{
|
|
action_list = (char **) XtMalloc(sizeof(char *) * 2);
|
|
|
|
action_list[0] =
|
|
control_data->element_values[CONTROL_PUSH_ACTION].string_value;
|
|
action_list[1] = NULL;
|
|
num_actions = 1;
|
|
}
|
|
else
|
|
num_actions = 0;
|
|
}
|
|
|
|
control_data->actions = (PanelActionData **)
|
|
XtMalloc(sizeof(PanelActionData *) *
|
|
(num_actions + 1));
|
|
|
|
for (i = 0, j = 0; j < num_actions; i++, j++)
|
|
{
|
|
/* Remove the OpenInPlace action from the list of actions */
|
|
if (strcmp(action_list[j],"OpenInPlace") == 0)
|
|
{
|
|
i--;
|
|
continue;
|
|
}
|
|
|
|
control_data->actions[i] = (PanelActionData *)
|
|
XtMalloc(sizeof(PanelActionData));
|
|
|
|
control_data->actions[i]->action_name = strdup(action_list[j]);
|
|
|
|
control_data->actions[i]->aap = NULL;
|
|
control_data->actions[i]->count = 0;
|
|
|
|
label = DtActionLabel (action_list[j]);
|
|
|
|
if (label != NULL)
|
|
control_data->actions[i]->action_label = label;
|
|
else
|
|
control_data->actions[i]->action_label = strdup (action_list[j]);
|
|
|
|
|
|
}
|
|
|
|
control_data->actions[i] = NULL;
|
|
|
|
if (act_list)
|
|
free (act_list);
|
|
|
|
if (action_list)
|
|
XtFree ((char *) action_list);
|
|
|
|
if ((data_type != NULL) && is_file_control)
|
|
DtDtsFreeDataType (data_type);
|
|
}
|
|
|
|
|
|
|
|
|
|
/************************************************************************
|
|
*
|
|
* ProcessBox
|
|
* For a box structure, find the control set that is to be contained
|
|
* by it, allocate a ControlData array and reassign the element
|
|
* values pointers. Further process each control.
|
|
*
|
|
* Inputs: box_data - a pointer the BoxData structure to be initialized.
|
|
*
|
|
************************************************************************/
|
|
|
|
static void
|
|
ProcessBox (BoxData * box_data)
|
|
|
|
|
|
{
|
|
ElementValue * element_values;
|
|
|
|
int box_control_count = 0;
|
|
int i;
|
|
|
|
|
|
/* Loop the control array and check each control to see if it belongs */
|
|
/* in this box. If so, call a function to add it and then see if the */
|
|
/* control has a subpanel to process. */
|
|
|
|
for (i = 0; i < control_count; i++)
|
|
{
|
|
element_values = control_data[i].element_values;
|
|
|
|
if ((intptr_t) element_values[CONTROL_CONTAINER_TYPE].parsed_value == BOX &&
|
|
strcmp ((char *) box_data->element_values[BOX_NAME].parsed_value,
|
|
(char *) element_values[CONTROL_CONTAINER_NAME].parsed_value) == 0)
|
|
{
|
|
ProcessControl ((XtPointer) box_data, BOX, &(box_data->control_data),
|
|
&box_control_count, element_values);
|
|
|
|
box_data->subpanel_count +=
|
|
ProcessBoxControl (box_data->control_data[box_control_count - 1]);
|
|
}
|
|
}
|
|
|
|
box_data->control_data_count = box_control_count;
|
|
}
|
|
|
|
|
|
|
|
|
|
/************************************************************************
|
|
*
|
|
* ProcessControl
|
|
* For each control that is created, reallocate the array of
|
|
* pointer that hold the control and allocate a control structure.
|
|
* Initialize the control fields. This is called for BOX, SUBPANEL
|
|
* and SWITCH controls.
|
|
*
|
|
* Inputs: parent - a pointer to the head of the structure that is to
|
|
* contain this control.
|
|
* parent_type - the type of parent of the control.
|
|
* control_data_ptr - a pointer to the array of control pointers.
|
|
* control_count - the current count of controls within the array.
|
|
* element_values - the new controls database values.
|
|
*
|
|
************************************************************************/
|
|
|
|
|
|
static void
|
|
ProcessControl (XtPointer parent,
|
|
char parent_type,
|
|
ControlData *** control_data_ptr,
|
|
int * control_count,
|
|
ElementValue * element_values)
|
|
|
|
|
|
{
|
|
ControlData * control;
|
|
|
|
*control_data_ptr =
|
|
(ControlData **) XtRealloc ((char *) *control_data_ptr,
|
|
sizeof (ControlData *) * (*control_count + 1));
|
|
(*control_data_ptr)[*control_count] =
|
|
(ControlData *) XtMalloc (sizeof (ControlData));
|
|
|
|
control = (*control_data_ptr)[*control_count];
|
|
|
|
control->element_values = element_values;
|
|
control->parent_data = parent;
|
|
control->parent_type = parent_type;
|
|
control->subpanel_data = NULL;
|
|
control->icon = NULL;
|
|
control->arrow = NULL;
|
|
control->arrow_separator = NULL;
|
|
control->indicator = NULL;
|
|
control->actions = NULL;
|
|
control->is_action = False;
|
|
control->move_action = NULL;
|
|
control->copy_action = NULL;
|
|
control->link_action = NULL;
|
|
control->operation = 0;
|
|
|
|
AddControlActionList (control);
|
|
|
|
*control_count = *control_count + 1;
|
|
}
|
|
|
|
|
|
|
|
|
|
/************************************************************************
|
|
*
|
|
* ProcessBoxControl
|
|
* For a control structure within a box, see if there is a subpanel
|
|
* attached to it and if so, process the subpanel and its controls.
|
|
* Return the subpanel count to be stored as part of the box data.
|
|
*
|
|
* Inputs: control_data - a pointer to the control to be processed
|
|
*
|
|
************************************************************************/
|
|
|
|
static int
|
|
ProcessBoxControl (ControlData * control_data)
|
|
|
|
|
|
{
|
|
int i;
|
|
ElementValue * element_values;
|
|
int box_subpanel_count = 0;
|
|
SubpanelData * subpanel;
|
|
|
|
|
|
/* Loop through the subpanel data and find one that is attached */
|
|
/* to the provided control. */
|
|
|
|
for (i = 0; i < subpanel_count; i++)
|
|
{
|
|
element_values = subpanel_data[i].element_values;
|
|
|
|
if (strcmp ((char *) control_data->element_values[CONTROL_NAME].parsed_value,
|
|
(char *) element_values[SUBPANEL_CONTAINER_NAME].parsed_value) == 0)
|
|
{
|
|
box_subpanel_count = 1;
|
|
|
|
control_data->subpanel_data =
|
|
(SubpanelData *) XtMalloc (sizeof (SubpanelData));
|
|
|
|
subpanel = control_data->subpanel_data;
|
|
subpanel->element_values = element_values;
|
|
subpanel->control_data = NULL;
|
|
subpanel->control_data_count = 0;
|
|
subpanel->parent_control_data = control_data;
|
|
subpanel->default_control = NULL;
|
|
subpanel->shell = NULL;
|
|
subpanel->form = NULL;
|
|
subpanel->dropzone = NULL;
|
|
subpanel->separator = NULL;
|
|
subpanel->main_panel_icon_copy = NULL;
|
|
subpanel->torn = False;
|
|
|
|
ProcessSubpanel (subpanel);
|
|
|
|
}
|
|
}
|
|
|
|
return (box_subpanel_count);
|
|
}
|
|
|
|
|
|
|
|
|
|
/************************************************************************
|
|
*
|
|
* ProcessSubpanel
|
|
* For a Subpanel, find all of the controls within it an allocate
|
|
* a ControlData array and move the element values for the controls.
|
|
*
|
|
* Inputs: subpanel_data - A pointer the the subpanel structure to be
|
|
* processed.
|
|
*
|
|
************************************************************************/
|
|
|
|
static void
|
|
ProcessSubpanel (SubpanelData * subpanel_data)
|
|
|
|
|
|
{
|
|
ElementValue * element_values;
|
|
|
|
int subpanel_control_count = 0;
|
|
int i;
|
|
|
|
|
|
|
|
/* Loop the control array and check each control to see if it belongs */
|
|
/* in this subpanel. If so, call a function to add it. */
|
|
|
|
for (i = 0; i < control_count; i++)
|
|
{
|
|
element_values = control_data[i].element_values;
|
|
|
|
if ((intptr_t) element_values[CONTROL_CONTAINER_TYPE].parsed_value == SUBPANEL &&
|
|
strcmp ((char *) subpanel_data->element_values[SUBPANEL_NAME].parsed_value,
|
|
(char *) element_values[CONTROL_CONTAINER_NAME].parsed_value) == 0)
|
|
{
|
|
ProcessControl ((XtPointer) subpanel_data, SUBPANEL,
|
|
&(subpanel_data->control_data),
|
|
&subpanel_control_count, element_values);
|
|
}
|
|
}
|
|
|
|
subpanel_data->control_data_count = subpanel_control_count;
|
|
}
|
|
|
|
|
|
|
|
|
|
/************************************************************************
|
|
*
|
|
* ProcessSwitch
|
|
* For a Switch, find all of the controls within it an allocate
|
|
* a ControlData array and move the element values for the controls.
|
|
*
|
|
* Inputs: switch_data - a pointer to the switch data structure to be
|
|
* processed.
|
|
*
|
|
************************************************************************/
|
|
|
|
static void
|
|
ProcessSwitch (SwitchData * switch_data)
|
|
|
|
|
|
{
|
|
ElementValue * element_values;
|
|
|
|
int switch_control_count = 0;
|
|
int i;
|
|
|
|
|
|
/* Count the number of controls that are to go into this switch */
|
|
/* and allocate a ControlData array to hold the controls. */
|
|
|
|
for (i = 0; i < control_count; i++)
|
|
{
|
|
element_values = control_data[i].element_values;
|
|
|
|
if ((intptr_t) element_values[CONTROL_CONTAINER_TYPE].parsed_value == SWITCH &&
|
|
strcmp ((char *) switch_data->element_values[SWITCH_NAME].parsed_value,
|
|
(char *) element_values[CONTROL_CONTAINER_NAME].parsed_value) == 0)
|
|
{
|
|
ProcessControl ((XtPointer) switch_data, SWITCH,
|
|
&(switch_data->control_data),
|
|
&switch_control_count, element_values);
|
|
}
|
|
}
|
|
|
|
switch_data->control_data_count = switch_control_count;
|
|
}
|
|
|
|
|
|
|
|
|
|
/************************************************************************
|
|
*
|
|
* CreateComponentFileName
|
|
* Create a file name in which to store a component file. This is
|
|
* accomplished by using the components name with an integer value
|
|
* appended.
|
|
*
|
|
* Inputs: record_data - a pointer to the struture that contains the
|
|
* components name, as well as other values.
|
|
*
|
|
************************************************************************/
|
|
|
|
|
|
static char *
|
|
CreateComponentFileName (RecordData * record_data)
|
|
|
|
|
|
{
|
|
char * file_name;
|
|
char * component_name;
|
|
struct stat stat_info;
|
|
int i;
|
|
|
|
|
|
component_name = XtMalloc(9);
|
|
strncpy (component_name, record_data->element_values[0].string_value, 8);
|
|
component_name[8] = '\0';
|
|
|
|
file_name = XtMalloc (strlen (HOME_DIR) + strlen (TYPES_DIR) + 14);
|
|
|
|
for (i = 1; i < 1000; i++)
|
|
{
|
|
sprintf(file_name, "%s%s%s%d.fp", HOME_DIR, TYPES_DIR, component_name, i);
|
|
|
|
if (lstat (file_name, &stat_info) != 0)
|
|
break;
|
|
}
|
|
|
|
XtFree(component_name);
|
|
|
|
return (file_name);
|
|
}
|
|
|
|
|
|
|
|
|
|
/************************************************************************
|
|
*
|
|
* WriteComponentToFile
|
|
* Write a component (contained within record_data) to a .fp file.
|
|
*
|
|
* Inputs: record_data - a pointer to the data for the component,
|
|
* including its element values.
|
|
* record_type - the type of component (CONTROL, SUBPANEL, ...)
|
|
* keywords - the ordered array of keywords for the component
|
|
* type, used to reference into the element values array.
|
|
* container_name - the parent of the component.
|
|
* container_type - the type of parent of the component.
|
|
* delete - whether the component is be added or deleted.
|
|
*
|
|
************************************************************************/
|
|
|
|
|
|
static void
|
|
WriteComponentToFile (RecordData * record_data,
|
|
int record_type,
|
|
char ** keywords,
|
|
char * container_name,
|
|
int container_type,
|
|
Boolean delete)
|
|
|
|
|
|
{
|
|
FILE * fd;
|
|
char * file_name = CreateComponentFileName (record_data);
|
|
int k;
|
|
|
|
if ((fd = fopen(file_name, "w")) != NULL)
|
|
{
|
|
fprintf (fd, "%s %s\n{\n", keywords[0],
|
|
record_data->element_values[0].string_value);
|
|
|
|
if (delete)
|
|
{
|
|
if (record_type == CONTROL)
|
|
{
|
|
fprintf(fd, " TYPE %s\n",
|
|
record_data->element_values[CONTROL_TYPE].string_value);
|
|
fprintf(fd, " CONTAINER_TYPE %s\n",
|
|
record_data->element_values[CONTROL_CONTAINER_TYPE].string_value);
|
|
}
|
|
|
|
fprintf(fd, " CONTAINER_NAME %s\n", container_name);
|
|
fprintf(fd, " DELETE True\n");
|
|
|
|
}
|
|
else
|
|
{
|
|
for (k = 1; k < record_descriptor[record_type].maxFields; k++)
|
|
{
|
|
if (record_data->element_values[k].string_value != NULL &&
|
|
record_data->element_values[k].use_default == False)
|
|
{
|
|
if (record_type == CONTROL &&
|
|
(intptr_t) record_data->element_values[CONTROL_TYPE].parsed_value == CONTROL_FILE &&
|
|
(k == CONTROL_PUSH_ACTION ||
|
|
k == CONTROL_LABEL || k == CONTROL_DROP_ACTION))
|
|
continue;
|
|
|
|
fprintf (fd, " %s %s\n", keywords[k],
|
|
record_data->element_values[k].string_value);
|
|
}
|
|
}
|
|
}
|
|
|
|
fprintf(fd, "}\n");
|
|
|
|
fflush(fd);
|
|
fclose(fd);
|
|
|
|
if (record_type == CONTROL)
|
|
SessionAddFileData(file_name,
|
|
record_data->element_values[CONTROL_NAME].string_value,
|
|
(int) CONTROL,
|
|
container_name, container_type, delete);
|
|
else
|
|
SessionAddFileData(file_name,
|
|
record_data->element_values[0].string_value,
|
|
record_type, container_name, container_type,delete);
|
|
}
|
|
|
|
WmFrontPanelSessionSaveData ();
|
|
|
|
XtFree (file_name);
|
|
}
|
|
|
|
|
|
|
|
|
|
/************************************************************************
|
|
*
|
|
* RemoveComponentFile
|
|
* Find the dynamic .fp file name of a file in the session data and
|
|
* unlink the file to remove the component. If no file name is
|
|
* found or the unlink fails, Call a function to write a .fp for
|
|
* the file which will have the DELETE keyword set to True.
|
|
*
|
|
************************************************************************/
|
|
|
|
|
|
static void
|
|
RemoveComponentFile (RecordData * record_data,
|
|
int record_type,
|
|
char ** keywords,
|
|
char * container_name,
|
|
int container_type)
|
|
|
|
|
|
{
|
|
char * file_name;
|
|
|
|
file_name =
|
|
SessionFileNameLookup (record_data->element_values[0].string_value,
|
|
record_type, container_name, container_type);
|
|
|
|
if (file_name == NULL || unlink (file_name) < 0)
|
|
WriteComponentToFile (record_data, record_type, keywords,
|
|
container_name, container_type, True);
|
|
else
|
|
{
|
|
SessionDeleteFileData (file_name);
|
|
WmFrontPanelSessionSaveData ();
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
/************************************************************************
|
|
*
|
|
* WriteControlComponentFile
|
|
* Set up the parameters to call a function which will write out
|
|
* to a .fp file a control description.
|
|
*
|
|
* Inputs: control_data - a pointer to the control to be written.
|
|
*
|
|
************************************************************************/
|
|
|
|
|
|
void
|
|
WriteControlComponentFile (ControlData * control_data)
|
|
|
|
|
|
{
|
|
ElementValue * element_values;
|
|
|
|
element_values = control_data->element_values;
|
|
|
|
WriteComponentToFile ((RecordData *) control_data, CONTROL, control_keywords,
|
|
(char *) element_values[CONTROL_CONTAINER_NAME].parsed_value,
|
|
(int) (intptr_t) element_values[CONTROL_CONTAINER_TYPE].parsed_value,
|
|
False);
|
|
}
|
|
|
|
|
|
|
|
|
|
/************************************************************************
|
|
*
|
|
* WriteSubpanelComponentFile
|
|
* Set up the parameters to call a function which will write out
|
|
* to a .fp file a subpanel description.
|
|
*
|
|
* Inputs: subpanel_data - a pointer to the subpanel to be written.
|
|
*
|
|
************************************************************************/
|
|
|
|
void
|
|
WriteSubpanelComponentFile (SubpanelData * subpanel_data)
|
|
|
|
|
|
{
|
|
ElementValue * element_values = subpanel_data->element_values;
|
|
|
|
WriteComponentToFile ((RecordData *) subpanel_data, SUBPANEL, subpanel_keywords,
|
|
(char *) element_values[SUBPANEL_CONTAINER_NAME].parsed_value,
|
|
CONTROL, False);
|
|
}
|
|
|
|
|
|
|
|
|
|
/************************************************************************
|
|
*
|
|
* RemoveControlComponentFile
|
|
* Set up the parameters to call a function which delete a control's
|
|
* .fp file.
|
|
*
|
|
* Inputs: control_data - a pointer to the control to be deleted.
|
|
*
|
|
************************************************************************/
|
|
|
|
|
|
void
|
|
RemoveControlComponentFile (ControlData * control_data)
|
|
|
|
|
|
{
|
|
ElementValue * element_values = control_data->element_values;
|
|
|
|
RemoveComponentFile ((RecordData *) control_data, CONTROL, control_keywords,
|
|
(char *) element_values[CONTROL_CONTAINER_NAME].parsed_value,
|
|
(int) (intptr_t) element_values[CONTROL_CONTAINER_TYPE].parsed_value);
|
|
}
|
|
|
|
|
|
|
|
|
|
/************************************************************************
|
|
*
|
|
* RemoveSubpanelComponentFile
|
|
* Set up the parameters to call a function which delete a subpanel's
|
|
* .fp file.
|
|
*
|
|
* Inputs: subpanel_data - a pointer to the subpanel to be deleted.
|
|
*
|
|
************************************************************************/
|
|
|
|
void
|
|
RemoveSubpanelComponentFile (SubpanelData * subpanel_data)
|
|
|
|
|
|
{
|
|
ElementValue * element_values = subpanel_data->element_values;
|
|
|
|
RemoveComponentFile ((RecordData *) subpanel_data, SUBPANEL, subpanel_keywords,
|
|
(char *) element_values[SUBPANEL_CONTAINER_NAME].parsed_value,
|
|
CONTROL);
|
|
}
|
|
|
|
|
|
|
|
|
|
/************************************************************************
|
|
*
|
|
* _WriteControlElementValues
|
|
* Set up a loop which write out all of the values that define
|
|
* a control. These are written as normal keyword, value pairs.
|
|
*
|
|
* Inputs: element_values - a pointer to the array of element value
|
|
* strutures each of which contain a value for a keyword.
|
|
*
|
|
************************************************************************/
|
|
|
|
|
|
void
|
|
_WriteControlElementValues (ElementValue * element_values)
|
|
|
|
|
|
{
|
|
int k;
|
|
|
|
printf("%s %s\n{\n", control_keywords[0], element_values[0].string_value);
|
|
|
|
for (k = 1; k < record_descriptor[CONTROL].maxFields; k++)
|
|
{
|
|
if (element_values[k].string_value != NULL)
|
|
printf(" %s %s\n",
|
|
control_keywords[k], element_values[k].string_value);
|
|
}
|
|
|
|
printf("}\n");
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/************************************************************************
|
|
*
|
|
* InitParse
|
|
*
|
|
************************************************************************/
|
|
|
|
void
|
|
InitParse (char * file_name,
|
|
ElementValue ** elem_vals)
|
|
|
|
|
|
{
|
|
char * tmpPath;
|
|
char * tmpDir;
|
|
char * hostName;
|
|
char * tmpName;
|
|
char * baseName;
|
|
char * tmpFile;
|
|
DtDirPaths * dirPath;
|
|
|
|
|
|
/* create directory for dir path */
|
|
|
|
tmpPath = XtMalloc (strlen(HOME_DIR) + strlen(TYPES_DIR) + 34);
|
|
sprintf (tmpPath, "%s%s%s%d", HOME_DIR, TYPES_DIR, "fp", (int) getpid());
|
|
mkdir (tmpPath, S_IRUSR | S_IWUSR | S_IXUSR);
|
|
|
|
|
|
/* create symbolic link to file_name */
|
|
|
|
tmpName = XtNewString(file_name);
|
|
baseName = strrchr(tmpName, '/');
|
|
tmpFile = XtMalloc(strlen(tmpPath) + strlen(baseName) + 1);
|
|
sprintf(tmpFile, "%s%s", tmpPath, baseName);
|
|
symlink(file_name, tmpFile);
|
|
|
|
hostName = XtMalloc((Cardinal)(MAXHOSTNAMELEN + 1));
|
|
DtGetShortHostname (hostName, MAXHOSTNAMELEN + 1);
|
|
|
|
tmpDir = XtMalloc(strlen(hostName) + strlen(tmpPath) + 2);
|
|
sprintf(tmpDir, "%s:%s", hostName, tmpPath);
|
|
|
|
dirPath = (DtDirPaths *) XtMalloc(sizeof(DtDirPaths));
|
|
dirPath->dirs = (char **) XtMalloc(sizeof(char *) * 2);
|
|
dirPath->paths = (char **) XtMalloc(sizeof(char *) * 2);
|
|
|
|
dirPath->dirs[0] = tmpDir;
|
|
dirPath->dirs[1] = NULL;
|
|
dirPath->paths[0] = tmpPath;
|
|
dirPath->paths[1] = NULL;
|
|
|
|
_DtDbRead (dirPath, FILE_TYPE_SUFFIX, control_record_descriptor, 2);
|
|
|
|
control_element_value_found = False;
|
|
|
|
/* remove link and directory */
|
|
|
|
unlink(tmpFile);
|
|
rmdir(tmpPath);
|
|
|
|
XtFree((char *) dirPath->dirs);
|
|
XtFree((char *) dirPath->paths);
|
|
XtFree((char *) dirPath);
|
|
XtFree(hostName);
|
|
XtFree(tmpName);
|
|
XtFree(tmpDir);
|
|
XtFree(tmpPath);
|
|
XtFree(tmpFile);
|
|
|
|
*elem_vals = control_element_values;
|
|
}
|
|
|
|
|
|
|
|
|
|
/************************************************************************
|
|
*
|
|
* FreeFileControlField
|
|
*
|
|
************************************************************************/
|
|
|
|
|
|
static void
|
|
FreeFileControlField (ElementValue * element_values,
|
|
int indx)
|
|
|
|
|
|
{
|
|
if (control_parse_functions[indx].free_function != NULL &&
|
|
element_values[indx].parsed_value != NULL &&
|
|
element_values[indx].use_default == False)
|
|
{
|
|
(*(control_parse_functions[indx].free_function))
|
|
(&(element_values[indx].parsed_value));
|
|
element_values[indx].parsed_value = NULL;
|
|
}
|
|
|
|
if (element_values[indx].use_default == False &&
|
|
element_values[indx].string_value != NULL)
|
|
{
|
|
free(element_values[indx].string_value);
|
|
element_values[indx].string_value = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
/************************************************************************
|
|
*
|
|
* InitializePrimaryControlFields
|
|
*
|
|
************************************************************************/
|
|
|
|
|
|
static void
|
|
InitializePrimaryControlFields (ElementValue * element_values)
|
|
|
|
|
|
{
|
|
InitializeField (element_values,
|
|
CONTROL_NAME, control_parse_functions);
|
|
InitializeField (element_values,
|
|
CONTROL_CONTAINER_NAME, control_parse_functions);
|
|
InitializeField (element_values,
|
|
CONTROL_CONTAINER_TYPE, control_parse_functions);
|
|
InitializeField (element_values,
|
|
CONTROL_LOCKED, control_parse_functions);
|
|
InitializeField (element_values,
|
|
CONTROL_DELETE, control_parse_functions);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/************************************************************************
|
|
*
|
|
* InitializeSecondaryControlFields
|
|
*
|
|
************************************************************************/
|
|
|
|
|
|
static void
|
|
InitializeSecondaryControlFields (ElementValue * element_values)
|
|
|
|
|
|
{
|
|
InitializeField (element_values,
|
|
CONTROL_TYPE, control_parse_functions);
|
|
InitializeField (element_values,
|
|
CONTROL_POSITION_HINTS, control_parse_functions);
|
|
InitializeField (element_values,
|
|
CONTROL_ALTERNATE_ICON, control_parse_functions);
|
|
InitializeField (element_values,
|
|
CONTROL_PUSH_ANIMATION, control_parse_functions);
|
|
InitializeField (element_values,
|
|
CONTROL_DROP_ANIMATION, control_parse_functions);
|
|
InitializeField (element_values,
|
|
CONTROL_PUSH_RECALL, control_parse_functions);
|
|
InitializeField (element_values,
|
|
CONTROL_MONITOR_TYPE, control_parse_functions);
|
|
InitializeField (element_values,
|
|
CONTROL_CLIENT_NAME, control_parse_functions);
|
|
InitializeField (element_values,
|
|
CONTROL_CLIENT_GEOMETRY, control_parse_functions);
|
|
InitializeField (element_values,
|
|
CONTROL_FILE_NAME, control_parse_functions);
|
|
InitializeField (element_values,
|
|
CONTROL_DATE_FORMAT, control_parse_functions);
|
|
InitializeField (element_values,
|
|
CONTROL_HELP_STRING, control_parse_functions);
|
|
InitializeField (element_values,
|
|
CONTROL_HELP_VOLUME, control_parse_functions);
|
|
InitializeField (element_values,
|
|
CONTROL_HELP_TOPIC, control_parse_functions);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/************************************************************************
|
|
*
|
|
* InitializeFileControlFields
|
|
*
|
|
************************************************************************/
|
|
|
|
|
|
static void
|
|
InitializeFileControlFields (ElementValue * element_values,
|
|
char * data_type)
|
|
|
|
|
|
{
|
|
if ((intptr_t)element_values[CONTROL_TYPE].parsed_value == CONTROL_FILE)
|
|
{
|
|
Boolean free_data_type = False;
|
|
char * act_list;
|
|
char ** action_list = NULL;
|
|
char * icon_name;
|
|
char * file_name;
|
|
char * description;
|
|
char * file_str;
|
|
char * label = NULL;
|
|
int i, j, result;
|
|
|
|
struct stat stat_info;
|
|
Boolean valid_file = True;
|
|
|
|
|
|
file_name = (char *) element_values[CONTROL_FILE_NAME].parsed_value;
|
|
|
|
if (lstat (file_name, &stat_info) != 0)
|
|
valid_file = False;
|
|
|
|
if (data_type == NULL && file_name != NULL)
|
|
{
|
|
data_type = DtDtsFileToDataType (file_name);
|
|
free_data_type = True;
|
|
}
|
|
|
|
if (data_type != NULL)
|
|
{
|
|
if (valid_file)
|
|
{
|
|
icon_name = DtDtsDataTypeToAttributeValue (data_type,
|
|
DtDTS_DA_ICON, NULL);
|
|
|
|
if (element_values[CONTROL_NORMAL_ICON].string_value != NULL)
|
|
{
|
|
XtFree (element_values[CONTROL_NORMAL_ICON].string_value);
|
|
element_values[CONTROL_NORMAL_ICON].string_value = NULL;
|
|
}
|
|
|
|
element_values[CONTROL_NORMAL_ICON].string_value =
|
|
XtNewString (icon_name);
|
|
|
|
DtDtsFreeAttributeValue(icon_name);
|
|
}
|
|
|
|
description =
|
|
DtDtsDataTypeToAttributeValue(data_type, DtDTS_DA_DESCRIPTION, NULL);
|
|
|
|
if (element_values[CONTROL_HELP_STRING].string_value != NULL)
|
|
{
|
|
XtFree (element_values[CONTROL_HELP_STRING].string_value);
|
|
element_values[CONTROL_HELP_STRING].string_value = NULL;
|
|
}
|
|
|
|
element_values[CONTROL_HELP_STRING].string_value = XtNewString (description);
|
|
DtDtsFreeAttributeValue (description);
|
|
|
|
|
|
act_list = DtDtsDataTypeToAttributeValue (data_type,
|
|
DtDTS_DA_ACTION_LIST,
|
|
NULL);
|
|
if (act_list)
|
|
action_list = _DtVectorizeInPlace (act_list, ',');
|
|
|
|
if (action_list && action_list[0] != NULL)
|
|
{
|
|
element_values[CONTROL_PUSH_ACTION].string_value =
|
|
strdup (action_list[0]);
|
|
element_values[CONTROL_DROP_ACTION].string_value =
|
|
strdup (action_list[0]);
|
|
|
|
if (DtDtsDataTypeIsAction (data_type))
|
|
label = DtActionLabel (action_list[0]);
|
|
}
|
|
|
|
/* try to set it to the name of the type */
|
|
if (label == NULL) {
|
|
label = DtDtsDataTypeToAttributeValue (data_type,
|
|
DtDTS_DA_LABEL, NULL);
|
|
|
|
/* copy & correctly free the memory */
|
|
if (label) {
|
|
char *t = label;
|
|
|
|
label = XtNewString(t);
|
|
|
|
DtDtsFreeAttributeValue(t);
|
|
}
|
|
}
|
|
|
|
|
|
if (label == NULL && file_name != NULL)
|
|
{
|
|
if ((file_str = (char *)strrchr(file_name, '/')) == NULL)
|
|
file_str = file_name;
|
|
else
|
|
file_str++;
|
|
label = XtNewString(file_str);
|
|
}
|
|
|
|
if (label != NULL)
|
|
element_values[CONTROL_LABEL].string_value = label;
|
|
|
|
|
|
if (data_type != NULL)
|
|
{
|
|
if (act_list)
|
|
{
|
|
DtDtsFreeAttributeValue (act_list);
|
|
XtFree ((char *) action_list);
|
|
}
|
|
|
|
if (free_data_type)
|
|
DtDtsFreeDataType (data_type);
|
|
}
|
|
}
|
|
}
|
|
|
|
InitializeField (element_values,
|
|
CONTROL_NORMAL_ICON, control_parse_functions);
|
|
InitializeField (element_values,
|
|
CONTROL_HELP_STRING, control_parse_functions);
|
|
InitializeField (element_values,
|
|
CONTROL_LABEL, control_parse_functions);
|
|
InitializeField (element_values,
|
|
CONTROL_PUSH_ACTION, control_parse_functions);
|
|
InitializeField (element_values,
|
|
CONTROL_DROP_ACTION, control_parse_functions);
|
|
}
|
|
|
|
|
|
|
|
|
|
/************************************************************************
|
|
*
|
|
* InitializeControlFields
|
|
*
|
|
************************************************************************/
|
|
|
|
|
|
void
|
|
InitializeControlFields (ElementValue * element_values,
|
|
char * data_type)
|
|
|
|
|
|
{
|
|
InitializePrimaryControlFields (element_values);
|
|
InitializeSecondaryControlFields (element_values);
|
|
InitializeFileControlFields (element_values, data_type);
|
|
}
|
|
|
|
|
|
|
|
|
|
/************************************************************************
|
|
*
|
|
* UpdateFileType
|
|
*
|
|
************************************************************************/
|
|
|
|
|
|
static void
|
|
UpdateFileType (ControlData * control_data)
|
|
|
|
|
|
{
|
|
char * icon_name;
|
|
char * control_label;
|
|
XmString icon_label;
|
|
Arg al[2];
|
|
|
|
FreeFileControlField (control_data->element_values, CONTROL_NORMAL_ICON);
|
|
FreeFileControlField (control_data->element_values, CONTROL_PUSH_ACTION);
|
|
FreeFileControlField (control_data->element_values, CONTROL_DROP_ACTION);
|
|
FreeFileControlField (control_data->element_values, CONTROL_LABEL);
|
|
InitializeFileControlFields (control_data->element_values, NULL);
|
|
|
|
DeleteControlActionList (control_data);
|
|
AddControlActionList (control_data);
|
|
|
|
icon_name =
|
|
(char *)control_data->element_values[CONTROL_NORMAL_ICON].parsed_value;
|
|
|
|
if ((intptr_t)control_data->element_values[CONTROL_CONTAINER_TYPE].parsed_value ==
|
|
SUBPANEL)
|
|
{
|
|
icon_name = GetIconName (icon_name, panel.sub_icon_size);
|
|
}
|
|
else
|
|
{
|
|
icon_name = GetIconName (icon_name, panel.main_icon_size);
|
|
|
|
if (icon_name == NULL)
|
|
icon_name = GetIconName (icon_name, panel.sub_icon_size);
|
|
}
|
|
|
|
control_label = (char *)
|
|
control_data->element_values[CONTROL_LABEL].parsed_value;
|
|
|
|
icon_label = XmStringCreateLocalized (control_label);
|
|
|
|
XtSetArg(al[0], XmNimageName, icon_name);
|
|
XtSetArg(al[1], XmNstring, icon_label);
|
|
XtSetValues(control_data->icon, al, 2);
|
|
}
|
|
|
|
|
|
|
|
|
|
/************************************************************************
|
|
*
|
|
* UpdateFileTypeControlFields
|
|
*
|
|
************************************************************************/
|
|
|
|
|
|
void
|
|
UpdateFileTypeControlFields (void)
|
|
|
|
|
|
{
|
|
BoxData * box_data;
|
|
ControlData * control_data;
|
|
SubpanelData * subpanel_data;
|
|
SwitchData * switch_data;
|
|
int i, j, k;
|
|
|
|
if (panel_count == 0) return;
|
|
|
|
for (i = 0; i < panel.box_data_count; i++)
|
|
{
|
|
box_data = panel.box_data[i];
|
|
|
|
for (j = 0; j < box_data->control_data_count; j++)
|
|
{
|
|
control_data = box_data->control_data[j];
|
|
|
|
if ((intptr_t)control_data->element_values[CONTROL_TYPE].parsed_value ==
|
|
CONTROL_FILE)
|
|
UpdateFileType(control_data);
|
|
|
|
if (control_data->subpanel_data != NULL)
|
|
{
|
|
subpanel_data = control_data->subpanel_data;
|
|
|
|
for (k = 0; k < subpanel_data->control_data_count; k++)
|
|
{
|
|
control_data = subpanel_data->control_data[k];
|
|
|
|
if ((intptr_t)control_data->element_values[CONTROL_TYPE].parsed_value
|
|
== CONTROL_FILE)
|
|
UpdateFileType(control_data);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (box_data->switch_data != NULL)
|
|
{
|
|
switch_data = box_data->switch_data;
|
|
for (j = 0; j < switch_data->control_data_count; j++)
|
|
{
|
|
control_data = switch_data->control_data[j];
|
|
|
|
if ((intptr_t)control_data->element_values[CONTROL_TYPE].parsed_value ==
|
|
CONTROL_FILE)
|
|
UpdateFileType(control_data);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
/************************************************************************
|
|
*
|
|
* InitializeSubpanelFields
|
|
*
|
|
************************************************************************/
|
|
|
|
|
|
void
|
|
InitializeSubpanelFields (ElementValue * element_values)
|
|
|
|
|
|
{
|
|
InitializeField (element_values,
|
|
SUBPANEL_NAME, subpanel_parse_functions);
|
|
InitializeField (element_values,
|
|
SUBPANEL_CONTAINER_NAME, subpanel_parse_functions);
|
|
InitializeField (element_values,
|
|
SUBPANEL_LOCKED, subpanel_parse_functions);
|
|
InitializeField (element_values,
|
|
SUBPANEL_CONTROL_INSTALL, subpanel_parse_functions);
|
|
InitializeField (element_values,
|
|
SUBPANEL_TITLE, subpanel_parse_functions);
|
|
InitializeField (element_values,
|
|
SUBPANEL_DELETE, subpanel_parse_functions);
|
|
InitializeField (element_values,
|
|
SUBPANEL_HELP_STRING, subpanel_parse_functions);
|
|
InitializeField (element_values,
|
|
SUBPANEL_HELP_TOPIC, subpanel_parse_functions);
|
|
InitializeField (element_values,
|
|
SUBPANEL_HELP_VOLUME, subpanel_parse_functions);
|
|
}
|
|
|
|
|