コード例 #1
0
ファイル: guifont.cpp プロジェクト: rongzhou/speed-dreams
void gfuiLoadFonts(void)
{
	void *param;
	int	size;
	int	i;
	int nFontId;

	snprintf(buf, sizeof(buf), "%s%s", GfLocalDir(), GFSCR_CONF_FILE);
	param = GfParmReadFile(buf, GFPARM_RMODE_STD | GFPARM_RMODE_CREAT);

	snprintf(buf, sizeof(buf), "%sdata/fonts/%s", GfDataDir(),
			 GfParmGetStr(param, "Menu Font", "name", "b5.glf"));
	GfLogTrace("Loading font 'Menu Font' from %s : Sizes", buf);
	nFontId = GFUI_FONT_BIG;
	for(i = 0; i < 4; i++, nFontId++) {
		size = (int)GfParmGetNum(param, "Menu Font", keySize[i], (char*)NULL, 10.0);
		GfLogTrace(" %d,", size);
		gfuiFont[nFontId] = new GfuiFontClass(buf);
		gfuiFont[nFontId]->create(size);
	}
	GfLogTrace("\n");

	snprintf(buf, sizeof(buf), "%sdata/fonts/%s", GfDataDir(),
			 GfParmGetStr(param, "Console Font", "name", "b7.glf"));
	GfLogTrace("Loading font 'Console Font' from %s : Sizes", buf);
	nFontId = GFUI_FONT_BIG_C;
	for(i = 0; i < 4; i++, nFontId++) {
		size = (int)GfParmGetNum(param, "Console Font", keySize[i], (char*)NULL, 10.0);
		GfLogTrace(" %d,", size);
		gfuiFont[nFontId] = new GfuiFontClass(buf);
		gfuiFont[nFontId]->create(size);
	}
	GfLogTrace("\n");

	snprintf(buf, sizeof(buf), "%sdata/fonts/%s", GfDataDir(),
			 GfParmGetStr(param, "Text Font", "name", "b6.glf"));
	GfLogTrace("Loading font 'Text Font' from %s : Sizes", buf);
	nFontId = GFUI_FONT_BIG_T;
	for(i = 0; i < 4; i++, nFontId++) {
		size = (int)GfParmGetNum(param, "Text Font", keySize[i], (char*)NULL, 10.0);
		GfLogTrace(" %d,", size);
		gfuiFont[nFontId] = new GfuiFontClass(buf);
		gfuiFont[nFontId]->create(size);
	}
	GfLogTrace("\n");

	snprintf(buf, sizeof(buf), "%sdata/fonts/%s", GfDataDir(),
			 GfParmGetStr(param, "Digital Font", "name", "digital.glf"));
	GfLogTrace("Loading font 'Digital Font' from %s : Sizes", buf);
	nFontId = GFUI_FONT_DIGIT;
	size = (int)GfParmGetNum(param, "Digital Font", keySize[0], (char*)NULL, 8.0);
	GfLogTrace(" %d\n", size);
	gfuiFont[nFontId] = new GfuiFontClass(buf);
	gfuiFont[nFontId]->create(size);

	GfParmReleaseHandle(param);
}
コード例 #2
0
ファイル: guimenu.cpp プロジェクト: rongzhou/speed-dreams
void* 
GfuiMenuLoad(const char* pszMenuPath)
{
	std::string strPath("data/menu/");
	strPath += pszMenuPath;
        
	char buf[512];
	sprintf(buf, "%s%s", GfDataDir(), strPath.c_str());

	return GfParmReadFile(buf, GFPARM_RMODE_STD);
}
コード例 #3
0
int main(int argc, char **argv)
{
	// Create and initialize the application
	Application app;
	app.initialize(/*bLoggingEnabled=*/true, argc, argv);
	
	// Parse the command line options
    if (!app.parseOptions())
		return 1;

	// If "data dir" specified in any way, cd to it.
	if(chdir(GfDataDir()))
	{
		GfLogError("Could not start %s : failed to cd to the datadir '%s' (%s)\n",
				   app.name().c_str(), GfDataDir(), strerror(errno));
		return 1;
	}
	
	// Do the requested job.
	app.generate();
	
 	// That's all.
	return 0;
}
コード例 #4
0
ファイル: guiobject.cpp プロジェクト: 702nADOS/speed-dreams
void
gfuiInitObject(void)
{
	//Read mouse pointer settings
	char buf[512];
	snprintf(buf, sizeof(buf), "%s%s", GfLocalDir(), GFSCR_CONF_FILE);
	void *param = GfParmReadFile(buf, GFPARM_RMODE_STD | GFPARM_RMODE_CREAT);

	NMouseCursorXOffset =
		(int)GfParmGetNum(param, GFSCR_SECT_MOUSECURSOR, GFSCR_ATT_XOFFSET, (char*)NULL, 0.0);
	NMouseCursorYOffset =
		(int)GfParmGetNum(param, GFSCR_SECT_MOUSECURSOR, GFSCR_ATT_YOFFSET, (char*)NULL, 0.0);
	NMouseCursorHeight =
		(int)GfParmGetNum(param, GFSCR_SECT_MOUSECURSOR, GFSCR_ATT_HEIGHT, (char*)NULL, 20.0);
	NMouseCursorWidth =
		(int)GfParmGetNum(param, GFSCR_SECT_MOUSECURSOR, GFSCR_ATT_WIDTH, (char*)NULL, 20.0);

	const char* pszImageFile =
		GfParmGetStr(param, GFSCR_SECT_MOUSECURSOR, GFSCR_ATT_IMAGEFILE, "data/img/mouse.png");
	snprintf(buf, sizeof(buf), "%s%s", GfDataDir(), pszImageFile);
	NMouseCursorTexture = GfTexReadTexture(buf);
}
コード例 #5
0
/*
 * Function
 *    main
 *
 * Description
 *    Main function of the game
 *
 * Parameters
 *    argc Number of command line args, + 1 for the executable name
 *    argv Array of zero-terminated strings, 1 for each arg
 *
 * Return
 *    0 status code if OK, non-0 otherwise.
 */
