1
0
Fork 0
mirror of git://git.code.sf.net/p/cdesktopenv/code synced 2025-03-09 15:50:02 +00:00
cde/cde/programs/dtsession/SmSave.c

2203 lines
55 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* 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 libraries and programs; if not, write
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
* Floor, Boston, MA 02110-1301 USA
*/
/* $TOG: SmSave.c /main/27 1998/07/23 18:07:58 mgreess $ */
/*************************************<+>*************************************
*****************************************************************************
**
** File: SmSave.c
**
** Project: HP DT Session Manager (dtsession)
**
** Description:
** -----------
** This file contains all routines that save off the session at any point
** in time. The session includes settings, resources, and clients. How
** the session manager behaves during a save depends on how the user has
** configured it to behave.
**
**
*****************************************************************************
*************************************<+>*************************************/
/*
* (c) Copyright 1997 The Open Group
* (c) Copyright 1996 Digital Equipment Corporation.
* (c) Copyright 1990, 1993, 1994, 1996 Hewlett-Packard Company.
* (c) Copyright 1993, 1994, 1996 International Business Machines Corp.
* (c) Copyright 1993, 1994, 1996 Sun Microsystems, Inc.
* (c) Copyright 1993, 1994, 1996 Novell, Inc.
* (c) Copyright 1996 FUJITSU LIMITED.
* (c) Copyright 1996 Hitachi.
*/
#include <stdio.h>
#include <string.h>
#include <dirent.h>
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/param.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#ifdef _SUN_OS
#include <arpa/inet.h>
#include <string.h>
#endif /* _SUN_OS */
#include <X11/Intrinsic.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#include <X11/StringDefs.h>
#include <X11/keysymdef.h>
#include <Dt/DtP.h>
#include <Dt/Connect.h>
#include <Dt/UserMsg.h>
#include <Dt/SessionM.h>
#include <Dt/MsgLog.h>
#include "Sm.h"
#include "SmSave.h"
#include "SmResource.h"
#include "SmError.h"
#include "SmGlobals.h"
#include "SmUI.h"
#include "SmWindow.h"
#include "SmProtocol.h"
#include "SmRestore.h"
#include "SmXSMP.h"
#include "SmDB.h"
#include "SmProperty.h"
#include "SmProp.h"
#include "Srv.h"
#include "SrvFile_io.h"
#ifdef MULTIBYTE
#include <stdlib.h>
#include <limits.h>
#endif
#include <X11/Xlibint.h>
typedef struct _ProxyClientCache {
Window window;
int screen;
} ProxyClientCache, *ProxyClientCachePtr;
static ProxyClientCachePtr proxyList;
static int numProxyClients = 0;
static int numProxyAllocated = 0;
static int proxyCacheAllocIncrement = 10;
/*
* Local Function Declarations
*/
static void CacheProxyClient (
Boolean firstClient,
int screenNum,
Window window);
static void PruneSessionDirectory ();
static Boolean WriteClientDatabase ();
static void OutputXSMPClients (
ClientDB outputDB);
static void OutputProxyClients (
ClientDB outputDB);
static Boolean CheckRequiredProperties (
ClientRecPtr pClientRec);
static void PrintStartupInfo(
ClientDB outputDB,
int screen,
Window window);
static int QueryServerSettings( void ) ;
static int SaveCustomizeSettings( void ) ;
static int OutputResource( void ) ;
static void PrintPointerControl(
XrmDatabase *smBase) ;
static void PrintSessionInfo(
XrmDatabase *smBase) ;
static void PrintScreenSaver(
XrmDatabase *smBase) ;
static int PrintFontPaths(
XrmDatabase *smBase,
char **fontPath,
int numPaths) ;
static int PrintKeyboardControl(
XrmDatabase *smBase);
static int PrintPointerMapping(
XrmDatabase *smBase,
char *buttonRet,
int numButton) ;
static void PrintWorkHintString(
FILE *hintFile,
char *hintString) ;
static void PrintCmdHintString(
FILE *hintFile,
char *hintString) ;
static void PrintCmdString(
FILE *cmdFile,
char *cmdString) ;
static void PrintRemoteCmdString(
FILE *cmdFile,
char *cmdString) ;
/*
* Global variables that are exposed
*/
SmScreenInfo screenSaverVals;
SmAudioInfo audioVals;
SmKeyboardInfo keyboardVals;
/*
* Variables global to this module only
*/
/*
* used as a buffer to write resources into
* before they are written out
*/
static int resSize = 10000;
static char *resSpec;
/*
* Vars used to maintain state that is sent to the SaveState
* function.
*/
static Boolean saveHome;
int saveMode;
/*************************************<->*************************************
*
* SetupSaveState
*
* Description:
* -----------
* Do all of the preliminary work that must be done before the state
* of a checkpoint can be saved.
*
* Inputs:
* ------
* saveToHome: This session is to be saved to the home session or current
* mode = whether the session is to be reset or restarted
*
*************************************<->***********************************/
void
SetupSaveState(
Boolean saveToHome,
int mode)
{
unsigned char *propData;
/*
* Cache saveToHome and mode - they will be needed after all of
* the XSMP clients are saved and the Proxy clients are saved.
*/
saveHome = saveToHome;
saveMode = mode;
/*
* First set up the save paths so we know if we have to do anything here
*/
if ((SetSavePath(saveToHome, mode)) == -1)
return;
/*
* Take care of the save mode property on the root window so that the
* clients will know how to save this file (if they save files)
*/
if(saveToHome == False)
{
propData = (unsigned char *) SM_CURRENT_DIRECTORY;
}
else
{
propData = (unsigned char *) SM_HOME_DIRECTORY;
}
/*
* Change the save mode to give the subdirectory saved to
*
*/
XChangeProperty(smGD.display, RootWindow(smGD.display, 0),
XaSmSaveMode, XA_STRING, 8, PropModeReplace,
propData, strlen((char *)propData));
XFlush(smGD.display);
}
/*************************************<->*************************************
*
* SaveState
*
* Description:
* -----------
* Tells the SM to notify the XSMP clients to save their state.
* The function CompleteSave fill be invoked after the XSMP clients
* have completed their save.
*
* Inputs:
* ------
* saveToHome: This session is to be saved to the home session or current
* mode = whether the session is to be reset or restarted
*
* Comments:
* --------
* As a result of this routine files will be saved in the users .dt directory
* that will allow the session manager to restore the session at a later
* time.
*
* NOTE - this function is called as the result of the following
* events:
*
* 1. User initiates a Save Home Session via the Style Manager
* 2. The Session Manager receives a SM_XSESSION_EXIT message
* 3. The Session Manager receives a SM_SAVE_SESSION message
*
*************************************<->***********************************/
void
SaveState(
Boolean saveToHome,
int mode,
int saveType,
Bool shutdown,
int interactStyle,
Bool fast,
Bool global)
{
/*
* Notify XSMP clients of the save
*/
SaveYourselfReqProc (NULL, NULL, saveType, shutdown, interactStyle,
fast, global);
}
/*************************************<->*************************************
*
* CompleteSave
*
* Description:
* -----------
* Called after the XSMP clients have saved their state. In charge of
* calling all routines that save session information for XSMP client
* and Proxy clients as well as settings, resources, etc.
*
* Outputs:
* -------
*
*************************************<->***********************************/
int
CompleteSave (void)
{
FILE *convertFP;
unsigned char *propData;
char *tmpPath, tmpVersion[20];
Boolean saveToHome = saveHome;
int mode = saveMode;
/*
* If this is a Home session and the user is logging out, return
* now - the XSMP clients have all responded to the save and the
* ICCC clients don't save their state when a Home session is
* exited.
*/
if (smGD.sessionType == HOME_SESSION &&
smXSMP.saveState.shutdown == True &&
smSettings.startState == DtSM_HOME_STATE)
return (0);
/*
* Start a wait state - don't want anything to happen while
* ICCC clients are being saved
*/
ShowWaitState(True);
resSpec = (char *) SM_MALLOC(resSize * sizeof(char));
if (resSpec==NULL)
{
PrintErrnoError(DtError, smNLS.cantMallocErrorString);
return(-1);
}
if (!WriteClientDatabase ()) {
ShowWaitState(False);
SM_FREE(resSpec);
return (-1);
}
/*
* WARNING - THIS VARIABLE MUST BE SET BEFORE THE SETTING INFORMATION IS
* CALLED - SETTINGS MUST BE SAVED BEFORE RESOURCES BECAUSE SETTINGS
* GETS INFORMATION SAVED IN RESOURCES (smToSet.dClickBuf)
*/
smToSet.dClickBuf[0] = 0;
/*
* Do the actual output of the X settings information. Output will
* go to the resource database at this point and be written to the
* resource file with the rest of the resources (below).
*/
if(smRes.querySettings == True)
{
QueryServerSettings();
}
else
{
SaveCustomizeSettings();
}
/*
* Do the output of resource information.
*/
if(OutputResource())
{
ShowWaitState(False);
SM_FREE(resSpec);
return(-1);
}
XDeleteProperty(smGD.display, DefaultRootWindow(smGD.display), XaSmSaveMode);
/*
* Go save the default palette at this time
*/
if(saveToHome == True)
SaveDefaultPalette(smGD.display, smGD.savePath, DtSM_HOME_STATE);
else
SaveDefaultPalette(smGD.display, smGD.savePath, mode);
PruneSessionDirectory ();
ShowWaitState(False);
return(0);
}
/*************************************<->*************************************
*
* PruneSessionDirectory -
*
* Description: Removes the oldest session direcotry if the number
* of directories exceeds the smRes.numSessionsBackedup.
*
* Inputs: void
*
*************************************<->***********************************/
static void
PruneSessionDirectory (void)
{
DIR * dirp;
struct dirent * dp;
int numDirs = 0;
struct stat buf;
time_t oldestTime;
char *clientDB;
char *dirPrefix;
char *oldDir; /* the .old dir */
char *oldestDir;
char *saveDir;
char *tmpDir;
if ((dirp = opendir (smGD.savePath)) == NULL)
return;
clientDB = (char*) XtMalloc((2*MAXPATHLEN) + 1);
oldestDir = (char*) XtMalloc(MAXPATHLEN + 1);
saveDir = (char*) XtMalloc(MAXPATHLEN + 1);
tmpDir = (char*) XtMalloc(MAXPATHLEN + 1);
dirPrefix = XtMalloc (strlen (smGD.restoreSession) + 2);
sprintf (dirPrefix, "%s.", smGD.restoreSession);
if (strlen (dirPrefix) > 5) {
dirPrefix[4] = '.';
dirPrefix[5] = '\000';
}
oldDir = XtMalloc (strlen (smGD.restoreSession) +
strlen (SM_OLD_EXTENSION) + 2);
sprintf (oldDir, "%s.%s", smGD.restoreSession, SM_OLD_EXTENSION);
(void) time (&oldestTime);
while ((dp = readdir (dirp)) != NULL) {
/*
* Do some sanity checks to limit the number of * stat()
* calls. Note that for backward compatibility with CDE
* 1.0 if a ".old" directory exists, keep it.
*/
if ((!strcmp (dp->d_name, ".")) ||
(!strcmp (dp->d_name, "..")) ||
(!strcmp (dp->d_name, oldDir)) ||
(strncmp (dp->d_name, dirPrefix, strlen (dirPrefix))))
continue;
sprintf (tmpDir, "%s/%s", smGD.savePath, dp->d_name);
if (((stat (tmpDir, &buf)) == 0) && S_ISDIR (buf.st_mode)) {
if (buf.st_mtime < oldestTime) {
/*
* Keep track of the oldest dir in case
* it needs to be removed
*/
oldestTime = buf.st_mtime;
strcpy (oldestDir, tmpDir);
}
numDirs++;
}
}
closedir(dirp);
if (numDirs > smRes.numSessionsBackedup) {
/*
* Need to remove the oldest directory. The general
* process (using "home" as an example) is:
*
* mv home home.tmp
* mv oldestDir home
* Execute the DiscardCommand props in the home directory
* rm -rf home
* mv home.tmp home
*
* The reason this is done is because when the
* DiscardCommand were saved, the directory at the time of
* the save contained "home". For example, a DiscardCommand
* may look like:
*
* rm -f /u/somebody/.dt/sessions/home/app.state
*
* yet because of the session archiving, the app.state
* file may actually be in a directory like:
*
* /u/somebody/.dt/sessions/home.<tempnam>
*/
char * tmpName;
int len, tfd;
len = strlen(smGD.savePath) + strlen(smGD.restoreSession)
+ strlen("XXXXXX") + 3;
tmpName = XtCalloc (1, len);
sprintf(tmpName, "%s/%s.XXXXXX", smGD.savePath,
smGD.restoreSession);
if ((tfd = mkstemp(tmpName)) == -1)
{
PrintErrnoError(DtError, smNLS.cantCreateDirsString);
}
else
{
close(tfd);
unlink(tmpName);
sprintf (saveDir, "%s/%s",
smGD.savePath, smGD.restoreSession);
MoveDirectory (saveDir, tmpName, False);
MoveDirectory (oldestDir, saveDir, False);
sprintf (clientDB, "%s/%s/%s", smGD.savePath,
smGD.restoreSession, SM_CLIENT_FILE2);
ExecuteDiscardCommands (clientDB);
MoveDirectory (tmpName, saveDir, True);
}
XtFree (tmpName);
}
/*
* If exiting and the current session is a Current session
* but smSettings.startState has been set to to a
* Home session (this would be true if a user started a
* Current session but used the Style Manager to set the session
* upon next login to be a Home session), then if a home
* directory exists, mv current to current.old
*/
if (smXSMP.saveState.shutdown && smGD.sessionType == CURRENT_SESSION &&
smSettings.startState == DtSM_HOME_STATE) {
sprintf (tmpDir, "%s/%s", smGD.savePath, SM_HOME_DIRECTORY);
if (((stat (tmpDir, &buf)) == 0) && S_ISDIR (buf.st_mode)) {
sprintf (saveDir, "%s/%s", smGD.savePath, oldDir);
if (((stat (saveDir, &buf)) == 0) &&
S_ISDIR (buf.st_mode)) {
sprintf (clientDB, "/bin/rm -rf %s", saveDir);
SystemCmd (clientDB);
sprintf (oldestDir, "%s/%s", smGD.savePath,
SM_CURRENT_DIRECTORY);
MoveDirectory (oldestDir, saveDir, False);
}
}
}
XtFree(clientDB);
XtFree(dirPrefix);
XtFree(oldDir);
XtFree(oldestDir);
XtFree(saveDir);
XtFree(tmpDir);
}
/*************************************<->*************************************
*
* WriteClientDatabase -
*
* Description: Writes the client database (for XSMP and Proxy clients)
*
* Inputs: None
*
* Returns True if the database is wrtten OK; False otherwise
*
*************************************<->***********************************/
static Boolean
WriteClientDatabase (void)
{
char *db;
ClientDB outputDB;
db = (char*) XtMalloc(MAXPATHLEN + 1);
(void) sprintf (db, "%s/%s/%s", smGD.savePath, smGD.restoreSession,
SM_CLIENT_FILE2);
if ((outputDB = OpenOutputClientDB (db, smXSMP.dbVersion,
smXSMP.dbSessionId)) == NULL) {
char * str;
str = strdup ((char *) GETMESSAGE (40, 18,
"The following database file cannot be opened for writing:\n\n %s\n\nThe session will not be saved."));
if (str) {
DtMsgLogMessage (smGD.programName, DtMsgLogError,
str, db);
free (str);
}
XtFree(db);
return (False);
}
XtFree(db);
OutputProxyClients (outputDB);
OutputXSMPClients (outputDB);
CloseClientDB (outputDB, True);
return (True);
}
/*************************************<->*************************************
*
* OutputProxyClients -
*
* Description: Outputs the Proxy clients
*
* Inputs: database pointer
*
* Returns: void
*
*************************************<->***********************************/
static void
OutputProxyClients (
ClientDB outputDB)
{
int i;
for (i = 0; i < numProxyClients; i++)
PrintStartupInfo (outputDB,
proxyList[i].screen,
proxyList[i].window);
}
/*************************************<->*************************************
*
* OutputXSMPClients -
*
* Description: Outputs the XSMP clients
*
* Inputs: database pointer
*
* Returns: void
*
*************************************<->***********************************/
static void
OutputXSMPClients (
ClientDB outputDB)
{
XSMPClientDBRec dbRec;
ClientRecPtr pClientRec;
for (pClientRec = connectedList; pClientRec != NULL;
pClientRec = pClientRec->next) {
dbRec.restartHint = pClientRec->restartHint;
(void) GetCardPropertyValue (pClientRec, SmRestartStyleHint,
&dbRec.restartHint);
if (dbRec.restartHint == SmRestartNever)
continue;
if (!pClientRec->active)
continue;
if (!CheckRequiredProperties (pClientRec))
continue;
dbRec.screenNum = 0;
dbRec.clientId = pClientRec->clientId;
dbRec.clientHost = pClientRec->clientHost;
dbRec.program = GetArrayPropertyValue (pClientRec,
SmProgram);
dbRec.cwd = GetArrayPropertyValue (pClientRec,
SmCurrentDirectory);
dbRec.restartCommand = GetListOfArrayPropertyValue (pClientRec,
SmRestartCommand);
dbRec.cloneCommand = GetListOfArrayPropertyValue (pClientRec,
SmCloneCommand);
dbRec.discardCommand = GetListOfArrayPropertyValue (pClientRec,
SmDiscardCommand);
dbRec.environment = GetListOfArrayPropertyValue (pClientRec,
SmEnvironment);
if (!PutXSMPClientDBRec (outputDB, &dbRec)) {
char *str;
str = strdup ((char *) GETMESSAGE (40, 19,
"Application '%s' cannot be saved."));
if (str) {
DtMsgLogMessage (smGD.programName,
DtMsgLogError, str,
dbRec.program);
free (str);
}
}
if (dbRec.restartCommand)
XtFree ((char *) dbRec.restartCommand);
if (dbRec.cloneCommand)
XtFree ((char *) dbRec.cloneCommand);
if (dbRec.discardCommand)
XtFree ((char *) dbRec.discardCommand);
if (dbRec.environment)
XtFree ((char *) dbRec.environment);
}
}
/*************************************<->*************************************
*
* CheckRequiredProperties -
*
* Description: Check a client's required properties
*
* Inputs: ClientRecPtr
*
* Returns: True if the client has all of the required properties;
* otherwise returns False
*
*************************************<->***********************************/
static Boolean
CheckRequiredProperties (
ClientRecPtr pClientRec)
{
PropertyRecPtr pPropRec;
char * str;
char * program = NULL;
if ((program = GetArrayPropertyValue (pClientRec, SmProgram)) == NULL){
str = strdup ((char *) GETMESSAGE (40, 23,
"The following application did not set the required\nproperty '%s':\n\n %s\n\nThis application will not be saved."));
if (str) {
DtMsgLogMessage (smGD.programName, DtMsgLogError, str,
SmProgram, pClientRec->clientId);
free (str);
}
return (False);
}
if ((pPropRec = GetPropertyRec (pClientRec, SmRestartCommand)) == NULL){
str = strdup ((char *) GETMESSAGE (40, 24,
"24 Application '%s' will not be saved because it did not set\nthe required property '%s'."));
if (str) {
DtMsgLogMessage (smGD.programName, DtMsgLogError,
str, program, SmRestartCommand);
free (str);
}
return (False);
}
if ((pPropRec = GetPropertyRec (pClientRec, SmCloneCommand)) == NULL) {
/*
* This is a warning - still want to save the client
*/
str = strdup ((char *) GETMESSAGE (40, 25,
"Application '%s' did not set the required property '%s'."));
if (str) {
DtMsgLogMessage (smGD.programName, DtMsgLogWarning, str,
program, SmCloneCommand);
free (str);
}
}
return (True);
}
/*************************************<->*************************************
*
* NotifyProxyClients -
*
*
* Description:
* -----------
* Notify Proxy clients - calls routines to find top level windows, and
* notifies the Proxy clients about an impending save.
*
* Inputs:
* ------
*
* Outputs:
* -------
*
*************************************<->***********************************/
void
NotifyProxyClients (void)
{
unsigned int topListLength, containedListLength;
WindowInfo * topList; /* list of top-level windows */
WindowInfo topLevelWindowInfo;
Atom actualType;
int actualFormat;
unsigned long nitems;
unsigned long leftover;
unsigned char * data = NULL;
Boolean containedClient;
int i, j;
int numClients = 0;
/*
* Save off the clients currently running. This will be done
* one screen at a time
*/
for(j = 0;j < smGD.numSavedScreens;j++)
{
/*
* Get a list of children of the root window. If there are none
* return with an error condition.
*/
if(GetTopLevelWindows(j,&topList,&topListLength, &containedListLength))
return;
/*
* Figure out how to restart the client associate with each window.
*/
for (i=0 ; i<(topListLength + containedListLength); ++i)
{
topLevelWindowInfo=topList[i];
if(i >= topListLength)
{
containedClient = True;
}
else
{
containedClient = False;
}
/*
* If this window is my window - skip it I don't want to
* save myself because I will be started automatically
*/
if (XGetWindowProperty(smGD.display, topLevelWindowInfo.wid,
XA_WM_CLASS,0L,
(long)BUFSIZ,False,XA_STRING,&actualType,
&actualFormat,&nitems,&leftover,
&data)==Success)
{
if (actualType==XA_STRING &&
!strcmp((char *) data, SM_RESOURCE_NAME))
{
SM_FREE((char *)data);
continue;
}
else
{
SM_FREE((char *)data);
}
}
/*
* If the client participates in the WM_SAVE_YOURSELF protocol,
* send the appropriate messages and wait for the proper
* responses.
*/
(void) SaveYourself(topLevelWindowInfo);
CacheProxyClient ((numClients == 0), j, topLevelWindowInfo.wid);
numClients++;
}
/*
* Free space malloc'd by GetTopLevelWindowInfo
*/
if(topListLength > 0)
{
SM_FREE((char *) topList);
}
}
}
/*************************************<->*************************************
*
* CacheProxyClient -
*
* Description:
* -----------
* Add a Proxy client to the proxy client cache.
*
* Inputs:
* ------
* firstClient - if True, this is the first client in the cache
* screenNum - the client's screen number
* window - the client's window number
*
* Outputs:
* -------
*
*************************************<->***********************************/
static void CacheProxyClient (
Boolean firstClient,
int screenNum,
Window window)
{
if (firstClient)
numProxyClients = 0;
if (numProxyClients >= numProxyAllocated) {
numProxyAllocated += proxyCacheAllocIncrement;
proxyList = (ProxyClientCachePtr) XtRealloc ((char *) proxyList,
numProxyAllocated * sizeof (ProxyClientCache));
}
proxyList[numProxyClients].screen = screenNum;
proxyList[numProxyClients].window = window;
numProxyClients++;
}
/*************************************<->*************************************
*
* PrintStartupInfo -
*
* Description:
* -----------
* Output startup information for one proxy client
*
* Inputs:
* ------
* outputDB = a pointer to the client database
* screen = which screen the client is running on
* window = the top level window of the lient
*
* Outputs:
* -------
*
* Comments:
* --------
*
*************************************<->***********************************/
static void
PrintStartupInfo(
ClientDB outputDB,
int screen,
Window window)
{
Boolean writeStatus;
int wargc;
char ** wargv;
char *clientMachine;
XWindowAttributes windowAttr;
Boolean remoteHost;
Boolean xsmpClient;
ProxyClientDBRec dbRec;
char ** argv;
int i;
Status status;
#ifdef _SUN_OS /* pull out quotes from OpenWindow tools commands */
char * ptr;
#endif
/*
* Get the attributes and properties on the window
*/
if ((XGetWindowAttributes(smGD.display, window, &windowAttr)) == 0)
return;
if (GetStandardProperties(window, screen, &wargc, &wargv,
&clientMachine, &xsmpClient)==0)
return;
/*
* If the client doesn't have a WM_COMMAND property, we can't restart it
*/
if (!wargv||!wargv[0])
return;
/*
* If the client is an XSMP client, don't save it as a Proxy client.
*/
if (xsmpClient)
return;
#ifdef _SUN_OS /* pull out quotes from OpenWindow tools commands */
if (wargc == 1) {
ptr = wargv[0];
/* check for foreground */
if ((ptr = strstr (ptr, "fg \"")) != NULL) {
if (strlen (ptr) > 3)
ptr[3] = ' ';
if ((ptr = strchr (ptr, '"')) != NULL)
ptr[0] = ' ';
}
/* check for background */
if ((ptr = strstr (wargv[0], "bg \"")) != NULL) {
if (strlen (ptr) > 3)
ptr[3] = ' ';
if ((ptr = strchr (ptr, '"')) != NULL)
ptr[0] = ' ';
}
}
#endif
/*
* Find out if the client is running locally
*/
dbRec.clientHost = NULL;
if(clientMachine != NULL)
{
if(DtIsLocalHostP(clientMachine) == FALSE)
{
dbRec.clientHost = clientMachine;
}
}
/*
* Must NULL-terminate the WM_COMMAND before writing it
*/
argv = (char **) XtMalloc ((wargc + 1) * sizeof (char *));
if (!argv)
return;
for (i = 0; i < wargc; i++)
argv[i] = wargv[i];
argv[wargc] = NULL;
dbRec.command = argv;
dbRec.screenNum = screen;
writeStatus = PutProxyClientDBRec (outputDB, &dbRec);
XtFree ((char *) argv);
if (writeStatus == False)
{
/*
* There should be an error written here - however
* since this means that there already is a write error to
* the disk - no error can be written
*/
(void) CloseClientDB (outputDB, True);
/*
* On a write error - move the old session back to
* be used and exit with an error condition
*/
XFreeStringList(wargv);
strcat(smGD.savePath, "/");
if(smGD.sessionType == HOME_SESSION)
{
strcat(smGD.savePath, SM_HOME_DIRECTORY);
}
else
{
strcat(smGD.savePath, SM_CURRENT_DIRECTORY);
}
MoveDirectory(smGD.etcPath, smGD.savePath, False);
SM_EXIT(-1);
}
/*
* Free up the argv property
*/
XFreeStringList(wargv);
}
/*************************************<->*************************************
*
* QueryServerSettings ()
*
*
* Description:
* -----------
* Query the server for all it's current settings information, and then
* write that information to the session managers settings resource file.
*
* Inputs:
* ------
* smGD.settingPath = (global) pointer to file where
* setting info should be saved.
*
* Outputs:
* -------
*
* Comments:
* --------
* This routine slows down the session manager's shutdown process
* considerably, and is therefore only called when the user specifies
* that all settings should be queried. Otherwise, only settings set in
* the customizer should be saved.
*
*************************************<->***********************************/
static int
QueryServerSettings( void )
{
int i, numLoops;
char **fontPath;
KeySym *tmpSyms, tmpMod;
XModifierKeymap *modMap;
char *buttonRet;
int numButton, numPaths;
int buttonSize = 128;
XrmDatabase smBase = NULL;
char tmpChar[35];
buttonRet = (char *) SM_MALLOC(buttonSize * sizeof(char));
if (buttonRet==NULL)
{
PrintErrnoError(DtError, smNLS.cantMallocErrorString);
return(-1);
}
/*
* First set up all pointer control parameters
* These are simple integer values that get saved
* here, then read into a structure and set at restore
* time
*/
XGetPointerControl(smGD.display, &smSettings.accelNum,
&smSettings.accelDenom,
&smSettings.threshold);
PrintPointerControl(&smBase);
/*
* Get all the screen saver values. These are all simple integer
* values that are read back into a structure and set at restore
* time.
*/
XGetScreenSaver(smGD.display, &screenSaverVals.smTimeout,
&screenSaverVals.smInterval,
&screenSaverVals.smPreferBlank,
&screenSaverVals.smAllowExp);
PrintScreenSaver(&smBase);
/*
* Write out all font path information.
* Write out all the paths one by one concatenated by commas.
*/
fontPath = XGetFontPath(smGD.display, &numPaths);
if(fontPath != NULL)
{
if(PrintFontPaths(&smBase, fontPath, numPaths) != 0)
{
XFreeFontPath(fontPath);
SM_FREE(buttonRet);
return(-1);
}
}
/*
* Write out all the keyboard control information.
*/
XGetKeyboardControl(smGD.display, &smSettings.kbdState);
if(PrintKeyboardControl(&smBase) != 0)
{
if (fontPath)
XFreeFontPath(fontPath);
return(-1);
}
/*
* Put all the button modifier information into the resource database.
* Find out the number of buttons and then write out the character
* string for each button.
*/
numButton = XGetPointerMapping(smGD.display, (unsigned char *)buttonRet, 128);
if(numButton > 128)
{
buttonRet = (char *) SM_REALLOC(buttonRet, numButton * sizeof(char));
if (buttonRet==NULL)
{
if (fontPath)
XFreeFontPath(fontPath);
PrintErrnoError(DtError, smNLS.cantMallocErrorString);
return(-1);
}
numButton = XGetPointerMapping(smGD.display, (unsigned char *)buttonRet, numButton);
}
if(PrintPointerMapping(&smBase, buttonRet,
numButton) != 0)
{
if (fontPath)
XFreeFontPath(fontPath);
SM_FREE(buttonRet);
return(-1);
}
/*
* Put all keyboard mapping information in the resource database
* Don't bother putting this in a separate print function because
* the customizer doesn't do keymap savings this way.
*/
smSettings.numKeyCode = smGD.display->max_keycode -
smGD.display->min_keycode;
tmpSyms = XGetKeyboardMapping(smGD.display,
(KeyCode) smGD.display->min_keycode,
smSettings.numKeyCode,
&smSettings.keySymPerCode);
if(tmpSyms == NULL)
{
if (fontPath)
XFreeFontPath(fontPath);
SM_FREE(buttonRet);
PrintErrnoError(DtError, smNLS.cantMallocErrorString);
return(-1);
}
strcpy(resSpec, SM_RESOURCE_CLASS);
strcat(resSpec, "*");
strcat(resSpec, SmCnumKeyCode);
strcat(resSpec, ":");
sprintf(tmpChar,"%d", smSettings.numKeyCode);
strcat(resSpec, tmpChar);
XrmPutLineResource( &smBase, resSpec);
strcpy(resSpec, SM_RESOURCE_CLASS);
strcat(resSpec, "*");
strcat(resSpec, SmCkeySymsPerKey);
strcat(resSpec, ":");
sprintf(tmpChar,"%d", smSettings.keySymPerCode);
strcat(resSpec, tmpChar);
XrmPutLineResource( &smBase, resSpec);
strcpy(resSpec, SM_RESOURCE_CLASS);
strcat(resSpec, "*");
strcat(resSpec, SmCkeySyms);
strcat(resSpec, ":");
numLoops = smSettings.numKeyCode * smSettings.keySymPerCode;
sprintf(tmpChar,"%ld", tmpSyms[0]);
strcat(resSpec, tmpChar);
for(i = 1;i < numLoops;i++)
{
if((strlen(resSpec) + 5) >= resSize)
{
resSize += 5000;
resSpec = (char *) SM_REALLOC(resSpec, resSize * sizeof(char));
if (resSpec==NULL)
{
SM_FREE((char *)tmpSyms);
if (fontPath)
SM_FREE((char *)fontPath);
SM_FREE(buttonRet);
PrintErrnoError(DtError, smNLS.cantMallocErrorString);
return(-1);
}
}
strcat(resSpec, ",");
sprintf(tmpChar,"%ld", tmpSyms[i]);
strcat(resSpec, tmpChar);
}
XrmPutLineResource( &smBase, resSpec);
/*
* Write out all keyboard modifier info. This will be a pretty slow
* process considering that every keycode will have to be turned into
* a keysym before writing. Don't bother putting print stuff in a
* separate function because it will not be handled in the customize
* version.
*/
modMap = XGetModifierMapping(smGD.display);
if(modMap == NULL)
{
SM_FREE((char *)tmpSyms);
if (fontPath)
XFreeFontPath(fontPath);
SM_FREE(buttonRet);
PrintErrnoError(DtError, smNLS.cantMallocErrorString);
return(-1);
}
strcpy(resSpec, SM_RESOURCE_CLASS);
strcat(resSpec, "*");
strcat(resSpec, SmCmaxKeyPerMod);
strcat(resSpec, ":");
sprintf(tmpChar,"%d", modMap->max_keypermod);
strcat(resSpec, tmpChar);
XrmPutLineResource( &smBase, resSpec);
strcpy(resSpec, SM_RESOURCE_CLASS);
strcat(resSpec, "*");
strcat(resSpec, SmCmodMap);
strcat(resSpec, ":");
numLoops = (8 * modMap->max_keypermod) - 1;
for(i = 0;i <= numLoops;i++)
{
if((strlen(resSpec) + 9) >= resSize)
{
resSize += 5000;
resSpec = (char *) SM_REALLOC(resSpec, resSize * sizeof(char));
if (resSpec==NULL)
{
SM_FREE((char *)tmpSyms);
XFreeModifiermap(modMap);
if (fontPath)
XFreeFontPath(fontPath);
SM_FREE(buttonRet);
PrintErrnoError(DtError, smNLS.cantMallocErrorString);
return(-1);
}
}
tmpMod = XKeycodeToKeysym(smGD.display, modMap->modifiermap[i], 0);
sprintf(tmpChar,"%ld", tmpMod);
strcat(resSpec, tmpChar);
if(i != numLoops)
{
strcat(resSpec, ",");
}
}
XrmPutLineResource( &smBase, resSpec);
/*
* Print session manager settings
*/
PrintSessionInfo(&smBase);
/*
* Write settings resources out to disk
*/
XrmPutFileDatabase(smBase, smGD.settingPath);
/*
* Free all allocated resources
*/
if (fontPath)
XFreeFontPath(fontPath);
SM_FREE((char *)tmpSyms);
XFreeModifiermap(modMap);
SM_FREE(buttonRet);
XrmDestroyDatabase(smBase);
return(0);
}
/*************************************<->*************************************
*
* SaveCustomizeSettings ()
*
*
* Description:
* ------------
* Saves those settings that have been set in the customizer during the
* session to whatever values they were set to during the session.
*
*
* Inputs:
* ------
* smGD.resourcePath = (global) a pointer
* to where the settings should be stored.
*
*
* Outputs:
* -------
*
*
* Comments:
* --------
* This routine is the default saved for saving settings. If the user
* wants all settings saved, they have to set a resource saying that that
* will be the case.
*
*************************************<->***********************************/
static int
SaveCustomizeSettings( void )
{
int i,numPaths;
char **fontPath;
XrmDatabase smBase = NULL;
char *tmpChar[20], *ptrRet = NULL, *tmpKey;
Status newStat;
char tmpMap[128];
if(smCust.pointerChange)
{
newStat = _DtGetSmPointer(smGD.display, smGD.topLevelWindow,
XaDtSmPointerInfo, &ptrRet);
if(newStat != Success)
{
smToSet.pointerChange = False;
smToSet.pointerMapChange = False;
}
else
{
sscanf(ptrRet, "%d %s %d %d %s",
&smToSet.numButton,
tmpMap,
&smSettings.accelNum,
&smSettings.threshold,
smToSet.dClickBuf);
smSettings.accelDenom = 1;
tmpKey = strtok(tmpMap, "_");
i = 0;
while(tmpKey != NULL)
{
smToSet.pointerMap[i] = (char) atoi(tmpKey);
i++;
tmpKey = strtok(NULL, "_");
}
/*
* append a \n to dClickBuf because it was scanned out
*/
strcat(smToSet.dClickBuf, "\n");
}
if (ptrRet) XFree(ptrRet);
}
if(smToSet.pointerChange == True)
{
PrintPointerControl(&smBase);
}
if(smToSet.pointerMapChange == True)
{
if(PrintPointerMapping(&smBase, smToSet.pointerMap,
smToSet.numButton) != 0)
{
return(-1);
}
}
if(smToSet.screenSavChange == True)
{
PrintScreenSaver(&smBase);
}
if(smCust.audioChange == True)
{
newStat = _DtGetSmAudio(smGD.display, smGD.topLevelWindow,
XaDtSmAudioInfo, &audioVals);
if(newStat == Success)
{
smSettings.kbdState.bell_percent = audioVals.smBellPercent;
smSettings.kbdState.bell_pitch = audioVals.smBellPitch;
smSettings.kbdState.bell_duration = audioVals.smBellDuration;
}
else
{
smToSet.audioChange = False;
}
}
if (smToSet.audioChange)
{
strcpy(resSpec, SM_RESOURCE_CLASS);
strcat(resSpec, "*");
strcat(resSpec, SmCbellPercent);
strcat(resSpec, ":");
sprintf((char *)tmpChar,"%d",smSettings.kbdState.bell_percent);
strcat(resSpec, (char *)tmpChar);
XrmPutLineResource(&smBase, resSpec);
strcpy(resSpec, SM_RESOURCE_CLASS);
strcat(resSpec, "*");
strcat(resSpec, SmCbellPitch);
strcat(resSpec, ":");
sprintf((char *)tmpChar,"%d",smSettings.kbdState.bell_pitch);
strcat(resSpec, (char *)tmpChar);
XrmPutLineResource(&smBase, resSpec);
strcpy(resSpec, SM_RESOURCE_CLASS);
strcat(resSpec, "*");
strcat(resSpec, SmCbellDuration);
strcat(resSpec, ":");
sprintf((char *)tmpChar,"%d",smSettings.kbdState.bell_duration);
strcat(resSpec, (char *)tmpChar);
XrmPutLineResource(&smBase, resSpec);
}
if(smCust.keyboardChange == True)
{
newStat = _DtGetSmKeyboard(smGD.display, smGD.topLevelWindow,
XaDtSmKeyboardInfo, &keyboardVals);
if(newStat == Success)
{
smSettings.kbdState.key_click_percent = keyboardVals.smKeyClickPercent;
smSettings.kbdState.global_auto_repeat = keyboardVals.smGlobalAutoRepeat;
}
else
{
smToSet.keyboardChange = False;
}
}
if(smToSet.keyboardChange == True)
{
strcpy(resSpec, SM_RESOURCE_CLASS);
strcat(resSpec, "*");
strcat(resSpec, SmCkeyClick);
strcat(resSpec, ":");
sprintf((char *)tmpChar,"%d", smSettings.kbdState.key_click_percent);
strcat(resSpec, (char *)tmpChar);
XrmPutLineResource(&smBase, resSpec);
strcpy(resSpec, SM_RESOURCE_CLASS);
strcat(resSpec, "*");
strcat(resSpec, SmCglobalRepeats);
strcat(resSpec, ":");
sprintf((char *)tmpChar,"%d", smSettings.kbdState.global_auto_repeat);
strcat(resSpec, (char *)tmpChar);
XrmPutLineResource(&smBase, resSpec);
}
/*
* Write out all font path information.
* Write out all the paths one by one concatenated by commas.
*/
fontPath = XGetFontPath(smGD.display, &numPaths);
if(fontPath != NULL) {
if(PrintFontPaths(&smBase, fontPath, numPaths) != 0) {
XFreeFontPath(fontPath);
return(-1);
}
}
/*
* Save session manager settings
*/
PrintSessionInfo(&smBase);
if (fontPath)
XFreeFontPath(fontPath);
/*
* Write settings resources out to disk
*/
XrmPutFileDatabase(smBase, smGD.settingPath);
XrmDestroyDatabase(smBase);
return(0);
}
/*************************************<->*************************************
*
* OutputResource ()
*
*
* Description:
* -----------
* Save session resources by getting the current RESOURCE_MANAGER property
* on the root window.
*
* Inputs:
* ------
* smGD.resourcePath = (global) file name
* where property contents should be saved.
*
* Outputs:
* -------
*
*
* Comments:
* --------
* This method is not a 100% accurate representation of currently active
* resources in the system. It is however, the best representation (the
* values with the highest priority) without becoming overly invasive
* and slow.
*
*************************************<->***********************************/
static int
OutputResource( void )
{
Atom actualType;
int actualFormat;
unsigned long nitems, leftover;
char *data = NULL;
XrmDatabase db;
Status newStat;
char *fontBuf = NULL, *langPtr, tmpChar[20], *sessionRes;
float fltYRes;
int intYRes;
char *preeditBuf = NULL;
/*
* Add anything to the Resource Manager property that needs to be added
*/
/*
* Write out the LANG variable and the screen's Y resolution
*/
*resSpec = 0;
langPtr = getenv("LANG");
if((langPtr != NULL) && (*langPtr != 0))
{
snprintf(resSpec, resSize, "%s*%s: %s\n", SM_RESOURCE_NAME, SmNsessionLang,
langPtr);
}
else
{
snprintf(resSpec, resSize, "%s*%s: \n", SM_RESOURCE_NAME, SmNsessionLang);
}
fltYRes = ((float) DisplayHeight(smGD.display, 0) /
(float) DisplayHeightMM(smGD.display, 0)) * 1000;
intYRes = fltYRes;
if(*resSpec == 0)
{
strcpy(resSpec, SM_RESOURCE_NAME);
}
else
{
strcat(resSpec, SM_RESOURCE_NAME);
}
strcat(resSpec, "*");
strcat(resSpec, SmNdisplayResolution);
strcat(resSpec, ":");
sprintf(tmpChar, "%d",intYRes);
strcat(resSpec, tmpChar);
strcat(resSpec, "\n");
_DtAddToResource(smGD.display, resSpec);
if(smCust.fontChange == True)
{
newStat = _DtGetSmFont(smGD.display, smGD.topLevelWindow,
XaDtSmFontInfo, &fontBuf);
if(newStat == Success)
{
/*
* Create the auxillary resource file
*/
if(SetFontSavePath(langPtr) != -1)
{
db = XrmGetStringDatabase(fontBuf);
if(intYRes < MED_RES_Y_RES)
{
sessionRes = SM_LOW_RES_EXT;
}
else
{
if(intYRes >= HIGH_RES_Y_RES)
{
sessionRes = SM_HIGH_RES_EXT;
}
else
{
sessionRes = SM_MED_RES_EXT;
}
}
strcat(smGD.fontPath, "/");
strcat(smGD.fontPath, SM_FONT_FILE);
strcat(smGD.fontPath, ".");
strcat(smGD.fontPath, sessionRes);
XrmPutFileDatabase(db, smGD.fontPath);
XrmDestroyDatabase(db);
}
/*
* Now add this to the resource manager property to be saved
*/
_DtAddToResource(smGD.display, fontBuf);
}
if (fontBuf) XFree(fontBuf);
}
if(smCust.preeditChange == True)
{
newStat = _DtGetSmPreedit(smGD.display, smGD.topLevelWindow,
XaDtSmPreeditInfo, &preeditBuf);
if(newStat == Success)
{
_DtAddToResource(smGD.display, preeditBuf);
}
if (preeditBuf) XFree(preeditBuf);
}
if((smCust.dClickChange == True) && (smToSet.dClickBuf[0] != 0))
{
_DtAddToResource(smGD.display, (char *)smToSet.dClickBuf);
}
/*
* Get the contents of the _DT_SM_PREFERENCES property
*/
data = _DtGetResString(smGD.display, _DT_ATR_PREFS);
/*
* Get _DT_SM_PREFERENCES database 'db'.
*/
db = XrmGetStringDatabase((char *)data);
XrmPutFileDatabase(db, smGD.resourcePath);
/*
* Don't forget to free your data
*/
SM_FREE((char *)data);
XrmDestroyDatabase(db);
return(0);
}
/*************************************<->*************************************
*
* PrintPointerControl (smBase)
*
*
* Description:
* -----------
* A convenience function that is separated out instead of being included
* in both QueryServerSettings, and SaveCustomizeSettings.
* Saves pointer control information to the named resource file.
*
* Inputs:
* ------
* smBase = pointer to newly opened resource db used to store setting info
* resSpec = a buffer to hold string resource information until it is
* printed.
* smSettings = place where settings are stored.
*
* Outputs:
* -------
*
* Comments:
* --------
*
*************************************<->***********************************/
static void
PrintPointerControl(
XrmDatabase *smBase)
{
char tmpChar[20];
strcpy(resSpec, SM_RESOURCE_CLASS);
strcat(resSpec, "*");
strcat(resSpec, SmCaccelNum);
strcat(resSpec, ":");
sprintf(tmpChar, "%d", smSettings.accelNum);
strcat(resSpec, tmpChar);
XrmPutLineResource(smBase, resSpec);
strcpy(resSpec, SM_RESOURCE_CLASS);
strcat(resSpec, "*");
strcat(resSpec, SmCaccelDenom);
strcat(resSpec, ":");
sprintf(tmpChar, "%d",smSettings.accelDenom);
strcat(resSpec, tmpChar);
XrmPutLineResource(smBase, resSpec);
strcpy(resSpec, SM_RESOURCE_CLASS);
strcat(resSpec, "*");
strcat(resSpec, SmCthreshold);
strcat(resSpec, ":");
sprintf(tmpChar, "%d",smSettings.threshold);
strcat(resSpec, tmpChar);
XrmPutLineResource(smBase, resSpec);
return;
}
/*************************************<->*************************************
*
* PrintSessionInfo (smBase)
*
*
* Description:
* -----------
* A convenience function that is separated out instead of being included
* in both QueryServerSettings, and SaveCustomizeSettings.
* Saves session manager settings to the named resource file.
*
* Inputs:
* ------
* smBase = pointer to newly opened resource db used to store setting info
* resSpec = a buffer to hold string resource information until it is
* printed.
* smSettings = place where settings are stored.
*
* Outputs:
* -------
*
* Comments:
* --------
*
*************************************<->***********************************/
static void
PrintSessionInfo(
XrmDatabase *smBase)
{
char tmpChar[20];
/*
* Write out the settings for logout confirmation and
* the correct session to return to
*/
strcpy(resSpec, SM_RESOURCE_CLASS);
strcat(resSpec, "*");
strcat(resSpec, SmCshutDownState);
strcat(resSpec, ":");
sprintf(tmpChar, "%d",smSettings.confirmMode);
strcat(resSpec, tmpChar);
XrmPutLineResource(smBase, resSpec);
strcpy(resSpec, SM_RESOURCE_CLASS);
strcat(resSpec, "*");
strcat(resSpec, SmCshutDownMode);
strcat(resSpec, ":");
sprintf(tmpChar, "%d",smSettings.startState);
strcat(resSpec, tmpChar);
XrmPutLineResource(smBase, resSpec);
return;
}
/*************************************<->*************************************
*
* PrintScreenSaver (smBase)
*
*
* Description:
* -----------
* A convenience function that is separated out instead of being included
* in both QueryServerSettings, and SaveCustomizeSettings.
* Saves screen saver information to the named resource file.
*
* Inputs:
* ------
* smBase = pointer to newly opened resource db used to store setting info
* resSpec = a buffer to hold string resource information until it is
* printed.
*
* Outputs:
* -------
*
* Comments:
* --------
*
*************************************<->***********************************/
static void
PrintScreenSaver(
XrmDatabase *smBase)
{
Status newScreenStat;
char tmpChar[20];
if(smCust.screenSavChange == True)
{
newScreenStat = _DtGetSmScreen(smGD.display, smGD.topLevelWindow,
XaDtSmScreenInfo, &screenSaverVals);
/*
* If the property has been deleted, it means that we return to
* the default
*/
if(newScreenStat != Success)
{
return;
}
}
strcpy(resSpec, SM_RESOURCE_CLASS);
strcat(resSpec, "*");
strcat(resSpec, SmCtimeout);
strcat(resSpec, ":");
sprintf(tmpChar, "%d", screenSaverVals.smTimeout);
strcat(resSpec, tmpChar);
XrmPutLineResource(smBase, resSpec);
strcpy(resSpec, SM_RESOURCE_CLASS);
strcat(resSpec, "*");
strcat(resSpec, SmCinterval);
strcat(resSpec, ":");
sprintf(tmpChar, "%d", screenSaverVals.smInterval);
strcat(resSpec, tmpChar);
XrmPutLineResource(smBase, resSpec);
strcpy(resSpec, SM_RESOURCE_CLASS);
strcat(resSpec, "*");
strcat(resSpec, SmCpreferBlank);
strcat(resSpec, ":");
sprintf(tmpChar, "%d", screenSaverVals.smPreferBlank);
strcat(resSpec, tmpChar);
XrmPutLineResource(smBase, resSpec);
strcpy(resSpec, SM_RESOURCE_CLASS);
strcat(resSpec, "*");
strcat(resSpec, SmCallowExp);
strcat(resSpec, ":");
sprintf(tmpChar, "%d", screenSaverVals.smAllowExp);
strcat(resSpec, tmpChar);
XrmPutLineResource(smBase, resSpec);
return;
}
/*************************************<->*************************************
*
* PrintFontPaths (smBase, fontPaths, numPaths)
*
*
* Description:
* -----------
* A convenience function that is separated out instead of being included
* in both QueryServerSettings, and SaveCustomizeSettings.
* Saves pointer control information to the named resource file.
*
* Inputs:
* ------
* smBase = pointer to newly opened resource db used to store setting info
* resSpec = a buffer to hold string resource information until it is
* printed
* fontPaths = font paths to be saved
* numPaths = number of font paths to be saved
*
* Outputs:
* -------
* resSize = made bigger if current buffer is too small to hold all font info
*
* Comments:
* --------
*
*************************************<->***********************************/
static int
PrintFontPaths(
XrmDatabase *smBase,
char **fontPath,
int numPaths)
{
int i;
/* If no fp save req'd, just pretend we did it */
if (smRes.saveFontPath == False) return 0;
strcpy(resSpec, SM_RESOURCE_CLASS);
strcat(resSpec, "*");
strcat(resSpec, SmCfontPath);
strcat(resSpec, ":");
strcat(resSpec, *fontPath);
for(i = 1;i < numPaths;i++)
{
if((strlen(resSpec) + strlen(fontPath[i]) + 1) >= resSize)
{
resSize += 5000;
resSpec = (char *) SM_REALLOC(resSpec, resSize * sizeof(char));
if (resSpec==NULL)
{
PrintErrnoError(DtError, smNLS.cantMallocErrorString);
return(-1);
}
}
strcat(resSpec, ",");
strcat(resSpec, fontPath[i]);
}
XrmPutLineResource(smBase, resSpec);
return(0);
}
/*************************************<->*************************************
*
* PrintKeyboardControl (smBase)
*
*
* Description:
* -----------
* A convenience function that is separated out instead of being included
* in both QueryServerSettings, and SaveCustomizeSettings.
* Saves pointer control information to the named resource file.
*
* Inputs:
* ------
* smBase = pointer to newly opened resource db used to store setting info
* resSpec = a buffer to hold string resource information until it is
* printed
* resSize = size of current resource buffer
*
* Outputs:
* -------
* resSize = buffer is enlarged if more room is need to hold this info
*
* Comments:
* --------
*
*************************************<->***********************************/
static int
PrintKeyboardControl(
XrmDatabase *smBase)
{
int i,j;
char bitTest;
Bool firstRepeat = True;
char tmpChar[20];
strcpy(resSpec, SM_RESOURCE_CLASS);
strcat(resSpec, "*");
strcat(resSpec, SmCkeyClick);
strcat(resSpec, ":");
sprintf(tmpChar, "%d",smSettings.kbdState.key_click_percent);
strcat(resSpec, tmpChar);
XrmPutLineResource(smBase, resSpec);
strcpy(resSpec, SM_RESOURCE_CLASS);
strcat(resSpec, "*");
strcat(resSpec, SmCbellPercent);
strcat(resSpec, ":");
sprintf(tmpChar, "%d",smSettings.kbdState.bell_percent);
strcat(resSpec, tmpChar);
XrmPutLineResource(smBase, resSpec);
strcpy(resSpec, SM_RESOURCE_CLASS);
strcat(resSpec, "*");
strcat(resSpec, SmCbellPitch);
strcat(resSpec, ":");
sprintf(tmpChar, "%d",smSettings.kbdState.bell_pitch);
strcat(resSpec, tmpChar);
XrmPutLineResource(smBase, resSpec);
strcpy(resSpec, SM_RESOURCE_CLASS);
strcat(resSpec, "*");
strcat(resSpec, SmCbellDuration);
strcat(resSpec, ":");
sprintf(tmpChar, "%d",smSettings.kbdState.bell_duration);
strcat(resSpec, tmpChar);
XrmPutLineResource(smBase, resSpec);
strcpy(resSpec, SM_RESOURCE_CLASS);
strcat(resSpec, "*");
strcat(resSpec, SmCledMask);
strcat(resSpec, ":");
sprintf(tmpChar, "%ld",smSettings.kbdState.led_mask);
strcat(resSpec, tmpChar);
XrmPutLineResource(smBase, resSpec);
strcpy(resSpec, SM_RESOURCE_CLASS);
strcat(resSpec, "*");
strcat(resSpec, SmCglobalRepeats);
strcat(resSpec, ":");
sprintf(tmpChar, "%d",smSettings.kbdState.global_auto_repeat);
strcat(resSpec, tmpChar);
XrmPutLineResource(smBase, resSpec);
strcpy(resSpec, SM_RESOURCE_CLASS);
strcat(resSpec, "*");
strcat(resSpec, SmCautoRepeats);
strcat(resSpec, ":");
/*
* Now write out which keys need to be auto repeated one at a time
*/
if(smSettings.kbdState.global_auto_repeat != AutoRepeatModeOn)
{
for(i = 0;i < 32;i++)
{
bitTest = 0x01;
for(j = 0;j < 8;j++)
{
if((bitTest & smSettings.kbdState.auto_repeats[i]) != 0)
{
if(firstRepeat == True)
{
firstRepeat = False;
}
else
{
strcat(resSpec, ",");
}
if((strlen(resSpec) + 5) >= resSize)
{
resSize += 5000;
resSpec = (char *) SM_REALLOC(resSpec,
resSize * sizeof(char));
if (resSpec==NULL)
{
PrintErrnoError(DtError,
smNLS.cantMallocErrorString);
return(-1);
}
}
sprintf(tmpChar, "%d", ((8 * i) + j));
strcat(resSpec, tmpChar);
}
bitTest <<= 1;
}
}
}
else
{
strcat(resSpec, "");
}
XrmPutLineResource(smBase, resSpec);
return(0);
}
/*************************************<->*************************************
*
* PrintPointerMapping (smBase, buttonRet, numButton)
*
*
* Description:
* -----------
* A convenience function that is separated out instead of being included
* in both QueryServerSettings, and SaveCustomizeSettings.
* Saves pointer mapping information to the named resource file.
*
* Inputs:
* ------
* smBase = pointer to newly opened resource db used to store setting info
* resSpec = a buffer to hold string resource information until it is
* printed
* resSize = size of resource buffer
* buttonRet = button mapping to be saved
* numButton = number of buttons in button mapping
*
* Outputs:
* -------
* resSize = size of buffer is change if it needs to be enlarged during
* routine
*
* Comments:
* --------
*
*************************************<->***********************************/
static int
PrintPointerMapping(
XrmDatabase *smBase,
char *buttonRet,
int numButton )
{
int i, numLoops;
char tmpChar[20];
strcpy(resSpec, SM_RESOURCE_CLASS);
strcat(resSpec, "*");
strcat(resSpec, SmCbuttonMap);
strcat(resSpec, ":");
numLoops = numButton - 1;
for(i = 0;i <= numLoops;i++)
{
if((strlen(resSpec) + 5) >= resSize)
{
resSize += 5000;
resSpec = (char *) SM_REALLOC(resSpec, resSize * sizeof(char));
if (resSpec==NULL)
{
PrintErrnoError(DtError, smNLS.cantMallocErrorString);
return(-1);
}
}
sprintf(tmpChar, "%d",buttonRet[i]);
strcat(resSpec, tmpChar);
if(i != numLoops)
{
strcat(resSpec, ",");
}
XrmPutLineResource(smBase, resSpec);
}
return(0);
}