2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these librararies and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
23 /* $TOG: SmSave.c /main/27 1998/07/23 18:07:58 mgreess $ */
24 /*************************************<+>*************************************
25 *****************************************************************************
29 ** Project: HP DT Session Manager (dtsession)
33 ** This file contains all routines that save off the session at any point
34 ** in time. The session includes settings, resources, and clients. How
35 ** the session manager behaves during a save depends on how the user has
36 ** configured it to behave.
39 *****************************************************************************
40 *************************************<+>*************************************/
42 * (c) Copyright 1997 The Open Group
43 * (c) Copyright 1996 Digital Equipment Corporation.
44 * (c) Copyright 1990, 1993, 1994, 1996 Hewlett-Packard Company.
45 * (c) Copyright 1993, 1994, 1996 International Business Machines Corp.
46 * (c) Copyright 1993, 1994, 1996 Sun Microsystems, Inc.
47 * (c) Copyright 1993, 1994, 1996 Novell, Inc.
48 * (c) Copyright 1996 FUJITSU LIMITED.
49 * (c) Copyright 1996 Hitachi.
56 #include <sys/types.h>
58 #include <sys/param.h>
60 #include <sys/socket.h>
61 #include <netinet/in.h>
64 #include <arpa/inet.h>
68 #include <X11/Intrinsic.h>
69 #include <X11/Xutil.h>
70 #include <X11/Xatom.h>
71 #include <X11/StringDefs.h>
72 #include <X11/keysymdef.h>
74 #include <Dt/Connect.h>
75 #include <Dt/UserMsg.h>
76 #include <Dt/SessionM.h>
77 #include <Dt/MsgLog.h>
80 #include "SmResource.h"
82 #include "SmGlobals.h"
85 #include "SmProtocol.h"
86 #include "SmRestore.h"
89 #include "SmProperty.h"
98 #include <X11/Xlibint.h>
101 typedef struct _ProxyClientCache {
104 } ProxyClientCache, *ProxyClientCachePtr;
106 static ProxyClientCachePtr proxyList;
107 static int numProxyClients = 0;
108 static int numProxyAllocated = 0;
109 static int proxyCacheAllocIncrement = 10;
112 * Local Function Declarations
114 static void CacheProxyClient (
119 static void PruneSessionDirectory ();
121 static Boolean WriteClientDatabase ();
123 static void OutputXSMPClients (
126 static void OutputProxyClients (
129 static Boolean CheckRequiredProperties (
130 ClientRecPtr pClientRec);
132 static void PrintStartupInfo(
136 static int QueryServerSettings( void ) ;
137 static int SaveCustomizeSettings( void ) ;
138 static int OutputResource( void ) ;
139 static void PrintPointerControl(
140 XrmDatabase *smBase) ;
141 static void PrintSessionInfo(
142 XrmDatabase *smBase) ;
143 static void PrintScreenSaver(
144 XrmDatabase *smBase) ;
145 static int PrintFontPaths(
149 static int PrintKeyboardControl(
150 XrmDatabase *smBase);
151 static int PrintPointerMapping(
155 static void PrintWorkHintString(
158 static void PrintCmdHintString(
161 static void PrintCmdString(
164 static void PrintRemoteCmdString(
170 * Global variables that are exposed
172 SmScreenInfo screenSaverVals;
173 SmAudioInfo audioVals;
174 SmKeyboardInfo keyboardVals;
177 * Variables global to this module only
181 * used as a buffer to write resources into
182 * before they are written out
184 static int resSize = 10000;
185 static char *resSpec;
188 * Vars used to maintain state that is sent to the SaveState
191 static Boolean saveHome;
197 /*************************************<->*************************************
203 * Do all of the preliminary work that must be done before the state
204 * of a checkpoint can be saved.
208 * saveToHome: This session is to be saved to the home session or current
209 * mode = whether the session is to be reset or restarted
211 *************************************<->***********************************/
217 unsigned char *propData;
220 * Cache saveToHome and mode - they will be needed after all of
221 * the XSMP clients are saved and the Proxy clients are saved.
223 saveHome = saveToHome;
227 * First set up the save paths so we know if we have to do anything here
229 if ((SetSavePath(saveToHome, mode)) == -1)
233 * Take care of the save mode property on the root window so that the
234 * clients will know how to save this file (if they save files)
236 if(saveToHome == False)
238 propData = (unsigned char *) SM_CURRENT_DIRECTORY;
242 propData = (unsigned char *) SM_HOME_DIRECTORY;
246 * Change the save mode to give the subdirectory saved to
249 XChangeProperty(smGD.display, RootWindow(smGD.display, 0),
250 XaSmSaveMode, XA_STRING, 8, PropModeReplace,
251 propData, strlen((char *)propData));
252 XFlush(smGD.display);
255 /*************************************<->*************************************
261 * Tells the SM to notify the XSMP clients to save their state.
262 * The function CompleteSave fill be invoked after the XSMP clients
263 * have completed their save.
267 * saveToHome: This session is to be saved to the home session or current
268 * mode = whether the session is to be reset or restarted
272 * As a result of this routine files will be saved in the users .dt directory
273 * that will allow the session manager to restore the session at a later
276 * NOTE - this function is called as the result of the following
279 * 1. User initiates a Save Home Session via the Style Manager
280 * 2. The Session Manager receives a SM_XSESSION_EXIT message
281 * 3. The Session Manager receives a SM_SAVE_SESSION message
283 *************************************<->***********************************/
295 * Notify XSMP clients of the save
297 SaveYourselfReqProc (NULL, NULL, saveType, shutdown, interactStyle,
302 /*************************************<->*************************************
308 * Called after the XSMP clients have saved their state. In charge of
309 * calling all routines that save session information for XSMP client
310 * and Proxy clients as well as settings, resources, etc.
315 *************************************<->***********************************/
321 unsigned char *propData;
322 char *tmpPath, tmpVersion[20];
324 Boolean saveToHome = saveHome;
328 * If this is a Home session and the user is logging out, return
329 * now - the XSMP clients have all responded to the save and the
330 * ICCC clients don't save their state when a Home session is
333 if (smGD.sessionType == HOME_SESSION &&
334 smXSMP.saveState.shutdown == True &&
335 smSettings.startState == DtSM_HOME_STATE)
339 * Start a wait state - don't want anything to happen while
340 * ICCC clients are being saved
344 resSpec = (char *) SM_MALLOC(resSize * sizeof(char));
347 PrintErrnoError(DtError, smNLS.cantMallocErrorString);
351 if (!WriteClientDatabase ()) {
352 ShowWaitState(False);
358 * WARNING - THIS VARIABLE MUST BE SET BEFORE THE SETTING INFORMATION IS
359 * CALLED - SETTINGS MUST BE SAVED BEFORE RESOURCES BECAUSE SETTINGS
360 * GETS INFORMATION SAVED IN RESOURCES (smToSet.dClickBuf)
362 smToSet.dClickBuf[0] = NULL;
365 * Do the actual output of the X settings information. Output will
366 * go to the resource database at this point and be written to the
367 * resource file with the rest of the resources (below).
369 if(smRes.querySettings == True)
371 QueryServerSettings();
375 SaveCustomizeSettings();
379 * Do the output of resource information.
383 ShowWaitState(False);
388 XDeleteProperty(smGD.display, DefaultRootWindow(smGD.display), XaSmSaveMode);
391 * Go save the default palette at this time
393 if(saveToHome == True)
394 SaveDefaultPalette(smGD.display, smGD.savePath, DtSM_HOME_STATE);
396 SaveDefaultPalette(smGD.display, smGD.savePath, mode);
398 PruneSessionDirectory ();
400 ShowWaitState(False);
406 /*************************************<->*************************************
408 * PruneSessionDirectory -
410 * Description: Removes the oldest session direcotry if the number
411 * of directories exceeds the smRes.numSessionsBackedup.
415 *************************************<->***********************************/
417 PruneSessionDirectory ()
426 char *oldDir; /* the .old dir */
431 if ((dirp = opendir (smGD.savePath)) == NULL)
434 clientDB = (char*) XtMalloc((2*MAXPATHLEN) + 1);
435 oldestDir = (char*) XtMalloc(MAXPATHLEN + 1);
436 saveDir = (char*) XtMalloc(MAXPATHLEN + 1);
437 tmpDir = (char*) XtMalloc(MAXPATHLEN + 1);
439 dirPrefix = XtMalloc (strlen (smGD.restoreSession) + 2);
440 sprintf (dirPrefix, "%s.", smGD.restoreSession);
441 if (strlen (dirPrefix) > 5) {
443 dirPrefix[5] = '\000';
446 oldDir = XtMalloc (strlen (smGD.restoreSession) +
447 strlen (SM_OLD_EXTENSION) + 2);
448 sprintf (oldDir, "%s.%s", smGD.restoreSession, SM_OLD_EXTENSION);
450 (void) time (&oldestTime);
452 while ((dp = readdir (dirp)) != NULL) {
454 * Do some sanity checks to limit the number of * stat()
455 * calls. Note that for backward compatibility with CDE
456 * 1.0 if a ".old" directory exists, keep it.
458 if ((!strcmp (dp->d_name, ".")) ||
459 (!strcmp (dp->d_name, "..")) ||
460 (!strcmp (dp->d_name, oldDir)) ||
461 (strncmp (dp->d_name, dirPrefix, strlen (dirPrefix))))
464 sprintf (tmpDir, "%s/%s", smGD.savePath, dp->d_name);
466 if (((stat (tmpDir, &buf)) == 0) && S_ISDIR (buf.st_mode)) {
467 if (buf.st_mtime < oldestTime) {
469 * Keep track of the oldest dir in case
470 * it needs to be removed
472 oldestTime = buf.st_mtime;
473 strcpy (oldestDir, tmpDir);
480 if (numDirs > smRes.numSessionsBackedup) {
482 * Need to remove the oldest directory. The general
483 * process (using "home" as an example) is:
487 * Execute the DiscardCommand props in the home directory
491 * The reason this is done is because when the
492 * DiscardCommand were saved, the directory at the time of
493 * the save contained "home". For example, a DiscardCommand
496 * rm -f /u/somebody/.dt/sessions/home/app.state
498 * yet because of the session archiving, the app.state
499 * file may actually be in a directory like:
501 * /u/somebody/.dt/sessions/home.<tempnam>
507 tmpName = (char *) XtMalloc (strlen (smGD.restoreSession) + 2);
508 sprintf (tmpName, "%s.", smGD.restoreSession);
509 if (strlen (tmpName) > 5) {
513 tmp = (char *) tempnam (smGD.savePath, tmpName);
515 sprintf (saveDir, "%s/%s", smGD.savePath, smGD.restoreSession);
517 MoveDirectory (saveDir, tmp, False);
518 MoveDirectory (oldestDir, saveDir, False);
520 sprintf (clientDB, "%s/%s/%s", smGD.savePath,
521 smGD.restoreSession, SM_CLIENT_FILE2);
523 ExecuteDiscardCommands (clientDB);
525 MoveDirectory (tmp, saveDir, True);
532 * If exiting and the current session is a Current session
533 * but smSettings.startState has been set to to a
534 * Home session (this would be true if a user started a
535 * Current session but used the Style Manager to set the session
536 * upon next login to be a Home session), then if a home
537 * directory exists, mv current to current.old
540 if (smXSMP.saveState.shutdown && smGD.sessionType == CURRENT_SESSION &&
541 smSettings.startState == DtSM_HOME_STATE) {
543 sprintf (tmpDir, "%s/%s", smGD.savePath, SM_HOME_DIRECTORY);
545 if (((stat (tmpDir, &buf)) == 0) && S_ISDIR (buf.st_mode)) {
547 sprintf (saveDir, "%s/%s", smGD.savePath, oldDir);
549 if (((stat (saveDir, &buf)) == 0) &&
550 S_ISDIR (buf.st_mode)) {
552 sprintf (clientDB, "rm -rf %s", saveDir);
553 SystemCmd (clientDB);
555 sprintf (oldestDir, "%s/%s", smGD.savePath,
556 SM_CURRENT_DIRECTORY);
558 MoveDirectory (oldestDir, saveDir, False);
572 /*************************************<->*************************************
574 * WriteClientDatabase -
576 * Description: Writes the client database (for XSMP and Proxy clients)
580 * Returns True if the database is wrtten OK; False otherwise
582 *************************************<->***********************************/
584 WriteClientDatabase ()
589 db = (char*) XtMalloc(MAXPATHLEN + 1);
590 (void) sprintf (db, "%s/%s/%s", smGD.savePath, smGD.restoreSession,
593 if ((outputDB = OpenOutputClientDB (db, smXSMP.dbVersion,
594 smXSMP.dbSessionId)) == NULL) {
597 str = strdup ((char *) GETMESSAGE (40, 18,
598 "The following database file cannot be opened for writing:\n\n %s\n\nThe session will not be saved."));
601 DtMsgLogMessage (smGD.programName, DtMsgLogError,
611 OutputProxyClients (outputDB);
613 OutputXSMPClients (outputDB);
615 CloseClientDB (outputDB, True);
621 /*************************************<->*************************************
623 * OutputProxyClients -
625 * Description: Outputs the Proxy clients
627 * Inputs: database pointer
631 *************************************<->***********************************/
637 for (i = 0; i < numProxyClients; i++)
638 PrintStartupInfo (outputDB,
640 proxyList[i].window);
644 /*************************************<->*************************************
646 * OutputXSMPClients -
648 * Description: Outputs the XSMP clients
650 * Inputs: database pointer
654 *************************************<->***********************************/
659 XSMPClientDBRec dbRec;
660 ClientRecPtr pClientRec;
662 for (pClientRec = connectedList; pClientRec != NULL;
663 pClientRec = pClientRec->next) {
665 dbRec.restartHint = pClientRec->restartHint;
666 (void) GetCardPropertyValue (pClientRec, SmRestartStyleHint,
669 if (dbRec.restartHint == SmRestartNever)
672 if (!pClientRec->active)
675 if (!CheckRequiredProperties (pClientRec))
680 dbRec.clientId = pClientRec->clientId;
681 dbRec.clientHost = pClientRec->clientHost;
683 dbRec.program = GetArrayPropertyValue (pClientRec,
685 dbRec.cwd = GetArrayPropertyValue (pClientRec,
688 dbRec.restartCommand = GetListOfArrayPropertyValue (pClientRec,
690 dbRec.cloneCommand = GetListOfArrayPropertyValue (pClientRec,
692 dbRec.discardCommand = GetListOfArrayPropertyValue (pClientRec,
694 dbRec.environment = GetListOfArrayPropertyValue (pClientRec,
697 if (!PutXSMPClientDBRec (outputDB, &dbRec)) {
701 str = strdup ((char *) GETMESSAGE (40, 19,
702 "Application '%s' cannot be saved."));
705 DtMsgLogMessage (smGD.programName,
712 if (dbRec.restartCommand)
713 XtFree ((char *) dbRec.restartCommand);
714 if (dbRec.cloneCommand)
715 XtFree ((char *) dbRec.cloneCommand);
716 if (dbRec.discardCommand)
717 XtFree ((char *) dbRec.discardCommand);
718 if (dbRec.environment)
719 XtFree ((char *) dbRec.environment);
724 /*************************************<->*************************************
726 * CheckRequiredProperties -
728 * Description: Check a client's required properties
730 * Inputs: ClientRecPtr
732 * Returns: True if the client has all of the required properties;
733 * otherwise returns False
735 *************************************<->***********************************/
737 CheckRequiredProperties (
738 ClientRecPtr pClientRec)
740 PropertyRecPtr pPropRec;
742 char * program = NULL;
744 if ((program = GetArrayPropertyValue (pClientRec, SmProgram)) == NULL){
746 str = strdup ((char *) GETMESSAGE (40, 23,
747 "The following application did not set the required\nproperty '%s':\n\n %s\n\nThis application will not be saved."));
750 DtMsgLogMessage (smGD.programName, DtMsgLogError, str,
751 SmProgram, pClientRec->clientId);
757 if ((pPropRec = GetPropertyRec (pClientRec, SmRestartCommand)) == NULL){
759 str = strdup ((char *) GETMESSAGE (40, 24,
760 "24 Application '%s' will not be saved because it did not set\nthe required property '%s'."));
763 DtMsgLogMessage (smGD.programName, DtMsgLogError,
764 str, program, SmRestartCommand);
770 if ((pPropRec = GetPropertyRec (pClientRec, SmCloneCommand)) == NULL) {
772 * This is a warning - still want to save the client
774 str = strdup ((char *) GETMESSAGE (40, 25,
775 "Application '%s' did not set the required property '%s'."));
778 DtMsgLogMessage (smGD.programName, DtMsgLogWarning, str,
779 program, SmCloneCommand);
788 /*************************************<->*************************************
790 * NotifyProxyClients -
795 * Notify Proxy clients - calls routines to find top level windows, and
796 * notifies the Proxy clients about an impending save.
804 *************************************<->***********************************/
806 NotifyProxyClients ( )
808 unsigned int topListLength, containedListLength;
809 WindowInfo * topList; /* list of top-level windows */
810 WindowInfo topLevelWindowInfo;
813 unsigned long nitems;
814 unsigned long leftover;
815 unsigned char * data = NULL;
816 Boolean containedClient;
821 * Save off the clients currently running. This will be done
822 * one screen at a time
824 for(j = 0;j < smGD.numSavedScreens;j++)
827 * Get a list of children of the root window. If there are none
828 * return with an error condition.
830 if(GetTopLevelWindows(j,&topList,&topListLength, &containedListLength))
834 * Figure out how to restart the client associate with each window.
836 for (i=0 ; i<(topListLength + containedListLength); ++i)
838 topLevelWindowInfo=topList[i];
840 if(i >= topListLength)
842 containedClient = True;
846 containedClient = False;
850 * If this window is my window - skip it I don't want to
851 * save myself because I will be started automatically
853 if (XGetWindowProperty(smGD.display, topLevelWindowInfo.wid,
855 (long)BUFSIZ,False,XA_STRING,&actualType,
856 &actualFormat,&nitems,&leftover,
859 if (actualType==XA_STRING &&
860 !strcmp((char *) data, SM_RESOURCE_NAME))
862 SM_FREE((char *)data);
867 SM_FREE((char *)data);
872 * If the client participates in the WM_SAVE_YOURSELF protocol,
873 * send the appropriate messages and wait for the proper
876 (void) SaveYourself(topLevelWindowInfo);
878 CacheProxyClient ((numClients == 0), j, topLevelWindowInfo.wid);
884 * Free space malloc'd by GetTopLevelWindowInfo
886 if(topListLength > 0)
888 SM_FREE((char *) topList);
894 /*************************************<->*************************************
900 * Add a Proxy client to the proxy client cache.
904 * firstClient - if True, this is the first client in the cache
905 * screenNum - the client's screen number
906 * window - the client's window number
911 *************************************<->***********************************/
912 static void CacheProxyClient (
920 if (numProxyClients >= numProxyAllocated) {
921 numProxyAllocated += proxyCacheAllocIncrement;
922 proxyList = (ProxyClientCachePtr) XtRealloc ((char *) proxyList,
923 numProxyAllocated * sizeof (ProxyClientCache));
926 proxyList[numProxyClients].screen = screenNum;
927 proxyList[numProxyClients].window = window;
934 /*************************************<->*************************************
940 * Output startup information for one proxy client
944 * outputDB = a pointer to the client database
945 * screen = which screen the client is running on
946 * window = the top level window of the lient
954 *************************************<->***********************************/
965 XWindowAttributes windowAttr;
968 ProxyClientDBRec dbRec;
973 #ifdef _SUN_OS /* pull out quotes from OpenWindow tools commands */
978 * Get the attributes and properties on the window
980 if ((XGetWindowAttributes(smGD.display, window, &windowAttr)) == 0)
983 if (GetStandardProperties(window, screen, &wargc, &wargv,
984 &clientMachine, &xsmpClient)==0)
988 * If the client doesn't have a WM_COMMAND property, we can't restart it
990 if (!wargv||!wargv[0])
994 * If the client is an XSMP client, don't save it as a Proxy client.
999 #ifdef _SUN_OS /* pull out quotes from OpenWindow tools commands */
1002 /* check for foreground */
1003 if ((ptr = strstr (ptr, "fg \"")) != NULL) {
1004 if (strlen (ptr) > 3)
1006 if ((ptr = strchr (ptr, '"')) != NULL)
1010 /* check for background */
1011 if ((ptr = strstr (wargv[0], "bg \"")) != NULL) {
1012 if (strlen (ptr) > 3)
1014 if ((ptr = strchr (ptr, '"')) != NULL)
1021 * Find out if the client is running locally
1023 dbRec.clientHost = NULL;
1024 if(clientMachine != NULL)
1026 if(DtIsLocalHostP(clientMachine) == FALSE)
1028 dbRec.clientHost = clientMachine;
1033 * Must NULL-terminate the WM_COMMAND before writing it
1035 argv = (char **) XtMalloc ((wargc + 1) * sizeof (char *));
1039 for (i = 0; i < wargc; i++)
1043 dbRec.command = argv;
1044 dbRec.screenNum = screen;
1046 writeStatus = PutProxyClientDBRec (outputDB, &dbRec);
1048 XtFree ((char *) argv);
1050 if (writeStatus == False)
1053 * There should be an error written here - however
1054 * since this means that there already is a write error to
1055 * the disk - no error can be written
1057 (void) CloseClientDB (outputDB, True);
1060 * On a write error - move the old session back to
1061 * be used and exit with an error condition
1063 XFreeStringList(wargv);
1065 strcat(smGD.savePath, "/");
1066 if(smGD.sessionType == HOME_SESSION)
1068 strcat(smGD.savePath, SM_HOME_DIRECTORY);
1072 strcat(smGD.savePath, SM_CURRENT_DIRECTORY);
1075 MoveDirectory(smGD.etcPath, smGD.savePath, False);
1080 * Free up the argv property
1082 XFreeStringList(wargv);
1086 /*************************************<->*************************************
1088 * QueryServerSettings ()
1093 * Query the server for all it's current settings information, and then
1094 * write that information to the session managers settings resource file.
1098 * smGD.settingPath = (global) pointer to file where
1099 * setting info should be saved.
1106 * This routine slows down the session manager's shutdown process
1107 * considerably, and is therefore only called when the user specifies
1108 * that all settings should be queried. Otherwise, only settings set in
1109 * the customizer should be saved.
1111 *************************************<->***********************************/
1113 QueryServerSettings( void )
1117 KeySym *tmpSyms, tmpMod;
1118 XModifierKeymap *modMap;
1120 int numButton, numPaths;
1121 int buttonSize = 128;
1122 XrmDatabase smBase = NULL;
1126 buttonRet = (char *) SM_MALLOC(buttonSize * sizeof(char));
1127 if (buttonRet==NULL)
1129 PrintErrnoError(DtError, smNLS.cantMallocErrorString);
1134 * First set up all pointer control parameters
1135 * These are simple integer values that get saved
1136 * here, then read into a structure and set at restore
1139 XGetPointerControl(smGD.display, &smSettings.accelNum,
1140 &smSettings.accelDenom,
1141 &smSettings.threshold);
1142 PrintPointerControl(&smBase);
1145 * Get all the screen saver values. These are all simple integer
1146 * values that are read back into a structure and set at restore
1149 XGetScreenSaver(smGD.display, &screenSaverVals.smTimeout,
1150 &screenSaverVals.smInterval,
1151 &screenSaverVals.smPreferBlank,
1152 &screenSaverVals.smAllowExp);
1153 PrintScreenSaver(&smBase);
1156 * Write out all font path information.
1157 * Write out all the paths one by one concatenated by commas.
1159 fontPath = XGetFontPath(smGD.display, &numPaths);
1160 if(fontPath != NULL)
1162 if(PrintFontPaths(&smBase, fontPath, numPaths) != 0)
1164 XFreeFontPath(fontPath);
1171 * Write out all the keyboard control information.
1173 XGetKeyboardControl(smGD.display, &smSettings.kbdState);
1174 if(PrintKeyboardControl(&smBase) != 0)
1177 XFreeFontPath(fontPath);
1182 * Put all the button modifier information into the resource database.
1183 * Find out the number of buttons and then write out the character
1184 * string for each button.
1186 numButton = XGetPointerMapping(smGD.display, (unsigned char *)buttonRet, 128);
1189 buttonRet = (char *) SM_REALLOC(buttonRet, numButton * sizeof(char));
1190 if (buttonRet==NULL)
1193 XFreeFontPath(fontPath);
1194 PrintErrnoError(DtError, smNLS.cantMallocErrorString);
1197 numButton = XGetPointerMapping(smGD.display, (unsigned char *)buttonRet, numButton);
1199 if(PrintPointerMapping(&smBase, buttonRet,
1203 XFreeFontPath(fontPath);
1209 * Put all keyboard mapping information in the resource database
1210 * Don't bother putting this in a separate print function because
1211 * the customizer doesn't do keymap savings this way.
1213 smSettings.numKeyCode = smGD.display->max_keycode -
1214 smGD.display->min_keycode;
1215 tmpSyms = XGetKeyboardMapping(smGD.display,
1216 (KeyCode) smGD.display->min_keycode,
1217 smSettings.numKeyCode,
1218 &smSettings.keySymPerCode);
1222 XFreeFontPath(fontPath);
1224 PrintErrnoError(DtError, smNLS.cantMallocErrorString);
1228 strcpy(resSpec, SM_RESOURCE_CLASS);
1229 strcat(resSpec, "*");
1230 strcat(resSpec, SmCnumKeyCode);
1231 strcat(resSpec, ":");
1232 sprintf(tmpChar,"%d", smSettings.numKeyCode);
1233 strcat(resSpec, tmpChar);
1234 XrmPutLineResource( &smBase, resSpec);
1236 strcpy(resSpec, SM_RESOURCE_CLASS);
1237 strcat(resSpec, "*");
1238 strcat(resSpec, SmCkeySymsPerKey);
1239 strcat(resSpec, ":");
1240 sprintf(tmpChar,"%d", smSettings.keySymPerCode);
1241 strcat(resSpec, tmpChar);
1242 XrmPutLineResource( &smBase, resSpec);
1244 strcpy(resSpec, SM_RESOURCE_CLASS);
1245 strcat(resSpec, "*");
1246 strcat(resSpec, SmCkeySyms);
1247 strcat(resSpec, ":");
1248 numLoops = smSettings.numKeyCode * smSettings.keySymPerCode;
1249 sprintf(tmpChar,"%ld", tmpSyms[0]);
1250 strcat(resSpec, tmpChar);
1251 for(i = 1;i < numLoops;i++)
1253 if((strlen(resSpec) + 5) >= resSize)
1256 resSpec = (char *) SM_REALLOC(resSpec, resSize * sizeof(char));
1259 SM_FREE((char *)tmpSyms);
1261 SM_FREE((char *)fontPath);
1263 PrintErrnoError(DtError, smNLS.cantMallocErrorString);
1267 strcat(resSpec, ",");
1268 sprintf(tmpChar,"%ld", tmpSyms[i]);
1269 strcat(resSpec, tmpChar);
1271 XrmPutLineResource( &smBase, resSpec);
1275 * Write out all keyboard modifier info. This will be a pretty slow
1276 * process considering that every keycode will have to be turned into
1277 * a keysym before writing. Don't bother putting print stuff in a
1278 * separate function because it will not be handled in the customize
1281 modMap = XGetModifierMapping(smGD.display);
1284 SM_FREE((char *)tmpSyms);
1286 XFreeFontPath(fontPath);
1288 PrintErrnoError(DtError, smNLS.cantMallocErrorString);
1292 strcpy(resSpec, SM_RESOURCE_CLASS);
1293 strcat(resSpec, "*");
1294 strcat(resSpec, SmCmaxKeyPerMod);
1295 strcat(resSpec, ":");
1296 sprintf(tmpChar,"%d", modMap->max_keypermod);
1297 strcat(resSpec, tmpChar);
1298 XrmPutLineResource( &smBase, resSpec);
1300 strcpy(resSpec, SM_RESOURCE_CLASS);
1301 strcat(resSpec, "*");
1302 strcat(resSpec, SmCmodMap);
1303 strcat(resSpec, ":");
1304 numLoops = (8 * modMap->max_keypermod) - 1;
1305 for(i = 0;i <= numLoops;i++)
1307 if((strlen(resSpec) + 9) >= resSize)
1310 resSpec = (char *) SM_REALLOC(resSpec, resSize * sizeof(char));
1313 SM_FREE((char *)tmpSyms);
1314 XFreeModifiermap(modMap);
1316 XFreeFontPath(fontPath);
1318 PrintErrnoError(DtError, smNLS.cantMallocErrorString);
1322 tmpMod = XKeycodeToKeysym(smGD.display, modMap->modifiermap[i], 0);
1323 sprintf(tmpChar,"%ld", tmpMod);
1324 strcat(resSpec, tmpChar);
1327 strcat(resSpec, ",");
1330 XrmPutLineResource( &smBase, resSpec);
1334 * Print session manager settings
1336 PrintSessionInfo(&smBase);
1339 * Write settings resources out to disk
1341 XrmPutFileDatabase(smBase, smGD.settingPath);
1344 * Free all allocated resources
1347 XFreeFontPath(fontPath);
1348 SM_FREE((char *)tmpSyms);
1349 XFreeModifiermap(modMap);
1351 XrmDestroyDatabase(smBase);
1356 /*************************************<->*************************************
1358 * SaveCustomizeSettings ()
1363 * Saves those settings that have been set in the customizer during the
1364 * session to whatever values they were set to during the session.
1369 * smGD.resourcePath = (global) a pointer
1370 * to where the settings should be stored.
1379 * This routine is the default saved for saving settings. If the user
1380 * wants all settings saved, they have to set a resource saying that that
1383 *************************************<->***********************************/
1385 SaveCustomizeSettings( void )
1389 XrmDatabase smBase = NULL;
1390 char *tmpChar[20], *ptrRet = NULL, *tmpKey;
1395 if(smCust.pointerChange)
1397 newStat = _DtGetSmPointer(smGD.display, smGD.topLevelWindow,
1398 XaDtSmPointerInfo, &ptrRet);
1399 if(newStat != Success)
1401 smToSet.pointerChange = False;
1402 smToSet.pointerMapChange = False;
1406 sscanf(ptrRet, "%d %s %d %d %s",
1409 &smSettings.accelNum,
1410 &smSettings.threshold,
1411 &smToSet.dClickBuf);
1412 smSettings.accelDenom = 1;
1414 tmpKey = strtok(tmpMap, "_");
1416 while(tmpKey != NULL)
1418 smToSet.pointerMap[i] = (char) atoi(tmpKey);
1420 tmpKey = strtok(NULL, "_");
1425 * append a \n to dClickBuf because it was scanned out
1427 strcat(smToSet.dClickBuf, "\n");
1429 if (ptrRet) XFree(ptrRet);
1432 if(smToSet.pointerChange == True)
1434 PrintPointerControl(&smBase);
1437 if(smToSet.pointerMapChange == True)
1439 if(PrintPointerMapping(&smBase, smToSet.pointerMap,
1440 smToSet.numButton) != 0)
1446 if(smToSet.screenSavChange == True)
1448 PrintScreenSaver(&smBase);
1451 if(smCust.audioChange == True)
1453 newStat = _DtGetSmAudio(smGD.display, smGD.topLevelWindow,
1454 XaDtSmAudioInfo, &audioVals);
1456 if(newStat == Success)
1458 smSettings.kbdState.bell_percent = audioVals.smBellPercent;
1459 smSettings.kbdState.bell_pitch = audioVals.smBellPitch;
1460 smSettings.kbdState.bell_duration = audioVals.smBellDuration;
1464 smToSet.audioChange = False;
1468 if (smToSet.audioChange)
1470 strcpy(resSpec, SM_RESOURCE_CLASS);
1471 strcat(resSpec, "*");
1472 strcat(resSpec, SmCbellPercent);
1473 strcat(resSpec, ":");
1474 sprintf((char *)tmpChar,"%d",smSettings.kbdState.bell_percent);
1475 strcat(resSpec, (char *)tmpChar);
1476 XrmPutLineResource(&smBase, resSpec);
1478 strcpy(resSpec, SM_RESOURCE_CLASS);
1479 strcat(resSpec, "*");
1480 strcat(resSpec, SmCbellPitch);
1481 strcat(resSpec, ":");
1482 sprintf((char *)tmpChar,"%d",smSettings.kbdState.bell_pitch);
1483 strcat(resSpec, (char *)tmpChar);
1484 XrmPutLineResource(&smBase, resSpec);
1486 strcpy(resSpec, SM_RESOURCE_CLASS);
1487 strcat(resSpec, "*");
1488 strcat(resSpec, SmCbellDuration);
1489 strcat(resSpec, ":");
1490 sprintf((char *)tmpChar,"%d",smSettings.kbdState.bell_duration);
1491 strcat(resSpec, (char *)tmpChar);
1492 XrmPutLineResource(&smBase, resSpec);
1495 if(smCust.keyboardChange == True)
1497 newStat = _DtGetSmKeyboard(smGD.display, smGD.topLevelWindow,
1498 XaDtSmKeyboardInfo, &keyboardVals);
1499 if(newStat == Success)
1501 smSettings.kbdState.key_click_percent = keyboardVals.smKeyClickPercent;
1502 smSettings.kbdState.global_auto_repeat = keyboardVals.smGlobalAutoRepeat;
1506 smToSet.keyboardChange = False;
1510 if(smToSet.keyboardChange == True)
1512 strcpy(resSpec, SM_RESOURCE_CLASS);
1513 strcat(resSpec, "*");
1514 strcat(resSpec, SmCkeyClick);
1515 strcat(resSpec, ":");
1516 sprintf((char *)tmpChar,"%d", smSettings.kbdState.key_click_percent);
1517 strcat(resSpec, (char *)tmpChar);
1518 XrmPutLineResource(&smBase, resSpec);
1520 strcpy(resSpec, SM_RESOURCE_CLASS);
1521 strcat(resSpec, "*");
1522 strcat(resSpec, SmCglobalRepeats);
1523 strcat(resSpec, ":");
1524 sprintf((char *)tmpChar,"%d", smSettings.kbdState.global_auto_repeat);
1525 strcat(resSpec, (char *)tmpChar);
1526 XrmPutLineResource(&smBase, resSpec);
1531 * Write out all font path information.
1532 * Write out all the paths one by one concatenated by commas.
1535 fontPath = XGetFontPath(smGD.display, &numPaths);
1536 if(fontPath != NULL) {
1537 if(PrintFontPaths(&smBase, fontPath, numPaths) != 0) {
1538 XFreeFontPath(fontPath);
1544 * Save session manager settings
1546 PrintSessionInfo(&smBase);
1549 XFreeFontPath(fontPath);
1552 * Write settings resources out to disk
1554 XrmPutFileDatabase(smBase, smGD.settingPath);
1555 XrmDestroyDatabase(smBase);
1562 /*************************************<->*************************************
1569 * Save session resources by getting the current RESOURCE_MANAGER property
1570 * on the root window.
1574 * smGD.resourcePath = (global) file name
1575 * where property contents should be saved.
1583 * This method is not a 100% accurate representation of currently active
1584 * resources in the system. It is however, the best representation (the
1585 * values with the highest priority) without becoming overly invasive
1588 *************************************<->***********************************/
1590 OutputResource( void )
1594 unsigned long nitems, leftover;
1598 char *fontBuf = NULL, *langPtr, tmpChar[20], *sessionRes;
1601 char *preeditBuf = NULL;
1604 * Add anything to the Resource Manager property that needs to be added
1608 * Write out the LANG variable and the screen's Y resolution
1611 langPtr = getenv("LANG");
1612 if((langPtr != NULL) && (*langPtr != NULL))
1614 sprintf(resSpec, "%s*%s: %s\n", SM_RESOURCE_NAME, SmNsessionLang,
1619 sprintf(resSpec, "%s*%s: \n", SM_RESOURCE_NAME, SmNsessionLang);
1622 fltYRes = ((float) DisplayHeight(smGD.display, 0) /
1623 (float) DisplayHeightMM(smGD.display, 0)) * 1000;
1626 if(*resSpec == NULL)
1628 strcpy(resSpec, SM_RESOURCE_NAME);
1632 strcat(resSpec, SM_RESOURCE_NAME);
1634 strcat(resSpec, "*");
1635 strcat(resSpec, SmNdisplayResolution);
1636 strcat(resSpec, ":");
1637 sprintf(tmpChar, "%d",intYRes);
1638 strcat(resSpec, tmpChar);
1639 strcat(resSpec, "\n");
1640 _DtAddToResource(smGD.display, resSpec);
1642 if(smCust.fontChange == True)
1644 newStat = _DtGetSmFont(smGD.display, smGD.topLevelWindow,
1645 XaDtSmFontInfo, &fontBuf);
1646 if(newStat == Success)
1649 * Create the auxillary resource file
1651 if(SetFontSavePath(langPtr) != -1)
1653 db = XrmGetStringDatabase(fontBuf);
1655 if(intYRes < MED_RES_Y_RES)
1657 sessionRes = SM_LOW_RES_EXT;
1661 if(intYRes >= HIGH_RES_Y_RES)
1663 sessionRes = SM_HIGH_RES_EXT;
1667 sessionRes = SM_MED_RES_EXT;
1671 strcat(smGD.fontPath, "/");
1672 strcat(smGD.fontPath, SM_FONT_FILE);
1674 strcat(smGD.fontPath, ".");
1675 strcat(smGD.fontPath, sessionRes);
1677 XrmPutFileDatabase(db, smGD.fontPath);
1678 XrmDestroyDatabase(db);
1682 * Now add this to the resource manager property to be saved
1684 _DtAddToResource(smGD.display, fontBuf);
1686 if (fontBuf) XFree(fontBuf);
1689 if(smCust.preeditChange == True)
1691 newStat = _DtGetSmPreedit(smGD.display, smGD.topLevelWindow,
1692 XaDtSmPreeditInfo, &preeditBuf);
1693 if(newStat == Success)
1695 _DtAddToResource(smGD.display, preeditBuf);
1697 if (preeditBuf) XFree(preeditBuf);
1700 if((smCust.dClickChange == True) && (smToSet.dClickBuf[0] != NULL))
1702 _DtAddToResource(smGD.display, (char *)smToSet.dClickBuf);
1706 * Get the contents of the _DT_SM_PREFERENCES property
1708 data = _DtGetResString(smGD.display, _DT_ATR_PREFS);
1711 * Get _DT_SM_PREFERENCES database 'db'.
1713 db = XrmGetStringDatabase((char *)data);
1715 XrmPutFileDatabase(db, smGD.resourcePath);
1718 * Don't forget to free your data
1720 SM_FREE((char *)data);
1721 XrmDestroyDatabase(db);
1728 /*************************************<->*************************************
1730 * PrintPointerControl (smBase)
1735 * A convenience function that is separated out instead of being included
1736 * in both QueryServerSettings, and SaveCustomizeSettings.
1737 * Saves pointer control information to the named resource file.
1741 * smBase = pointer to newly opened resource db used to store setting info
1742 * resSpec = a buffer to hold string resource information until it is
1744 * smSettings = place where settings are stored.
1752 *************************************<->***********************************/
1754 PrintPointerControl(
1755 XrmDatabase *smBase)
1759 strcpy(resSpec, SM_RESOURCE_CLASS);
1760 strcat(resSpec, "*");
1761 strcat(resSpec, SmCaccelNum);
1762 strcat(resSpec, ":");
1763 sprintf(tmpChar, "%d", smSettings.accelNum);
1764 strcat(resSpec, tmpChar);
1765 XrmPutLineResource(smBase, resSpec);
1767 strcpy(resSpec, SM_RESOURCE_CLASS);
1768 strcat(resSpec, "*");
1769 strcat(resSpec, SmCaccelDenom);
1770 strcat(resSpec, ":");
1771 sprintf(tmpChar, "%d",smSettings.accelDenom);
1772 strcat(resSpec, tmpChar);
1773 XrmPutLineResource(smBase, resSpec);
1775 strcpy(resSpec, SM_RESOURCE_CLASS);
1776 strcat(resSpec, "*");
1777 strcat(resSpec, SmCthreshold);
1778 strcat(resSpec, ":");
1779 sprintf(tmpChar, "%d",smSettings.threshold);
1780 strcat(resSpec, tmpChar);
1781 XrmPutLineResource(smBase, resSpec);
1787 /*************************************<->*************************************
1789 * PrintSessionInfo (smBase)
1794 * A convenience function that is separated out instead of being included
1795 * in both QueryServerSettings, and SaveCustomizeSettings.
1796 * Saves session manager settings to the named resource file.
1800 * smBase = pointer to newly opened resource db used to store setting info
1801 * resSpec = a buffer to hold string resource information until it is
1803 * smSettings = place where settings are stored.
1811 *************************************<->***********************************/
1814 XrmDatabase *smBase)
1819 * Write out the settings for logout confirmation and
1820 * the correct session to return to
1822 strcpy(resSpec, SM_RESOURCE_CLASS);
1823 strcat(resSpec, "*");
1824 strcat(resSpec, SmCshutDownState);
1825 strcat(resSpec, ":");
1826 sprintf(tmpChar, "%d",smSettings.confirmMode);
1827 strcat(resSpec, tmpChar);
1828 XrmPutLineResource(smBase, resSpec);
1830 strcpy(resSpec, SM_RESOURCE_CLASS);
1831 strcat(resSpec, "*");
1832 strcat(resSpec, SmCshutDownMode);
1833 strcat(resSpec, ":");
1834 sprintf(tmpChar, "%d",smSettings.startState);
1835 strcat(resSpec, tmpChar);
1836 XrmPutLineResource(smBase, resSpec);
1842 /*************************************<->*************************************
1844 * PrintScreenSaver (smBase)
1849 * A convenience function that is separated out instead of being included
1850 * in both QueryServerSettings, and SaveCustomizeSettings.
1851 * Saves screen saver information to the named resource file.
1855 * smBase = pointer to newly opened resource db used to store setting info
1856 * resSpec = a buffer to hold string resource information until it is
1865 *************************************<->***********************************/
1868 XrmDatabase *smBase)
1870 Status newScreenStat;
1873 if(smCust.screenSavChange == True)
1875 newScreenStat = _DtGetSmScreen(smGD.display, smGD.topLevelWindow,
1876 XaDtSmScreenInfo, &screenSaverVals);
1878 * If the property has been deleted, it means that we return to
1881 if(newScreenStat != Success)
1887 strcpy(resSpec, SM_RESOURCE_CLASS);
1888 strcat(resSpec, "*");
1889 strcat(resSpec, SmCtimeout);
1890 strcat(resSpec, ":");
1891 sprintf(tmpChar, "%d", screenSaverVals.smTimeout);
1892 strcat(resSpec, tmpChar);
1893 XrmPutLineResource(smBase, resSpec);
1895 strcpy(resSpec, SM_RESOURCE_CLASS);
1896 strcat(resSpec, "*");
1897 strcat(resSpec, SmCinterval);
1898 strcat(resSpec, ":");
1899 sprintf(tmpChar, "%d", screenSaverVals.smInterval);
1900 strcat(resSpec, tmpChar);
1901 XrmPutLineResource(smBase, resSpec);
1903 strcpy(resSpec, SM_RESOURCE_CLASS);
1904 strcat(resSpec, "*");
1905 strcat(resSpec, SmCpreferBlank);
1906 strcat(resSpec, ":");
1907 sprintf(tmpChar, "%d", screenSaverVals.smPreferBlank);
1908 strcat(resSpec, tmpChar);
1909 XrmPutLineResource(smBase, resSpec);
1911 strcpy(resSpec, SM_RESOURCE_CLASS);
1912 strcat(resSpec, "*");
1913 strcat(resSpec, SmCallowExp);
1914 strcat(resSpec, ":");
1915 sprintf(tmpChar, "%d", screenSaverVals.smAllowExp);
1916 strcat(resSpec, tmpChar);
1917 XrmPutLineResource(smBase, resSpec);
1923 /*************************************<->*************************************
1925 * PrintFontPaths (smBase, fontPaths, numPaths)
1930 * A convenience function that is separated out instead of being included
1931 * in both QueryServerSettings, and SaveCustomizeSettings.
1932 * Saves pointer control information to the named resource file.
1936 * smBase = pointer to newly opened resource db used to store setting info
1937 * resSpec = a buffer to hold string resource information until it is
1939 * fontPaths = font paths to be saved
1940 * numPaths = number of font paths to be saved
1944 * resSize = made bigger if current buffer is too small to hold all font info
1949 *************************************<->***********************************/
1952 XrmDatabase *smBase,
1958 /* If no fp save req'd, just pretend we did it */
1959 if (smRes.saveFontPath == False) return 0;
1961 strcpy(resSpec, SM_RESOURCE_CLASS);
1962 strcat(resSpec, "*");
1963 strcat(resSpec, SmCfontPath);
1964 strcat(resSpec, ":");
1965 strcat(resSpec, *fontPath);
1966 for(i = 1;i < numPaths;i++)
1968 if((strlen(resSpec) + strlen(fontPath[i]) + 1) >= resSize)
1971 resSpec = (char *) SM_REALLOC(resSpec, resSize * sizeof(char));
1974 PrintErrnoError(DtError, smNLS.cantMallocErrorString);
1978 strcat(resSpec, ",");
1979 strcat(resSpec, fontPath[i]);
1981 XrmPutLineResource(smBase, resSpec);
1988 /*************************************<->*************************************
1990 * PrintKeyboardControl (smBase)
1995 * A convenience function that is separated out instead of being included
1996 * in both QueryServerSettings, and SaveCustomizeSettings.
1997 * Saves pointer control information to the named resource file.
2001 * smBase = pointer to newly opened resource db used to store setting info
2002 * resSpec = a buffer to hold string resource information until it is
2004 * resSize = size of current resource buffer
2008 * resSize = buffer is enlarged if more room is need to hold this info
2013 *************************************<->***********************************/
2015 PrintKeyboardControl(
2016 XrmDatabase *smBase)
2020 Bool firstRepeat = True;
2023 strcpy(resSpec, SM_RESOURCE_CLASS);
2024 strcat(resSpec, "*");
2025 strcat(resSpec, SmCkeyClick);
2026 strcat(resSpec, ":");
2027 sprintf(tmpChar, "%d",smSettings.kbdState.key_click_percent);
2028 strcat(resSpec, tmpChar);
2029 XrmPutLineResource(smBase, resSpec);
2031 strcpy(resSpec, SM_RESOURCE_CLASS);
2032 strcat(resSpec, "*");
2033 strcat(resSpec, SmCbellPercent);
2034 strcat(resSpec, ":");
2035 sprintf(tmpChar, "%d",smSettings.kbdState.bell_percent);
2036 strcat(resSpec, tmpChar);
2037 XrmPutLineResource(smBase, resSpec);
2039 strcpy(resSpec, SM_RESOURCE_CLASS);
2040 strcat(resSpec, "*");
2041 strcat(resSpec, SmCbellPitch);
2042 strcat(resSpec, ":");
2043 sprintf(tmpChar, "%d",smSettings.kbdState.bell_pitch);
2044 strcat(resSpec, tmpChar);
2045 XrmPutLineResource(smBase, resSpec);
2047 strcpy(resSpec, SM_RESOURCE_CLASS);
2048 strcat(resSpec, "*");
2049 strcat(resSpec, SmCbellDuration);
2050 strcat(resSpec, ":");
2051 sprintf(tmpChar, "%d",smSettings.kbdState.bell_duration);
2052 strcat(resSpec, tmpChar);
2053 XrmPutLineResource(smBase, resSpec);
2055 strcpy(resSpec, SM_RESOURCE_CLASS);
2056 strcat(resSpec, "*");
2057 strcat(resSpec, SmCledMask);
2058 strcat(resSpec, ":");
2059 sprintf(tmpChar, "%ld",smSettings.kbdState.led_mask);
2060 strcat(resSpec, tmpChar);
2061 XrmPutLineResource(smBase, resSpec);
2063 strcpy(resSpec, SM_RESOURCE_CLASS);
2064 strcat(resSpec, "*");
2065 strcat(resSpec, SmCglobalRepeats);
2066 strcat(resSpec, ":");
2067 sprintf(tmpChar, "%d",smSettings.kbdState.global_auto_repeat);
2068 strcat(resSpec, tmpChar);
2069 XrmPutLineResource(smBase, resSpec);
2071 strcpy(resSpec, SM_RESOURCE_CLASS);
2072 strcat(resSpec, "*");
2073 strcat(resSpec, SmCautoRepeats);
2074 strcat(resSpec, ":");
2077 * Now write out which keys need to be auto repeated one at a time
2079 if(smSettings.kbdState.global_auto_repeat != AutoRepeatModeOn)
2081 for(i = 0;i < 32;i++)
2084 for(j = 0;j < 8;j++)
2086 if((bitTest & smSettings.kbdState.auto_repeats[i]) != 0)
2088 if(firstRepeat == True)
2090 firstRepeat = False;
2094 strcat(resSpec, ",");
2097 if((strlen(resSpec) + 5) >= resSize)
2100 resSpec = (char *) SM_REALLOC(resSpec,
2101 resSize * sizeof(char));
2104 PrintErrnoError(DtError,
2105 smNLS.cantMallocErrorString);
2110 sprintf(tmpChar, "%d", ((8 * i) + j));
2111 strcat(resSpec, tmpChar);
2119 strcat(resSpec, "");
2121 XrmPutLineResource(smBase, resSpec);
2128 /*************************************<->*************************************
2130 * PrintPointerMapping (smBase, buttonRet, numButton)
2135 * A convenience function that is separated out instead of being included
2136 * in both QueryServerSettings, and SaveCustomizeSettings.
2137 * Saves pointer mapping information to the named resource file.
2141 * smBase = pointer to newly opened resource db used to store setting info
2142 * resSpec = a buffer to hold string resource information until it is
2144 * resSize = size of resource buffer
2145 * buttonRet = button mapping to be saved
2146 * numButton = number of buttons in button mapping
2150 * resSize = size of buffer is change if it needs to be enlarged during
2156 *************************************<->***********************************/
2158 PrintPointerMapping(
2159 XrmDatabase *smBase,
2166 strcpy(resSpec, SM_RESOURCE_CLASS);
2167 strcat(resSpec, "*");
2168 strcat(resSpec, SmCbuttonMap);
2169 strcat(resSpec, ":");
2171 numLoops = numButton - 1;
2172 for(i = 0;i <= numLoops;i++)
2174 if((strlen(resSpec) + 5) >= resSize)
2177 resSpec = (char *) SM_REALLOC(resSpec, resSize * sizeof(char));
2180 PrintErrnoError(DtError, smNLS.cantMallocErrorString);
2185 sprintf(tmpChar, "%d",buttonRet[i]);
2186 strcat(resSpec, tmpChar);
2189 strcat(resSpec, ",");
2191 XrmPutLineResource(smBase, resSpec);