int
main(int argc, char *argv[])
{
	// Look for the "text-only" option flag in the command-line args.
	bool bTextOnly = false;
	for (int i = 1; i < argc; i++)
		if (!strcmp(argv[i], "-x") || !strcmp(argv[i], "--textonly"))
		{
			bTextOnly = true;
			break;
		}

	// Create and initialize the application (graphical or text-only UI).
	GfApplication* pApp;
	if (bTextOnly)
		pApp = new GfApplication("Speed Dreams", VERSION_LONG, "an Open Motorsport Sim");
	else
		pApp = new GfuiApplication("Speed Dreams", VERSION_LONG, "an Open Motorsport Sim");
	pApp->initialize(/*bLoggingEnabled=*/true, argc, argv);
	
	// Register app. specific options and help text.
	pApp->registerOption("s", "startrace", /* nHasValue = */ true);
	pApp->registerOption("x", "textonly", /* nHasValue = */ false);
	
	pApp->addOptionsHelpSyntaxLine("[-s|--startrace <race name> [-x|--textonly] ]");
	pApp->addOptionsHelpExplainLine
	 	("- race name : Name without extension of the selected raceman file,");
	pApp->addOptionsHelpExplainLine
	 	("              among the .xml files in <user settings>/config/raceman (no default)");
	pApp->addOptionsHelpExplainLine
	 	("- text-only : Run the specified race without any GUI (suitable for a headless computer)");

	// Parse the command line for registered options.
    if (!pApp->parseOptions())
		return 1;

	// Some more checks about command line options.
	std::string strRaceToStart;
	if (bTextOnly && (!pApp->hasOption("startrace", strRaceToStart) || strRaceToStart.empty()))
	{
		std::cerr << "Exiting from " << pApp->name()
				  << " because no race specified in text-only mode." << std::endl;
		return 1;
	}
	
	// If "data dir" specified in any way, cd to it.
	if(chdir(GfDataDir()))
	{
		GfLogError("Could not start %s : failed to cd to the datadir '%s' (%s)\n",
				   pApp->name().c_str(), GfDataDir(), strerror(errno));
		return 1;
	}

	// Update user settings files from installed ones.
    pApp->updateUserSettings();

   // Initialize the event loop management layer (graphical or text-only UI).
	GfEventLoop* pEventLoop;
	if (bTextOnly)
		pEventLoop = new GfEventLoop;
	else
		pEventLoop = new GfuiEventLoop;
	pApp->setEventLoop(pEventLoop);

	// When there's a GUI, setup the window / screen and menu infrastructure.
    if (!bTextOnly && !dynamic_cast<GfuiApplication*>(pApp)->setupWindow())
	{
		std::cerr << "Exiting from " << pApp->name()
				  << " after some error occurred (see above)." << std::endl;
		return 1;
	}

	// Load the user interface module (graphical or text-only UI).
	GfModule* pmodUserItf =
		GfModule::load("userinterface", (bTextOnly ?  "textonly" : "legacymenu"));

	// Check that it implements IUserInterface.
	IUserInterface* piUserItf = 0;
	if (pmodUserItf)
	{
		piUserItf = pmodUserItf->getInterface<IUserInterface>();
	}

	// Initialize the data layer (needed by any race engine module).
	GfData::initialize();

	// Load the race engine module (specified in the user settings : raceengine.xml file).
	std::ostringstream ossParm;
	ossParm << GfLocalDir() << RACE_ENG_CFG;
	void* hREParams =
		GfParmReadFile(ossParm.str().c_str(), GFPARM_RMODE_REREAD | GFPARM_RMODE_CREAT);
	const char* pszModName = GfParmGetStr(hREParams, "Modules", "racing", "standardgame");
	GfModule* pmodRaceEngine = GfModule::load("racing", pszModName);

	// Check that it implements IRaceEngine.
	IRaceEngine* piRaceEngine = 0;
	if (pmodRaceEngine)
	{
		piRaceEngine = pmodRaceEngine->getInterface<IRaceEngine>();
	}

	// Connect the race engine and the user interface modules.
	if (piUserItf && piRaceEngine)
	{
		piRaceEngine->setUserInterface(*piUserItf);
		piUserItf->setRaceEngine(*piRaceEngine);
	}
	
	if (piUserItf && piRaceEngine)
	{
		// Enter the user interface.
		if (piUserItf->activate())
		{
			// Game event loop (when it returns, it's simply because we are exiting).
			pApp->eventLoop()();
		}
		
		// Shutdown and unload the user interface and race engine modules.
		piUserItf->shutdown();
		piRaceEngine->shutdown();
		
		GfModule::unload(pmodUserItf);
		GfModule::unload(pmodRaceEngine);
		
		// Shutdown the data layer.
		GfData::shutdown();
	}

	// Done with the app instance.
	const std::string strAppName(pApp->name());
	delete pApp;
	
 	// That's all (but trace what we are doing).
	if (piUserItf && piRaceEngine)
		GfLogInfo("Exiting normally from %s.\n", strAppName.c_str());
	else
		std::cerr << "Exiting from " << strAppName
				  << " after some error occurred (see above)." << std::endl;
	
	return (piUserItf && piRaceEngine) ? 0 : 1;
}
コード例 #6
0
void Application::generate()
{
	const char *extName;
	FILE *outfd = NULL;

	// Get the trackgen paramaters.
	sprintf(buf, "%s", CFG_FILE);
	CfgHandle = GfParmReadFile(buf, GFPARM_RMODE_STD | GFPARM_RMODE_CREAT);

	// Load and initialize the track loader module.
	GfLogInfo("Loading Track Loader ...\n");
	std::ostringstream ossModLibName;
	ossModLibName << GfLibDir() << "modules/track/" << "track" << '.' << DLLEXT;
	GfModule* pmodTrkLoader = GfModule::load(ossModLibName.str());

	// Check that it implements ITrackLoader.
	ITrackLoader* PiTrackLoader = 0;
	if (pmodTrkLoader)
		PiTrackLoader = pmodTrkLoader->getInterface<ITrackLoader>();
	if (!PiTrackLoader)
		return;

	// This is the track definition.
	sprintf(trackdef, "%stracks/%s/%s/%s.xml", GfDataDir(), TrackCategory, TrackName, TrackName);
	TrackHandle = GfParmReadFile(trackdef, GFPARM_RMODE_STD);
	if (!TrackHandle) {
		fprintf(stderr, "Cannot find %s\n", trackdef);
		::exit(1);
	}

	// Build the track structure with graphic extensions.
	Track = PiTrackLoader->load(trackdef, true);

	if (!JustCalculate) {
		// Get the output file radix.
		sprintf(buf2, "%stracks/%s/%s/%s", GfDataDir(), Track->category, Track->internalname, Track->internalname);
		OutputFileName = strdup(buf2);

		// Number of groups for the complete track.
		if (TrackOnly) {
			sprintf(buf2, "%s.ac", OutputFileName);
			// Track.
			outfd = Ac3dOpen(buf2, 1);
		} else if (MergeAll) {
			sprintf(buf2, "%s.ac", OutputFileName);
			// track + terrain + objects.
			outfd = Ac3dOpen(buf2, 2 + GetObjectsNb(TrackHandle));
		}

		// Main Track.
		if (Bump) {
			extName = "trk-bump";
		} else {
			extName = "trk";
		}

		sprintf(buf2, "%s-%s.ac", OutputFileName, extName);
		OutTrackName = strdup(buf2);
	}

	if (JustCalculate){
		CalculateTrack(Track, TrackHandle, Bump);
		return;
	}

	GenerateTrack(Track, TrackHandle, OutTrackName, outfd, Bump);

	if (TrackOnly) {
		return;
	}

	// Terrain.
	if (MergeTerrain && !MergeAll) {
		sprintf(buf2, "%s.ac", OutputFileName);
		/* terrain + objects  */
		outfd = Ac3dOpen(buf2, 1 + GetObjectsNb(TrackHandle));
	}

	extName = "msh";
	sprintf(buf2, "%s-%s.ac", OutputFileName, extName);
	OutMeshName = strdup(buf2);

	GenerateTerrain(Track, TrackHandle, OutMeshName, outfd, DoSaveElevation);

	if (DoSaveElevation != -1) {
		if (outfd) {
			Ac3dClose(outfd);
		}
		switch (DoSaveElevation) {
			case 0:
			case 1:
				sprintf(buf2, "%s.ac", OutputFileName);
				sprintf(buf, "%s-elv.png", OutputFileName);
				SaveElevation(Track, TrackHandle, buf, buf2, 1);
				if (DoSaveElevation) {
					break;
				}
			case 2:
				sprintf(buf, "%s-elv2.png", OutputFileName);
				SaveElevation(Track, TrackHandle, buf, OutMeshName, 1);
				if (DoSaveElevation) {
					break;
				}
			case 3:
				sprintf(buf, "%s-elv3.png", OutputFileName);
				SaveElevation(Track, TrackHandle, buf, OutMeshName, 0);
				if (DoSaveElevation) {
					break;
				}
			case 4:
				sprintf(buf, "%s-elv4.png", OutputFileName);
				SaveElevation(Track, TrackHandle, buf, OutTrackName, 2);
				break;
		}
		return;
	}

	GenerateObjects(Track, TrackHandle, CfgHandle, outfd, OutMeshName);
}
コード例 #7
0
ファイル: raceresults.cpp プロジェクト: 702nADOS/speed-dreams
void
ReUpdateStandings(void)
{
	tReStandings st;
	std::string drvName;
	std::vector<tReStandings> *standings;
	std::vector<tReStandings>::iterator found;
	std::vector<tReStandings>::iterator it;
	int runDrv, curDrv;
	int i;
	void *results = ReInfo->results;

	snprintf(path, sizeof(path), "%s/%s/%s/%s", ReInfo->track->name, RE_SECT_RESULTS, ReInfo->_reRaceName, RE_SECT_RANK);
	runDrv = GfParmGetEltNb(results, path);
	curDrv = GfParmGetEltNb(results, RE_SECT_STANDINGS);
	
	standings = new std::vector<tReStandings>;

	standings->reserve(curDrv);

	/* Read the current standings */
	for (i = 0; i < curDrv; i++) 
	{
		snprintf(path2, sizeof(path2), "%s/%d", RE_SECT_STANDINGS, i + 1);
		st.drvName = GfParmGetStr(results, path2, RE_ATTR_NAME, 0);
		st.modName = GfParmGetStr(results, path2, RE_ATTR_MODULE, 0);
		st.carName = GfParmGetStr(results, path2, RE_ATTR_CAR, 0);
		st.extended = (int)GfParmGetNum(results, path2, RM_ATTR_EXTENDED, NULL, 0);
		st.drvIdx  = (int)GfParmGetNum(results, path2, RE_ATTR_IDX, NULL, 0);
		st.points  = (int)GfParmGetNum(results, path2, RE_ATTR_POINTS, NULL, 0);
		standings->push_back(st);
	}//for i

	//Void the stored results
	GfParmListClean(results, RE_SECT_STANDINGS);
	
	//Check last races' drivers and search their name in the results.
	//If found there, adds recent points.
	//If not found, adds the driver
	for (i = 0; i < runDrv; i++) {
		//Search the driver name in the standings
		snprintf(path, sizeof(path), "%s/%s/%s/%s/%d", ReInfo->track->name, RE_SECT_RESULTS, ReInfo->_reRaceName, RE_SECT_RANK, i + 1);
		drvName = GfParmGetStr(results, path, RE_ATTR_NAME, 0);
		found = std::find(standings->begin(), standings->end(), drvName);
		
		if(found == standings->end()) {
			//No such driver in the standings, let's add it
			st.drvName = drvName;
			st.modName = GfParmGetStr(results, path, RE_ATTR_MODULE, 0);
			st.carName = GfParmGetStr(results, path, RE_ATTR_CAR, 0);
			st.extended = (int)GfParmGetNum(results, path, RM_ATTR_EXTENDED, NULL, 0);
			st.drvIdx  = (int)GfParmGetNum(results, path, RE_ATTR_IDX, NULL, 0);
			st.points  = (int)GfParmGetNum(results, path, RE_ATTR_POINTS, NULL, 0);
			standings->push_back(st);
		} else {
			//Driver found, add recent points
			found->points += (int)GfParmGetNum(results, path, RE_ATTR_POINTS, NULL, 0);
		}//if found
	}//for i
	
	//sort standings by score
	std::sort(standings->begin(), standings->end(), sortByScore);
	
	//Store the standing back
	for(it = standings->begin(), i = 0; it != standings->end(); ++it, ++i) {
		snprintf(path, sizeof(path), "%s/%d", RE_SECT_STANDINGS, i + 1);
		GfParmSetStr(results, path, RE_ATTR_NAME, it->drvName.c_str());
		GfParmSetStr(results, path, RE_ATTR_MODULE, it->modName.c_str());
		GfParmSetStr(results, path, RE_ATTR_CAR, it->carName.c_str());
		GfParmSetNum(results, path, RE_ATTR_IDX, NULL, (tdble)it->drvIdx);
		GfParmSetNum(results, path, RE_ATTR_POINTS, NULL, (tdble)it->points);
	}//for it
	delete standings;
	
	char str1[512], str2[512];
	snprintf(str1, sizeof(str1), "%sconfig/params.dtd", GfDataDir());
	snprintf(str2, sizeof(str2), "<?xml-stylesheet type=\"text/xsl\" href=\"file:///%sconfig/raceresults.xsl\"?>", GfDataDir());
	
	GfParmSetDTD (results, str1, str2);
	GfParmWriteFile(0, results, "Results");
}//ReUpdateStandings
コード例 #8
0
void GfFileSetup()
{
	void *dataVersionHandle;
	void *localVersionHandle;
	char *filename;
	size_t filenameLength;
	char *dataLocation;
	char *localLocation;
	char *absLocalLocation;
	char *absDataLocation;
	bool *isIndexUsed;
	int isIndexUsedLen;
	int index;
	bool anyLocalChange, fileFound;
	int major;
	int minor;
	struct stat st;

	// Open data (installation) version.xml.
	filenameLength = strlen(GfDataDir()) + 12 + 40;
	filename = (char*)malloc( sizeof(char) * filenameLength );
	sprintf( filename, "%sversion.xml", GfDataDir() );
	dataVersionHandle = GfParmReadFile( filename, GFPARM_RMODE_STD );
	if( !dataVersionHandle )
	{
		free( filename );
		return;
	}

	// Exit if nothing inside.
	if( GfParmListSeekFirst( dataVersionHandle, "versions" ) != 0 )
	{
		free( filename );
		GfParmReleaseHandle( dataVersionHandle );
		return;
	}

	// Create LocalDir (user settings root) if not already done.
	GfDirCreate( GfLocalDir() );

	// Open local (user settings) version.xml (create it if not there).
	if( filenameLength < strlen(GfLocalDir()) + 12 )
	{
		free( filename );
		filenameLength = strlen(GfLocalDir()) + 12 + 40;
		filename = (char*)malloc( sizeof(char) * filenameLength );
	}

	sprintf( filename, "%sversion.xml", GfLocalDir() );
	anyLocalChange = !GfFileExists(filename);
	localVersionHandle = GfParmReadFile( filename, GFPARM_RMODE_CREAT );

	// Exit if open/creation failed.
	if( !localVersionHandle )
	{
		free( filename );
		GfParmReleaseHandle( dataVersionHandle );
		return;
	}

	// Setup the index of the XML files referenced in the local version.xml.
	isIndexUsedLen = GfParmGetEltNb( localVersionHandle, "versions" )
		             + GfParmGetEltNb( dataVersionHandle, "versions" ) + 2;
	isIndexUsed = (bool*)malloc( sizeof(bool) * isIndexUsedLen );
	for( index = 0; index < isIndexUsedLen; index++ )
		isIndexUsed[index] = false;
	if( GfParmListSeekFirst( localVersionHandle, "versions" ) == 0 )
	{
		do
		{
			index = atoi( GfParmListGetCurEltName( localVersionHandle, "versions" ) );
			if( 0 <= index && index < isIndexUsedLen )
				isIndexUsed[index] = true;
		} while( GfParmListSeekNext( localVersionHandle, "versions" ) == 0 );
	}

	// For each file referenced in the installation version.xml
	do
	{
		fileFound = false;

		// Get its installation path (data), user settings path (local),
		// and new major and minor version numbers
		dataLocation = strdup( GfParmGetCurStr( dataVersionHandle, "versions", "Data location", "" ) );
		localLocation = strdup( GfParmGetCurStr( dataVersionHandle, "versions", "Local location", "" ) );
		major = (int)GfParmGetCurNum( dataVersionHandle, "versions", "Major version", NULL, 0 );
		minor = (int)GfParmGetCurNum( dataVersionHandle, "versions", "Minor version", NULL, 0 );

		absLocalLocation = (char*)malloc( sizeof(char)*(strlen(GfLocalDir())+strlen(localLocation)+3) );
		sprintf( absLocalLocation, "%s%s", GfLocalDir(), localLocation );

		absDataLocation = (char*)malloc( sizeof(char)*(strlen(GfDataDir())+strlen(dataLocation)+3) );
		sprintf( absDataLocation, "%s%s", GfDataDir(), dataLocation );

		GfLogTrace("Checking %s : user settings version ", localLocation);

		// Search for its old major and minor version numbers in the user settings.
		if( GfParmListSeekFirst( localVersionHandle, "versions" ) == 0 )
		{
			do
			{
				if( strcmp( absLocalLocation, GfParmGetCurStr( localVersionHandle, "versions", "Local location", "" ) ) == 0 )
				{
					fileFound = true;
					const int locMinor = (int)GfParmGetCurNum( localVersionHandle, "versions", "Minor version", NULL, 0 );
					const int locMajor = (int)GfParmGetCurNum( localVersionHandle, "versions", "Major version", NULL, 0 );

					GfLogTrace("%d.%d is ", locMajor, locMinor);

					if( locMajor != major || locMinor < minor)
					{
						GfLogTrace("obsolete (installed one is %d.%d) => updating ...\n",
								   major, minor);
						if ( gfFileSetupCopy( absDataLocation, absLocalLocation, major, minor, localVersionHandle, -1 ) )
							anyLocalChange = true;
					}
					else
					{
					    GfLogTrace("up-to-date");
						if (stat(absLocalLocation, &st))
						{
							GfLogTrace(", but not there => installing ...\n");
							if ( gfFileSetupCopy( absDataLocation, absLocalLocation, major, minor, localVersionHandle, -1 ) )
								anyLocalChange = true;
						}
						else
							GfLogTrace(".\n");
					}
					
					break;
				}
			} while( GfParmListSeekNext( localVersionHandle, "versions" ) == 0 );
		}

		if( !fileFound)
		{
			index = 0;
			while( isIndexUsed[index] )
				++index;
			GfLogTrace("not found => installing ...\n");
			if ( gfFileSetupCopy( absDataLocation, absLocalLocation, major, minor, localVersionHandle, index ) )
				anyLocalChange = true;
			isIndexUsed[index] = true;
		}

		free( dataLocation );
		free( localLocation );
		free( absDataLocation );
		free( absLocalLocation );

	} while( GfParmListSeekNext( dataVersionHandle, "versions" ) == 0 );

	// Write the user settings version.xml if changed.
	if (anyLocalChange)
		GfParmWriteFile( NULL, localVersionHandle, "versions" );

	GfParmReleaseHandle( localVersionHandle );
	GfParmReleaseHandle( dataVersionHandle );
	free( isIndexUsed );
	free( filename );
}