mirror of
git://git.code.sf.net/p/cdesktopenv/code
synced 2025-03-09 15:50:02 +00:00
2203 lines
55 KiB
C
2203 lines
55 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 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);
|
||
}
|