// This tries to find a filename (in the same directory as inBaseName) based on 'inBaseName' but that is not yet used. // The current logic tries inBaseName first, then 'inBaseName 2', then 'inBaseName 3', and so on. // The resulting name will have no more than inMaxNameLength actual characters. // Returns whether it was successful (the current logic either returns true or loops forever; fortunately, the // probability of looping forever is really, REALLY tiny; the directory would have to contain every possible variant). static bool make_nonconflicting_filename_variant(/*const*/ FileSpecifier& inBaseName, FileSpecifier& outNonconflictingName, size_t inMaxNameLength) { FileSpecifier theNameToTry; DirectorySpecifier theDirectory; inBaseName.ToDirectory(theDirectory); char theBaseNameString[256]; // XXX I don't like this, but the SDL code already imposes this maxlen throughout. inBaseName.GetName(theBaseNameString); size_t theBaseNameLength = strlen(theBaseNameString); char theNameToTryString[256]; char theVariantSuffix[32]; // way more than enough unsigned int theVariant = 0; size_t theSuffixLength; size_t theBaseNameLengthToUse; bool theVariantIsAcceptable = false; while(!theVariantIsAcceptable) { theVariant++; if(theVariant == 1) { theVariantSuffix[0] = '\0'; theSuffixLength = 0; } else { theSuffixLength = sprintf(theVariantSuffix, " %d", theVariant); } assert(theSuffixLength <= inMaxNameLength); if(theSuffixLength + theBaseNameLength > inMaxNameLength) theBaseNameLengthToUse = inMaxNameLength - theSuffixLength; else theBaseNameLengthToUse = theBaseNameLength; sprintf(theNameToTryString, "%.*s%s", (int) theBaseNameLengthToUse, theBaseNameString, theVariantSuffix); theNameToTry.FromDirectory(theDirectory); #if defined(mac) || defined(SDL_RFORK_HACK) // Note: SetName() currently ignores the 'type' argument, so I feel // little compulsion to try to figure it out. theNameToTry.SetName(theNameToTryString,NONE); #else theNameToTry.AddPart(theNameToTryString); #endif if(!theNameToTry.Exists()) theVariantIsAcceptable = true; } if(theVariantIsAcceptable) { outNonconflictingName = theNameToTry; } return theVariantIsAcceptable; }
// Analogous to 'save_game()', but does not present any dialog to the user, and reports the results // using screen_printf(). If inOverwriteRecent is set, it will save over the most recently saved // or restored game (if possible). If inOverwriteRecent is not set, or if there is no recent game // to save over, it will pick a new, nonconflicting filename and save to it. // Returns whether save was successful. bool save_game_full_auto(bool inOverwriteRecent) { bool createNewFile = !inOverwriteRecent; FileSpecifier theRecentSavedGame; get_current_saved_game_name(theRecentSavedGame); char theSavedGameName[256]; // XXX // If we're supposed to overwrite, change our minds if we seem to have no 'existing file'. if(!createNewFile) { theRecentSavedGame.GetName(theSavedGameName); if(strcmp(theSavedGameName, TS_GetCString(strFILENAMES, filenameDEFAULT_SAVE_GAME)) == 0) createNewFile = true; } // Make up a filename (currently based on level name) if(createNewFile) { if(strncpy_filename_friendly(theSavedGameName, static_world->level_name, kMaxFilenameChars) <= 0) strcpy(theSavedGameName, "Automatic Save"); DirectorySpecifier theDirectory; theRecentSavedGame.ToDirectory(theDirectory); theRecentSavedGame.FromDirectory(theDirectory); #if defined(mac) || defined(SDL_RFORK_HACK) // Note: SetName() currently ignores the 'type' argument, so I feel // little compulsion to try to figure it out. theRecentSavedGame.SetName(theSavedGameName,NONE); #else theRecentSavedGame.AddPart(theSavedGameName); #endif } FileSpecifier theOutputFile; if(createNewFile) make_nonconflicting_filename_variant(theRecentSavedGame, theOutputFile, kMaxFilenameChars); else theOutputFile = theRecentSavedGame; bool successfulSave = save_game_file(theOutputFile); theOutputFile.GetName(theSavedGameName); if(successfulSave) { screen_printf("%s saved game '%s'", createNewFile ? "Created new" : "Replaced existing", theSavedGameName); // play a sound? } else { screen_printf("Unable to save game as '%s'", theSavedGameName); // play a sound? } return successfulSave; }