/* ** 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 --- December 1997 */ /* * CvsPrefs.cpp --- class to handle CVS settings */ #include "stdafx.h" #include #include #include "CvsPrefs.h" #include "Authen.h" #include "AppConsole.h" #include "CvsArgs.h" #include "MultiString.h" #include "FileTraversal.h" #ifdef macintosh # define PCVS "\pCVSROOT" # include # include # include # include # include "VolsPaths.h" # include "MacMisc.h" # include "AppGlue.h" #endif /* macintosh */ #ifdef HAVE_UNISTD_H # include #endif #ifdef HAVE_PWD_H # include #endif #ifdef WIN32 # include # include "WinCvsBrowser.h" # include "wincvs.h" # include "TextBinary.h" # ifdef _DEBUG # define new DEBUG_NEW # undef THIS_FILE static char THIS_FILE[] = __FILE__; # endif #endif /* WIN32 */ #ifdef qMacCvsPP # include "GUSIInternal.h" # include "GUSIFileSpec.h" # include "MacCvsApp.h" # include #endif #if qUnix # include "UCvsApp.h" # include "UCvsFolders.h" #endif CvsPrefs gCvsPrefs; static CPersistentInt gPersistentShema("P_PersistentShema", SCHEMA_0); static CPersistentBool gCheckoutRO("P_CheckoutRO", true, kAddSettings); static CPersistentBool gZ9Option("P_Z9Option", false, kAddSettings); static CPersistentBool gPruneOption("P_PruneOption", true, kAddSettings); static CPersistentBool gQuietOption("P_QuietOption", false); static CPersistentInt gIsoConvert("P_NIsoConvert", ISO8559_none, kAddSettings); static CPersistentBool gICTextOption("P_ICTextOption", false, kAddSettings); static CPersistentBool gAddBinControl("P_AddBinControl", true); static CPersistentBool gUseViewerAlways("P_UseViewerAlways", false, kAddSettings); static CPersistentInt gMacBinEncoding("P_NMacBinEncoding", MAC_HQX, kAddSettings); static CPersistentInt gUseShell("P_UseShell", SHELL_TCL); static PCPStr gCvsroot("P_Cvsroot"); CMString gOldCvsroots(20, "P_OldCvsroots"); // migration #ifndef MIGRATECVSROOTLIST static PCPStr gCvsroot1("P_Cvsroot1"); static PCPStr gCvsroot2("P_Cvsroot2"); static PCPStr gCvsroot3("P_Cvsroot3"); static PCPStr gCvsroot4("P_Cvsroot4"); static PCPStr gCvsroot5("P_Cvsroot5"); static PCPStr gCvsroot6("P_Cvsroot6"); static PCPStr gCvsroot7("P_Cvsroot7"); static PCPStr gCvsroot8("P_Cvsroot8"); static PCPStr gCvsroot9("P_Cvsroot9"); static PCPStr gCvsroot10("P_Cvsroot10"); static PCPStr gCvsroot11("P_Cvsroot11"); static PCPStr gCvsroot12("P_Cvsroot12"); static PCPStr gCvsroot13("P_Cvsroot13"); static PCPStr gCvsroot14("P_Cvsroot14"); static PCPStr gCvsroot15("P_Cvsroot15"); static PCPStr gCvsroot16("P_Cvsroot16"); static PCPStr gCvsroot17("P_Cvsroot17"); static PCPStr gCvsroot18("P_Cvsroot18"); static PCPStr gCvsroot19("P_Cvsroot19"); static PCPStr gCvsroot20("P_Cvsroot20"); #endif static CPersistentInt gKserverPort("P_KserverPort", -1, kAddSettings); static CPersistentInt gPserverPort("P_PserverPort", -1, kAddSettings); static CPersistentInt gRhostPort("P_RhostPort", -1, kAddSettings); static PCPStr gServerName("P_ServerName", 0L, kAddSettings); static PCStr gRshName("P_RshName", 0L, kAddSettings); static CPersistentBool gEncryptCommunication("P_EncryptCommunication", false, kAddSettings); #ifndef qUnix static PCStr gHome("P_Home", 0L, kAddSettings); #endif /* !qUnix */ #ifdef qUnix static PCStr gViewer("P_Viewer", "emacs"); // not vi ;-) #else static PCStr gViewer("P_Viewer", "Notepad"); #endif static PCStr gHelper("P_Helper", "netscape"); static PCStr gBrowser("P_Browser", "gmc"); #ifdef qUnix static PCStr gExtdiff("P_Extdiff", "emacs"); #else static PCStr gExtdiff("P_Extdiff", ""); #endif static CPersistentBool gDirtySupport("P_DirtySupport", true, kAddSettings); static CPersistentBool gAlwaysUseCvsroot("P_AlwaysUseCvsroot", false, kAddSettings); static CPersistentInt gLogoutTimeOut("P_LogoutTimeOut", 0); static PCStr gProxyHost("P_ProxyHost", "www.mydomain", kAddSettings); static CPersistentInt gProxyPort("P_ProxyPort", 8888, kAddSettings); static CPersistentBool gUseProxy("P_UseProxy", false, kAddSettings); static CPersistentBool gUnixLF("P_UnixLF", false, kAddSettings); static CPersistentBool gMacLF("P_MacLF", false, kAddSettings); static CPersistentInt gZLevel("P_ZLevel", 9, kAddSettings); static CPersistentInt gCvsVersion("P_CvsVersion", 0, kAddSettings); static CPersistentBool gCvsConsole("P_CvsConsole", false, kAddSettings); static CPersistentInt gWordWrapLogMsg("P_WordWrapLogMsg", 0, kAddSettings); static PCStr gLastWorkingDir("P_LastWorkingDir", 0L, kAddSettings); static CPersistentBool gDisableSplashScreen("P_DisableSplashScreen", false); static CPersistentInt gStatusOutputType("P_StatusOutputType", STATUSOUTPUT_VERBOSE); static CPersistentBool gHideCommandDlgUpdate("P_HideCommandDlgUpdate", false); static CPersistentBool gHideCommandDlgDiff("P_HideCommandDlgDiff", false); static CPersistentBool gHideCommandDlgLog("P_HideCommandDlgLog", false); static CPersistentBool gHideCommandDlgGraph("P_HideCommandDlgGraph", false); static CPersistentBool gHideCommandDlgAnnotate("P_HideCommandDlgAnnotate", false); static CPersistentBool gHideCommandDlgStatus("P_HideCommandDlgStatus", false); static CPersistentBool gHideCommandDlgUseShift("P_HideCommandDlgUseShift", true); static CKeyString gWhichCvs(10, "P_WhichCvs" ); static CPersistentBool gUseAltCvs("P_UseAltCvs", false, kAddSettings); bool CvsPrefs::CheckoutRO(void) const {return gCheckoutRO;} bool CvsPrefs::Z9Option(void) const { #ifdef macintosh // because of the problem with LSH... return true; #endif return gZ9Option; } bool CvsPrefs::PruneOption(void) const {return gPruneOption;} bool CvsPrefs::QuietOption(void) const {return gQuietOption;} ISO8559 CvsPrefs::IsoConvert(void) const {return (ISO8559)(int)gIsoConvert;} bool CvsPrefs::ICTextOption(void) const {return gICTextOption;} bool CvsPrefs::AddControl(void) const {return gAddBinControl;} bool CvsPrefs::UseViewerAlways(void) const {return gUseViewerAlways;} MACENCODING CvsPrefs::MacBinEncoding(void) const {return (MACENCODING)(int)gMacBinEncoding;} int CvsPrefs::KserverPort(void) const {return gKserverPort;} int CvsPrefs::PserverPort(void) const {return gPserverPort;} int CvsPrefs::RhostPort(void) const {return gRhostPort;} const char * CvsPrefs::ServerName(void) const { return gServerName.empty() ? 0L : (const char *)gServerName; } const char * CvsPrefs::RshName(void) const { return gRshName.empty() ? 0L : (const char *)gRshName; } bool CvsPrefs::EncryptCommunication(void) const {return gEncryptCommunication;} const char * CvsPrefs::Home(void) const { #if !qUnix && !TARGET_RT_MAC_MACHO # ifdef WIN32 // Windows 98 doesn't like C:\/.cvspass if(!gHome.empty() && gHome.endsWith(kPathDelimiter)) { gHome[gHome.length() - 1] = '\0'; } # endif return gHome.empty() ? 0L : (const char *)gHome; #else /* qUnix */ static CStr home; if (!home.empty()) return home; char *env = getenv ("HOME"); struct passwd *pw; if (env) home = env; else if ((pw = (struct passwd *) getpwuid (getuid ())) && pw->pw_dir) home = pw->pw_dir; else return 0L; return home; #endif /* qUnix */ } const char * CvsPrefs::Viewer(void) const { return gViewer.empty() ? 0L : (const char *)gViewer; } const char * CvsPrefs::Helper(void) const { return gHelper.empty() ? 0L : (const char *)gHelper; } const char * CvsPrefs::Browser(void) const { return gBrowser.empty() ? 0L : (const char *)gBrowser; } const char * CvsPrefs::ExtDiff(void) const { return gExtdiff.empty() ? 0L : (const char *)gExtdiff; } bool CvsPrefs::DirtySupport(void) const {return gDirtySupport;} int CvsPrefs::LogoutTimeOut(void) const {return gLogoutTimeOut;} bool CvsPrefs::AlwaysUseCvsroot(void) const {return gAlwaysUseCvsroot;} const char *CvsPrefs::ProxyHost(void) const {return gProxyHost;} int CvsPrefs::ProxyPort(void) const {return gProxyPort;} bool CvsPrefs::UseProxy(void) const {return gUseProxy;} bool CvsPrefs::UnixLF(void) const {return gUnixLF;} bool CvsPrefs::MacLF(void) const {return gMacLF;} int CvsPrefs::ZLevel(void) const {return gZLevel;} int CvsPrefs::CvsVersion(void) const {return gCvsVersion;} bool CvsPrefs::CvsConsole(void) const {return gCvsConsole;} int CvsPrefs::WordWrapLogMsg(void) const {return gWordWrapLogMsg;} SHELL_KIND CvsPrefs::GetUseShell(void) const {return (SHELL_KIND)(int)gUseShell;} bool CvsPrefs::DisableSplashScreen(void) const {return gDisableSplashScreen;} STATUSOUTPUT_TYPE CvsPrefs::StatusOutputType(void) const {return (STATUSOUTPUT_TYPE)(int)gStatusOutputType;} /* Return the current working dir (last working dir). */ /* This directory is automatically selected when WinCVS */ /* is opened the next time. */ const char * CvsPrefs::LastWorkingDir(void) const { return gLastWorkingDir.empty() ? 0L : (const char *)gLastWorkingDir; } bool CvsPrefs::HideCommandDlgUpdate(void) const {return gHideCommandDlgUpdate;} bool CvsPrefs::HideCommandDlgDiff(void) const {return gHideCommandDlgDiff;} bool CvsPrefs::HideCommandDlgLog(void) const {return gHideCommandDlgLog;} bool CvsPrefs::HideCommandDlgGraph(void) const {return gHideCommandDlgGraph;} bool CvsPrefs::HideCommandDlgAnnotate(void) const {return gHideCommandDlgAnnotate;} bool CvsPrefs::HideCommandDlgStatus(void) const {return gHideCommandDlgStatus;} bool CvsPrefs::HideCommandDlgUseShift(void) const {return gHideCommandDlgUseShift;} void CvsPrefs::SetCheckoutRO(bool newState) {gCheckoutRO = newState;} void CvsPrefs::SetZ9Option(bool newState) {gZ9Option = newState;} void CvsPrefs::SetPruneOption(bool newState) {gPruneOption = newState;} void CvsPrefs::SetQuietOption(bool newState) {gQuietOption = newState;} void CvsPrefs::SetIsoConvert(ISO8559 newState) {gIsoConvert = (int)newState;} void CvsPrefs::SetICTextOption(bool newState) {gICTextOption = newState;} void CvsPrefs::SetAddControl(bool newState) {gAddBinControl = newState;} void CvsPrefs::SetUseViewerAlways(bool newState) {gUseViewerAlways = newState;} void CvsPrefs::SetMacBinEncoding(MACENCODING newState) {gMacBinEncoding = (int)newState;} void CvsPrefs::SetKserverPort(int newState) {gKserverPort = newState;} void CvsPrefs::SetPserverPort(int newState) {gPserverPort = newState;} void CvsPrefs::SetRhostPort(int newState) {gRhostPort = newState;} void CvsPrefs::SetServerName(const char *newservername) {gServerName = newservername;} void CvsPrefs::SetRshName(const char *newrshname) {gRshName = newrshname;} void CvsPrefs::SetEncryptCommunication(bool newState) {gEncryptCommunication = newState;} void CvsPrefs::SetHome(const char *newhome) { #ifndef qUnix gHome = newhome; # ifdef WIN32 // Windows 98 doesn't like C:\/.cvspass if(!gHome.empty() && gHome.endsWith(kPathDelimiter)) { gHome[gHome.length() - 1] = '\0'; } # endif #endif /* !qUnix */ } void CvsPrefs::SetViewer(const char *newviewer) {gViewer = newviewer;} void CvsPrefs::SetBrowser(const char *newviewer) {gBrowser = newviewer;} void CvsPrefs::SetHelper(const char *newviewer) {gHelper = newviewer;} void CvsPrefs::SetExtDiff(const char *newdiff) {gExtdiff = newdiff;} void CvsPrefs::SetDirtySupport(bool newState) {gDirtySupport = newState;} void CvsPrefs::SetLogoutTimeOut(int newTimeout) {gLogoutTimeOut = newTimeout;} void CvsPrefs::SetAlwaysUseCvsroot(bool newState) {gAlwaysUseCvsroot = newState;} void CvsPrefs::SetUseProxy(bool useit) {gUseProxy = useit;} void CvsPrefs::SetUnixLF(bool useit) {gUnixLF = useit;} void CvsPrefs::SetMacLF(bool useit) {gMacLF = useit;} void CvsPrefs::SetZLevel(int level) {gZLevel = level;} void CvsPrefs::SetProxyHost(const char *newhost) {gProxyHost = newhost;} void CvsPrefs::SetProxyPort(int newport) {gProxyPort = newport;} void CvsPrefs::SetCvsVersion(int vers) {gCvsVersion = vers;} void CvsPrefs::SetCvsConsole(bool console) {gCvsConsole = console;} void CvsPrefs::SetWordWrapLogMsg(int wordwrap) {gWordWrapLogMsg = wordwrap;} void CvsPrefs::SetLastWorkingDir(const char *workdir) {gLastWorkingDir = workdir;} void CvsPrefs::SetUseShell(SHELL_KIND shell) {gUseShell = shell;} void CvsPrefs::SetDisableSplashScreen(bool newState) {gDisableSplashScreen = newState;} void CvsPrefs::SetStatusOutputType(STATUSOUTPUT_TYPE outputType) {gStatusOutputType = outputType;} void CvsPrefs::SetHideCommandDlgUpdate(bool newState) {gHideCommandDlgUpdate = newState;} void CvsPrefs::SetHideCommandDlgDiff(bool newState) {gHideCommandDlgDiff = newState;} void CvsPrefs::SetHideCommandDlgLog(bool newState) {gHideCommandDlgLog = newState;} void CvsPrefs::SetHideCommandDlgGraph(bool newState) {gHideCommandDlgGraph = newState;} void CvsPrefs::SetHideCommandDlgAnnotate(bool newState) {gHideCommandDlgAnnotate = newState;} void CvsPrefs::SetHideCommandDlgStatus(bool newState) {gHideCommandDlgStatus = newState;} void CvsPrefs::SetHideCommandDlgUseShift(bool newState) {gHideCommandDlgUseShift = newState;} bool CvsPrefs::empty(void) const { return gCvsroot.empty(); } int CvsPrefs::length(void) const { return gCvsroot.length(); } CvsPrefs::operator const char *() const { return (const char *)gCvsroot; } CvsPrefs::operator const unsigned char *() const {return (const unsigned char *)gCvsroot;} const char *CvsPrefs::operator=(const char *newstr) { return gCvsroot = newstr; } const unsigned char *CvsPrefs::operator=(const unsigned char *newstr) { return gCvsroot = newstr; } // migration #ifndef MIGRATECVSROOTLIST CPStr & CvsPrefs::get_cvsroot_list(int entry) { switch(entry) { case 0: return gCvsroot1; break; case 1: return gCvsroot2; break; case 2: return gCvsroot3; break; case 3: return gCvsroot4; break; case 4: return gCvsroot5; break; case 5: return gCvsroot6; break; case 6: return gCvsroot7; break; case 7: return gCvsroot8; break; case 8: return gCvsroot9; break; case 9: return gCvsroot10; break; case 10: return gCvsroot11; break; case 11: return gCvsroot12; break; case 12: return gCvsroot13; break; case 13: return gCvsroot14; break; case 14: return gCvsroot15; break; case 15: return gCvsroot16; break; case 16: return gCvsroot17; break; case 17: return gCvsroot18; break; case 18: return gCvsroot19; break; case 19: return gCvsroot20; break; } return gCvsroot1; } bool CvsPrefs::has_cvsroot_in_list(const char *cvsroot, int & entry) { for(int i = 0; i < NUM_CVSROOT; i++) { CPStr & str = get_cvsroot_list(i); if(str.empty()) continue; if(strcmp(str, cvsroot) == 0) { entry = i; return true; } } return false; } void CvsPrefs::insert_cvsroot_in_list(const char *cvsroot) { int entry; if(has_cvsroot_in_list(cvsroot, entry)) { // move to the first entry CPStr tmp; tmp = get_cvsroot_list(0); get_cvsroot_list(0) = get_cvsroot_list(entry); get_cvsroot_list(entry) = tmp; } else { // push back the entry for(int i = (NUM_CVSROOT - 1); i >= 1; i--) { get_cvsroot_list(i) = get_cvsroot_list(i - 1); } get_cvsroot_list(0) = cvsroot; } } void CvsPrefs::flush_list(void) { for(int i = 0; i < NUM_CVSROOT; i++) { get_cvsroot_list(i) = ""; } } #endif /* MIGRATECVSROOTLIST */ void CvsPrefs::save(void) { if(empty()) return; if( SCHEMA_1 != gPersistentShema ) { gPersistentShema = SCHEMA_1; } bool needSave = CPersistent::NeedSave(); bool needSaveSettings = CPersistent::NeedSave(true); if(!needSave) return; // migration #ifndef MIGRATECVSROOTLIST // update the CVSROOT list insert_cvsroot_in_list((const char *)*this); #endif CPersistent::SaveAll(); if(!needSaveSettings) return; #ifdef WIN32 CWincvsApp* app = (CWincvsApp *)AfxGetApp(); SavePersistentSettings(app->GetBrowserView()->GetRoot()); #endif #ifdef qMacCvsPP CMacCvsApp::SavePersistentSettings(); #endif /* qMacCvsPP */ #if qUnix UCvsFolders *browser = UCvsApp::gApp->GetBrowserView(); if(browser != 0L && browser->GetRoot() != 0L) SavePersistentSettings(browser->GetRoot()); #endif } void CvsPrefs::load(void) { // migration #ifndef MIGRATECVSROOTLIST // flush the CVSROOT list, it will be filled later flush_list(); #endif bool loaded = CPersistent::LoadAll(); if( loaded ) { if( SCHEMA_0 == gPersistentShema ) { MigrateCvsrootList(); } return; } // backward compatibility #ifdef WIN32 UINT value; CString cstr = AfxGetApp()->GetProfileString(PROFILE_NAME, "CVSROOT"); if(!cstr.IsEmpty()) *this = (const char *)cstr; if((value = AfxGetApp()->GetProfileInt(PROFILE_NAME, "CheckoutRO", -1)) != -1) SetCheckoutRO(value ? 1 : 0); if((value = AfxGetApp()->GetProfileInt(PROFILE_NAME, "Z9Option", -1)) != -1) SetZ9Option(value ? 1 : 0); if((value = AfxGetApp()->GetProfileInt(PROFILE_NAME, "QuietOption", -1)) != -1) SetQuietOption(value ? 1 : 0); if((value = AfxGetApp()->GetProfileInt(PROFILE_NAME, "PruneOption", -1)) != -1) SetPruneOption(value ? 1 : 0); if((value = AfxGetApp()->GetProfileInt(PROFILE_NAME, "Authentication", -1)) != -1) gAuthen.setkind((AuthenKind)value); if((value = AfxGetApp()->GetProfileInt(PROFILE_NAME, "AddControl", -1)) != -1) SetAddControl(value ? 1 : 0); char tmp[20]; for(int i = 0; i < NUM_CVSROOT; i++) { sprintf(tmp, "CVSROOTLIST%d", i); cstr = AfxGetApp()->GetProfileString(PROFILE_NAME, tmp); if(!cstr.IsEmpty()) gOldCvsroots.Insert((const char *)cstr); } #endif /* WIN32 */ #if defined(macintosh) && !TARGET_API_MAC_CARBON FSSpec theFolder; short FRef; Handle hdl; OSErr err; Str255 thePath; err = MacGetPrefsFolder(theFolder, thePath); if(err != noErr) return; err = HSetVol(NULL, theFolder.vRefNum, theFolder.parID); FRef = OpenResFile(PCVS); if(FRef < 0) return; hdl = GetResource('CVS ', 128); if(hdl != NULL) { Str255 str; HLock(hdl); BlockMove(*hdl, str, (*hdl)[0] + 1); str[str[0] + 1] = '\0'; *this = (const char *)str + 1; HUnlock(hdl); } hdl = GetResource('CHRO', 128); if(hdl != NULL) { SetCheckoutRO(**hdl); } hdl = GetResource('Z9OP', 128); if(hdl != NULL) { SetZ9Option(**hdl); } hdl = GetResource('QUIE', 128); if(hdl != NULL) { SetQuietOption(**hdl); } hdl = GetResource('POPT', 128); if(hdl != NULL) { SetPruneOption(**hdl); } hdl = GetResource('AUTH', 128); if(hdl != NULL) { gAuthen.setkind((AuthenKind)**hdl); } hdl = GetResource('ISOC', 128); if(hdl != NULL) { SetIsoConvert((ISO8559)**hdl); } hdl = GetResource('ICTO', 128); if(hdl != NULL) { SetICTextOption(**hdl); } hdl = GetResource('ACTL', 128); if(hdl != NULL) { SetAddControl(**hdl); } for(int i = 0; i < NUM_CVSROOT; i++) { hdl = GetResource('CROL', 128 + i); if(hdl != NULL) { HLock(hdl); get_cvsroot_list(i) = (const char *)*hdl; HUnlock(hdl); } } CloseResFile (FRef); #endif /* macintosh && !TARGET_API_MAC_CARBON */ } /// Helper method to migrate into a single CMString for cvsroot history void MigrateCvsrootList() { for(int nIndex = 0; nIndex <= NUM_CVSROOT; nIndex++) { CStr cvsroot; #ifdef WIN32 char tmp[20]; sprintf(tmp, "P_Cvsroot%d", nIndex); BYTE* ppData; UINT pBytes = 0; if( !AfxGetApp()->GetProfileBinary(PROFILE_NAME, tmp, &ppData, &pBytes) ) { continue; } cvsroot = (char*)ppData; delete ppData; #endif /* WIN32 */ #if qUnix #endif // qUnix #if qMacCvsPP #endif // qMacCvsPP if( !cvsroot.empty() ) { gOldCvsroots.Insert(cvsroot); } } } #ifdef WIN32 kWinVersion CvsPrefs::WhichVersion() { DWORD dwVersion = GetVersion(); // Get major and minor version numbers of Windows DWORD dwWindowsMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion))); DWORD dwWindowsMinorVersion = (DWORD)(HIBYTE(LOWORD(dwVersion))); DWORD dwBuild; // Get build numbers for Windows NT or Win32s if (dwVersion < 0x80000000) // Windows NT { dwBuild = (DWORD)(HIWORD(dwVersion)); return dwWindowsMajorVersion == 3 ? kWinNT35 : kWinNT4; } else if (dwWindowsMajorVersion < 4) // Win16s { dwBuild = (DWORD)(HIWORD(dwVersion)); return kWin16; } // Windows 95 -- No build numbers provided dwBuild = 0; return kWin32; } #endif /* WIN32 */ // // TODO: If we sometimes implement multi-threaded CVS/TCL macro // execution then we have to implement thread synchronization in // IsXXXRunning and SetXXXRunning methods. // // NOTE! IsCvsRunning and SetCvsRunning methods are not yet // used in Mac/Unix/WinCVS. Each of these version have had // their own app.gCvsRunning variable. I haven't cleaned up // the code and changed them to use this "one and only" // CvsRunning methods. // bool CvsPrefs::IsCvsRunning(void) const { return(fCvsRunningCounter > 0); } int CvsPrefs::SetCvsRunning(bool launched) { if(launched) fCvsRunningCounter++; else if(fCvsRunningCounter > 0) fCvsRunningCounter--; return fCvsRunningCounter; } bool CvsPrefs::IsTclFileRunning(void) const { return(fTclFileRunningCounter > 0); } int CvsPrefs::SetTclFileRunning(bool launched) { if(launched) fTclFileRunningCounter++; else if(fTclFileRunningCounter > 0) fTclFileRunningCounter--; return fTclFileRunningCounter; } bool LaunchDiff(const char *f1, const char *f2) { #ifdef qMacCvsPP const OSType kBBEditDiffCreatorCode = FOUR_CHAR_CODE('BBds'); const OSType kResourcererCreatorCode = FOUR_CHAR_CODE('Doug'); // Resourcerer's Compare suite const DescType kAECompareClass = 'Comp'; const DescType kAECompareEvent = 'Comp'; const DescType keyNewer = 'kNew'; const DescType keyOlder = 'kOld'; const DescType keyShowDiff = 'kShD'; const DescType keyReturnDiff = 'kRtD'; OSErr e = noErr; try { // Convert to file specs Boolean inShowDiffs = true; #if TARGET_RT_MAC_CFM FSSpec spec1 = GUSIFileSpec (f1); FSSpec spec2 = GUSIFileSpec (f2); #else FSRef ref1 = GUSIFileSpec (f1); FSRef ref2 = GUSIFileSpec (f2); FSSpec spec1; FSSpec spec2; ThrowIfOSErr_(FSGetCatalogInfo(&ref1, kFSCatInfoNone, NULL, NULL, &spec1, NULL)); ThrowIfOSErr_(FSGetCatalogInfo(&ref2, kFSCatInfoNone, NULL, NULL, &spec2, NULL)); #endif // Find the file type FInfo info; e = ::FSpGetFInfo (&spec2, &info); ThrowIfOSErr_(e); // Decide on the application OSType applCreator = FOUR_CHAR_CODE('????'); switch (info.fdType) { case 'TEXT': applCreator = kBBEditDiffCreatorCode; break; default: applCreator = kResourcererCreatorCode; break; } // switch // Try to launch it LaunchFlags launchFlags = launchContinue + launchNoFileFlags; OSType applType = FOUR_CHAR_CODE('APPL'); FSSpec applSpec; ProcessSerialNumber applPSN; if (!UProcess::Launch (applCreator, applType, launchFlags, &applSpec, &applPSN)) Throw_(fnfErr); // Now, diff the files. We use the Resourcerer suite and a BBEdit glue applet. // Create the parameters StAEDescriptor newerDesc (spec1); StAEDescriptor olderDesc (spec2); StAEDescriptor showDesc (inShowDiffs); // Create the event StAEDescriptor addressDesc (typeProcessSerialNumber, &applPSN, sizeof (applPSN)); StAEDescriptor diffEvent; e = ::AECreateAppleEvent (kAECompareClass, kAECompareEvent, addressDesc, kAutoGenerateReturnID, kAnyTransactionID, diffEvent); ThrowIfOSErr_(e); // Add the parameters e = ::AEPutParamDesc (diffEvent, keyNewer, newerDesc); ThrowIfOSErr_(e); e = ::AEPutParamDesc (diffEvent, keyOlder, olderDesc); ThrowIfOSErr_(e); e = ::AEPutParamDesc (diffEvent, keyShowDiff, showDesc); ThrowIfOSErr_(e); // Send the event UAppleEventsMgr::SendAppleEvent (diffEvent); return true; } // try catch (LException ex) { } // catch #endif if(gCvsPrefs.ExtDiff() == 0L) { cvs_err("The external diff program is not defined,\n"); cvs_err("you need to set it in the preferences dialog.\n"); return false; } #ifdef WIN32 CString args; CStr program, file1, file2; if(strchr(gCvsPrefs.ExtDiff(), ' ') != 0L) { program << '\"'; program << gCvsPrefs.ExtDiff(); program << '\"'; } else program = gCvsPrefs.ExtDiff(); if(strchr(f1, ' ') != 0L) { file1 << '\"'; file1 << f1; file1 << '\"'; } else file1 = f1; if(strchr(f2, ' ') != 0L) { file2 << '\"'; file2 << f2; file2 << '\"'; } else file2 = f2; args += file1; args += " "; args += file2; HINSTANCE hInst = ShellExecute(*AfxGetMainWnd(), NULL, gCvsPrefs.ExtDiff(), args, NULL, SW_SHOWDEFAULT); if((UINT)hInst < 32) { // ExtDiff app was not found. Let's try to execute it from // the application path. However, this is done only when ExtDiff // value doesn't contain absolute path ("c:\subdir\" or "\subdir\"). if(strchr(gCvsPrefs.ExtDiff(), ':') == 0L && (gCvsPrefs.ExtDiff()[0]) != '\\') { CStr appPath; ((CWincvsApp *)AfxGetApp())->GetAppPath(appPath); if(!appPath.endsWith(kPathDelimiter)) appPath << kPathDelimiter; appPath << gCvsPrefs.ExtDiff(); hInst = ShellExecute(*AfxGetMainWnd(), NULL, appPath, args, NULL, SW_SHOWDEFAULT); } } if((UINT)hInst < 32) { LPVOID lpMsgBuf; FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language (LPTSTR) &lpMsgBuf, 0, NULL ); cvs_err("Unable to open '%s' (%s), using console instead\n", (char *)gCvsPrefs.ExtDiff(), (LPCSTR)lpMsgBuf); // Free the buffer. LocalFree( lpMsgBuf ); return false; } return true; #elif qUnix CvsArgs args(false); args.add(gCvsPrefs.ExtDiff()); args.add(f1); args.add(f2); UCvsApp::gApp->Execute(args.Argc(), args.Argv()); return true; #else return false; #endif } bool LaunchViewer(const char *fullpath, bool useDefault /*= false*/) { #ifdef WIN32 bool done = false; if( !gCvsPrefs.UseViewerAlways() ) { CStr uppath, folder; SplitPath(fullpath, uppath, folder); // MSS fix bug with files not being found by FindExecutable // (see Article ID: Q140724 for the problem desc of FindExecutable) if( !useDefault ) { HINSTANCE hInst = ShellExecute(*AfxGetMainWnd(), "open", fullpath, 0L, folder, SW_SHOWDEFAULT); if( (long)hInst < 32 ) { cvs_err("Unable to open '%s' (error %d), using default viewer instead\n", (char *)fullpath, GetLastError()); } else done = true; } } if(!done) { if(gCvsPrefs.Viewer() == 0L) { cvs_err("You need to define a default viewer for this file in the preferences\n"); return false; } const char * argv[3] = {0L, 0L, 0L}; CStr program, file; if(strchr(gCvsPrefs.Viewer(), ' ') != 0L) { program << '\"'; program << gCvsPrefs.Viewer(); program << '\"'; } else program = gCvsPrefs.Viewer(); if(strchr(fullpath, ' ') != 0L) { file << '\"'; file << fullpath; file << '\"'; } else file = fullpath; argv[0] = program; argv[1] = file; int process = _spawnvp(_P_NOWAIT, gCvsPrefs.Viewer(), argv); } return true; #endif /* WIN32 */ #ifdef qMacCvsPP return true; #endif /* qMacCvsPP */ #if qUnix return true; #endif // qUnix } bool LaunchEditor(const char* tmpFile, void* par /*= 0L*/) { CStr program, file; if(strchr(gCvsPrefs.Viewer(), ' ') != 0L) { program << '\"'; program << gCvsPrefs.Viewer(); program << '\"'; } else program = gCvsPrefs.Viewer(); if(strchr(tmpFile, ' ') != 0L) { file << '\"'; file << tmpFile; file << '\"'; } else file = tmpFile; CStr command; command << program; command << " "; command << file; #ifdef WIN32 STARTUPINFO sStartupInfo; PROCESS_INFORMATION sProcessInformation; // Execute the command with a call to the CreateProcess API call. memset( &sStartupInfo, 0, sizeof(sStartupInfo) ); sStartupInfo.cb = sizeof( sStartupInfo ); sStartupInfo.dwFlags = STARTF_USESHOWWINDOW; sStartupInfo.wShowWindow = SW_SHOWNORMAL; if( !CreateProcess( NULL, (char*)command, NULL, NULL, FALSE, 0, NULL, NULL, &sStartupInfo, &sProcessInformation) ) { sProcessInformation.hProcess = INVALID_HANDLE_VALUE; sProcessInformation.hThread = INVALID_HANDLE_VALUE; } *((PROCESS_INFORMATION*)par) = sProcessInformation; return sProcessInformation.hProcess != INVALID_HANDLE_VALUE; #endif /* WIN32 */ #ifdef qMacCvsPP return true; #endif /* qMacCvsPP */ #if qUnix return true; #endif // qUnix } bool CvsPrefs::UseAltCvs(void) const {return gUseAltCvs;} void CvsPrefs::SetUseAltCvs(bool useit) {gUseAltCvs = useit;} void CvsPrefs::SetWhichCvs(const char *cvsPath) { UStr appPath; #ifdef WIN32 HINSTANCE hInst = ::AfxGetInstanceHandle(); char apath[512]; DWORD len; if(hInst != 0L && (len = ::GetModuleFileName(hInst, apath, 512)) > 0) { CString tmp(apath); tmp.MakeLower(); appPath = tmp; } #elif qUnix appPath << EXECLIB << "/" << "cvs"; #elif TARGET_RT_MAC_MACHO appPath = CMacCvsApp::gApp->GetAppPath(); #endif if(!appPath.empty()) { UStr value; gWhichCvs.Concatenate(value, appPath, cvsPath); gWhichCvs.Insert(value); } else { gWhichCvs.Insert( cvsPath ); } } const char *CvsPrefs::WhichCvs(UStr & path, bool userOnly) const { path = ""; UStr appPath = ""; #ifdef WIN32 HINSTANCE hInst = ::AfxGetInstanceHandle(); char apath[512]; DWORD len; if(hInst != 0L && (len = ::GetModuleFileName(hInst, apath, 512)) > 0) { CString tmp(apath); tmp.MakeLower(); appPath = tmp; } #elif qUnix appPath << EXECLIB << "/" << "cvs"; #elif TARGET_RT_MAC_MACHO appPath = CMacCvsApp::gApp->GetAppPath(); #endif // search if beside the default cvs, the user defined one to use // with this application only. UStr candidate; if(!appPath.empty()) { UStr value; gWhichCvs.Concatenate(value, appPath, ""); TMString::list_t::const_iterator i = gWhichCvs.Find(value); if(i != gWhichCvs.end()) { UStr key; gWhichCvs.Split(*i, key, candidate); } } // verify this cvs exe is still there struct stat sb; if(!candidate.empty() && stat(candidate, &sb) != -1 && S_ISREG(sb.st_mode)) { path = candidate; return path.c_str(); } // fallback to the default one. if(userOnly) return 0L; #ifdef WIN32 CWincvsApp* app = (CWincvsApp *)AfxGetApp(); app->GetAppPath(path); if(!path.endsWith(kPathDelimiter)) path << kPathDelimiter; path << (gCvsPrefs.WhichVersion() == kWin32 ? "cvs95.exe" : "cvs.exe"); #elif qUnix if( path.empty() ) path = EXECLIB; if(!path.endsWith(kPathDelimiter)) path << kPathDelimiter; path << "cvs"; #elif TARGET_RT_MAC_MACHO path = CMacCvsApp::gApp->GetAppPath(); if(!path.endsWith(kPathDelimiter)) path << kPathDelimiter; # if qCvsDebug path << "cvsguidbg"; # else path << "cvsgui"; # endif #endif return path.c_str(); }