/* ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 1, or (at your option) ** any later version. ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** You should have received a copy of the GNU General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* * Author : Alexandre Parenteau --- February 1998 */ /* * Persistent.cpp --- utilities to store persitent values */ #ifdef macintosh # include "GUSIInternal.h" # include "GUSIFileSpec.h" #endif #include "stdafx.h" #include #include #include #if defined(HAVE_ERRNO_H) || defined(WIN32) # include #endif #ifdef HAVE_UNISTD_H # include #endif #ifndef WIN32 # include #endif /* !WIN32 */ #ifdef WIN32 # include "wincvs.h" #endif #include "Persistent.h" #include "AppConsole.h" #include "CPStr.h" #include "uconsole.h" #include "uwidget.h" #include "FileTraversal.h" #include "Authen.h" #include "CvsPrefs.h" #include "getline.h" #include "CvsAlert.h" #ifdef macintosh # include # include # include # include "VolsPaths.h" # include "MacMisc.h" # ifndef Assert_ // for mpw # include # define Assert_(cond) assert(cond) # endif #endif /* macintosh */ #if qMacCvsPP # include "MacCvsApp.h" # include "MacCvsConstant.h" #endif #if TARGET_RT_MAC_MACHO # include #endif #if qUnix # include "UCvsDialogs.h" #endif #ifdef WIN32 # ifdef _DEBUG # define new DEBUG_NEW # undef THIS_FILE static char THIS_FILE[] = __FILE__; # endif #endif /* WIN32 */ #ifndef NEW #define NEW new #endif std::vector *CPersistent::fAllEntries = 0L; UIMPLEMENT_DYNAMIC(CPersistent, UObject) UIMPLEMENT_DYNAMIC(CPersistentInt, CPersistent) UIMPLEMENT_DYNAMIC(CPersistentBool, CPersistent) UIMPLEMENT_DYNAMIC(PCStr, CPersistent) UIMPLEMENT_DYNAMIC(PCPStr, CPersistent) CPersistent::CPersistent(const char *uniqueName, kClassPersistent pclass) : fTimeStamp(0) { Register(this, uniqueName, pclass); TouchTimeStamp(); } CPersistent::~CPersistent() { UnRegister(this); } void CPersistent::Register(CPersistent *value, const char *uniqueName, kClassPersistent pclass) { std::vector::const_iterator i; if(fAllEntries == 0L) fAllEntries = NEW std::vector; for(i = fAllEntries->begin(); i != fAllEntries->end(); ++i) { if(strcmp(uniqueName, (*i).fUniqueName) == 0) { UAppConsole("Error : duplicate persistent %s !\n", uniqueName); } } CPersistentEntry newentry; newentry.fClass = pclass; newentry.fUniqueName = uniqueName; newentry.fValue = value; fAllEntries->push_back(newentry); } void CPersistent::UnRegister(CPersistent *value) { std::vector::iterator i; for(i = fAllEntries->begin(); i != fAllEntries->end(); ++i) { if(value == (*i).fValue) break; } if(i == fAllEntries->end()) { UAppConsole("Error : Unknown persistent value !\n"); return; } fAllEntries->erase(i); if(fAllEntries->size() == 0) { delete fAllEntries; fAllEntries = 0L; } } // very simple diff static int simple_diff(const char *file1, const char *file2) { FILE *f1 = fopen(file1, "rb"); if(f1 == 0L) return -1; FILE *f2 = fopen(file2, "rb"); if(f2 == 0L) { fclose(f1); return 1; } int res = -1; char buf1[8000]; char buf2[8000]; size_t num1, num2; while(!feof(f1) && !feof(f2) && !ferror(f1) && !ferror(f2)) { num1 = fread(buf1, sizeof(char), 8000, f1); num2 = fread(buf2, sizeof(char), 8000, f2); if(num1 != num2 || (res = memcmp(buf1, buf2, num1 * sizeof(char))) != 0) goto fail; } if(ferror(f1) || ferror(f2)) goto fail; if(feof(f1) ^ feof(f2)) goto fail; res = 0; fail: fclose(f1); fclose(f2); return res; } bool CPersistent::SaveAllSettings(const char *settingFileName, const char *forPath) { UStr tmpSettingsFile(settingFileName); tmpSettingsFile << "__"; FILE *fd = fopen(tmpSettingsFile, "w"); if(fd == 0L) { cvs_err("Failed to open the setting file '%s' for writing (error %d)", (const char *)tmpSettingsFile, errno); return false; } fprintf(fd, "VERSION=%d\n", 1); UStr path(forPath); if(path.endsWith(kPathDelimiter)) path[path.length() - 1] = '\0'; fprintf(fd, "PATH=%s\n", (const char *)path); fprintf(fd, "AUTHENTICATION=%s\n", (const char *)Authen::kindToToken(gAuthen.kind())); fprintf(fd, "CVSROOT=%s\n", (const char *)gCvsPrefs); std::vector::const_iterator i; for(i = fAllEntries->begin(); i != fAllEntries->end(); ++i) { const CPersistentEntry & entry = *i; if((entry.fClass & kAddSettings) == 0) continue; if(entry.fValue->IsKindOf(URUNTIME_CLASS(CPersistentBool))) { CPersistentBool *pbool = (CPersistentBool *)entry.fValue; bool state = *pbool; fprintf(fd, "%s=%s\n", entry.fUniqueName, state ? "true" : "false"); } else if(entry.fValue->IsKindOf(URUNTIME_CLASS(CPersistentInt))) { CPersistentInt *pint = (CPersistentInt *)entry.fValue; int val = *pint; fprintf(fd, "%s=%d\n", entry.fUniqueName, val); } else if(entry.fValue->IsKindOf(URUNTIME_CLASS(PCStr))) { PCStr *pstr = (PCStr *)entry.fValue; const char *str = *pstr; fprintf(fd, "%s=%s\n", entry.fUniqueName, (const char *)(str == 0L ? "" : str)); } else if(entry.fValue->IsKindOf(URUNTIME_CLASS(PCPStr))) { PCPStr *pstr = (PCPStr *)entry.fValue; const char *str = *pstr; fprintf(fd, "%s=%s\n", entry.fUniqueName, (const char *)(str == 0L ? "" : str)); } else { cvs_err("Unknown persistent value '%s'\n", entry.fUniqueName); } } fclose(fd); if(simple_diff(tmpSettingsFile, settingFileName) == 0) { if(unlink(tmpSettingsFile) != 0 && errno != ENOENT) cvs_err("Could not remove file '%s' (error %d)\n", (const char *)tmpSettingsFile, errno); return false; } if(unlink(settingFileName) != 0 && errno != ENOENT) { cvs_err("Could not remove file '%s' (error %d)\n", (const char *)settingFileName, errno); return false; } if(rename(tmpSettingsFile, settingFileName) != 0) { cvs_err("Could not rename file '%s' (error %d)\n", (const char *)tmpSettingsFile, errno); return false; } return true; } #ifdef macintosh static OSErr GetPreferencesFile(FSSpec & mMacFileSpec) { OSErr theErr; #if TARGET_RT_MAC_CFM short theVRef; long theDirID; Str255 name = {'\0'}; theErr = ::FindFolder(kOnSystemDisk, kPreferencesFolderType, kDontCreateFolder, &theVRef, &theDirID); if (theErr == noErr) { GUSIFileSpec spec(theVRef, theDirID, name); theErr = spec.Error(); if (theErr == noErr) { spec += kCVS_prefName; theErr = spec.Error(); if (theErr == noErr || theErr == fnfErr) { mMacFileSpec = spec; } } } #else FSRef ref, newref; theErr = ::FSFindFolder(kOnAppropriateDisk, kPreferencesFolderType, kDontCreateFolder, &ref); if (theErr == noErr) { LCFString str(kCVS_prefName); UniChar buffer[PATH_MAX]; CFRange range = {0, str.GetLength()}; ::CFStringGetCharacters(str, range, buffer); theErr = ::FSMakeFSRefUnicode(&ref, str.GetLength(), buffer, kTextEncodingDefaultFormat, &newref); if (theErr == noErr) { return ::FSGetCatalogInfo(&newref, kFSCatInfoNone, NULL, NULL, &mMacFileSpec, NULL); } else if(theErr == fnfErr) { return ::FSCreateFileUnicode(&ref, str.GetLength(), buffer, kFSCatInfoNone, NULL, NULL, &mMacFileSpec); } } #endif return theErr; } #endif // macintosh void CPersistent::SaveAll(void) { #ifdef macintosh short FRef, oldRef; Handle hdl; OSErr err; FSSpec thePrefFile; err = GetPreferencesFile(thePrefFile); if(err != noErr) { cvs_err("Error while searching preference folder (error %d)!\n", err); return; } oldRef = CurResFile(); FRef = FSpOpenResFile(&thePrefFile, fsRdWrPerm); if(FRef < 0) { ::FSpCreateResFile (&thePrefFile, 'mCVS', 'pref', smRoman); FRef = FSpOpenResFile(&thePrefFile, fsRdWrPerm); if(FRef < 0) { cvs_err("Error while saving preferences (error %d)!\n", ResError()); return; } } UseResFile (FRef); CPStr name; std::vector::iterator i; for(i = fAllEntries->begin(); i != fAllEntries->end(); ++i) { CPersistentEntry & entry = *i; int size = entry.fValue->SizeOf(); if(size <= 0) continue; //short id = Unique1ID(kCVS_prefID); name = entry.fUniqueName; Handle removing = Get1NamedResource(kCVS_prefID, name); if (removing != nil) { RemoveResource(removing); Assert_(ResError() == noErr); DisposeHandle(removing); } short theID; do { theID = Unique1ID(kCVS_prefID); } while (theID <= 127); Handle hdl = NewHandle(size); Assert_(hdl != 0L); HLock(hdl); BlockMove(entry.fValue->GetData(), *hdl, size); HUnlock(hdl); AddResource(hdl, kCVS_prefID, theID, name); Assert_(ResError() == noErr); UpdateResFile(FRef); Assert_(ResError() == noErr); ReleaseResource(hdl); Assert_(ResError() == noErr); } UseResFile(oldRef); Assert_(ResError() == noErr); CloseResFile (FRef); Assert_(ResError() == noErr); #endif /* macintosh */ #ifdef WIN32 std::vector::iterator i; for(i = fAllEntries->begin(); i != fAllEntries->end(); ++i) { CPersistentEntry & entry = *i; unsigned int size = entry.fValue->SizeOf(); if(size == 0) continue; if(!AfxGetApp()->WriteProfileBinary(PROFILE_NAME, entry.fUniqueName, (BYTE *)entry.fValue->GetData(), size)) { cvs_err("Error while saving preferences !\n"); break; } } #endif /* WIN32 */ #ifdef qUnix CStr home; home = gCvsPrefs.Home(); if(!home.endsWith(kPathDelimiter)) home << kPathDelimiter; home << ".gcvsrc"; FILE *out = fopen(home, "wb"); if(out == 0L) { cvs_err("Unable to open '%s' for writing (error %d)", (char *)home, errno); return; } int version = 1; fwrite(&version, sizeof(int), 1, out); int numEntries = fAllEntries->size(); fwrite(&numEntries, sizeof(int), 1, out); std::vector::iterator i; for(i = fAllEntries->begin(); i != fAllEntries->end(); ++i) { CPersistentEntry & entry = *i; unsigned int size = entry.fValue->SizeOf(); fwrite(entry.fUniqueName, sizeof(char), strlen(entry.fUniqueName) + 1, out); fwrite(&size, sizeof(unsigned int), 1, out); fwrite(entry.fValue->GetData(), 1, size, out); } if(ferror(out)) cvs_err("Error while writing '%s' (error %d)", (char *)home, errno); fclose(out); #endif /* qUnix */ for(i = fAllEntries->begin(); i != fAllEntries->end(); ++i) { CPersistentEntry & entry = *i; entry.fValue->ResetTimeStamp(); } } bool CPersistent::LoadAll(void) { #ifdef macintosh FSSpec thePrefFile; short FRef, oldRef; Handle hdl; OSErr err; err = GetPreferencesFile(thePrefFile); if(err != noErr) return false; oldRef = CurResFile(); FRef = FSpOpenResFile(&thePrefFile, fsRdPerm); if(FRef < 0) return false; CPStr name; UseResFile(FRef); std::vector::iterator i; for(i = fAllEntries->begin(); i != fAllEntries->end(); ++i) { CPersistentEntry & entry = *i; name = entry.fUniqueName; Handle hdl = Get1NamedResource(kCVS_prefID, name); if(hdl == 0L) continue; HLock(hdl); entry.fValue->SetData(*hdl, GetHandleSize(hdl)); entry.fValue->ResetTimeStamp(); HUnlock(hdl); } // migrate to the new gOldCvsroots container if(gOldCvsroots.GetList().size() == 0) { for(int nIndex = 0; nIndex <= NUM_CVSROOT; nIndex++) { char tmp[20]; sprintf(tmp, "P_Cvsroot%d", nIndex); CPStr pstr(tmp); Handle hdl = Get1NamedResource(kCVS_prefID, pstr); if(hdl == 0L) continue; CStr root((char *)*hdl); if( !root.empty() ) gOldCvsroots.Insert(root); } } CloseResFile (FRef); UseResFile(oldRef); return true; #endif /* macintosh */ #ifdef WIN32 bool found_one = false; std::vector::iterator i; for(i = fAllEntries->begin(); i != fAllEntries->end(); ++i) { CPersistentEntry & entry = *i; BYTE* ppData; UINT pBytes; if(!AfxGetApp()->GetProfileBinary(PROFILE_NAME, entry.fUniqueName, &ppData, &pBytes)) { continue; } found_one = true; entry.fValue->SetData(ppData, pBytes); entry.fValue->ResetTimeStamp(); delete ppData; } return found_one; #endif /* WIN32 */ #ifdef qUnix CStr home; home = gCvsPrefs.Home(); if(!home.endsWith(kPathDelimiter)) home << kPathDelimiter; home << ".gcvsrc"; FILE *out = fopen(home, "rb"); if(out == 0L) return false; int version; int numEntries; CStaticAllocT alloc; fread(&version, sizeof(int), 1, out); if(version != 1) { cvs_err("Unexpected version %d in the file '%s'\n", version, (char *)home); goto close; } fread(&numEntries, sizeof(int), 1, out); if(numEntries < 0) { cvs_err("Unexpected # %d in the file '%s'\n", numEntries, (char *)home); goto close; } for(int i = 0; i < numEntries; i++) { CStr name; while(!feof(out) && !ferror(out)) { int c = getc(out); name << (char)c; if(c == '\0') break; } if(feof(out)) { cvs_err("Unexpected end of file in '%s'\n", (char *)home); goto close; } if(ferror(out)) { cvs_err("Unexpected error %d in '%s'\n", errno, (char *)home); goto close; } CPersistentEntry * entry = CPersistent::Find(name); if(entry == 0L) { cvs_err("Unexpected token '%s' in '%s'\n", (char *)name, (char *)home); } unsigned int size; fread(&size, sizeof(unsigned int), 1, out); alloc.AdjustSize(size); fread((char *)alloc, 1, size, out); if(entry != 0L) { entry->fValue->SetData((char *)alloc, size); entry->fValue->ResetTimeStamp(); } } if(ferror(out)) cvs_err("Error while reading '%s' (error %d)", (char *)home, errno); fclose(out); return true; close: fclose(out); #endif /* qUnix */ return false; } CPersistent::CPersistentEntry * CPersistent::Find(const char *uniqueName) { std::vector::iterator i; for(i = fAllEntries->begin(); i != fAllEntries->end(); ++i) { CPersistentEntry & entry = *i; if(!strcmp(uniqueName, entry.fUniqueName)) return &entry; } return 0L; } bool CPersistent::NeedSave(bool onlySettings) { std::vector::const_iterator i; for(i = fAllEntries->begin(); i != fAllEntries->end(); ++i) { const CPersistentEntry & entry = *i; if(onlySettings && (entry.fClass & kAddSettings) == 0) continue; if(entry.fValue->fTimeStamp != 0) return true; } return false; } #if !qMPWCvs // // Settings management // #define SETTINGS_FOLDER "Settings" static bool SettingsGetLoc(CStr & path) { struct stat sb; path = ""; #ifdef WIN32 CWincvsApp* pApp = (CWincvsApp *)AfxGetApp(); pApp->GetAppPath(path); if(!path.empty() && !path.endsWith(kPathDelimiter)) { path << kPathDelimiter; } path << SETTINGS_FOLDER; #elif defined(qUnix) path = gCvsPrefs.Home(); if(!path.endsWith(kPathDelimiter)) path << kPathDelimiter; path << ".gcvs"; if(stat(path, &sb) != -1) { if(!S_ISDIR(sb.st_mode)) { cvs_err("The file '%s' already exists and is not a directory", (char *)path, errno); return false; } } else if(mkdir(path, 0750) != 0) { cvs_err("Unable to create the directory '%s' (error %d)", (char *)path, errno); return false; } if(!path.endsWith(kPathDelimiter)) path << kPathDelimiter; path << SETTINGS_FOLDER; #else # ifdef qMacCvsPP path = CMacCvsApp::GetAppPath(); # endif /* qMacCvsPP */ if(!path.empty() && !path.endsWith(kPathDelimiter)) { path << kPathDelimiter; } path << SETTINGS_FOLDER; #endif if(stat(path, &sb) != -1 && S_ISDIR(sb.st_mode)) return true; #if qUnix || TARGET_RT_MAC_MACHO if(mkdir(path, 0750) != 0) #else if(mkdir(path) != 0) #endif { cvs_err("Failed to create the setting folder '%s' (error %d)", (const char *)path, errno); return false; } return true; } class USaveSettings : public UWidget { public: UDECLARE_DYNAMIC(USaveSettings) public: USaveSettings(const char *path, const char *oldname); virtual ~USaveSettings(); virtual void DoDataExchange(bool fill); enum { #if qUnix kOK = EV_COMMAND_START, kCancel, kSettingName, #else kSettingName = EV_COMMAND_START, #endif kCopyPath, kCopyFrom, kCopyList }; UStr m_settingName; UStr m_copyFromPath; protected: UStr m_path; UStr m_oldname; std::map m_list; ev_msg int OnCopyFrom(void); #if qUnix ev_msg int OnOK(void); ev_msg int OnCancel(void); #endif UDECLARE_MESSAGE_MAP() }; UIMPLEMENT_DYNAMIC(USaveSettings, UWidget) UBEGIN_MESSAGE_MAP(USaveSettings, UWidget) ON_UCOMMAND(USaveSettings::kCopyFrom, USaveSettings::OnCopyFrom) #if qUnix ON_UCOMMAND(USaveSettings::kOK, USaveSettings::OnOK) ON_UCOMMAND(USaveSettings::kCancel, USaveSettings::OnCancel) #endif UEND_MESSAGE_MAP() #if qUnix int USaveSettings::OnOK(void) { EndModal(true); return 0; } int USaveSettings::OnCancel(void) { EndModal(false); return 0; } #endif USaveSettings::USaveSettings(const char *path, const char *oldname) : UWidget(::UEventGetWidID()), m_path(path), m_oldname(oldname) { } USaveSettings::~USaveSettings() { } static bool GetAllPersistentSettings(std::map & res); void USaveSettings::DoDataExchange(bool fill) { if(fill) { UEventSendMessage(GetWidID(), EV_SETTEXT, kCopyPath, (void *)(const char *)m_path); UStr defname; if(m_oldname.empty()) { UStr uppath; SplitPath(m_path, uppath, defname); } else defname = m_oldname; UEventSendMessage(GetWidID(), EV_SETTEXT, kSettingName, (void *)(const char *)defname); UEventSendMessage(GetWidID(), EV_ENABLECMD, UMAKEINT(kCopyList, 0), 0L); UEventSendMessage(GetWidID(), EV_COMBO_RESETALL, kCopyList, 0L); if(GetAllPersistentSettings(m_list)) { std::map::const_iterator i; for(i = m_list.begin(); i != m_list.end(); ++i) { UEventSendMessage(GetWidID(), EV_COMBO_APPEND, kCopyList, (void *)(const char *)(*i).first); } } } else { UEventSendMessage(GetWidID(), EV_GETTEXT, kSettingName, &m_settingName); int state = UEventSendMessage(GetWidID(), EV_QUERYSTATE, kCopyFrom, 0L); if(state) { UStr what; UEventSendMessage(GetWidID(), EV_COMBO_GETSEL, kCopyList, &what); std::map::const_iterator i; i = m_list.find(what); if(i != m_list.end()) { m_copyFromPath = (*i).second; } } } } int USaveSettings::OnCopyFrom(void) { int state = UEventSendMessage(GetWidID(), EV_QUERYSTATE, kCopyFrom, 0L); UEventSendMessage(GetWidID(), EV_ENABLECMD, UMAKEINT(kCopyList, state), 0L); return 1; } static bool loadSettingsInternal(const char *fullname, bool (*func)(const char *token, const char *value, void *data), void *data) { bool res = false; int line_length; char *line = 0L; size_t line_chars_allocated = 0; FILE *fp = fopen(fullname, "r"); if(fp == 0L) { cvs_err("Failed to open the setting file '%s' for reading (error %d)", fullname, errno); goto fail; } while ((line_length = getline (&line, &line_chars_allocated, fp)) > 0) { // read each token=value char *tmp = 0L; if((tmp = strchr(line, '\n')) != 0L) *tmp = '\0'; tmp = line; while(isspace(*tmp) && *tmp != '\0') tmp++; if(*tmp == '\0' || *tmp == '#') continue; UStr token; UStr value; const char *tmp2 = strchr(tmp, '='); if(tmp2 == 0L) continue; token.set(tmp, tmp2 - tmp); value = tmp2 + 1; // check version if(strcmp(token, "VERSION") == 0) { if(atoi(value) != 1) { cvs_err("Newer format than expected in the setting file '%s'\n", fullname); goto fail; } continue; } if(func(token, value, data)) break; } if (line_length < 0 && !feof (fp)) { cvs_err("Cannot read file (error %d)\n", errno); goto fail; } res = true; fail: if(line != 0L) free(line); if(fp!= 0L) fclose(fp); return res; } static void getSettingName(const char *fromfile, UStr & res) { CStr base, ext, uppath, filename; SplitPath(fromfile, uppath, filename); GetExtension(filename, base, ext); if(!base.empty() && stricmp(ext, "txt") == 0) res = base; else res = filename; } class CFindSettings : public TraversalReport { public: CFindSettings(const char *findPath) : m_pathToFind(findPath), m_list(0L) { if(m_pathToFind.endsWith(kPathDelimiter)) m_pathToFind[m_pathToFind.length() - 1] = '\0'; } CFindSettings(std::map & list) : m_list(&list) { } virtual ~CFindSettings() {} virtual kTraversal OnError(const char *err, int errcode) { cvs_err(err); cvs_err("\n"); return kTraversalError; } virtual kTraversal OnFile(const char *fullpath, const char *fullname, const char *name, const struct stat & dir, const UFSSpec * macspec); static bool searchPath(const char *token, const char *value, void *data); static bool searchAllPath(const char *token, const char *value, void *data); UStr m_pathToFind; UStr m_settingsFile; bool m_foundIt; UStr m_topfolder; std::map *m_list; }; bool CFindSettings::searchPath(const char *token, const char *value, void *data) { CFindSettings *loader = (CFindSettings *)data; // if we give a sub-folder to look for, it will return the // top folder's settings if(strcmp(token, "PATH") == 0 && #if qUnix strncmp(value, loader->m_pathToFind, strlen(value)) == 0 #else strnicmp(value, loader->m_pathToFind, strlen(value)) == 0 #endif ) { loader->m_foundIt = true; loader->m_topfolder = value; return true; } return false; } bool CFindSettings::searchAllPath(const char *token, const char *value, void *data) { CFindSettings *loader = (CFindSettings *)data; if(strcmp(token, "PATH") == 0) { getSettingName(loader->m_settingsFile, loader->m_settingsFile); std::map::value_type v(loader->m_settingsFile, UStr(value)); loader->m_list->insert(v); return true; } return false; } kTraversal CFindSettings::OnFile(const char *fullpath, const char *fullname, const char *name, const struct stat & dir, const UFSSpec * macspec) { m_foundIt = false; if(m_list == 0L) { loadSettingsInternal(fullname, searchPath, this); } else { m_settingsFile = fullname; loadSettingsInternal(fullname, searchAllPath, this); } if(m_foundIt) m_settingsFile = fullname; return m_foundIt ? kStopTraversal : kContinueTraversal; } static bool GetAllPersistentSettings(std::map & res) { UStr settingsDir; if(!SettingsGetLoc(settingsDir)) return false; CFindSettings finder(res); FileTraverse(settingsDir, finder); return !res.empty(); } bool HasPersistentSettings(const char *path) { UStr settingsDir; if(!SettingsGetLoc(settingsDir)) return false; CFindSettings finder(path); FileTraverse(settingsDir, finder); return !finder.m_settingsFile.empty(); } static bool _loadPersistentSettings(const char *token, const char *value, void *data) { if(strcmp(token, "CVSROOT") == 0) { gCvsPrefs = value; } else if(strcmp(token, "AUTHENTICATION") == 0) { gAuthen.setkind(Authen::tokenToKind(value)); } else if(strcmp(token, "PATH") == 0) { } else { CPersistent::CPersistentEntry *entry = CPersistent::Find(token); if(entry == 0L) { //cvs_err("Persistent value '%s' is not registred\n", token); } else { if(entry->fValue->IsKindOf(URUNTIME_CLASS(CPersistentBool))) { CPersistentBool *pbool = (CPersistentBool *)entry->fValue; if(strcmp(value, "true") == 0) *pbool = true; else if(strcmp(value, "false") == 0) *pbool = false; else cvs_err("Invalid value '%s' for persistent '%s'\n", (const char *)value, entry->fUniqueName); } else if(entry->fValue->IsKindOf(URUNTIME_CLASS(CPersistentInt))) { CPersistentInt *pint = (CPersistentInt *)entry->fValue; int aint; int check = sscanf(value, "%d", &aint); if(check == 1) *pint = aint; else cvs_err("Invalid value '%s' for persistent '%s'\n", (const char *)value, entry->fUniqueName); } else if(entry->fValue->IsKindOf(URUNTIME_CLASS(PCStr))) { PCStr *pstr = (PCStr *)entry->fValue; *pstr = value; } else if(entry->fValue->IsKindOf(URUNTIME_CLASS(PCPStr))) { PCPStr *pstr = (PCPStr *)entry->fValue; *pstr = value; } else { cvs_err("Unknown persistent value '%s'\n", entry->fUniqueName); } } } return false; } void LoadPersistentSettings(const char *path, bool quiet) { UStr settingsDir; if(!SettingsGetLoc(settingsDir)) return; CFindSettings finder(path); FileTraverse(settingsDir, finder); if(finder.m_settingsFile.empty()) return; if(loadSettingsInternal(finder.m_settingsFile, _loadPersistentSettings, 0L) && !quiet) { CColorConsole out; out << kBold << "Loaded settings for " << kNormal << kUnderline << path << kNormal << kBold << " successfully..." << kNormal << kNL; } } static void SaveAsPersistentSettings(const char *name, const char *path) { UStr settingFileName; if(!SettingsGetLoc(settingFileName)) return; if(!settingFileName.empty() && !settingFileName.endsWith(kPathDelimiter)) settingFileName << kPathDelimiter; settingFileName << name; settingFileName << ".txt"; if(CPersistent::SaveAllSettings(settingFileName, path)) { CColorConsole out; out << kBold << "Saved settings for " << kNormal << kUnderline << path << kNormal << kBold << " successfully..." << kNormal << kNL; } } void AskCreatePersistentSettings(const char *path) { UStr settingsDir; if(!SettingsGetLoc(settingsDir)) return; int id = 0; #ifdef WIN32 id = IDD_SAVESETTINGS; #endif #ifdef qMacCvsPP id = dlg_SaveSettings; #endif CFindSettings finder(path); FileTraverse(settingsDir, finder); UStr oldName; if(!finder.m_settingsFile.empty()) { getSettingName(finder.m_settingsFile, oldName); } USaveSettings *dlg = NEW USaveSettings(path, oldName); #if qUnix void *wid; # if qGTK wid = UCreate_SettingsDlg(); # endif UEventSendMessage(dlg->GetWidID(), EV_INIT_WIDGET, kUMainWidget, wid); #endif if(dlg->DoModal(id)) { UStr name = dlg->m_settingName; UStr fileToDelete; if(!name.empty()) { if(!oldName.empty()) { if(stricmp(oldName, name) != 0) { UStr prompt("The setting '"); prompt << oldName; prompt << "' already points on the same folder. "; prompt << "Press 'Delete' if you want to overide this setting "; prompt << "(two settings cannot point on the same location)."; if(CvsAlert(prompt, "Cancel", "Delete")) { delete dlg; return; } fileToDelete = finder.m_settingsFile; } } if(!dlg->m_copyFromPath.empty()) LoadPersistentSettings(dlg->m_copyFromPath); SaveAsPersistentSettings(name, path); if(!fileToDelete.empty()) { if(remove(fileToDelete) != 0) cvs_err("Error while deleting '%s' (error %d)\n", (const char *)fileToDelete, errno); } } } delete dlg; } void SavePersistentSettings(const char *path) { UStr settingsDir; if(!SettingsGetLoc(settingsDir)) return; CFindSettings finder(path); FileTraverse(settingsDir, finder); if(finder.m_settingsFile.empty()) return; if(CPersistent::SaveAllSettings(finder.m_settingsFile, finder.m_topfolder)) { CColorConsole out; out << kBold << "Saved settings for " << kNormal << kUnderline << path << kNormal << kBold << " successfully..." << kNormal << kNL; } } #endif // !qMPWCvs