2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these libraries and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
23 /* $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"
92 #include "SrvFile_io.h"
99 #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] = 0;
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 (void)
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 len = strlen(smGD.savePath) + strlen(smGD.restoreSession)
508 + strlen("XXXXXX") + 3;
509 tmpName = XtCalloc (1, len);
510 sprintf(tmpName, "%s/%s.XXXXXX", smGD.savePath,
511 smGD.restoreSession);
513 if ((tfd = mkstemp(tmpName)) == -1)
515 PrintErrnoError(DtError, smNLS.cantCreateDirsString);
522 sprintf (saveDir, "%s/%s",
523 smGD.savePath, smGD.restoreSession);
525 MoveDirectory (saveDir, tmpName, False);
526 MoveDirectory (oldestDir, saveDir, False);
528 sprintf (clientDB, "%s/%s/%s", smGD.savePath,
529 smGD.restoreSession, SM_CLIENT_FILE2);
531 ExecuteDiscardCommands (clientDB);
533 MoveDirectory (tmpName, saveDir, True);
539 * If exiting and the current session is a Current session
540 * but smSettings.startState has been set to to a
541 * Home session (this would be true if a user started a
542 * Current session but used the Style Manager to set the session
543 * upon next login to be a Home session), then if a home
544 * directory exists, mv current to current.old
547 if (smXSMP.saveState.shutdown && smGD.sessionType == CURRENT_SESSION &&
548 smSettings.startState == DtSM_HOME_STATE) {
550 sprintf (tmpDir, "%s/%s", smGD.savePath, SM_HOME_DIRECTORY);
552 if (((stat (tmpDir, &buf)) == 0) && S_ISDIR (buf.st_mode)) {
554 sprintf (saveDir, "%s/%s", smGD.savePath, oldDir);
556 if (((stat (saveDir, &buf)) == 0) &&
557 S_ISDIR (buf.st_mode)) {
559 sprintf (clientDB, "/bin/rm -rf %s", saveDir);
560 SystemCmd (clientDB);
562 sprintf (oldestDir, "%s/%s", smGD.savePath,
563 SM_CURRENT_DIRECTORY);
565 MoveDirectory (oldestDir, saveDir, False);
579 /*************************************<->*************************************
581 * WriteClientDatabase -
583 * Description: Writes the client database (for XSMP and Proxy clients)
587 * Returns True if the database is wrtten OK; False otherwise
589 *************************************<->***********************************/
591 WriteClientDatabase (void)
596 db = (char*) XtMalloc(MAXPATHLEN + 1);
597 (void) sprintf (db, "%s/%s/%s", smGD.savePath, smGD.restoreSession,
600 if ((outputDB = OpenOutputClientDB (db, smXSMP.dbVersion,
601 smXSMP.dbSessionId)) == NULL) {
604 str = strdup ((char *) GETMESSAGE (40, 18,
605 "The following database file cannot be opened for writing:\n\n %s\n\nThe session will not be saved."));
608 DtMsgLogMessage (smGD.programName, DtMsgLogError,
618 OutputProxyClients (outputDB);
620 OutputXSMPClients (outputDB);
622 CloseClientDB (outputDB, True);
628 /*************************************<->*************************************
630 * OutputProxyClients -
632 * Description: Outputs the Proxy clients
634 * Inputs: database pointer
638 *************************************<->***********************************/
644 for (i = 0; i < numProxyClients; i++)
645 PrintStartupInfo (outputDB,
647 proxyList[i].window);
651 /*************************************<->*************************************
653 * OutputXSMPClients -
655 * Description: Outputs the XSMP clients
657 * Inputs: database pointer
661 *************************************<->***********************************/
666 XSMPClientDBRec dbRec;
667 ClientRecPtr pClientRec;
669 for (pClientRec = connectedList; pClientRec != NULL;
670 pClientRec = pClientRec->next) {
672 dbRec.restartHint = pClientRec->restartHint;
673 (void) GetCardPropertyValue (pClientRec, SmRestartStyleHint,
676 if (dbRec.restartHint == SmRestartNever)
679 if (!pClientRec->active)
682 if (!CheckRequiredProperties (pClientRec))
687 dbRec.clientId = pClientRec->clientId;
688 dbRec.clientHost = pClientRec->clientHost;
690 dbRec.program = GetArrayPropertyValue (pClientRec,
692 dbRec.cwd = GetArrayPropertyValue (pClientRec,
695 dbRec.restartCommand = GetListOfArrayPropertyValue (pClientRec,
697 dbRec.cloneCommand = GetListOfArrayPropertyValue (pClientRec,
699 dbRec.discardCommand = GetListOfArrayPropertyValue (pClientRec,
701 dbRec.environment = GetListOfArrayPropertyValue (pClientRec,
704 if (!PutXSMPClientDBRec (outputDB, &dbRec)) {
708 str = strdup ((char *) GETMESSAGE (40, 19,
709 "Application '%s' cannot be saved."));
712 DtMsgLogMessage (smGD.programName,
719 if (dbRec.restartCommand)
720 XtFree ((char *) dbRec.restartCommand);
721 if (dbRec.cloneCommand)
722 XtFree ((char *) dbRec.cloneCommand);
723 if (dbRec.discardCommand)
724 XtFree ((char *) dbRec.discardCommand);
725 if (dbRec.environment)
726 XtFree ((char *) dbRec.environment);
731 /*************************************<->*************************************
733 * CheckRequiredProperties -
735 * Description: Check a client's required properties
737 * Inputs: ClientRecPtr
739 * Returns: True if the client has all of the required properties;
740 * otherwise returns False
742 *************************************<->***********************************/
744 CheckRequiredProperties (
745 ClientRecPtr pClientRec)
747 PropertyRecPtr pPropRec;
749 char * program = NULL;
751 if ((program = GetArrayPropertyValue (pClientRec, SmProgram)) == NULL){
753 str = strdup ((char *) GETMESSAGE (40, 23,
754 "The following application did not set the required\nproperty '%s':\n\n %s\n\nThis application will not be saved."));
757 DtMsgLogMessage (smGD.programName, DtMsgLogError, str,
758 SmProgram, pClientRec->clientId);
764 if ((pPropRec = GetPropertyRec (pClientRec, SmRestartCommand)) == NULL){
766 str = strdup ((char *) GETMESSAGE (40, 24,
767 "24 Application '%s' will not be saved because it did not set\nthe required property '%s'."));
770 DtMsgLogMessage (smGD.programName, DtMsgLogError,
771 str, program, SmRestartCommand);
777 if ((pPropRec = GetPropertyRec (pClientRec, SmCloneCommand)) == NULL) {
779 * This is a warning - still want to save the client
781 str = strdup ((char *) GETMESSAGE (40, 25,
782 "Application '%s' did not set the required property '%s'."));
785 DtMsgLogMessage (smGD.programName, DtMsgLogWarning, str,
786 program, SmCloneCommand);
795 /*************************************<->*************************************
797 * NotifyProxyClients -
802 * Notify Proxy clients - calls routines to find top level windows, and
803 * notifies the Proxy clients about an impending save.
811 *************************************<->***********************************/
813 NotifyProxyClients (void)
815 unsigned int topListLength, containedListLength;
816 WindowInfo * topList; /* list of top-level windows */
817 WindowInfo topLevelWindowInfo;
820 unsigned long nitems;
821 unsigned long leftover;
822 unsigned char * data = NULL;
823 Boolean containedClient;
828 * Save off the clients currently running. This will be done
829 * one screen at a time
831 for(j = 0;j < smGD.numSavedScreens;j++)
834 * Get a list of children of the root window. If there are none
835 * return with an error condition.
837 if(GetTopLevelWindows(j,&topList,&topListLength, &containedListLength))
841 * Figure out how to restart the client associate with each window.
843 for (i=0 ; i<(topListLength + containedListLength); ++i)
845 topLevelWindowInfo=topList[i];
847 if(i >= topListLength)
849 containedClient = True;
853 containedClient = False;
857 * If this window is my window - skip it I don't want to
858 * save myself because I will be started automatically
860 if (XGetWindowProperty(smGD.display, topLevelWindowInfo.wid,
862 (long)BUFSIZ,False,XA_STRING,&actualType,
863 &actualFormat,&nitems,&leftover,
866 if (actualType==XA_STRING &&
867 !strcmp((char *) data, SM_RESOURCE_NAME))
869 SM_FREE((char *)data);
874 SM_FREE((char *)data);
879 * If the client participates in the WM_SAVE_YOURSELF protocol,
880 * send the appropriate messages and wait for the proper
883 (void) SaveYourself(topLevelWindowInfo);
885 CacheProxyClient ((numClients == 0), j, topLevelWindowInfo.wid);
891 * Free space malloc'd by GetTopLevelWindowInfo
893 if(topListLength > 0)
895 SM_FREE((char *) topList);
901 /*************************************<->*************************************
907 * Add a Proxy client to the proxy client cache.
911 * firstClient - if True, this is the first client in the cache
912 * screenNum - the client's screen number
913 * window - the client's window number
918 *************************************<->***********************************/
919 static void CacheProxyClient (
927 if (numProxyClients >= numProxyAllocated) {
928 numProxyAllocated += proxyCacheAllocIncrement;
929 proxyList = (ProxyClientCachePtr) XtRealloc ((char *) proxyList,
930 numProxyAllocated * sizeof (ProxyClientCache));
933 proxyList[numProxyClients].screen = screenNum;
934 proxyList[numProxyClients].window = window;
941 /*************************************<->*************************************
947 * Output startup information for one proxy client
951 * outputDB = a pointer to the client database
952 * screen = which screen the client is running on
953 * window = the top level window of the lient
961 *************************************<->***********************************/
972 XWindowAttributes windowAttr;
975 ProxyClientDBRec dbRec;
980 #ifdef _SUN_OS /* pull out quotes from OpenWindow tools commands */
985 * Get the attributes and properties on the window
987 if ((XGetWindowAttributes(smGD.display, window, &windowAttr)) == 0)
990 if (GetStandardProperties(window, screen, &wargc, &wargv,
991 &clientMachine, &xsmpClient)==0)
995 * If the client doesn't have a WM_COMMAND property, we can't restart it
997 if (!wargv||!wargv[0])
1001 * If the client is an XSMP client, don't save it as a Proxy client.
1006 #ifdef _SUN_OS /* pull out quotes from OpenWindow tools commands */
1009 /* check for foreground */
1010 if ((ptr = strstr (ptr, "fg \"")) != NULL) {
1011 if (strlen (ptr) > 3)
1013 if ((ptr = strchr (ptr, '"')) != NULL)
1017 /* check for background */
1018 if ((ptr = strstr (wargv[0], "bg \"")) != NULL) {
1019 if (strlen (ptr) > 3)
1021 if ((ptr = strchr (ptr, '"')) != NULL)
1028 * Find out if the client is running locally
1030 dbRec.clientHost = NULL;
1031 if(clientMachine != NULL)
1033 if(DtIsLocalHostP(clientMachine) == FALSE)
1035 dbRec.clientHost = clientMachine;
1040 * Must NULL-terminate the WM_COMMAND before writing it
1042 argv = (char **) XtMalloc ((wargc + 1) * sizeof (char *));
1046 for (i = 0; i < wargc; i++)
1050 dbRec.command = argv;
1051 dbRec.screenNum = screen;
1053 writeStatus = PutProxyClientDBRec (outputDB, &dbRec);
1055 XtFree ((char *) argv);
1057 if (writeStatus == False)
1060 * There should be an error written here - however
1061 * since this means that there already is a write error to
1062 * the disk - no error can be written
1064 (void) CloseClientDB (outputDB, True);
1067 * On a write error - move the old session back to
1068 * be used and exit with an error condition
1070 XFreeStringList(wargv);
1072 strcat(smGD.savePath, "/");
1073 if(smGD.sessionType == HOME_SESSION)
1075 strcat(smGD.savePath, SM_HOME_DIRECTORY);
1079 strcat(smGD.savePath, SM_CURRENT_DIRECTORY);
1082 MoveDirectory(smGD.etcPath, smGD.savePath, False);
1087 * Free up the argv property
1089 XFreeStringList(wargv);
1093 /*************************************<->*************************************
1095 * QueryServerSettings ()
1100 * Query the server for all it's current settings information, and then
1101 * write that information to the session managers settings resource file.
1105 * smGD.settingPath = (global) pointer to file where
1106 * setting info should be saved.
1113 * This routine slows down the session manager's shutdown process
1114 * considerably, and is therefore only called when the user specifies
1115 * that all settings should be queried. Otherwise, only settings set in
1116 * the customizer should be saved.
1118 *************************************<->***********************************/
1120 QueryServerSettings( void )
1124 KeySym *tmpSyms, tmpMod;
1125 XModifierKeymap *modMap;
1127 int numButton, numPaths;
1128 int buttonSize = 128;
1129 XrmDatabase smBase = NULL;
1133 buttonRet = (char *) SM_MALLOC(buttonSize * sizeof(char));
1134 if (buttonRet==NULL)
1136 PrintErrnoError(DtError, smNLS.cantMallocErrorString);
1141 * First set up all pointer control parameters
1142 * These are simple integer values that get saved
1143 * here, then read into a structure and set at restore
1146 XGetPointerControl(smGD.display, &smSettings.accelNum,
1147 &smSettings.accelDenom,
1148 &smSettings.threshold);
1149 PrintPointerControl(&smBase);
1152 * Get all the screen saver values. These are all simple integer
1153 * values that are read back into a structure and set at restore
1156 XGetScreenSaver(smGD.display, &screenSaverVals.smTimeout,
1157 &screenSaverVals.smInterval,
1158 &screenSaverVals.smPreferBlank,
1159 &screenSaverVals.smAllowExp);
1160 PrintScreenSaver(&smBase);
1163 * Write out all font path information.
1164 * Write out all the paths one by one concatenated by commas.
1166 fontPath = XGetFontPath(smGD.display, &numPaths);
1167 if(fontPath != NULL)
1169 if(PrintFontPaths(&smBase, fontPath, numPaths) != 0)
1171 XFreeFontPath(fontPath);
1178 * Write out all the keyboard control information.
1180 XGetKeyboardControl(smGD.display, &smSettings.kbdState);
1181 if(PrintKeyboardControl(&smBase) != 0)
1184 XFreeFontPath(fontPath);
1189 * Put all the button modifier information into the resource database.
1190 * Find out the number of buttons and then write out the character
1191 * string for each button.
1193 numButton = XGetPointerMapping(smGD.display, (unsigned char *)buttonRet, 128);
1196 buttonRet = (char *) SM_REALLOC(buttonRet, numButton * sizeof(char));
1197 if (buttonRet==NULL)
1200 XFreeFontPath(fontPath);
1201 PrintErrnoError(DtError, smNLS.cantMallocErrorString);
1204 numButton = XGetPointerMapping(smGD.display, (unsigned char *)buttonRet, numButton);
1206 if(PrintPointerMapping(&smBase, buttonRet,
1210 XFreeFontPath(fontPath);
1216 * Put all keyboard mapping information in the resource database
1217 * Don't bother putting this in a separate print function because
1218 * the customizer doesn't do keymap savings this way.
1220 smSettings.numKeyCode = smGD.display->max_keycode -
1221 smGD.display->min_keycode;
1222 tmpSyms = XGetKeyboardMapping(smGD.display,
1223 (KeyCode) smGD.display->min_keycode,
1224 smSettings.numKeyCode,
1225 &smSettings.keySymPerCode);
1229 XFreeFontPath(fontPath);
1231 PrintErrnoError(DtError, smNLS.cantMallocErrorString);
1235 strcpy(resSpec, SM_RESOURCE_CLASS);
1236 strcat(resSpec, "*");
1237 strcat(resSpec, SmCnumKeyCode);
1238 strcat(resSpec, ":");
1239 sprintf(tmpChar,"%d", smSettings.numKeyCode);
1240 strcat(resSpec, tmpChar);
1241 XrmPutLineResource( &smBase, resSpec);
1243 strcpy(resSpec, SM_RESOURCE_CLASS);
1244 strcat(resSpec, "*");
1245 strcat(resSpec, SmCkeySymsPerKey);
1246 strcat(resSpec, ":");
1247 sprintf(tmpChar,"%d", smSettings.keySymPerCode);
1248 strcat(resSpec, tmpChar);
1249 XrmPutLineResource( &smBase, resSpec);
1251 strcpy(resSpec, SM_RESOURCE_CLASS);
1252 strcat(resSpec, "*");
1253 strcat(resSpec, SmCkeySyms);
1254 strcat(resSpec, ":");
1255 numLoops = smSettings.numKeyCode * smSettings.keySymPerCode;
1256 sprintf(tmpChar,"%ld", tmpSyms[0]);
1257 strcat(resSpec, tmpChar);
1258 for(i = 1;i < numLoops;i++)
1260 if((strlen(resSpec) + 5) >= resSize)
1263 resSpec = (char *) SM_REALLOC(resSpec, resSize * sizeof(char));
1266 SM_FREE((char *)tmpSyms);
1268 SM_FREE((char *)fontPath);
1270 PrintErrnoError(DtError, smNLS.cantMallocErrorString);
1274 strcat(resSpec, ",");
1275 sprintf(tmpChar,"%ld", tmpSyms[i]);
1276 strcat(resSpec, tmpChar);
1278 XrmPutLineResource( &smBase, resSpec);
1282 * Write out all keyboard modifier info. This will be a pretty slow
1283 * process considering that every keycode will have to be turned into
1284 * a keysym before writing. Don't bother putting print stuff in a
1285 * separate function because it will not be handled in the customize
1288 modMap = XGetModifierMapping(smGD.display);
1291 SM_FREE((char *)tmpSyms);
1293 XFreeFontPath(fontPath);
1295 PrintErrnoError(DtError, smNLS.cantMallocErrorString);
1299 strcpy(resSpec, SM_RESOURCE_CLASS);
1300 strcat(resSpec, "*");
1301 strcat(resSpec, SmCmaxKeyPerMod);
1302 strcat(resSpec, ":");
1303 sprintf(tmpChar,"%d", modMap->max_keypermod);
1304 strcat(resSpec, tmpChar);
1305 XrmPutLineResource( &smBase, resSpec);
1307 strcpy(resSpec, SM_RESOURCE_CLASS);
1308 strcat(resSpec, "*");
1309 strcat(resSpec, SmCmodMap);
1310 strcat(resSpec, ":");
1311 numLoops = (8 * modMap->max_keypermod) - 1;
1312 for(i = 0;i <= numLoops;i++)
1314 if((strlen(resSpec) + 9) >= resSize)
1317 resSpec = (char *) SM_REALLOC(resSpec, resSize * sizeof(char));
1320 SM_FREE((char *)tmpSyms);
1321 XFreeModifiermap(modMap);
1323 XFreeFontPath(fontPath);
1325 PrintErrnoError(DtError, smNLS.cantMallocErrorString);
1329 tmpMod = XKeycodeToKeysym(smGD.display, modMap->modifiermap[i], 0);
1330 sprintf(tmpChar,"%ld", tmpMod);
1331 strcat(resSpec, tmpChar);
1334 strcat(resSpec, ",");
1337 XrmPutLineResource( &smBase, resSpec);
1341 * Print session manager settings
1343 PrintSessionInfo(&smBase);
1346 * Write settings resources out to disk
1348 XrmPutFileDatabase(smBase, smGD.settingPath);
1351 * Free all allocated resources
1354 XFreeFontPath(fontPath);
1355 SM_FREE((char *)tmpSyms);
1356 XFreeModifiermap(modMap);
1358 XrmDestroyDatabase(smBase);
1363 /*************************************<->*************************************
1365 * SaveCustomizeSettings ()
1370 * Saves those settings that have been set in the customizer during the
1371 * session to whatever values they were set to during the session.
1376 * smGD.resourcePath = (global) a pointer
1377 * to where the settings should be stored.
1386 * This routine is the default saved for saving settings. If the user
1387 * wants all settings saved, they have to set a resource saying that that
1390 *************************************<->***********************************/
1392 SaveCustomizeSettings( void )
1396 XrmDatabase smBase = NULL;
1397 char *tmpChar[20], *ptrRet = NULL, *tmpKey;
1402 if(smCust.pointerChange)
1404 newStat = _DtGetSmPointer(smGD.display, smGD.topLevelWindow,
1405 XaDtSmPointerInfo, &ptrRet);
1406 if(newStat != Success)
1408 smToSet.pointerChange = False;
1409 smToSet.pointerMapChange = False;
1413 sscanf(ptrRet, "%d %s %d %d %s",
1416 &smSettings.accelNum,
1417 &smSettings.threshold,
1418 &smToSet.dClickBuf);
1419 smSettings.accelDenom = 1;
1421 tmpKey = strtok(tmpMap, "_");
1423 while(tmpKey != NULL)
1425 smToSet.pointerMap[i] = (char) atoi(tmpKey);
1427 tmpKey = strtok(NULL, "_");
1432 * append a \n to dClickBuf because it was scanned out
1434 strcat(smToSet.dClickBuf, "\n");
1436 if (ptrRet) XFree(ptrRet);
1439 if(smToSet.pointerChange == True)
1441 PrintPointerControl(&smBase);
1444 if(smToSet.pointerMapChange == True)
1446 if(PrintPointerMapping(&smBase, smToSet.pointerMap,
1447 smToSet.numButton) != 0)
1453 if(smToSet.screenSavChange == True)
1455 PrintScreenSaver(&smBase);
1458 if(smCust.audioChange == True)
1460 newStat = _DtGetSmAudio(smGD.display, smGD.topLevelWindow,
1461 XaDtSmAudioInfo, &audioVals);
1463 if(newStat == Success)
1465 smSettings.kbdState.bell_percent = audioVals.smBellPercent;
1466 smSettings.kbdState.bell_pitch = audioVals.smBellPitch;
1467 smSettings.kbdState.bell_duration = audioVals.smBellDuration;
1471 smToSet.audioChange = False;
1475 if (smToSet.audioChange)
1477 strcpy(resSpec, SM_RESOURCE_CLASS);
1478 strcat(resSpec, "*");
1479 strcat(resSpec, SmCbellPercent);
1480 strcat(resSpec, ":");
1481 sprintf((char *)tmpChar,"%d",smSettings.kbdState.bell_percent);
1482 strcat(resSpec, (char *)tmpChar);
1483 XrmPutLineResource(&smBase, resSpec);
1485 strcpy(resSpec, SM_RESOURCE_CLASS);
1486 strcat(resSpec, "*");
1487 strcat(resSpec, SmCbellPitch);
1488 strcat(resSpec, ":");
1489 sprintf((char *)tmpChar,"%d",smSettings.kbdState.bell_pitch);
1490 strcat(resSpec, (char *)tmpChar);
1491 XrmPutLineResource(&smBase, resSpec);
1493 strcpy(resSpec, SM_RESOURCE_CLASS);
1494 strcat(resSpec, "*");
1495 strcat(resSpec, SmCbellDuration);
1496 strcat(resSpec, ":");
1497 sprintf((char *)tmpChar,"%d",smSettings.kbdState.bell_duration);
1498 strcat(resSpec, (char *)tmpChar);
1499 XrmPutLineResource(&smBase, resSpec);
1502 if(smCust.keyboardChange == True)
1504 newStat = _DtGetSmKeyboard(smGD.display, smGD.topLevelWindow,
1505 XaDtSmKeyboardInfo, &keyboardVals);
1506 if(newStat == Success)
1508 smSettings.kbdState.key_click_percent = keyboardVals.smKeyClickPercent;
1509 smSettings.kbdState.global_auto_repeat = keyboardVals.smGlobalAutoRepeat;
1513 smToSet.keyboardChange = False;
1517 if(smToSet.keyboardChange == True)
1519 strcpy(resSpec, SM_RESOURCE_CLASS);
1520 strcat(resSpec, "*");
1521 strcat(resSpec, SmCkeyClick);
1522 strcat(resSpec, ":");
1523 sprintf((char *)tmpChar,"%d", smSettings.kbdState.key_click_percent);
1524 strcat(resSpec, (char *)tmpChar);
1525 XrmPutLineResource(&smBase, resSpec);
1527 strcpy(resSpec, SM_RESOURCE_CLASS);
1528 strcat(resSpec, "*");
1529 strcat(resSpec, SmCglobalRepeats);
1530 strcat(resSpec, ":");
1531 sprintf((char *)tmpChar,"%d", smSettings.kbdState.global_auto_repeat);
1532 strcat(resSpec, (char *)tmpChar);
1533 XrmPutLineResource(&smBase, resSpec);
1538 * Write out all font path information.
1539 * Write out all the paths one by one concatenated by commas.
1542 fontPath = XGetFontPath(smGD.display, &numPaths);
1543 if(fontPath != NULL) {
1544 if(PrintFontPaths(&smBase, fontPath, numPaths) != 0) {
1545 XFreeFontPath(fontPath);
1551 * Save session manager settings
1553 PrintSessionInfo(&smBase);
1556 XFreeFontPath(fontPath);
1559 * Write settings resources out to disk
1561 XrmPutFileDatabase(smBase, smGD.settingPath);
1562 XrmDestroyDatabase(smBase);
1569 /*************************************<->*************************************
1576 * Save session resources by getting the current RESOURCE_MANAGER property
1577 * on the root window.
1581 * smGD.resourcePath = (global) file name
1582 * where property contents should be saved.
1590 * This method is not a 100% accurate representation of currently active
1591 * resources in the system. It is however, the best representation (the
1592 * values with the highest priority) without becoming overly invasive
1595 *************************************<->***********************************/
1597 OutputResource( void )
1601 unsigned long nitems, leftover;
1605 char *fontBuf = NULL, *langPtr, tmpChar[20], *sessionRes;
1608 char *preeditBuf = NULL;
1611 * Add anything to the Resource Manager property that needs to be added
1615 * Write out the LANG variable and the screen's Y resolution
1618 langPtr = getenv("LANG");
1619 if((langPtr != NULL) && (*langPtr != 0))
1621 snprintf(resSpec, resSize, "%s*%s: %s\n", SM_RESOURCE_NAME, SmNsessionLang,
1626 snprintf(resSpec, resSize, "%s*%s: \n", SM_RESOURCE_NAME, SmNsessionLang);
1629 fltYRes = ((float) DisplayHeight(smGD.display, 0) /
1630 (float) DisplayHeightMM(smGD.display, 0)) * 1000;
1635 strcpy(resSpec, SM_RESOURCE_NAME);
1639 strcat(resSpec, SM_RESOURCE_NAME);
1641 strcat(resSpec, "*");
1642 strcat(resSpec, SmNdisplayResolution);
1643 strcat(resSpec, ":");
1644 sprintf(tmpChar, "%d",intYRes);
1645 strcat(resSpec, tmpChar);
1646 strcat(resSpec, "\n");
1647 _DtAddToResource(smGD.display, resSpec);
1649 if(smCust.fontChange == True)
1651 newStat = _DtGetSmFont(smGD.display, smGD.topLevelWindow,
1652 XaDtSmFontInfo, &fontBuf);
1653 if(newStat == Success)
1656 * Create the auxillary resource file
1658 if(SetFontSavePath(langPtr) != -1)
1660 db = XrmGetStringDatabase(fontBuf);
1662 if(intYRes < MED_RES_Y_RES)
1664 sessionRes = SM_LOW_RES_EXT;
1668 if(intYRes >= HIGH_RES_Y_RES)
1670 sessionRes = SM_HIGH_RES_EXT;
1674 sessionRes = SM_MED_RES_EXT;
1678 strcat(smGD.fontPath, "/");
1679 strcat(smGD.fontPath, SM_FONT_FILE);
1681 strcat(smGD.fontPath, ".");
1682 strcat(smGD.fontPath, sessionRes);
1684 XrmPutFileDatabase(db, smGD.fontPath);
1685 XrmDestroyDatabase(db);
1689 * Now add this to the resource manager property to be saved
1691 _DtAddToResource(smGD.display, fontBuf);
1693 if (fontBuf) XFree(fontBuf);
1696 if(smCust.preeditChange == True)
1698 newStat = _DtGetSmPreedit(smGD.display, smGD.topLevelWindow,
1699 XaDtSmPreeditInfo, &preeditBuf);
1700 if(newStat == Success)
1702 _DtAddToResource(smGD.display, preeditBuf);
1704 if (preeditBuf) XFree(preeditBuf);
1707 if((smCust.dClickChange == True) && (smToSet.dClickBuf[0] != 0))
1709 _DtAddToResource(smGD.display, (char *)smToSet.dClickBuf);
1713 * Get the contents of the _DT_SM_PREFERENCES property
1715 data = _DtGetResString(smGD.display, _DT_ATR_PREFS);
1718 * Get _DT_SM_PREFERENCES database 'db'.
1720 db = XrmGetStringDatabase((char *)data);
1722 XrmPutFileDatabase(db, smGD.resourcePath);
1725 * Don't forget to free your data
1727 SM_FREE((char *)data);
1728 XrmDestroyDatabase(db);
1735 /*************************************<->*************************************
1737 * PrintPointerControl (smBase)
1742 * A convenience function that is separated out instead of being included
1743 * in both QueryServerSettings, and SaveCustomizeSettings.
1744 * Saves pointer control information to the named resource file.
1748 * smBase = pointer to newly opened resource db used to store setting info
1749 * resSpec = a buffer to hold string resource information until it is
1751 * smSettings = place where settings are stored.
1759 *************************************<->***********************************/
1761 PrintPointerControl(
1762 XrmDatabase *smBase)
1766 strcpy(resSpec, SM_RESOURCE_CLASS);
1767 strcat(resSpec, "*");
1768 strcat(resSpec, SmCaccelNum);
1769 strcat(resSpec, ":");
1770 sprintf(tmpChar, "%d", smSettings.accelNum);
1771 strcat(resSpec, tmpChar);
1772 XrmPutLineResource(smBase, resSpec);
1774 strcpy(resSpec, SM_RESOURCE_CLASS);
1775 strcat(resSpec, "*");
1776 strcat(resSpec, SmCaccelDenom);
1777 strcat(resSpec, ":");
1778 sprintf(tmpChar, "%d",smSettings.accelDenom);
1779 strcat(resSpec, tmpChar);
1780 XrmPutLineResource(smBase, resSpec);
1782 strcpy(resSpec, SM_RESOURCE_CLASS);
1783 strcat(resSpec, "*");
1784 strcat(resSpec, SmCthreshold);
1785 strcat(resSpec, ":");
1786 sprintf(tmpChar, "%d",smSettings.threshold);
1787 strcat(resSpec, tmpChar);
1788 XrmPutLineResource(smBase, resSpec);
1794 /*************************************<->*************************************
1796 * PrintSessionInfo (smBase)
1801 * A convenience function that is separated out instead of being included
1802 * in both QueryServerSettings, and SaveCustomizeSettings.
1803 * Saves session manager settings to the named resource file.
1807 * smBase = pointer to newly opened resource db used to store setting info
1808 * resSpec = a buffer to hold string resource information until it is
1810 * smSettings = place where settings are stored.
1818 *************************************<->***********************************/
1821 XrmDatabase *smBase)
1826 * Write out the settings for logout confirmation and
1827 * the correct session to return to
1829 strcpy(resSpec, SM_RESOURCE_CLASS);
1830 strcat(resSpec, "*");
1831 strcat(resSpec, SmCshutDownState);
1832 strcat(resSpec, ":");
1833 sprintf(tmpChar, "%d",smSettings.confirmMode);
1834 strcat(resSpec, tmpChar);
1835 XrmPutLineResource(smBase, resSpec);
1837 strcpy(resSpec, SM_RESOURCE_CLASS);
1838 strcat(resSpec, "*");
1839 strcat(resSpec, SmCshutDownMode);
1840 strcat(resSpec, ":");
1841 sprintf(tmpChar, "%d",smSettings.startState);
1842 strcat(resSpec, tmpChar);
1843 XrmPutLineResource(smBase, resSpec);
1849 /*************************************<->*************************************
1851 * PrintScreenSaver (smBase)
1856 * A convenience function that is separated out instead of being included
1857 * in both QueryServerSettings, and SaveCustomizeSettings.
1858 * Saves screen saver information to the named resource file.
1862 * smBase = pointer to newly opened resource db used to store setting info
1863 * resSpec = a buffer to hold string resource information until it is
1872 *************************************<->***********************************/
1875 XrmDatabase *smBase)
1877 Status newScreenStat;
1880 if(smCust.screenSavChange == True)
1882 newScreenStat = _DtGetSmScreen(smGD.display, smGD.topLevelWindow,
1883 XaDtSmScreenInfo, &screenSaverVals);
1885 * If the property has been deleted, it means that we return to
1888 if(newScreenStat != Success)
1894 strcpy(resSpec, SM_RESOURCE_CLASS);
1895 strcat(resSpec, "*");
1896 strcat(resSpec, SmCtimeout);
1897 strcat(resSpec, ":");
1898 sprintf(tmpChar, "%d", screenSaverVals.smTimeout);
1899 strcat(resSpec, tmpChar);
1900 XrmPutLineResource(smBase, resSpec);
1902 strcpy(resSpec, SM_RESOURCE_CLASS);
1903 strcat(resSpec, "*");
1904 strcat(resSpec, SmCinterval);
1905 strcat(resSpec, ":");
1906 sprintf(tmpChar, "%d", screenSaverVals.smInterval);
1907 strcat(resSpec, tmpChar);
1908 XrmPutLineResource(smBase, resSpec);
1910 strcpy(resSpec, SM_RESOURCE_CLASS);
1911 strcat(resSpec, "*");
1912 strcat(resSpec, SmCpreferBlank);
1913 strcat(resSpec, ":");
1914 sprintf(tmpChar, "%d", screenSaverVals.smPreferBlank);
1915 strcat(resSpec, tmpChar);
1916 XrmPutLineResource(smBase, resSpec);
1918 strcpy(resSpec, SM_RESOURCE_CLASS);
1919 strcat(resSpec, "*");
1920 strcat(resSpec, SmCallowExp);
1921 strcat(resSpec, ":");
1922 sprintf(tmpChar, "%d", screenSaverVals.smAllowExp);
1923 strcat(resSpec, tmpChar);
1924 XrmPutLineResource(smBase, resSpec);
1930 /*************************************<->*************************************
1932 * PrintFontPaths (smBase, fontPaths, numPaths)
1937 * A convenience function that is separated out instead of being included
1938 * in both QueryServerSettings, and SaveCustomizeSettings.
1939 * Saves pointer control information to the named resource file.
1943 * smBase = pointer to newly opened resource db used to store setting info
1944 * resSpec = a buffer to hold string resource information until it is
1946 * fontPaths = font paths to be saved
1947 * numPaths = number of font paths to be saved
1951 * resSize = made bigger if current buffer is too small to hold all font info
1956 *************************************<->***********************************/
1959 XrmDatabase *smBase,
1965 /* If no fp save req'd, just pretend we did it */
1966 if (smRes.saveFontPath == False) return 0;
1968 strcpy(resSpec, SM_RESOURCE_CLASS);
1969 strcat(resSpec, "*");
1970 strcat(resSpec, SmCfontPath);
1971 strcat(resSpec, ":");
1972 strcat(resSpec, *fontPath);
1973 for(i = 1;i < numPaths;i++)
1975 if((strlen(resSpec) + strlen(fontPath[i]) + 1) >= resSize)
1978 resSpec = (char *) SM_REALLOC(resSpec, resSize * sizeof(char));
1981 PrintErrnoError(DtError, smNLS.cantMallocErrorString);
1985 strcat(resSpec, ",");
1986 strcat(resSpec, fontPath[i]);
1988 XrmPutLineResource(smBase, resSpec);
1995 /*************************************<->*************************************
1997 * PrintKeyboardControl (smBase)
2002 * A convenience function that is separated out instead of being included
2003 * in both QueryServerSettings, and SaveCustomizeSettings.
2004 * Saves pointer control information to the named resource file.
2008 * smBase = pointer to newly opened resource db used to store setting info
2009 * resSpec = a buffer to hold string resource information until it is
2011 * resSize = size of current resource buffer
2015 * resSize = buffer is enlarged if more room is need to hold this info
2020 *************************************<->***********************************/
2022 PrintKeyboardControl(
2023 XrmDatabase *smBase)
2027 Bool firstRepeat = True;
2030 strcpy(resSpec, SM_RESOURCE_CLASS);
2031 strcat(resSpec, "*");
2032 strcat(resSpec, SmCkeyClick);
2033 strcat(resSpec, ":");
2034 sprintf(tmpChar, "%d",smSettings.kbdState.key_click_percent);
2035 strcat(resSpec, tmpChar);
2036 XrmPutLineResource(smBase, resSpec);
2038 strcpy(resSpec, SM_RESOURCE_CLASS);
2039 strcat(resSpec, "*");
2040 strcat(resSpec, SmCbellPercent);
2041 strcat(resSpec, ":");
2042 sprintf(tmpChar, "%d",smSettings.kbdState.bell_percent);
2043 strcat(resSpec, tmpChar);
2044 XrmPutLineResource(smBase, resSpec);
2046 strcpy(resSpec, SM_RESOURCE_CLASS);
2047 strcat(resSpec, "*");
2048 strcat(resSpec, SmCbellPitch);
2049 strcat(resSpec, ":");
2050 sprintf(tmpChar, "%d",smSettings.kbdState.bell_pitch);
2051 strcat(resSpec, tmpChar);
2052 XrmPutLineResource(smBase, resSpec);
2054 strcpy(resSpec, SM_RESOURCE_CLASS);
2055 strcat(resSpec, "*");
2056 strcat(resSpec, SmCbellDuration);
2057 strcat(resSpec, ":");
2058 sprintf(tmpChar, "%d",smSettings.kbdState.bell_duration);
2059 strcat(resSpec, tmpChar);
2060 XrmPutLineResource(smBase, resSpec);
2062 strcpy(resSpec, SM_RESOURCE_CLASS);
2063 strcat(resSpec, "*");
2064 strcat(resSpec, SmCledMask);
2065 strcat(resSpec, ":");
2066 sprintf(tmpChar, "%ld",smSettings.kbdState.led_mask);
2067 strcat(resSpec, tmpChar);
2068 XrmPutLineResource(smBase, resSpec);
2070 strcpy(resSpec, SM_RESOURCE_CLASS);
2071 strcat(resSpec, "*");
2072 strcat(resSpec, SmCglobalRepeats);
2073 strcat(resSpec, ":");
2074 sprintf(tmpChar, "%d",smSettings.kbdState.global_auto_repeat);
2075 strcat(resSpec, tmpChar);
2076 XrmPutLineResource(smBase, resSpec);
2078 strcpy(resSpec, SM_RESOURCE_CLASS);
2079 strcat(resSpec, "*");
2080 strcat(resSpec, SmCautoRepeats);
2081 strcat(resSpec, ":");
2084 * Now write out which keys need to be auto repeated one at a time
2086 if(smSettings.kbdState.global_auto_repeat != AutoRepeatModeOn)
2088 for(i = 0;i < 32;i++)
2091 for(j = 0;j < 8;j++)
2093 if((bitTest & smSettings.kbdState.auto_repeats[i]) != 0)
2095 if(firstRepeat == True)
2097 firstRepeat = False;
2101 strcat(resSpec, ",");
2104 if((strlen(resSpec) + 5) >= resSize)
2107 resSpec = (char *) SM_REALLOC(resSpec,
2108 resSize * sizeof(char));
2111 PrintErrnoError(DtError,
2112 smNLS.cantMallocErrorString);
2117 sprintf(tmpChar, "%d", ((8 * i) + j));
2118 strcat(resSpec, tmpChar);
2126 strcat(resSpec, "");
2128 XrmPutLineResource(smBase, resSpec);
2135 /*************************************<->*************************************
2137 * PrintPointerMapping (smBase, buttonRet, numButton)
2142 * A convenience function that is separated out instead of being included
2143 * in both QueryServerSettings, and SaveCustomizeSettings.
2144 * Saves pointer mapping information to the named resource file.
2148 * smBase = pointer to newly opened resource db used to store setting info
2149 * resSpec = a buffer to hold string resource information until it is
2151 * resSize = size of resource buffer
2152 * buttonRet = button mapping to be saved
2153 * numButton = number of buttons in button mapping
2157 * resSize = size of buffer is change if it needs to be enlarged during
2163 *************************************<->***********************************/
2165 PrintPointerMapping(
2166 XrmDatabase *smBase,
2173 strcpy(resSpec, SM_RESOURCE_CLASS);
2174 strcat(resSpec, "*");
2175 strcat(resSpec, SmCbuttonMap);
2176 strcat(resSpec, ":");
2178 numLoops = numButton - 1;
2179 for(i = 0;i <= numLoops;i++)
2181 if((strlen(resSpec) + 5) >= resSize)
2184 resSpec = (char *) SM_REALLOC(resSpec, resSize * sizeof(char));
2187 PrintErrnoError(DtError, smNLS.cantMallocErrorString);
2192 sprintf(tmpChar, "%d",buttonRet[i]);
2193 strcat(resSpec, tmpChar);
2196 strcat(resSpec, ",");
2198 XrmPutLineResource(smBase, resSpec);