Index: trunk/ChameleonPrefPane/Sources/process.cpp =================================================================== --- trunk/ChameleonPrefPane/Sources/process.cpp (revision 46) +++ trunk/ChameleonPrefPane/Sources/process.cpp (revision 47) @@ -1,200 +0,0 @@ -/* - * shell_process.cpp - * - * Created by Rekursor on 1/17/2010. - * - */ - -#include "process.h" -#include -#include -#include - - -//---------------------------------------------------------------- -// portable open process: -FILE * ShellProcess::open(const char *cmd, const char *mode) { - _fpt=::popen(cmd,mode); - return _fpt; -} - -//---------------------------------------------------------------- -int ShellProcess::close() { - int ret = ::pclose(_fpt); - _fpt=NULL; - return ret; -} - -//---------------------------------------------------------------- -void PartitionInfo::removeSpaces(std::string &str) -{ - if (!str.size()) return; - int posl=0,posr=0; - for (posl=0; posl0 && str[posr]==' '; posr--); - str = (posl>posr) ? "" : str.substr(posl, posr-posl+1); -} -//---------------------------------------------------------------- -/** - * return the image index corresponding to a fs: - */ -int PartitionInfo::imageIndexFromFs() const -{ - if (_fsType.find("Apple")!=std::string::npos || - _fsType.find("HFS")!=std::string::npos) - return 0; // Windows - else if (_fsType.find("Windows")!=std::string::npos || - _fsType.find("Microsoft")!=std::string::npos || - _fsType.find("NTFS")!=std::string::npos || - _fsType.find("FAT")!=std::string::npos) - return 1; // Windows - else if (_fsType.find("Linux")!=std::string::npos) - return 2; // Unknown - return 10; //Unknown - -} -//---------------------------------------------------------------- -bool PartitionInfo::fromPartitionHdString(const char * inHdStr) -{ - if (!inHdStr || !(*inHdStr) || - strlen(inHdStr)<7 || !strstr(inHdStr,"hd(")) return false; - - // enhance me here: should not assume that we have less than 10 partitions per disk/ disks - _disk = inHdStr[3]-'0'; - _part = inHdStr[5]-'0'; - return true; -} -//---------------------------------------------------------------- -const char * PartitionExtractor::checkForRename(const char * label, const char *szHd) -{ - const int MAX_ALIAS_SIZE=31; - static char szAlias[MAX_ALIAS_SIZE+1]; - char *q=szAlias; - const char* szAliases = _renamedParts.c_str(); - - if (!szHd || !*szHd || !szAliases || !*szAliases) return label; // no renaming wanted - - const char * p = strstr(szAliases, szHd); - if(!p || !(*p)) return label; // this volume must not be renamed, or option is malformed - - p+= strlen(szHd); // skip the "hd(n,m) " field - // multiple aliases can be found separated by a semi-column - while(*p && *p != ';' && q<(szAlias+MAX_ALIAS_SIZE)) *q++=*p++; - *q='\0'; - - return szAlias; - -} -//---------------------------------------------------------------- -const std::vector& -PartitionExtractor::extractPartitions(const char* szHide, const char* szRenamed) -{ - const char * const diskTag = "/dev/disk"; - const char * const nameTag = "NAME"; - const char * const sizeTag = "SIZE"; - - PartitionInfo partInfo; - - char line[1024]=""; - char label[32]="", fsType[32]="" ; - size_t len=0; - int disk =0, part=0; - int label_pos=0, size_pos=0; - char * p=0,*q=0; - int skipwhite=0; - - _partList.clear(); - if (szHide) hidePartitions(szHide); - if (szRenamed) renamedPartitions(szRenamed); - this->open("diskutil list"); - - while(get_line(line, sizeof(line)-1)) - { - // printf("%s\n",line); - len = strlen(line); - for(skipwhite=0; line[skipwhite]==' ';skipwhite++); - - const char * sdisk = strstr(line, diskTag); - const char * sName = strstr(line, nameTag); - const char * sSize = strstr(line, sizeTag); - - if (sdisk) - { - // extract disk number - disk= sdisk[strlen(diskTag)]-'0'; - if (disk>=0 && disk 0 && - partInfo.clabel()[len-1] !='*' && - partInfo.fsType()!="EFI" && - partInfo.fsType()!="Apple_partition_scheme" && - partInfo.fsType()!="Apple_partition_map" && - partInfo.fsType()!="Apple_Free" - ) - { - std::string DiskLabel(label), UnixPath, WinPath; - DiskLabel.erase( DiskLabel.find_last_not_of(" ") + 1); - bool found=false; - - // early bail out if we found what we need: - if (fileExists((UnixPath = "/Volumes/" + DiskLabel + "/usr/bin/man"))) - found=true; - else if ((strstr(label,"System Reserved") ) || // don't filter system reserved windows 7 boot parts - fileExists((WinPath="/Volumes/" + DiskLabel + "/Windows/system.ini"))) - found=true; - else if (strstr(fsType,"Linux") && !strstr(fsType, "Linux_Swap")) - found=true; // Added Linux case - if (found) - { //check if one of them exists - if (partInfo.label().size()==0) partInfo.label("Untitled"); - if(_hiddenParts.length()==0 || - _hiddenParts.find(partInfo.toHdStr()) == std::string::npos) - _partList.push_back(partInfo); - } - } - } - } - close(); - - sort(_partList.begin(), _partList.end(), isDiskIndexInf); - return _partList; -} - -/** - * Get the index in the internal partlist of the hd(n,m) partition specified by the input string - * return -1 if no match, >=0 if a match happens - */ -int PartitionExtractor::getIndexFromHdStringSpec(const char* inHDStr) -{ - PartitionInfo info; - - if (info.fromPartitionHdString(inHDStr)) // try decode the partition disk and part infos - { - for (int i=0; i<_partList.size(); i++) - { - if (_partList[i].disk() == info.disk() && _partList[i].partition() == info.partition()) - return i; - } - } - - return -1; -} Index: trunk/ChameleonPrefPane/Sources/property_list.cpp =================================================================== --- trunk/ChameleonPrefPane/Sources/property_list.cpp (revision 46) +++ trunk/ChameleonPrefPane/Sources/property_list.cpp (revision 47) @@ -1,343 +0,0 @@ -/* - * property_list.cpp - * - * Created by Rekursor on 1/17/10. - * - */ - -#include "property_list.h" -#include -#include - -/****************************************************************************/ -/** - * Simple parsing and splitting args function, does handle env. vars - */ -static void parseArgs(const char * args, const char* argv[], int argvlen) -{ - // Create a list of args fron the space delimited args parameters - int n=0; - if (args && *args) - { - bool skipSpaces = true; - bool prevCharwasDelim =false; - char * buf = strdup(args); - char lastPriorityDelim=' '; - - printf("Parsing <%s>\n", args); - - int k=0; - for (int i=0; i< strlen(args); i++) - { - switch (args[i]) - { - case ' ': case '\t': - if(!skipSpaces) { - buf[k++]=args[i]; - } - else { - prevCharwasDelim = true; // // keep a track of delim to further split tokens - } - break; - case '\0': - case '\'': - case '"': - if (!skipSpaces &&lastPriorityDelim!=args[i]) - { // consider the imbricated delim as a simple char - buf[k++]=args[i]; - break; - } - - if (!skipSpaces) // end of priority substr - { - skipSpaces = true; - lastPriorityDelim=' '; - buf[k]='\0'; - argv[n++]=strdup(buf); // copy the priority substr - k=0; // reset the buf index for next token - buf[0]='\0'; - } - else - { // start of priority substr - skipSpaces=false; - lastPriorityDelim=args[i]; - if(k>0) // previous string to store first - { - buf[k++]='\0'; // finish the substr - argv[n++]=strdup(buf); // copy the substr - k=0; // rest the index for next token - buf[0]='\0'; - } - //if (args[i] !='\0') buf[k++] = args[i]; // start the new priority substr - } - break; - default: // non delimiters chars - if(skipSpaces && prevCharwasDelim) - { - if(k>0) // a previous substr was before the space - { // store previous token - buf[k++]='\0'; // finish the substr - argv[n++]=strdup(buf); // copy the substr - k=0; // rest the index for next token - buf[0]='\0'; - } - } - prevCharwasDelim = false; - buf[k++]=args[i]; - break; - } - } - - if(*buf) - { - buf[k]='\0'; - argv[n++]=strdup(buf); // copy the last buffer - } - free((void*) buf); - } - argv[n]=NULL; -} - -/****************************************************************************/ - bool executePrivilegedCmd(AuthorizationRef auth, - const char* pathToTool, - const char* args, - AuthorizationFlags flags) -{ - const char * argv[16]; - - parseArgs(args, argv, sizeof(argv)/sizeof(const char*)); - - // Execute Cmd - OSStatus status = AuthorizationExecuteWithPrivileges(auth, pathToTool,flags, (char**)argv, NULL); - - - // Cleanup mem - for (int i=0; argv[i]; i++) free ((void*) argv[i]); - - return status ? false : true; -} - - -/****************************************************************************/ -/** - * Write a property list from a file - */ -bool WritePropertyListToFile( CFPropertyListRef propertyList, CFURLRef fileURL ) -{ - CFDataRef xmlData; - Boolean status; - SInt32 errorCode; - - // Convert the property list into XML data. - xmlData = CFPropertyListCreateXMLData( kCFAllocatorDefault, propertyList ); - - // Write the XML data to the file. - status = CFURLWriteDataAndPropertiesToResource ( - fileURL, // URL to use - xmlData, // data to write - NULL, - &errorCode); - CFRelease(xmlData); - - return status ? true: false; -} - -/****************************************************************************/ -/** - * Read a property list from a file - */ -static CFPropertyListRef CreatePropertyListFromFile( CFURLRef fileURL, CFStringRef * errorString ) { - CFPropertyListRef propertyList; - CFDataRef resourceData; - Boolean status; - SInt32 errorCode; - - // Read the XML file. - status = CFURLCreateDataAndPropertiesFromResource( - kCFAllocatorDefault, - fileURL, - &resourceData, // place to put file data - NULL, - NULL, - &errorCode); - if (!status) return NULL; - - // Reconstitute the dictionary using the XML data. - propertyList = CFPropertyListCreateFromXMLData( kCFAllocatorDefault, - resourceData, - kCFPropertyListMutableContainersAndLeaves, - errorString); - - - CFRelease( resourceData ); - return propertyList; -} - -/****************************************************************************/ -static void show(CFStringRef formatString, ...) { - CFStringRef resultString; - CFDataRef data; - va_list argList; - - va_start(argList, formatString); - resultString = CFStringCreateWithFormatAndArguments(NULL, NULL, formatString, argList); - va_end(argList); - - data = CFStringCreateExternalRepresentation(NULL, resultString, CFStringGetSystemEncoding(), '?'); - - if (data != NULL) { - printf ("%.*s\n\n", (int)CFDataGetLength(data), CFDataGetBytePtr(data)); - CFRelease(data); - } - - CFRelease(resultString); -} -/****************************************************************************/ -/* - * Always return a valid static const string, if the CFSTR is not valid, then we return "" - */ -static const char * CfsToCs(CFStringRef inRef) -{ - static char buffer[512]=""; - if(CFStringGetFileSystemRepresentation (inRef, buffer, sizeof(buffer))) - return buffer; - return ""; -} - -/****************************************************************************/ -/** - * Creates a PropertyList Incstance - */ -PropertyList::~PropertyList() -{ - if (_CFURLRef) CFRelease(_CFURLRef); - if (_proplistRef) CFRelease(_proplistRef); - -} -bool PropertyList::chmodFile(const char * path, const char * chmodMask, - AuthorizationRef auth, AuthorizationFlags flags) -{ - if (!path || !*path) return false; - - if (auth) - { // give write temporary write rights to the file - std::string args = chmodMask; - args += ' '; - args += path; - if(!executePrivilegedCmd(auth, "/bin/chmod", args.c_str(), flags)) - return false; - } - return true; - -} - -/****************************************************************************/ -/** - * Open a properlist from a path name - */ -bool PropertyList::open(const char * path, CFStringRef * errorString, AuthorizationRef auth, AuthorizationFlags flags) -{ - bool ret = false; - - if (!path || !*path) return false; - struct stat st; - if(stat(path,&st) != 0) return false; // file does not exist; - - // give write temporary write rights to the file - if (!chmodFile(path,"0777", auth, flags)) return false; - - _propFilePath = path; - - CFStringRef cfPath = CFStringCreateWithCString (kCFAllocatorDefault, path, kCFStringEncodingUTF8); - CFURLRef inURL = CFURLCreateWithFileSystemPath( kCFAllocatorDefault, - cfPath, - kCFURLPOSIXPathStyle, // interpret as POSIX path - false ); // is it a directory? - CFRelease(cfPath); - if (_CFURLRef) CFRelease(_CFURLRef); - _CFURLRef = inURL; - - if (_CFURLRef) - { - _proplistRef = CreatePropertyListFromFile(inURL, errorString); - - if (_proplistRef) - ret= true; - } - // restore rights - ret= chmodFile(path,"0644", auth, flags); - - return ret; -} - -/****************************************************************************/ -/** - * Save the current property list - */ -bool PropertyList::save(AuthorizationRef auth, AuthorizationFlags flags) -{ - bool ret=false; - if (auth) - { // give write temporary write rights to the file - std::string args = " 0777 "+ _propFilePath; - if(!executePrivilegedCmd(auth, "/bin/chmod", args.c_str(), flags)) - return false; - } - if (_proplistRef && _CFURLRef) - ret= WritePropertyListToFile(_proplistRef,_CFURLRef); - if (auth) - { // give write temporary write rights to the file - std::string args = " 0644 "+ _propFilePath; - if(!executePrivilegedCmd(auth, "/bin/chmod", args.c_str(), flags)) - return false; - } - return ret; -} - -/****************************************************************************/ -/** - * Extract a sring value from a property list key, - * value returned is not owned by caller, copy it necessary. - */ -const char * PropertyList::getStringForKey(const char *key) -{ - if (!_proplistRef) return 0; - CFDictionaryRef myDict = - (CFGetTypeID(_proplistRef) == CFDictionaryGetTypeID()) ? (CFDictionaryRef) _proplistRef : NULL; - CFStringRef cfKey = CFStringCreateWithCString (kCFAllocatorDefault, key, kCFStringEncodingUTF8); - CFStringRef myString; - - if (myDict && CFDictionaryGetValueIfPresent(myDict, cfKey, (const void **) &myString)) - { - // show(CFSTR("Key '%@' found , value = <%@>\n"), cfKey, !myString ? CFSTR("") : myString); - CFRelease(cfKey); - return CfsToCs(myString); - } - - if(cfKey) CFRelease(cfKey); - return NULL; -} -/****************************************************************************/ -/** - * replace a sring value from a property list key, - * value returned is not owned by caller, copy it necessary. - */ -bool PropertyList::setStringForKey(const char *key, const char * value) -{ - if (!_proplistRef) return false; - bool ret = false; - CFMutableDictionaryRef myDict = - (CFGetTypeID(_proplistRef) == CFDictionaryGetTypeID()) ? (CFMutableDictionaryRef) _proplistRef : NULL; - CFStringRef cfKey = CFStringCreateWithCString (kCFAllocatorDefault, key, kCFStringEncodingUTF8); - CFStringRef myString = CFStringCreateWithCString (kCFAllocatorDefault, value, kCFStringEncodingUTF8); - - if (myDict) { - CFDictionaryReplaceValue(myDict, cfKey, myString); - ret=true; - } - if(cfKey) CFRelease(cfKey); - if(myString) CFRelease(myString); - return ret; -} - Index: trunk/ChameleonPrefPane/Sources/process.h =================================================================== --- trunk/ChameleonPrefPane/Sources/process.h (revision 46) +++ trunk/ChameleonPrefPane/Sources/process.h (revision 47) @@ -1,143 +0,0 @@ -/* - * shell_process.h - * - * Created by Rekursor on 1/17/2010. - * - */ -#include -#include -#include -#include -#include -#include -#include - -//---------------------------------------------------------------- -const int MAX_HD = 10; - -//---------------------------------------------------------------- - -/** - * Check whether file exists: - */ -inline bool fileExists(const char * str) -{ - struct stat stFileInfo; - if((stat(str,&stFileInfo)) == 0) return true; - else return false; -} - -inline bool fileExists(std::string str) {return fileExists(str.c_str());} - -//---------------------------------------------------------------- -class ShellProcess -{ -public: - // construction / destruction - ShellProcess() {_fpt= NULL;} - ~ShellProcess() {if (_fpt) close();} - - FILE * open (const char *cmd, const char *mode="r"); - int close(); - FILE * desc() const { return _fpt;} // non null if file is open - char * get_line(char * line, size_t s) const {return _fpt ? fgets(line, s, _fpt) : NULL;} - -protected: - FILE * _fpt; -}; - -//---------------------------------------------------------------- -class PartitionInfo -{ -public: - PartitionInfo() : _disk(0), _part(0) {} - PartitionInfo(int disk, int part) { set(disk, part);} - - void disk(int disk) { _disk=disk;} - int disk() const { return _disk;} - - void partition(int part) { _part=part;} - int partition () const { return _part;} - - const char * clabel() const { return _label.c_str();} - const std::string& label() const { return _label; } - void label(const char * l) { - if (l) _label = l; - removeSpaces(_label); - } - - const char * cfsType() const { return _fsType.c_str();} - const std::string& fsType() const { return _fsType;} - void fsType(const char * fs) { - if (fs) _fsType = fs; - removeSpaces(_fsType); - } - - void set(int disk, int part) { _disk =disk; _part = part;} - bool fromPartitionHdString(const char * inHdStr); - std::string toHdStr() const - { - std::string buf = "hd(n,m)"; - buf[3]= '0'+disk(); - buf[5]='0'+partition(); - return buf; - } - int imageIndexFromFs() const; -protected: - void removeSpaces(std::string & s); - -private: - int _disk, _part; - std::string _fsType, _label; -}; - -static inline bool isDiskIndexInf(PartitionInfo i, PartitionInfo j) -{ - return ((i.disk()*100+i.partition()) < (j.disk()*100 + j.partition()) ) ; -} - -//---------------------------------------------------------------- -class PartitionExtractor : public ShellProcess -{ -public: - PartitionExtractor() : ShellProcess() { init(); } - - const std::vector& extractPartitions( - const char* szHide=NULL, - const char* szRenamed=NULL); - int getListCount() const {return (int) _partList.size();} - - const std::vector& partList() const {return _partList;} - std::vector& editPartList() {return _partList;} - - // get the index in the internal partlist of the hd(n,m) partition specified by the input string - // return -1 if no match, >=0 if a match happens - int getIndexFromHdStringSpec(const char*); - - void hidePartitions(const char* szParts){ _hiddenParts = (szParts ? szParts : "");} - void renamedPartitions(const char* szParts){ _renamedParts = (szParts ? szParts : "");} - void sortPartList() { sort(_partList.begin(), _partList.end(), isDiskIndexInf); } - - const char * checkForRename(const char * label, const char* szHd); - - void swapHD(int src, int dst) - { - if(src < 0 || src > MAX_HD-1 || dst < 0 || dst > MAX_HD-1) return; - _hdRedirTable[src]=dst; - _hdRedirTable[dst]=src; - } - - void resetSwapping() { init();} - -protected: - void init() { - for (int i=0; i _partList; - int _hdRedirTable[MAX_HD]; - std::string _hiddenParts; - std::string _renamedParts; - -}; Index: trunk/ChameleonPrefPane/Sources/property_list.h =================================================================== --- trunk/ChameleonPrefPane/Sources/property_list.h (revision 46) +++ trunk/ChameleonPrefPane/Sources/property_list.h (revision 47) @@ -1,53 +0,0 @@ -/* - * property_list.h - * - * Created by Rekursor on 1/17/10. - * - */ - -#include -#include -#include -#include - -/****************************************************************/ - -/** - * priviledged command run for cmds like property chmods and restard command - */ -bool executePrivilegedCmd(AuthorizationRef auth, - const char* pathToTool, - const char* args=NULL, - AuthorizationFlags flags=kAuthorizationFlagDefaults); - -/****************************************************************/ - -/** - * Simple PropertyList Abstraction - */ -class PropertyList -{ - -public: - PropertyList() : _proplistRef(0), _CFURLRef(0) { } - virtual ~PropertyList(); - - bool open(const char *propListPath, CFStringRef* errString, - AuthorizationRef auth=NULL, AuthorizationFlags flags=kAuthorizationFlagDefaults); - bool save(AuthorizationRef auth=NULL, AuthorizationFlags flags=kAuthorizationFlagDefaults); - bool isValid() const { return _proplistRef!=NULL;} - - const char * getStringForKey(const char *key); - bool setStringForKey(const char* key, const char* value); - const char * bootConfigPath() const { - return _propFilePath.c_str(); - } - - static bool chmodFile(const char * path, const char * chmodMask, - AuthorizationRef auth, AuthorizationFlags flags=kAuthorizationFlagDefaults); -private: - CFPropertyListRef _proplistRef; - CFURLRef _CFURLRef; - std::string _propFilePath; // keep a track of the proplist filename -}; - Index: trunk/ChameleonPrefPane/Sources/AdvancedSetupController.h =================================================================== --- trunk/ChameleonPrefPane/Sources/AdvancedSetupController.h (revision 46) +++ trunk/ChameleonPrefPane/Sources/AdvancedSetupController.h (revision 47) @@ -45,6 +45,9 @@ IBOutlet NSTextField* mWakeImageText; } +- (IBAction) onCheckButtonChange: (NSButton*) sender; +- (IBAction) onTextFiedChange: (id) sender; + + (AdvancedSetupController *)instance; @end Index: trunk/ChameleonPrefPane/Sources/ChameleonPrefPane.mm =================================================================== --- trunk/ChameleonPrefPane/Sources/ChameleonPrefPane.mm (revision 46) +++ trunk/ChameleonPrefPane/Sources/ChameleonPrefPane.mm (revision 47) @@ -10,8 +10,8 @@ #import "PeripheralsController.h" #import "AdvancedSetupController.h" -#include -#include +#include "ShellProcess.h" +#import "BootPropertyList.h" #include //-------------------------------------------------------------------------- @@ -29,27 +29,15 @@ }; static const char* const szPropFileName = "com.apple.Boot.plist"; -static const char* const kDefaultPartition = "Default Partition"; -static const char* const kHidePartition = "Hide Partition"; -static const char* const kRenamePartition = "Rename Partition"; -static const NSString* const kPreferencesFilePath = @"/Library/Preferences/com.chameleon.prefPane.plist"; -static const NSString* const keyPreferencesFileVersion = @"version"; // for future back compatibility static const int CurrentPreferencesFileVersion = 0x01; // for future back compatibility -static const NSString* const keyForceBootConfigPath = @"forceBootConfigPath"; -static const NSString* const keySwapHD01 = @"swapHD01"; -static const NSString* const keySwapHD02 = @"swapHD02"; -static const NSString* const keyUseFrozenParts = @"useFrozenParts"; -static const NSString* const keyPartitionsList = @"partitionsList"; -static const char cPartDescSep = ';'; // partition descriptor separator -static const char* sPartDescSep = ";"; // cstring version //-------------------------------------------------------------------------- // Static file variables //-------------------------------------------------------------------------- static std::string sCurrentDefaultPartition; -static PartitionExtractor * partExtractor=NULL; -static PropertyList * prop = NULL; +PartitionExtractor * partExtractor=NULL; +BootPropertyList * prop = NULL; static int currentRowSel = -1; static ChameleonPrefPane *gInstance = NULL; @@ -73,16 +61,80 @@ mUnknownImage = [self getImageResource: @"Chameleon" ofType: @"tiff"]; + // create the propertylist object that will handle com.apple.Boot.plist + if(!prop) prop = new BootPropertyList(); + + // create the process that will extract the diskutil list infos + if(!partExtractor) partExtractor = new PartitionExtractor(); + // Retrieve the com.chameleon.prefPane.plist config return self; } -- (NSMutableDictionary*) getPreferencesFile +- (NSMutableDictionary*) preferencesFile { return mOptionsDict; } +- (NSMutableDictionary*) preferencesParts { return mPartitionsDict; } +- (NSTableView*) partitionsTable { return mPartitionsTable;} + +//-------------------------------------------------------------------------- +-(bool) savePreferences: (NSDictionary*) dict { - return mOptionsDict; + std::string sPath = [kPreferencesFilePath UTF8String]; + + if(dict==nil || sPath.length()==0) return false; + + AuthorizationRef auth = [self isUnlocked] ? [[authView authorization] authorizationRef] : NULL; + + PropertyList::chmodFile(sPath.c_str(), "0777", auth); + [dict writeToFile:kPreferencesFilePath atomically:YES]; + PropertyList::chmodFile(sPath.c_str(), "0644", auth); + return true; } //-------------------------------------------------------------------------- +- (void) loadPreferences + +{ + id oldGlobalPreferences = [ [NSDictionary dictionaryWithContentsOfFile: + kPreferencesFilePath ] retain]; + + mPartitionsDict = [[NSMutableDictionary alloc] init]; + [mPartitionsDict retain]; + + // Initialize bootConfig desc dict + [[BootSetupController instance] addOptionsDesc]; + [[BootFlagsController instance] addOptionsDesc]; + [[PeripheralsController instance] addOptionsDesc]; + [[AdvancedSetupController instance] addOptionsDesc]; + + if (oldGlobalPreferences!=nil) + { + mPreferenceFileVersion= [[oldGlobalPreferences objectForKey: keyPreferencesFileVersion] intValue ]; + [PreferencesControllerBase setDefaultValues: oldGlobalPreferences]; + [mPartitionsDict addEntriesFromDictionary: [oldGlobalPreferences objectForKey: keyPartitionsList] ]; + } + else + { // Create a preference plist file with Defaults values + oldGlobalPreferences = [[NSMutableDictionary alloc] init]; + [[BootSetupController instance]loadOptionsFromPreferencesFile: oldGlobalPreferences]; + [[BootSetupController instance]loadOptionsFromPreferencesFile: oldGlobalPreferences]; + [[BootSetupController instance]loadOptionsFromPreferencesFile: oldGlobalPreferences]; + [[BootSetupController instance]loadOptionsFromPreferencesFile: oldGlobalPreferences]; + // Initialize defaults + [oldGlobalPreferences setObject: [[NSNumber alloc] initWithInt: CurrentPreferencesFileVersion] + forKey: keyPreferencesFileVersion]; + [oldGlobalPreferences setObject: mPartitionsDict forKey: keyPartitionsList]; + + // Save the preferences file + [ self savePreferences:oldGlobalPreferences ]; + } + + mOptionsDict = [[NSMutableDictionary alloc] init]; + [mOptionsDict addEntriesFromDictionary:oldGlobalPreferences]; + if (mPartitionsDict!=nil) [mPartitionsDict retain]; + [oldGlobalPreferences release]; + } + +//-------------------------------------------------------------------------- /** * SFAuthorization delegates */ @@ -101,11 +153,7 @@ - (void) refreshLockStates { [mPartitionsTable setEnabled:[self isUnlocked]]; - [mSwapHD01 setEnabled:[self isUnlocked]]; - [mSwapHD02 setEnabled:[self isUnlocked]]; [mStatusText setEnabled:[self isUnlocked]]; - [mFreezeParts setEnabled:[self isUnlocked]]; - [mInjectFrozenParts setEnabled:[self isUnlocked]]; // Refresh other panels [[BootSetupController instance] refreshLockStates]; @@ -132,109 +180,8 @@ return img; } -//-------------------------------------------------------------------------- --(bool) savePreferences: (NSDictionary*) dict -{ - std::string sPath = [kPreferencesFilePath UTF8String]; - - if(dict==nil || sPath.length()==0) return false; - - AuthorizationRef auth = [self isUnlocked] ? [[authView authorization] authorizationRef] : NULL; - - PropertyList::chmodFile(sPath.c_str(), "0777", auth); - [dict writeToFile:kPreferencesFilePath atomically:YES]; - PropertyList::chmodFile(sPath.c_str(), "0644", auth); - return true; -} -//-------------------------------------------------------------------------- -- (void) loadFrozenParts -{ - std::vector& partList = partExtractor->editPartList(); //rw - // iterate for all entries to add - char keyPartN[32] = ""; - char buffer[256]=""; - int k=0; - partList.clear(); - for (int i=0; i<[mPartitionsDict count]; i++) - { - // get the key - snprintf(keyPartN, sizeof(keyPartN)-1, "partition%02d",i); - NSString* obj = [mPartitionsDict objectForKey: [[NSString alloc] initWithUTF8String: keyPartN] ]; - // assign this key if valid - if (obj!=nil && [obj length]>0) - { - PartitionInfo p; - // parse string - strncpy(buffer, [obj UTF8String], sizeof(buffer)-1); - k=0; - for(const char* word = strtok(buffer,";"); word; word=strtok(NULL,sPartDescSep),k++) - { - switch (k) { - case 0: // parse disk number - if (isdigit(*word)) p.disk(*word-'0'); - break; - case 1: // parse partition number - if (isdigit(*word)) p.partition(*word-'0'); - break; - case 2: // parse volume label - p.label(word); - case 3: - p.fsType(word); - break; - default: - break; - } - } - partList.push_back(p); - } - } - partExtractor->sortPartList(); -} //-------------------------------------------------------------------------- -- (void) loadPreferences - -{ - id oldGlobalPreferences = [ [NSDictionary dictionaryWithContentsOfFile: - kPreferencesFilePath ] retain]; - - mPartitionsDict = [[NSMutableDictionary alloc] init]; - [mPartitionsDict retain]; - - if (oldGlobalPreferences!=nil) - { - mPreferenceFileVersion= [[oldGlobalPreferences objectForKey: keyPreferencesFileVersion] intValue ]; - [mSwapHD01 setIntValue: [[oldGlobalPreferences objectForKey: keySwapHD01] intValue]]; - [mSwapHD02 setIntValue: [[oldGlobalPreferences objectForKey: keySwapHD02] intValue]]; - [mFreezeParts setIntValue: [[oldGlobalPreferences objectForKey: keyUseFrozenParts] intValue] ]; - [mPartitionsDict addEntriesFromDictionary: [oldGlobalPreferences objectForKey: keyPartitionsList] ]; - } - else - { // Create a preference plist file with Defaults values - [mSwapHD01 setIntValue: 0]; - [mSwapHD02 setIntValue: 0]; - [mFreezeParts setIntValue: 0]; - // Initialize defaults - oldGlobalPreferences = [[NSMutableDictionary alloc] init]; - [oldGlobalPreferences setObject: [[NSNumber alloc] initWithInt: CurrentPreferencesFileVersion] - forKey: keyPreferencesFileVersion]; - [oldGlobalPreferences setObject: [[NSNumber alloc] initWithBool: false] forKey: keySwapHD01]; - [oldGlobalPreferences setObject: [[NSNumber alloc] initWithBool: false] forKey: keySwapHD02]; - [oldGlobalPreferences setObject:[[NSNumber alloc] initWithBool: false] forKey: keyUseFrozenParts]; - [oldGlobalPreferences setObject: mPartitionsDict forKey: keyPartitionsList]; - - // Save the preferences file - [ self savePreferences:oldGlobalPreferences ]; - } - - mOptionsDict = [[NSMutableDictionary alloc] init]; - [mOptionsDict addEntriesFromDictionary:oldGlobalPreferences]; - if (mPartitionsDict!=nil) [mPartitionsDict retain]; - [oldGlobalPreferences release]; -} - - -//-------------------------------------------------------------------------- /** When called here, all outlets references are initialized */ - (void)awakeFromNib { // called more than once, we only need one resource init @@ -242,7 +189,7 @@ if(ft) { ft=false; - [self loadPreferences]; + [self loadPreferences]; [self initBootConfig]; } } @@ -261,12 +208,6 @@ authView.delegate = self; [authView updateStatus:nil]; - // create the propertylist object that will handle com.apple.Boot.plist - if(!prop) prop = new PropertyList(); - - // create the process that will extract the diskutil list infos - if(!partExtractor) partExtractor = new PartitionExtractor(); - if (!prop->isValid()) { std::string sPath; @@ -303,9 +244,10 @@ else { [mStatusText setTextColor: [NSColor grayColor] ]; - NSString* ns = [ [NSString alloc] initWithUTF8String:prop->bootConfigPath() ]; + NSString* ns = [ [NSString alloc] initWithUTF8String:prop->propFilePath() ]; [mStatusText setStringValue: [NSString stringWithFormat: @"bootConfig: %@", ns] ]; } + if (prop->isValid()) { // read options in the plist file @@ -315,12 +257,12 @@ // partExtractor->resetSwapping(); id val = [mOptionsDict valueForKey: keySwapHD01]; - [mSwapHD01 setIntValue: [val intValue] ]; - [self doSwapHD: [val boolValue] save: false src:0 dst:1]; + [[BootSetupController instance]->mSwapHD01 setIntValue: [val intValue] ]; + [[BootSetupController instance] doSwapHD: [val boolValue] save: false src:0 dst:1]; val = [mOptionsDict valueForKey: keySwapHD02]; - [mSwapHD02 setIntValue: [val intValue] ]; - [self doSwapHD: [val boolValue] save: false src:0 dst:2]; + [[BootSetupController instance]->mSwapHD02 setIntValue: [val intValue] ]; + [[BootSetupController instance] doSwapHD: [val boolValue] save: false src:0 dst:2]; [self selectDefaultPartition]; } @@ -354,115 +296,6 @@ } //-------------------------------------------------------------------------- -- (void) swapDisks: (bool) bSwap src: (int) iSrc dst: (int) iDst; -{ - if(!partExtractor || !prop || !prop->isValid()) return; - if (bSwap) - { - partExtractor->swapHD(iSrc, iDst); - } - - if ([mFreezeParts intValue]==0) - partExtractor->extractPartitions(); - else - [self loadFrozenParts ]; - - [ self selectDefaultPartition]; - -} - -//-------------------------------------------------------------------------- -- (void) doSwapHD: (int) val save: (bool) doSave src: (int) isrc dst: (int) idst -{ - - if( val>0 && ![mFreezeParts intValue]) //on - { - [self swapDisks: true src:isrc dst:idst ]; - } - else - { - [self swapDisks: false src:isrc dst:idst ]; - } - - if(doSave) - { - if (isrc==0 && idst==1) - [mOptionsDict setObject: [NSNumber numberWithBool: val ? true : false] forKey: keySwapHD01]; - if (isrc==0 && idst==2) - [mOptionsDict setObject: [NSNumber numberWithBool: val ? true : false] forKey: keySwapHD02]; - [ self savePreferences:mOptionsDict ]; - } - - [mPartitionsTable reloadData]; - [mPartitionsTable scrollRowToVisible: 0]; - //[self tableViewSelectionDidChange: nil]; - -} -//-------------------------------------------------------------------------- -- (IBAction)onSwapHD: (id)sender -{ - partExtractor->resetSwapping(); - [self doSwapHD: [mSwapHD01 intValue] save:true src:0 dst:1]; - [self doSwapHD: [mSwapHD02 intValue] save:true src:0 dst:2]; -} -//-------------------------------------------------------------------------- -- (IBAction)onUseFrozenParts: (id)sender -{ - bool val = !![sender intValue]; - [mOptionsDict setObject: [NSNumber numberWithBool: val] forKey: keyUseFrozenParts]; - [self savePreferences: mOptionsDict]; - [self onSwapHD: nil]; -} - -//-------------------------------------------------------------------------- -- (IBAction)onInjectPartsToFreeze: (id)sender -{ - int size = partExtractor ? partExtractor->partList().size() : 0; - if (!size) - { // nothing to inject - NSRunAlertPanel(@"Inject Partitions to Freeze Configuration", - @"No current partitions to inject, did you check boot config file ?",@"OK", nil,nil); - return; - } - // generate the parts list in preferences proplist - NSInteger n = NSRunAlertPanel(@"Inject Partitions to Freeze Configuration", - @"Are you sure you want to overwrite your Freeze settings with current partition list ?", - @"OK", @"Cancel",nil); - if (n==1) - { - // populate the dictionary with the current partitions - - // empty dictionary and update key in parent: - [mOptionsDict removeObjectForKey: keyPartitionsList]; - [mPartitionsDict removeAllObjects ]; - - // iterate for all entries to add - char partDesc[256]=""; - char keyPartN[32] = ""; - for (int i=0; i< size; i++) - { - - const PartitionInfo& p =partExtractor->partList()[i]; - - // format the partition key and descriptor string - snprintf(keyPartN, sizeof(keyPartN)-1, "partition%02d",i); - - snprintf(partDesc, sizeof(partDesc)-1, "%d%c%d%c%s%c%s", - p.disk(), cPartDescSep, - p.partition(), cPartDescSep, - p.clabel(), cPartDescSep, - p.cfsType()); - - // write it to the dictionary - NSString * key = [[NSString alloc] initWithUTF8String: keyPartN]; - NSString * desc = [[NSString alloc] initWithUTF8String: partDesc]; - [mPartitionsDict setObject: desc forKey: key]; - } - [mOptionsDict setObject: mPartitionsDict forKey: keyPartitionsList]; - [self savePreferences: mOptionsDict]; - } -} -//-------------------------------------------------------------------------- // following DieBuch recommendation : using applescript and system events (thanks!): - (IBAction)onRestart: (id)sender { @@ -542,7 +375,7 @@ case 2: ret = mLinuxImage; break; - defualt: + default: ret = mUnknownImage; break; Index: trunk/ChameleonPrefPane/Sources/BootPropertyList.cpp =================================================================== --- trunk/ChameleonPrefPane/Sources/BootPropertyList.cpp (revision 0) +++ trunk/ChameleonPrefPane/Sources/BootPropertyList.cpp (revision 47) @@ -0,0 +1,24 @@ +/* + * BootPropertyList.cpp + * ChameleonPrefPane + * + * Created by Rekursor on 1/22/10. + * + */ + +#include "BootPropertyList.h" + +void BootPropertyList::deleteOptionDesc() +{ + // delete all alloc'ed pointers + std::map::iterator bod; + for (bod=_idToDescDict.begin(); bod!=_idToDescDict.end(); bod++) + if(bod->second) delete bod->second; +} + +void BootPropertyList::clearOptionDesc() +{ + deleteOptionDesc(); + _idToDescDict.clear(); // now clear the pairs +} + Index: trunk/ChameleonPrefPane/Sources/PreferencesControllerBase.h =================================================================== --- trunk/ChameleonPrefPane/Sources/PreferencesControllerBase.h (revision 46) +++ trunk/ChameleonPrefPane/Sources/PreferencesControllerBase.h (revision 47) @@ -7,24 +7,59 @@ #import #import +#import "BootPropertyList.h" +#import +// ENHANCE ME: remove this globals and integrate them in ChameleonPrefPan or at least +// add function accessor entry points +extern PartitionExtractor * partExtractor; +extern BootPropertyList * prop; + +// Defintion of the required protocol for any derived classes of PreferencesControllerBase @protocol PreferenceController @required // must be implemented in all derived classes + +// Called by all buttons of each group in therface +- (IBAction) onCheckButtonChange: (NSButton*) sender; + +// Called by all text fields of each group in therface +- (IBAction) onTextFiedChange: (NSTextField*) sender; + +// Add the boot config options descriptors to the consolidated dictionary +- (void) addOptionsDesc; + +// Set refresh all group states {enabled | disabled} depending on the authorizations state - (void) refreshLockStates; --(IBAction) onCheckButtonChange: (id) sender; --(IBAction) onTextFiedChange: (id) sender; --(void) loadOptionsFromPreferencesFile; + +// load the corresponding Options from the interface +- (void) loadOptionsFromPreferencesFile: (NSMutableDictionary*) dict; + @end // Define common expected behavior for all derived controllers @interface PreferencesControllerBase : NSObject { - } --(NSMutableDictionary*) getPreferencesDictionary; +// from the id to desc map in prop, set all default values for dict ++ (void) setDefaultValues: (NSMutableDictionary*) dict; +// Set refresh state {enabled | disabled} depending on the authorizations state +- (void) refreshLockState: (id) item; + +- (void) loadPreferences; +- (bool) savePreferences; + +- (bool) handleSender: (id) sender withButton: (NSButton*) button forKey: (const char *) key; +- (bool) handleSender: (id) sender withButton: (NSButton*) button andField:(NSTextField*) field + forKey: (const char *) key; + +-(NSMutableDictionary*) preferencesFile; +-(NSMutableDictionary*) preferencesParts; + +-(ChameleonPrefPane*) chameleon; + @end Index: trunk/ChameleonPrefPane/Sources/ShellProcess.cpp =================================================================== --- trunk/ChameleonPrefPane/Sources/ShellProcess.cpp (revision 0) +++ trunk/ChameleonPrefPane/Sources/ShellProcess.cpp (revision 47) @@ -0,0 +1,200 @@ +/* + * shell_process.cpp + * + * Created by Rekursor on 1/17/2010. + * + */ + +#include "ShellProcess.h" +#include +#include +#include + + +//---------------------------------------------------------------- +// portable open process: +FILE * ShellProcess::open(const char *cmd, const char *mode) { + _fpt=::popen(cmd,mode); + return _fpt; +} + +//---------------------------------------------------------------- +int ShellProcess::close() { + int ret = ::pclose(_fpt); + _fpt=NULL; + return ret; +} + +//---------------------------------------------------------------- +void PartitionInfo::removeSpaces(std::string &str) +{ + if (!str.size()) return; + int posl=0,posr=0; + for (posl=0; posl0 && str[posr]==' '; posr--); + str = (posl>posr) ? "" : str.substr(posl, posr-posl+1); +} +//---------------------------------------------------------------- +/** + * return the image index corresponding to a fs: + */ +int PartitionInfo::imageIndexFromFs() const +{ + if (_fsType.find("Apple")!=std::string::npos || + _fsType.find("HFS")!=std::string::npos) + return 0; // Windows + else if (_fsType.find("Windows")!=std::string::npos || + _fsType.find("Microsoft")!=std::string::npos || + _fsType.find("NTFS")!=std::string::npos || + _fsType.find("FAT")!=std::string::npos) + return 1; // Windows + else if (_fsType.find("Linux")!=std::string::npos) + return 2; // Unknown + return 10; //Unknown + +} +//---------------------------------------------------------------- +bool PartitionInfo::fromPartitionHdString(const char * inHdStr) +{ + if (!inHdStr || !(*inHdStr) || + strlen(inHdStr)<7 || !strstr(inHdStr,"hd(")) return false; + + // enhance me here: should not assume that we have less than 10 partitions per disk/ disks + _disk = inHdStr[3]-'0'; + _part = inHdStr[5]-'0'; + return true; +} +//---------------------------------------------------------------- +const char * PartitionExtractor::checkForRename(const char * label, const char *szHd) +{ + const int MAX_ALIAS_SIZE=31; + static char szAlias[MAX_ALIAS_SIZE+1]; + char *q=szAlias; + const char* szAliases = _renamedParts.c_str(); + + if (!szHd || !*szHd || !szAliases || !*szAliases) return label; // no renaming wanted + + const char * p = strstr(szAliases, szHd); + if(!p || !(*p)) return label; // this volume must not be renamed, or option is malformed + + p+= strlen(szHd); // skip the "hd(n,m) " field + // multiple aliases can be found separated by a semi-column + while(*p && *p != ';' && q<(szAlias+MAX_ALIAS_SIZE)) *q++=*p++; + *q='\0'; + + return szAlias; + +} +//---------------------------------------------------------------- +const std::vector& +PartitionExtractor::extractPartitions(const char* szHide, const char* szRenamed) +{ + const char * const diskTag = "/dev/disk"; + const char * const nameTag = "NAME"; + const char * const sizeTag = "SIZE"; + + PartitionInfo partInfo; + + char line[1024]=""; + char label[32]="", fsType[32]="" ; + size_t len=0; + int disk =0, part=0; + int label_pos=0, size_pos=0; + char * p=0,*q=0; + int skipwhite=0; + + _partList.clear(); + if (szHide) hidePartitions(szHide); + if (szRenamed) renamedPartitions(szRenamed); + this->open("diskutil list"); + + while(get_line(line, sizeof(line)-1)) + { + // printf("%s\n",line); + len = strlen(line); + for(skipwhite=0; line[skipwhite]==' ';skipwhite++); + + const char * sdisk = strstr(line, diskTag); + const char * sName = strstr(line, nameTag); + const char * sSize = strstr(line, sizeTag); + + if (sdisk) + { + // extract disk number + disk= sdisk[strlen(diskTag)]-'0'; + if (disk>=0 && disk 0 && + partInfo.clabel()[len-1] !='*' && + partInfo.fsType()!="EFI" && + partInfo.fsType()!="Apple_partition_scheme" && + partInfo.fsType()!="Apple_partition_map" && + partInfo.fsType()!="Apple_Free" + ) + { + std::string DiskLabel(label), UnixPath, WinPath; + DiskLabel.erase( DiskLabel.find_last_not_of(" ") + 1); + bool found=false; + + // early bail out if we found what we need: + if (fileExists((UnixPath = "/Volumes/" + DiskLabel + "/usr/bin/man"))) + found=true; + else if ((strstr(label,"System Reserved") ) || // don't filter system reserved windows 7 boot parts + fileExists((WinPath="/Volumes/" + DiskLabel + "/Windows/system.ini"))) + found=true; + else if (strstr(fsType,"Linux") && !strstr(fsType, "Linux_Swap")) + found=true; // Added Linux case + if (found) + { //check if one of them exists + if (partInfo.label().size()==0) partInfo.label("Untitled"); + if(_hiddenParts.length()==0 || + _hiddenParts.find(partInfo.toHdStr()) == std::string::npos) + _partList.push_back(partInfo); + } + } + } + } + close(); + + sort(_partList.begin(), _partList.end(), isDiskIndexInf); + return _partList; +} + +/** + * Get the index in the internal partlist of the hd(n,m) partition specified by the input string + * return -1 if no match, >=0 if a match happens + */ +int PartitionExtractor::getIndexFromHdStringSpec(const char* inHDStr) +{ + PartitionInfo info; + + if (info.fromPartitionHdString(inHDStr)) // try decode the partition disk and part infos + { + for (int i=0; i<_partList.size(); i++) + { + if (_partList[i].disk() == info.disk() && _partList[i].partition() == info.partition()) + return i; + } + } + + return -1; +} Index: trunk/ChameleonPrefPane/Sources/BootPropertyList.h =================================================================== --- trunk/ChameleonPrefPane/Sources/BootPropertyList.h (revision 0) +++ trunk/ChameleonPrefPane/Sources/BootPropertyList.h (revision 47) @@ -0,0 +1,87 @@ +/* + * BootPropertyList.h + * ChameleonPrefPane + * + * Created by Rekursor on 1/22/10. + * + */ +#ifndef __CHBOOT_PROPERTYLIST_LIST_H +#define __CHBOOT_PROPERTYLIST_LIST_H + +#include "PropertyList.h" +#include + +// Chameleon Boot options type +typedef enum +{ + OptionYesNo=0, // "Yes" or "No" + OptionString, // String Content + OptionUnix, // Unix like command option like -x, -v ... + OptionKernel, // kernel cmd like "mach_kernel" or "blacklist=0" + OptionKernel1 // kernel cmd like "mach_kernel" or "blacklist=0" + +} BootOptionType; + +// Boot Option descriptor : used by all derived class to permit parameters handling automation ... +struct BootOptionDesc +{ + BootOptionDesc(void* i, void * cID, BootOptionType t, const char* n, const char* d) { + ID=i; contentID=cID, Type=t; Name=n; Default=d; + } + void* ID; // the corresponding button or textfield in the interface + void* contentID; // the corresponding content ID (i.e: the string content for text fields) + BootOptionType Type; + const char * Name; + const char * Default; + +} ; + +/** + * Specialization of PropertyList with Chameleon Boot Config, fast id key to desc search features + */ +class BootPropertyList : public PropertyList +{ +public: + BootPropertyList() { } + virtual ~BootPropertyList() { deleteOptionDesc(); } + + // id to map BootOptionDesc handling + void addOptionDesc(void * ID, void* cID, BootOptionType t, const char * szName, const char* szDefault) + { + if (ID) _idToDescDict[ID] = new BootOptionDesc(ID, cID, t, szName? szName : "", szDefault ? szDefault : ""); + } + + // find the desc corresponding to id: + const BootOptionDesc* findOption(void *ID) const + { + std::map::const_iterator bod; + if (!ID || (bod=_idToDescDict.find(ID))==_idToDescDict.end()) return NULL; + return bod->second; + } + + // opaque enumeration for the map + const BootOptionDesc* firstOption() + { + _bod=_idToDescDict.begin(); + if (_bod!= _idToDescDict.end()) return _bod->second; else return NULL; + } + + const BootOptionDesc* nextOption() + { + if(_bod++ ==_idToDescDict.end()) return NULL; + if (_bod != _idToDescDict.end()) return _bod->second; else return NULL; + } + + + // remove all elements in dict, calls deleteOptionsDesc() + void clearOptionDesc(); + +protected: + void deleteOptionDesc(); + +private: + std::map _idToDescDict; // dictionary for id -> desc association type + std::map::const_iterator _bod; +}; + +#endif \ No newline at end of file Index: trunk/ChameleonPrefPane/Sources/PeripheralsController.mm =================================================================== --- trunk/ChameleonPrefPane/Sources/PeripheralsController.mm (revision 46) +++ trunk/ChameleonPrefPane/Sources/PeripheralsController.mm (revision 47) @@ -14,41 +14,51 @@ - (id) init { self = [super init]; - gInstance = self; - + return (gInstance = self); } -// TODO implement a smart & reusable option modification, usable by all controllers -// these pair of methods in each controller should all rely on a single external class instance (singleton) -// that would implement in an opaque way the options streaming between the panels and the pref. file +//-------------------------------------------------------------------------- +- (void) addOptionsDesc +{ + prop->addOptionDesc(mLegacyLogo, nil, OptionYesNo, "Legacy Logo", "No"); + prop->addOptionDesc(mBootBanner, nil, OptionYesNo, "Boot Banner", "No"); + prop->addOptionDesc(mVBIOS, nil, OptionYesNo, "VBIOS", "No"); + prop->addOptionDesc(mVideoROM, mVideoROMText, OptionString, "VideoROM", ""); + prop->addOptionDesc(mGraphicsMode, mGraphicsModeText, OptionString, "Graphics Mode", ""); + prop->addOptionDesc(mGraphicsEnabler, nil, OptionYesNo, "GraphicsEnabler", "No"); + prop->addOptionDesc(mUSBBusFix, nil, OptionYesNo, "USBBusFix", "No"); + prop->addOptionDesc(mEHCIacquire, nil, OptionYesNo, "EHCIacquire", "No"); + prop->addOptionDesc(mUHCIreset, nil,OptionYesNo, "UHCIreset", "No"); + prop->addOptionDesc(mEthernetBuiltIn, nil, OptionYesNo, "EthernetBuiltIn", "No"); +} - (void) refreshLockStates { - [mLegacyLogo setEnabled:[[ChameleonPrefPane instance] isUnlocked]]; - [mBootBanner setEnabled:[[ChameleonPrefPane instance] isUnlocked]]; - [mVBIOS setEnabled:[[ChameleonPrefPane instance] isUnlocked]]; - [mVideoROM setEnabled:[[ChameleonPrefPane instance] isUnlocked]]; - [mVideoROMText setEnabled:[[ChameleonPrefPane instance] isUnlocked]]; - [mGraphicsMode setEnabled:[[ChameleonPrefPane instance] isUnlocked]]; - [mGraphicsModeText setEnabled:[[ChameleonPrefPane instance] isUnlocked]]; - [mGraphicsEnabler setEnabled:[[ChameleonPrefPane instance] isUnlocked]]; - [mUSBBusFix setEnabled:[[ChameleonPrefPane instance] isUnlocked]]; - [mEHCIacquire setEnabled:[[ChameleonPrefPane instance] isUnlocked]]; - [mUHCIreset setEnabled:[[ChameleonPrefPane instance] isUnlocked]]; - [mEthernetBuiltIn setEnabled:[[ChameleonPrefPane instance] isUnlocked]]; + [self refreshLockState: mLegacyLogo ]; + [self refreshLockState: mBootBanner ]; + [self refreshLockState: mVBIOS ]; + [self refreshLockState: mVideoROM ]; + [self refreshLockState: mVideoROMText ]; + [self refreshLockState: mGraphicsMode ]; + [self refreshLockState: mGraphicsModeText ]; + [self refreshLockState: mGraphicsEnabler ]; + [self refreshLockState: mUSBBusFix ]; + [self refreshLockState: mEHCIacquire ]; + [self refreshLockState: mUHCIreset ]; + [self refreshLockState: mEthernetBuiltIn ]; } --(IBAction) onCheckButtonChange: (id) sender +-(void) loadOptionsFromPreferencesFile: (NSMutableDictionary*) dict { } --(IBAction) onTextFiedChange: (id) sender +-(IBAction) onCheckButtonChange: (NSButton*) sender { } --(void) loadOptionsFromPreferencesFile +-(IBAction) onTextFiedChange: (NSTextField*) sender { } Index: trunk/ChameleonPrefPane/Sources/ShellProcess.h =================================================================== --- trunk/ChameleonPrefPane/Sources/ShellProcess.h (revision 0) +++ trunk/ChameleonPrefPane/Sources/ShellProcess.h (revision 47) @@ -0,0 +1,148 @@ +/* + * shell_process.h + * + * Created by Rekursor on 1/17/2010. + * + */ +#ifndef __CHSHELL_PROCESS_H +#define __CHSHELL_PROCESS_H + +#include +#include +#include +#include +#include +#include +#include + +//---------------------------------------------------------------- +const int MAX_HD = 10; + +//---------------------------------------------------------------- + +/** + * Check whether file exists: + */ +inline bool fileExists(const char * str) +{ + struct stat stFileInfo; + if((stat(str,&stFileInfo)) == 0) return true; + else return false; +} + +inline bool fileExists(std::string str) {return fileExists(str.c_str());} + +//---------------------------------------------------------------- +class ShellProcess +{ +public: + // construction / destruction + ShellProcess() {_fpt= NULL;} + ~ShellProcess() {if (_fpt) close();} + + FILE * open (const char *cmd, const char *mode="r"); + int close(); + FILE * desc() const { return _fpt;} // non null if file is open + char * get_line(char * line, size_t s) const {return _fpt ? fgets(line, s, _fpt) : NULL;} + +protected: + FILE * _fpt; +}; + +//---------------------------------------------------------------- +class PartitionInfo +{ +public: + PartitionInfo() : _disk(0), _part(0) {} + PartitionInfo(int disk, int part) { set(disk, part);} + + void disk(int disk) { _disk=disk;} + int disk() const { return _disk;} + + void partition(int part) { _part=part;} + int partition () const { return _part;} + + const char * clabel() const { return _label.c_str();} + const std::string& label() const { return _label; } + void label(const char * l) { + if (l) _label = l; + removeSpaces(_label); + } + + const char * cfsType() const { return _fsType.c_str();} + const std::string& fsType() const { return _fsType;} + void fsType(const char * fs) { + if (fs) _fsType = fs; + removeSpaces(_fsType); + } + + void set(int disk, int part) { _disk =disk; _part = part;} + bool fromPartitionHdString(const char * inHdStr); + std::string toHdStr() const + { + std::string buf = "hd(n,m)"; + buf[3]= '0'+disk(); + buf[5]='0'+partition(); + return buf; + } + int imageIndexFromFs() const; +protected: + void removeSpaces(std::string & s); + +private: + int _disk, _part; + std::string _fsType, _label; +}; + +static inline bool isDiskIndexInf(PartitionInfo i, PartitionInfo j) +{ + return ((i.disk()*100+i.partition()) < (j.disk()*100 + j.partition()) ) ; +} + +//---------------------------------------------------------------- +class PartitionExtractor : public ShellProcess +{ +public: + PartitionExtractor() : ShellProcess() { init(); } + + const std::vector& extractPartitions( + const char* szHide=NULL, + const char* szRenamed=NULL); + int getListCount() const {return (int) _partList.size();} + + const std::vector& partList() const {return _partList;} + std::vector& editPartList() {return _partList;} + + // get the index in the internal partlist of the hd(n,m) partition specified by the input string + // return -1 if no match, >=0 if a match happens + int getIndexFromHdStringSpec(const char*); + + void hidePartitions(const char* szParts){ _hiddenParts = (szParts ? szParts : "");} + void renamedPartitions(const char* szParts){ _renamedParts = (szParts ? szParts : "");} + void sortPartList() { sort(_partList.begin(), _partList.end(), isDiskIndexInf); } + + const char * checkForRename(const char * label, const char* szHd); + + void swapHD(int src, int dst) + { + if(src < 0 || src > MAX_HD-1 || dst < 0 || dst > MAX_HD-1) return; + _hdRedirTable[src]=dst; + _hdRedirTable[dst]=src; + } + + void resetSwapping() { init();} + +protected: + void init() { + for (int i=0; i _partList; + int _hdRedirTable[MAX_HD]; + std::string _hiddenParts; + std::string _renamedParts; + +}; + +#endif Index: trunk/ChameleonPrefPane/Sources/BootFlagsController.mm =================================================================== --- trunk/ChameleonPrefPane/Sources/BootFlagsController.mm (revision 46) +++ trunk/ChameleonPrefPane/Sources/BootFlagsController.mm (revision 47) @@ -7,8 +7,12 @@ #import "BootFlagsController.h" +// Constants + +// File static variables static BootFlagsController *gInstance = NULL; + @implementation BootFlagsController - (id) init @@ -17,39 +21,48 @@ return (gInstance = self); } -// TODO implement a smart & reusable option modification, usable by all controllers -// these pair of methods in each controller should all rely on a single external class instance (singleton) -// that would implement in an opaque way the options streaming between the panels and the pref. file +-(void) addOptionsDesc +{ + prop->addOptionDesc(mVerbose, nil, OptionUnix, "-v", ""); + prop->addOptionDesc(mSafeBoot, nil, OptionUnix, "-x", ""); + prop->addOptionDesc(mIgnoreBootConfig, nil, OptionUnix, "-F", ""); + prop->addOptionDesc(mSingleUser, nil, OptionUnix, "-s", ""); + prop->addOptionDesc(mTimeOut, mTimeOutText, OptionString,"Timeout", "5"); + prop->addOptionDesc(mQuietBoot, nil, OptionYesNo, "Quiet Boot", "No"); + prop->addOptionDesc(mInstantMenu, nil, OptionYesNo, "Instant Menu", "No"); + prop->addOptionDesc(mWait, nil, OptionYesNo, "Wait", "No"); + prop->addOptionDesc(mRescan, nil, OptionYesNo, "Rescan", "No"); + prop->addOptionDesc(mRescanPrompt, nil, OptionYesNo, "Rescan Prompt", "No"); + prop->addOptionDesc(mRescanSingleDrive, nil, OptionYesNo, "Rescan SingleDrive", "No"); +} - (void) refreshLockStates { - [mVerbose setEnabled:[[ChameleonPrefPane instance] isUnlocked]]; - [mSafeBoot setEnabled:[[ChameleonPrefPane instance] isUnlocked]]; - [mIgnoreBootConfig setEnabled:[[ChameleonPrefPane instance] isUnlocked]]; - [mTimeOut setEnabled:[[ChameleonPrefPane instance] isUnlocked]]; - [mTimeOutText setEnabled:[[ChameleonPrefPane instance] isUnlocked]]; - [mSingleUser setEnabled:[[ChameleonPrefPane instance] isUnlocked]]; - [mQuietBoot setEnabled:[[ChameleonPrefPane instance] isUnlocked]]; - [mInstantMenu setEnabled:[[ChameleonPrefPane instance] isUnlocked]]; - [mWait setEnabled:[[ChameleonPrefPane instance] isUnlocked]]; - [mSafeBoot setEnabled:[[ChameleonPrefPane instance] isUnlocked]]; - [mIgnoreBootConfig setEnabled:[[ChameleonPrefPane instance] isUnlocked]]; - [mRescan setEnabled:[[ChameleonPrefPane instance] isUnlocked]]; - [mRescanPrompt setEnabled:[[ChameleonPrefPane instance] isUnlocked]]; - [mRescanSingleDrive setEnabled:[[ChameleonPrefPane instance] isUnlocked]]; + [self refreshLockState: mVerbose]; + [self refreshLockState: mSafeBoot]; + [self refreshLockState: mIgnoreBootConfig]; + [self refreshLockState: mTimeOut]; + [self refreshLockState: mTimeOutText]; + [self refreshLockState: mSingleUser]; + [self refreshLockState: mQuietBoot]; + [self refreshLockState: mInstantMenu]; + [self refreshLockState: mWait]; + [self refreshLockState: mRescan]; + [self refreshLockState: mRescanPrompt]; + [self refreshLockState: mRescanSingleDrive]; } --(IBAction) onCheckButtonChange: (id) sender +-(void) loadOptionsFromPreferencesFile: (NSMutableDictionary*) dict { } --(IBAction) onTextFiedChange: (id) sender +-(IBAction) onCheckButtonChange: (NSButton*) sender { } --(void) loadOptionsFromPreferencesFile +-(IBAction) onTextFiedChange: (NSTextField*) sender { } Index: trunk/ChameleonPrefPane/Sources/BootSetupController.mm =================================================================== --- trunk/ChameleonPrefPane/Sources/BootSetupController.mm (revision 46) +++ trunk/ChameleonPrefPane/Sources/BootSetupController.mm (revision 47) @@ -1,51 +1,249 @@ // -// PartitionsSetupController.mm +// BootSetupController.mm // ChameleonPrefPane // // Created by Rekursor on 1/22/10. // #import "BootSetupController.h" +#import "ChameleonPrefPane.h" +static const char* sPartDescSep = ";"; // cstring version +static const char cPartDescSep = ';'; // partition descriptor separator static BootSetupController *gInstance = NULL; @implementation BootSetupController +//-------------------------------------------------------------------------- - (id) init { self = [super init]; return (gInstance = self); } -// TODO implement a smart & reusable option modification, usable by all controllers -// these pair of methods in each controller should all rely on a single external class instance (singleton) -// that would implement in an opaque way the options streaming between the panels and the pref. file +//-------------------------------------------------------------------------- +- (void) addOptionsDesc +{ + prop->addOptionDesc(mDefaultPartition, nil, OptionString, "Default Partition", ""); + prop->addOptionDesc(mHidePartition , mHidePartitionText, OptionString, "HidePartition", ""); + prop->addOptionDesc(mRenamePartition , mRenamePartitionText, OptionString, "RenamePartition", ""); +} + +//-------------------------------------------------------------------------- - (void) refreshLockStates { - [mDefaultPartition setEnabled:[[ChameleonPrefPane instance] isUnlocked]]; - [mDefaultPartitionText setEnabled:[[ChameleonPrefPane instance] isUnlocked]]; - [mHidePartition setEnabled:[[ChameleonPrefPane instance] isUnlocked]]; - [mHidePartitionText setEnabled:[[ChameleonPrefPane instance] isUnlocked]]; - [mRenamePartition setEnabled:[[ChameleonPrefPane instance] isUnlocked]]; - [mRenamePartitionText setEnabled:[[ChameleonPrefPane instance] isUnlocked]]; + [self refreshLockState: mSwapHD01 ]; + [self refreshLockState: mSwapHD02 ]; + [self refreshLockState: mFreezeParts ]; + [self refreshLockState: mInjectFrozenParts ]; + [self refreshLockState: mDefaultPartition ]; + [self refreshLockState: mDefaultPartitionText ]; + [self refreshLockState: mHidePartition ]; + [self refreshLockState: mHidePartitionText ]; + [self refreshLockState: mRenamePartition ]; + [self refreshLockState: mRenamePartitionText ]; } --(IBAction) onCheckButtonChange: (id) sender +//-------------------------------------------------------------------------- +-(void) setDefaultsValues: (NSMutableDictionary*) dict { + [mSwapHD01 setIntValue: [[dict objectForKey: keySwapHD01] intValue]]; + [mSwapHD02 setIntValue: [[dict objectForKey: keySwapHD02] intValue]]; + [mFreezeParts setIntValue: [[dict objectForKey: keyUseFrozenParts] intValue] ]; +} + +//-------------------------------------------------------------------------- +-(void) loadOptionsFromPreferencesFile: (NSMutableDictionary*) dict +{ + [dict setObject: [[NSNumber alloc] initWithBool: false] forKey: keySwapHD01]; + [dict setObject: [[NSNumber alloc] initWithBool: false] forKey: keySwapHD02]; + [dict setObject:[[NSNumber alloc] initWithBool: false] forKey: keyUseFrozenParts]; +} + +//-------------------------------------------------------------------------- +- (void) loadFrozenParts +{ + std::vector& partList = partExtractor->editPartList(); //rw + // iterate for all entries to add + char keyPartN[32] = ""; + char buffer[256]=""; + int k=0; + partList.clear(); + for (int i=0; i< [[self preferencesParts] count]; i++) + { + // get the key + snprintf(keyPartN, sizeof(keyPartN)-1, "partition%02d",i); + NSString* obj = [[self preferencesParts] objectForKey: [[NSString alloc] initWithUTF8String: keyPartN] ]; + // assign this key if valid + if (obj!=nil && [obj length]>0) + { + PartitionInfo p; + // parse string + strncpy(buffer, [obj UTF8String], sizeof(buffer)-1); + k=0; + for(const char* word = strtok(buffer,";"); word; word=strtok(NULL,sPartDescSep),k++) + { + switch (k) { + case 0: // parse disk number + if (isdigit(*word)) p.disk(*word-'0'); + break; + case 1: // parse partition number + if (isdigit(*word)) p.partition(*word-'0'); + break; + case 2: // parse volume label + p.label(word); + case 3: + p.fsType(word); + break; + default: + break; + } + } + partList.push_back(p); + } + } + partExtractor->sortPartList(); } --(IBAction) onTextFiedChange: (id) sender +//-------------------------------------------------------------------------- +- (void) swapDisks: (bool) bSwap src: (int) iSrc dst: (int) iDst; { + if(!partExtractor || !prop || !prop->isValid()) return; + if (bSwap) + { + partExtractor->swapHD(iSrc, iDst); + } + if ([mFreezeParts intValue]==0) + partExtractor->extractPartitions(); + else + [self loadFrozenParts ]; + + [ [self chameleon] selectDefaultPartition]; + } --(void) loadOptionsFromPreferencesFile +//-------------------------------------------------------------------------- +- (void) doSwapHD: (int) val save: (bool) doSave src: (int) isrc dst: (int) idst { + if( val>0 && ![[BootSetupController instance]->mFreezeParts intValue]) //on + { + [self swapDisks: true src:isrc dst:idst ]; + } + else + { + [self swapDisks: false src:isrc dst:idst ]; + } + + if(doSave) + { + if (isrc==0 && idst==1) + [[self preferencesFile] setObject: [NSNumber numberWithBool: val ? true : false] forKey: keySwapHD01]; + if (isrc==0 && idst==2) + [[self preferencesFile] setObject: [NSNumber numberWithBool: val ? true : false] forKey: keySwapHD02]; + [ [self chameleon] savePreferences:[self preferencesFile] ]; + } + + [[[ChameleonPrefPane instance] partitionsTable] reloadData]; + [[[ChameleonPrefPane instance] partitionsTable] scrollRowToVisible: 0]; + //[self tableViewSelectionDidChange: nil]; + } + +//-------------------------------------------------------------------------- +- (IBAction)onInjectPartsToFreeze: (id)sender +{ + int size = partExtractor ? partExtractor->partList().size() : 0; + if (!size) + { // nothing to inject + NSRunAlertPanel(@"Inject Partitions to Freeze Configuration", + @"No current partitions to inject, did you check boot config file ?",@"OK", nil,nil); + return; + } + // generate the parts list in preferences proplist + NSInteger n = NSRunAlertPanel(@"Inject Partitions to Freeze Configuration", + @"Are you sure you want to overwrite your Freeze settings with current partition list ?", + @"OK", @"Cancel",nil); + if (n==1) + { + // populate the dictionary with the current partitions + + // empty dictionary and update key in parent: + [[self preferencesFile] removeObjectForKey: keyPartitionsList]; + [[self preferencesParts] removeAllObjects ]; + + // iterate for all entries to add + char partDesc[256]=""; + char keyPartN[32] = ""; + for (int i=0; i< size; i++) + { + + const PartitionInfo& p =partExtractor->partList()[i]; + + // format the partition key and descriptor string + snprintf(keyPartN, sizeof(keyPartN)-1, "partition%02d",i); + + snprintf(partDesc, sizeof(partDesc)-1, "%d%c%d%c%s%c%s", + p.disk(), cPartDescSep, + p.partition(), cPartDescSep, + p.clabel(), cPartDescSep, + p.cfsType()); + + // write it to the dictionary + NSString * key = [[NSString alloc] initWithUTF8String: keyPartN]; + NSString * desc = [[NSString alloc] initWithUTF8String: partDesc]; + [[self preferencesParts] setObject: desc forKey: key]; + } + [[self preferencesFile] setObject: [self preferencesParts] forKey: keyPartitionsList]; + [self savePreferences ]; + } +} + +//-------------------------------------------------------------------------- +-(IBAction) onCheckButtonChange: (NSButton*) sender +{ + if (sender == mSwapHD01 || sender == mSwapHD01) + { + partExtractor->resetSwapping(); + [self doSwapHD: [mSwapHD01 intValue] save:true src:0 dst:1]; + [self doSwapHD: [mSwapHD02 intValue] save:true src:0 dst:2]; + } + else if (sender == mFreezeParts) + { + bool val = !![sender intValue]; + [[self preferencesFile] setObject: [NSNumber numberWithBool: val] forKey: keyUseFrozenParts]; + [[self chameleon] savePreferences: [self preferencesFile]]; + [ self onCheckButtonChange: mSwapHD01]; + } + else if (sender == mInjectFrozenParts) + { + [self onInjectPartsToFreeze: mInjectFrozenParts]; + } + else if ( [self handleSender:sender withButton: mDefaultPartition andField: mDefaultPartitionText + forKey: kDefaultPartition] ) + { + } + else if ( [self handleSender:sender withButton: mHidePartition andField: mHidePartitionText + forKey: kHidePartition] ) + { + } + else if ( [self handleSender:sender withButton: mRenamePartition andField: mRenamePartitionText + forKey: kHidePartition] ) + { + } +} + +//-------------------------------------------------------------------------- +-(IBAction) onTextFiedChange: (id) sender +{ + +} + +//-------------------------------------------------------------------------- + (BootSetupController *)instance { return(gInstance);} @end Index: trunk/ChameleonPrefPane/Sources/PropertyList.cpp =================================================================== --- trunk/ChameleonPrefPane/Sources/PropertyList.cpp (revision 0) +++ trunk/ChameleonPrefPane/Sources/PropertyList.cpp (revision 47) @@ -0,0 +1,343 @@ +/* + * property_list.cpp + * + * Created by Rekursor on 1/17/10. + * + */ + +#import "BootPropertyList.h" +#include +#include + +/****************************************************************************/ +/** + * Simple parsing and splitting args function, does handle env. vars + */ +static void parseArgs(const char * args, const char* argv[], int argvlen) +{ + // Create a list of args fron the space delimited args parameters + int n=0; + if (args && *args) + { + bool skipSpaces = true; + bool prevCharwasDelim =false; + char * buf = strdup(args); + char lastPriorityDelim=' '; + + printf("Parsing <%s>\n", args); + + int k=0; + for (int i=0; i< strlen(args); i++) + { + switch (args[i]) + { + case ' ': case '\t': + if(!skipSpaces) { + buf[k++]=args[i]; + } + else { + prevCharwasDelim = true; // // keep a track of delim to further split tokens + } + break; + case '\0': + case '\'': + case '"': + if (!skipSpaces &&lastPriorityDelim!=args[i]) + { // consider the imbricated delim as a simple char + buf[k++]=args[i]; + break; + } + + if (!skipSpaces) // end of priority substr + { + skipSpaces = true; + lastPriorityDelim=' '; + buf[k]='\0'; + argv[n++]=strdup(buf); // copy the priority substr + k=0; // reset the buf index for next token + buf[0]='\0'; + } + else + { // start of priority substr + skipSpaces=false; + lastPriorityDelim=args[i]; + if(k>0) // previous string to store first + { + buf[k++]='\0'; // finish the substr + argv[n++]=strdup(buf); // copy the substr + k=0; // rest the index for next token + buf[0]='\0'; + } + //if (args[i] !='\0') buf[k++] = args[i]; // start the new priority substr + } + break; + default: // non delimiters chars + if(skipSpaces && prevCharwasDelim) + { + if(k>0) // a previous substr was before the space + { // store previous token + buf[k++]='\0'; // finish the substr + argv[n++]=strdup(buf); // copy the substr + k=0; // rest the index for next token + buf[0]='\0'; + } + } + prevCharwasDelim = false; + buf[k++]=args[i]; + break; + } + } + + if(*buf) + { + buf[k]='\0'; + argv[n++]=strdup(buf); // copy the last buffer + } + free((void*) buf); + } + argv[n]=NULL; +} + +/****************************************************************************/ + bool executePrivilegedCmd(AuthorizationRef auth, + const char* pathToTool, + const char* args, + AuthorizationFlags flags) +{ + const char * argv[16]; + + parseArgs(args, argv, sizeof(argv)/sizeof(const char*)); + + // Execute Cmd + OSStatus status = AuthorizationExecuteWithPrivileges(auth, pathToTool,flags, (char**)argv, NULL); + + + // Cleanup mem + for (int i=0; argv[i]; i++) free ((void*) argv[i]); + + return status ? false : true; +} + + +/****************************************************************************/ +/** + * Write a property list from a file + */ +bool WritePropertyListToFile( CFPropertyListRef propertyList, CFURLRef fileURL ) +{ + CFDataRef xmlData; + Boolean status; + SInt32 errorCode; + + // Convert the property list into XML data. + xmlData = CFPropertyListCreateXMLData( kCFAllocatorDefault, propertyList ); + + // Write the XML data to the file. + status = CFURLWriteDataAndPropertiesToResource ( + fileURL, // URL to use + xmlData, // data to write + NULL, + &errorCode); + CFRelease(xmlData); + + return status ? true: false; +} + +/****************************************************************************/ +/** + * Read a property list from a file + */ +static CFPropertyListRef CreatePropertyListFromFile( CFURLRef fileURL, CFStringRef * errorString ) { + CFPropertyListRef propertyList; + CFDataRef resourceData; + Boolean status; + SInt32 errorCode; + + // Read the XML file. + status = CFURLCreateDataAndPropertiesFromResource( + kCFAllocatorDefault, + fileURL, + &resourceData, // place to put file data + NULL, + NULL, + &errorCode); + if (!status) return NULL; + + // Reconstitute the dictionary using the XML data. + propertyList = CFPropertyListCreateFromXMLData( kCFAllocatorDefault, + resourceData, + kCFPropertyListMutableContainersAndLeaves, + errorString); + + + CFRelease( resourceData ); + return propertyList; +} + +/****************************************************************************/ +static void show(CFStringRef formatString, ...) { + CFStringRef resultString; + CFDataRef data; + va_list argList; + + va_start(argList, formatString); + resultString = CFStringCreateWithFormatAndArguments(NULL, NULL, formatString, argList); + va_end(argList); + + data = CFStringCreateExternalRepresentation(NULL, resultString, CFStringGetSystemEncoding(), '?'); + + if (data != NULL) { + printf ("%.*s\n\n", (int)CFDataGetLength(data), CFDataGetBytePtr(data)); + CFRelease(data); + } + + CFRelease(resultString); +} +/****************************************************************************/ +/* + * Always return a valid static const string, if the CFSTR is not valid, then we return "" + */ +static const char * CfsToCs(CFStringRef inRef) +{ + static char buffer[512]=""; + if(CFStringGetFileSystemRepresentation (inRef, buffer, sizeof(buffer))) + return buffer; + return ""; +} + +/****************************************************************************/ +/** + * Creates a PropertyList Incstance + */ +PropertyList::~PropertyList() +{ + if (_CFURLRef) CFRelease(_CFURLRef); + if (_proplistRef) CFRelease(_proplistRef); + +} +bool PropertyList::chmodFile(const char * path, const char * chmodMask, + AuthorizationRef auth, AuthorizationFlags flags) +{ + if (!path || !*path) return false; + + if (auth) + { // give write temporary write rights to the file + std::string args = chmodMask; + args += ' '; + args += path; + if(!executePrivilegedCmd(auth, "/bin/chmod", args.c_str(), flags)) + return false; + } + return true; + +} + +/****************************************************************************/ +/** + * Open a properlist from a path name + */ +bool PropertyList::open(const char * path, CFStringRef * errorString, AuthorizationRef auth, AuthorizationFlags flags) +{ + bool ret = false; + + if (!path || !*path) return false; + struct stat st; + if(stat(path,&st) != 0) return false; // file does not exist; + + // give write temporary write rights to the file + if (!chmodFile(path,"0777", auth, flags)) return false; + + _propFilePath = path; + + CFStringRef cfPath = CFStringCreateWithCString (kCFAllocatorDefault, path, kCFStringEncodingUTF8); + CFURLRef inURL = CFURLCreateWithFileSystemPath( kCFAllocatorDefault, + cfPath, + kCFURLPOSIXPathStyle, // interpret as POSIX path + false ); // is it a directory? + CFRelease(cfPath); + if (_CFURLRef) CFRelease(_CFURLRef); + _CFURLRef = inURL; + + if (_CFURLRef) + { + _proplistRef = CreatePropertyListFromFile(inURL, errorString); + + if (_proplistRef) + ret= true; + } + // restore rights + ret= chmodFile(path,"0644", auth, flags); + + return ret; +} + +/****************************************************************************/ +/** + * Save the current property list + */ +bool PropertyList::save(AuthorizationRef auth, AuthorizationFlags flags) +{ + bool ret=false; + if (auth) + { // give write temporary write rights to the file + std::string args = " 0777 "+ _propFilePath; + if(!executePrivilegedCmd(auth, "/bin/chmod", args.c_str(), flags)) + return false; + } + if (_proplistRef && _CFURLRef) + ret= WritePropertyListToFile(_proplistRef,_CFURLRef); + if (auth) + { // give write temporary write rights to the file + std::string args = " 0644 "+ _propFilePath; + if(!executePrivilegedCmd(auth, "/bin/chmod", args.c_str(), flags)) + return false; + } + return ret; +} + +/****************************************************************************/ +/** + * Extract a sring value from a property list key, + * value returned is not owned by caller, copy it necessary. + */ +const char * PropertyList::getStringForKey(const char *key) +{ + if (!_proplistRef) return 0; + CFDictionaryRef myDict = + (CFGetTypeID(_proplistRef) == CFDictionaryGetTypeID()) ? (CFDictionaryRef) _proplistRef : NULL; + CFStringRef cfKey = CFStringCreateWithCString (kCFAllocatorDefault, key, kCFStringEncodingUTF8); + CFStringRef myString; + + if (myDict && CFDictionaryGetValueIfPresent(myDict, cfKey, (const void **) &myString)) + { + // show(CFSTR("Key '%@' found , value = <%@>\n"), cfKey, !myString ? CFSTR("") : myString); + CFRelease(cfKey); + return CfsToCs(myString); + } + + if(cfKey) CFRelease(cfKey); + return NULL; +} +/****************************************************************************/ +/** + * replace a sring value from a property list key, + * value returned is not owned by caller, copy it necessary. + */ +bool PropertyList::setStringForKey(const char *key, const char * value) +{ + if (!_proplistRef) return false; + bool ret = false; + CFMutableDictionaryRef myDict = + (CFGetTypeID(_proplistRef) == CFDictionaryGetTypeID()) ? (CFMutableDictionaryRef) _proplistRef : NULL; + CFStringRef cfKey = CFStringCreateWithCString (kCFAllocatorDefault, key, kCFStringEncodingUTF8); + CFStringRef myString = CFStringCreateWithCString (kCFAllocatorDefault, value, kCFStringEncodingUTF8); + + if (myDict) { + CFDictionaryReplaceValue(myDict, cfKey, myString); + ret=true; + } + if(cfKey) CFRelease(cfKey); + if(myString) CFRelease(myString); + return ret; +} + Index: trunk/ChameleonPrefPane/Sources/AdvancedSetupController.mm =================================================================== --- trunk/ChameleonPrefPane/Sources/AdvancedSetupController.mm (revision 46) +++ trunk/ChameleonPrefPane/Sources/AdvancedSetupController.mm (revision 47) @@ -17,53 +17,70 @@ return (gInstance = self); } -// TODO implement a smart & reusable option modification, usable by all controllers -// these pair of methods in each controller should all rely on a single external class instance (singleton) -// that would implement in an opaque way the options streaming between the panels and the pref. file +//-------------------------------------------------------------------------- +- (void) addOptionsDesc +{ + prop->addOptionDesc(mKernel, mKernelText, OptionKernel1, "", "mach_kernel"); // empty field for 1 field only "i.e: mach_kernel" syntax + prop->addOptionDesc(mDeviceRd, mDeviceRdText, OptionKernel, "rd", "disk0s1"); + prop->addOptionDesc(mArch, mArchText, OptionKernel, "arch", "X86_64"); + prop->addOptionDesc(mCPU, mCPUText, OptionKernel, "cpus", "4"); + prop->addOptionDesc(mBusRatio, mBusRatioText, OptionKernel, "busratio", "20"); + prop->addOptionDesc(mDebug, mDebugText, OptionString, "debug", "0x144"); + prop->addOptionDesc(mIO, mIOText, OptionString, "io", "0xffffffff"); + prop->addOptionDesc(mDisableKextsBlacklisting, nil, OptionString, "blacklist", "1"); + prop->addOptionDesc(mDSDTFile, mDSDTFileText, OptionString, "DSDT", ""); + prop->addOptionDesc(mDSDTDrop, nil, OptionYesNo, "DropSSDT", "No"); + prop->addOptionDesc(mSMBIOSFile,mSMBIOSFileText, OptionString, "SMBIOS", ""); + prop->addOptionDesc(mSMBIOSDefaults, nil, OptionYesNo, "SMBIOSdefaults", "No"); + prop->addOptionDesc(mWake, nil, OptionYesNo, "Wake", "No"); + prop->addOptionDesc(mForceWake, nil, OptionYesNo, "ForceWake", "No"); + prop->addOptionDesc(mWakeImage, mWakeImageText, OptionString, "WakeImage", ""); +} - (void) refreshLockStates { - [mKernel setEnabled:[[ChameleonPrefPane instance] isUnlocked]]; - [mKernelText setEnabled:[[ChameleonPrefPane instance] isUnlocked]]; - [mDeviceRd setEnabled:[[ChameleonPrefPane instance] isUnlocked]]; - [mDeviceRdText setEnabled:[[ChameleonPrefPane instance] isUnlocked]]; - [mArch setEnabled:[[ChameleonPrefPane instance] isUnlocked]]; - [mArchText setEnabled:[[ChameleonPrefPane instance] isUnlocked]]; - [mCPU setEnabled:[[ChameleonPrefPane instance] isUnlocked]]; - [mCPUText setEnabled:[[ChameleonPrefPane instance] isUnlocked]]; - [mBusRatio setEnabled:[[ChameleonPrefPane instance] isUnlocked]]; - [mBusRatioText setEnabled:[[ChameleonPrefPane instance] isUnlocked]]; - [mDebug setEnabled:[[ChameleonPrefPane instance] isUnlocked]]; - [mDebugText setEnabled:[[ChameleonPrefPane instance] isUnlocked]]; - [mIO setEnabled:[[ChameleonPrefPane instance] isUnlocked]]; - [mIOText setEnabled:[[ChameleonPrefPane instance] isUnlocked]]; - [mDisableKextsBlacklisting setEnabled:[[ChameleonPrefPane instance] isUnlocked]]; - [mDSDTFile setEnabled:[[ChameleonPrefPane instance] isUnlocked]]; - [mDSDTFileText setEnabled:[[ChameleonPrefPane instance] isUnlocked]]; - [mDSDTDrop setEnabled:[[ChameleonPrefPane instance] isUnlocked]]; - [mSMBIOSFile setEnabled:[[ChameleonPrefPane instance] isUnlocked]]; - [mSMBIOSFileText setEnabled:[[ChameleonPrefPane instance] isUnlocked]]; - [mSMBIOSDefaults setEnabled:[[ChameleonPrefPane instance] isUnlocked]]; - [mWake setEnabled:[[ChameleonPrefPane instance] isUnlocked]]; - [mForceWake setEnabled:[[ChameleonPrefPane instance] isUnlocked]]; - [mWakeImage setEnabled:[[ChameleonPrefPane instance] isUnlocked]]; - [mWakeImageText setEnabled:[[ChameleonPrefPane instance] isUnlocked]]; + [self refreshLockState: mKernel ]; + [self refreshLockState: mKernelText ]; + [self refreshLockState: mDeviceRd ]; + [self refreshLockState: mDeviceRdText ]; + [self refreshLockState: mArch ]; + [self refreshLockState: mArchText ]; + [self refreshLockState: mCPU ]; + [self refreshLockState: mCPUText ]; + [self refreshLockState: mBusRatio ]; + [self refreshLockState: mBusRatioText ]; + [self refreshLockState: mDebug ]; + [self refreshLockState: mDebugText ]; + [self refreshLockState: mIO ]; + [self refreshLockState: mIOText ]; + [self refreshLockState: mDisableKextsBlacklisting ]; + [self refreshLockState: mDSDTFile ]; + [self refreshLockState: mDSDTFileText ]; + [self refreshLockState: mDSDTDrop ]; + [self refreshLockState: mSMBIOSFile ]; + [self refreshLockState: mSMBIOSFileText ]; + [self refreshLockState: mSMBIOSDefaults ]; + [self refreshLockState: mWake ]; + [self refreshLockState: mForceWake ]; + [self refreshLockState: mWakeImage ]; + [self refreshLockState: mWakeImageText ]; } --(IBAction) onCheckButtonChange: (id) sender +-(void) loadOptionsFromPreferencesFile: (NSMutableDictionary*) dict { } --(IBAction) onTextFiedChange: (id) sender +-(IBAction) onCheckButtonChange: (NSButton*) sender { } --(void) loadOptionsFromPreferencesFile +-(IBAction) onTextFiedChange: (NSTextField*) sender { } + + (AdvancedSetupController *)instance { return(gInstance);} @end Index: trunk/ChameleonPrefPane/Sources/ChameleonPrefPane.h =================================================================== --- trunk/ChameleonPrefPane/Sources/ChameleonPrefPane.h (revision 46) +++ trunk/ChameleonPrefPane/Sources/ChameleonPrefPane.h (revision 47) @@ -9,9 +9,23 @@ #import #import +// Constants +static const NSString* const keyForceBootConfigPath = @"forceBootConfigPath"; +static const NSString* const keySwapHD01 = @"swapHD01"; +static const NSString* const keySwapHD02 = @"swapHD02"; +static const NSString* const keyUseFrozenParts = @"useFrozenParts"; +static const NSString* const keyPartitionsList = @"partitionsList"; +static const NSString* const kPreferencesFilePath = @"/Library/Preferences/com.chameleon.prefPane.plist"; +static const NSString* const keyPreferencesFileVersion = @"version"; // for future back compatibility +// Interface + @interface ChameleonPrefPane : NSPreferencePane { +@public + IBOutlet SFAuthorizationView *authView; + + @private // Objects corresponding to the interface mapping: IBOutlet NSTableView * mPartitionsTable; @@ -22,50 +36,43 @@ IBOutlet NSButton * mSleepButton; IBOutlet NSButton * mShutDownButton; IBOutlet NSButton * mRestartButton; - IBOutlet NSButton * mSwapHD01; - IBOutlet NSButton * mSwapHD02; - IBOutlet NSButton * mFreezeParts; - IBOutlet NSButton * mInjectFrozenParts; IBOutlet NSTextField* mStatusText; IBOutlet NSBox* mOptions; - IBOutlet SFAuthorizationView *authView; + + NSMutableDictionary* mOptionsDict; + NSMutableDictionary* mPartitionsDict; + NSImage* mMacOSXImage; NSImage* mWindowsImage; NSImage* mLinuxImage; NSImage* mUnknownImage; NSImage* mCDROMImage; - NSMutableDictionary* mOptionsDict; - NSMutableDictionary* mPartitionsDict; NSString* mOptionsPlistPath; int mPreferenceFileVersion; } + (ChameleonPrefPane*) instance; // return the current instance +- (void) loadPreferences; +- (bool) savePreferences: (NSDictionary*) dict; +- (NSMutableDictionary*) preferencesFile; +- (NSMutableDictionary*) preferencesParts; +- (NSTableView*) partitionsTable; + - (IBAction)onRestart: (id)sender; - (IBAction)onShutdown: (id)sender; - (IBAction)onSleep: (id)sender; -- (IBAction)onSwapHD: (id)sender; -- (IBAction)onUseFrozenParts: (id)sender; -- (IBAction)onInjectPartsToFreeze: (id)sender; -- (NSMutableDictionary*) getPreferencesFile; - - (void)awakeFromNib; - (void)initBootConfig; - (id) getImageResource: (NSString *) str ofType: (NSString*) sType; -- (void) loadPreferences; -- (bool) savePreferences: (NSDictionary*) dict; - (void)tableViewSelectionDidChange:(NSNotification *)notification; - (void) selectDefaultPartition; - (bool)isUnlocked; - (void) refreshLockStates; -- (void) doSwapHD: (int) val save: (bool) doSave src: (int)isrc dst: (int) idst; - (void)tableViewSelectionDidChange:(NSNotification *)notification; -- (void) swapDisks: (bool) bSwap src: (int) iSrc dst: (int) iDst; - @end Index: trunk/ChameleonPrefPane/Sources/PropertyList.h =================================================================== --- trunk/ChameleonPrefPane/Sources/PropertyList.h (revision 0) +++ trunk/ChameleonPrefPane/Sources/PropertyList.h (revision 47) @@ -0,0 +1,54 @@ +/* + * property_list.h + * + * Created by Rekursor on 1/17/10. + * + */ +#ifndef __CHPROPERTYLIST_LIST_H +#define __CHPROPERTYLIST_LIST_H + +#include +#include +#include +#include + +/****************************************************************/ + +/** + * priviledged command run for cmds like property chmods and restard command + */ +bool executePrivilegedCmd(AuthorizationRef auth, + const char* pathToTool, + const char* args=NULL, + AuthorizationFlags flags=kAuthorizationFlagDefaults); + +/****************************************************************/ + +/** + * Simple PropertyList Abstraction + */ +class PropertyList +{ + +public: + PropertyList() : _proplistRef(0), _CFURLRef(0) { } + virtual ~PropertyList(); + + bool open(const char *propListPath, CFStringRef* errString, + AuthorizationRef auth=NULL, AuthorizationFlags flags=kAuthorizationFlagDefaults); + bool save(AuthorizationRef auth=NULL, AuthorizationFlags flags=kAuthorizationFlagDefaults); + bool isValid() const { return _proplistRef!=NULL;} + + const char * getStringForKey(const char *key); + bool setStringForKey(const char* key, const char* value); + const char * propFilePath() const { return _propFilePath.c_str(); } + + static bool chmodFile(const char * path, const char * chmodMask, + AuthorizationRef auth, AuthorizationFlags flags=kAuthorizationFlagDefaults); +protected: + CFPropertyListRef _proplistRef; + CFURLRef _CFURLRef; + std::string _propFilePath; // keep a track of the proplist filename +}; + +#endif Index: trunk/ChameleonPrefPane/Sources/PreferencesControllerBase.mm =================================================================== --- trunk/ChameleonPrefPane/Sources/PreferencesControllerBase.mm (revision 46) +++ trunk/ChameleonPrefPane/Sources/PreferencesControllerBase.mm (revision 47) @@ -6,15 +6,110 @@ // #import "PreferencesControllerBase.h" +#include @implementation PreferencesControllerBase --(NSMutableDictionary*) getPreferencesDictionary +-(ChameleonPrefPane*) chameleon { return [ChameleonPrefPane instance]; } + +//-------------------------------------------------------------------------- +- (id) init { - if ([ChameleonPrefPane instance]==nil) return nil; + self = [super init]; + return self; +} + +//-------------------------------------------------------------------------- +// from the id to desc map in prop, set all default values for dict ++ (void) setDefaultValues: (NSMutableDictionary*) dict +{ - return [[ChameleonPrefPane instance] getPreferencesFile]; + for(const BootOptionDesc* bod = prop->firstOption();bod; bod=prop->nextOption()) + { + switch (bod->Type) + { + case OptionYesNo: + [(NSButton*)bod->ID setIntValue: (toupper(bod->Default[0])=='Y' ? 1 : 0) ]; + break; + case OptionKernel: + case OptionString: + [(NSButton*)bod->ID setIntValue: 0 ]; + case OptionKernel1: + [(NSTextField*)bod->contentID setStringValue: + [[NSString alloc] initWithUTF8String: bod->Default] ]; + break; + case OptionUnix: + [(NSButton*)bod->ID setIntValue: 0 ]; + break; + + default: + break; + } + } } +//-------------------------------------------------------------------------- +- (void) refreshLockState: (id) item +{ + [item setEnabled:[[ChameleonPrefPane instance] isUnlocked]]; + +} +//-------------------------------------------------------------------------- +- (void) loadPreferences +{ + [ [ChameleonPrefPane instance] loadPreferences]; +} + +//-------------------------------------------------------------------------- +- (bool) savePreferences +{ + return [ [ChameleonPrefPane instance] savePreferences: [self preferencesFile] ]; + +} +//-------------------------------------------------------------------------- +-(NSMutableDictionary*) preferencesFile +{ + return [[ChameleonPrefPane instance] preferencesFile]; +} + +//-------------------------------------------------------------------------- +-(NSMutableDictionary*) preferencesParts +{ + return [[ChameleonPrefPane instance] preferencesParts]; +} + +//-------------------------------------------------------------------------- +- (bool) handleSender: (id) sender withButton: (NSButton*) button forKey:(const char*) key +{ + return [self handleSender: sender withButton: button andField: nil forKey: key]; +} + +//-------------------------------------------------------------------------- +- (bool) handleSender: (id) sender withButton: (NSButton*) button andField:(NSTextField*) field forKey:(const char*) key +{ + if((NSButton*)sender!=button || (NSTextField*)sender !=field) return false; + if ((NSButton*)sender==button) + { + if (prop && prop->isValid()) + { + std::string keyValue = prop->getStringForKey(key); + if ( !![button intValue]) + { + + } + else + { + + } + } + } + else + { // field + + } + + return true; +} + @end Index: trunk/ChameleonPrefPane/Sources/PeripheralsController.h =================================================================== --- trunk/ChameleonPrefPane/Sources/PeripheralsController.h (revision 46) +++ trunk/ChameleonPrefPane/Sources/PeripheralsController.h (revision 47) @@ -17,7 +17,7 @@ IBOutlet NSButton* mBootBanner; IBOutlet NSButton* mVBIOS; IBOutlet NSButton* mVideoROM; - IBOutlet NSTextField* mVideoROMText; + IBOutlet NSTextField* mVideoROMText; IBOutlet NSButton* mGraphicsMode; IBOutlet NSTextField* mGraphicsModeText; @@ -30,6 +30,10 @@ IBOutlet NSButton* mEthernetBuiltIn; } + +- (IBAction) onCheckButtonChange: (NSButton*) sender; +- (IBAction) onTextFiedChange: (id) sender; + + (PeripheralsController *)instance; @end Index: trunk/ChameleonPrefPane/Sources/BootFlagsController.h =================================================================== --- trunk/ChameleonPrefPane/Sources/BootFlagsController.h (revision 46) +++ trunk/ChameleonPrefPane/Sources/BootFlagsController.h (revision 47) @@ -6,7 +6,7 @@ // #import -#import +#import "PreferencesControllerBase.h" // TabView subpane controller definition @@ -30,6 +30,9 @@ IBOutlet NSButton* mRescanSingleDrive; } +- (IBAction) onCheckButtonChange: (NSButton*) sender; +- (IBAction) onTextFiedChange: (id) sender; + + (BootFlagsController *)instance; @end Index: trunk/ChameleonPrefPane/Sources/BootSetupController.h =================================================================== --- trunk/ChameleonPrefPane/Sources/BootSetupController.h (revision 46) +++ trunk/ChameleonPrefPane/Sources/BootSetupController.h (revision 47) @@ -6,15 +6,22 @@ // #import -#import +#import "PreferencesControllerBase.h" +// Constants definitions +static const char* const kDefaultPartition = "Default Partition"; +static const char* const kHidePartition = "Hide Partition"; +static const char* const kRenamePartition = "Rename Partition"; // TabView subpane controller definition @interface BootSetupController : PreferencesControllerBase { - - // TODO move swap hds and freeze buttons to this class - +@public + IBOutlet NSButton * mSwapHD01; + IBOutlet NSButton * mSwapHD02; + IBOutlet NSButton * mFreezeParts; + IBOutlet NSButton * mInjectFrozenParts; + IBOutlet NSButton* mDefaultPartition; IBOutlet NSTextField* mDefaultPartitionText; @@ -26,7 +33,11 @@ } +- (IBAction) onCheckButtonChange: (NSButton*) sender; +- (IBAction) onTextFiedChange: (id) sender; +- (void) doSwapHD: (int) val save: (bool) doSave src: (int) isrc dst: (int) idst; + + (BootSetupController *)instance; @end Index: trunk/ChameleonPrefPane/ChameleonPrefPane.xcodeproj/project.pbxproj =================================================================== --- trunk/ChameleonPrefPane/ChameleonPrefPane.xcodeproj/project.pbxproj (revision 46) +++ trunk/ChameleonPrefPane/ChameleonPrefPane.xcodeproj/project.pbxproj (revision 47) @@ -23,13 +23,15 @@ 01993199110A2C61003B056E /* string_util.h in Headers */ = {isa = PBXBuildFile; fileRef = 01993198110A2C61003B056E /* string_util.h */; }; 019931DD110A37FA003B056E /* PreferencesControllerBase.h in Headers */ = {isa = PBXBuildFile; fileRef = 019931DB110A37FA003B056E /* PreferencesControllerBase.h */; }; 019931DE110A37FA003B056E /* PreferencesControllerBase.mm in Sources */ = {isa = PBXBuildFile; fileRef = 019931DC110A37FA003B056E /* PreferencesControllerBase.mm */; }; + 01993567110AA9FA003B056E /* BootPropertyList.h in Headers */ = {isa = PBXBuildFile; fileRef = 01993565110AA9FA003B056E /* BootPropertyList.h */; }; + 01993568110AA9FA003B056E /* BootPropertyList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 01993566110AA9FA003B056E /* BootPropertyList.cpp */; }; 01A40F75110550F4002A74CD /* CHANGES in Resources */ = {isa = PBXBuildFile; fileRef = 01A40F74110550F4002A74CD /* CHANGES */; }; 01B0E8141108B85A00ACF21B /* ChameleonPrefPane.h in Headers */ = {isa = PBXBuildFile; fileRef = 01B0E80E1108B85A00ACF21B /* ChameleonPrefPane.h */; }; 01B0E8151108B85A00ACF21B /* ChameleonPrefPane.mm in Sources */ = {isa = PBXBuildFile; fileRef = 01B0E80F1108B85A00ACF21B /* ChameleonPrefPane.mm */; }; - 01B0E8161108B85A00ACF21B /* process.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 01B0E8101108B85A00ACF21B /* process.cpp */; }; - 01B0E8171108B85A00ACF21B /* process.h in Headers */ = {isa = PBXBuildFile; fileRef = 01B0E8111108B85A00ACF21B /* process.h */; }; - 01B0E8181108B85A00ACF21B /* property_list.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 01B0E8121108B85A00ACF21B /* property_list.cpp */; }; - 01B0E8191108B85A00ACF21B /* property_list.h in Headers */ = {isa = PBXBuildFile; fileRef = 01B0E8131108B85A00ACF21B /* property_list.h */; }; + 01B0E8161108B85A00ACF21B /* ShellProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 01B0E8101108B85A00ACF21B /* ShellProcess.cpp */; }; + 01B0E8171108B85A00ACF21B /* ShellProcess.h in Headers */ = {isa = PBXBuildFile; fileRef = 01B0E8111108B85A00ACF21B /* ShellProcess.h */; }; + 01B0E8181108B85A00ACF21B /* PropertyList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 01B0E8121108B85A00ACF21B /* PropertyList.cpp */; }; + 01B0E8191108B85A00ACF21B /* PropertyList.h in Headers */ = {isa = PBXBuildFile; fileRef = 01B0E8131108B85A00ACF21B /* PropertyList.h */; }; 01B0E8201108B87A00ACF21B /* CDROM.png in Resources */ = {isa = PBXBuildFile; fileRef = 01B0E81A1108B87A00ACF21B /* CDROM.png */; }; 01B0E8211108B87A00ACF21B /* Chameleon.icns in Resources */ = {isa = PBXBuildFile; fileRef = 01B0E81B1108B87A00ACF21B /* Chameleon.icns */; }; 01B0E8221108B87A00ACF21B /* Chameleon.tiff in Resources */ = {isa = PBXBuildFile; fileRef = 01B0E81C1108B87A00ACF21B /* Chameleon.tiff */; }; @@ -63,13 +65,15 @@ 01993198110A2C61003B056E /* string_util.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = string_util.h; path = Sources/string_util.h; sourceTree = SOURCE_ROOT; }; 019931DB110A37FA003B056E /* PreferencesControllerBase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PreferencesControllerBase.h; path = Sources/PreferencesControllerBase.h; sourceTree = ""; }; 019931DC110A37FA003B056E /* PreferencesControllerBase.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = PreferencesControllerBase.mm; path = Sources/PreferencesControllerBase.mm; sourceTree = ""; }; + 01993565110AA9FA003B056E /* BootPropertyList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BootPropertyList.h; path = Sources/BootPropertyList.h; sourceTree = ""; }; + 01993566110AA9FA003B056E /* BootPropertyList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = BootPropertyList.cpp; path = Sources/BootPropertyList.cpp; sourceTree = ""; }; 01A40F74110550F4002A74CD /* CHANGES */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CHANGES; sourceTree = ""; }; 01B0E80E1108B85A00ACF21B /* ChameleonPrefPane.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ChameleonPrefPane.h; path = Sources/ChameleonPrefPane.h; sourceTree = ""; }; 01B0E80F1108B85A00ACF21B /* ChameleonPrefPane.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = ChameleonPrefPane.mm; path = Sources/ChameleonPrefPane.mm; sourceTree = ""; }; - 01B0E8101108B85A00ACF21B /* process.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = process.cpp; path = Sources/process.cpp; sourceTree = ""; }; - 01B0E8111108B85A00ACF21B /* process.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = process.h; path = Sources/process.h; sourceTree = ""; }; - 01B0E8121108B85A00ACF21B /* property_list.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = property_list.cpp; path = Sources/property_list.cpp; sourceTree = ""; }; - 01B0E8131108B85A00ACF21B /* property_list.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = property_list.h; path = Sources/property_list.h; sourceTree = ""; }; + 01B0E8101108B85A00ACF21B /* ShellProcess.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ShellProcess.cpp; path = Sources/ShellProcess.cpp; sourceTree = ""; }; + 01B0E8111108B85A00ACF21B /* ShellProcess.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ShellProcess.h; path = Sources/ShellProcess.h; sourceTree = ""; }; + 01B0E8121108B85A00ACF21B /* PropertyList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PropertyList.cpp; path = Sources/PropertyList.cpp; sourceTree = ""; }; + 01B0E8131108B85A00ACF21B /* PropertyList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PropertyList.h; path = Sources/PropertyList.h; sourceTree = ""; }; 01B0E81A1108B87A00ACF21B /* CDROM.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = CDROM.png; path = Resources/CDROM.png; sourceTree = ""; }; 01B0E81B1108B87A00ACF21B /* Chameleon.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; name = Chameleon.icns; path = Resources/Chameleon.icns; sourceTree = ""; }; 01B0E81C1108B87A00ACF21B /* Chameleon.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; name = Chameleon.tiff; path = Resources/Chameleon.tiff; sourceTree = ""; }; @@ -148,10 +152,10 @@ isa = PBXGroup; children = ( 01993198110A2C61003B056E /* string_util.h */, + 019931DB110A37FA003B056E /* PreferencesControllerBase.h */, + 019931DC110A37FA003B056E /* PreferencesControllerBase.mm */, 01B0E80E1108B85A00ACF21B /* ChameleonPrefPane.h */, 01B0E80F1108B85A00ACF21B /* ChameleonPrefPane.mm */, - 019931DB110A37FA003B056E /* PreferencesControllerBase.h */, - 019931DC110A37FA003B056E /* PreferencesControllerBase.mm */, 019930DF110A0CB4003B056E /* BootSetupController.h */, 019930E0110A0CB4003B056E /* BootSetupController.mm */, 019930E6110A0D80003B056E /* BootFlagsController.h */, @@ -160,10 +164,12 @@ 019930FD110A0E6F003B056E /* PeripheralsController.mm */, 01993113110A0EB9003B056E /* AdvancedSetupController.h */, 01993114110A0EB9003B056E /* AdvancedSetupController.mm */, - 01B0E8111108B85A00ACF21B /* process.h */, - 01B0E8101108B85A00ACF21B /* process.cpp */, - 01B0E8131108B85A00ACF21B /* property_list.h */, - 01B0E8121108B85A00ACF21B /* property_list.cpp */, + 01B0E8111108B85A00ACF21B /* ShellProcess.h */, + 01B0E8101108B85A00ACF21B /* ShellProcess.cpp */, + 01B0E8131108B85A00ACF21B /* PropertyList.h */, + 01B0E8121108B85A00ACF21B /* PropertyList.cpp */, + 01993565110AA9FA003B056E /* BootPropertyList.h */, + 01993566110AA9FA003B056E /* BootPropertyList.cpp */, ); name = Classes; sourceTree = ""; @@ -219,14 +225,15 @@ files = ( 8D202CEA0486D31800D8A456 /* StartupPrefPane_Prefix.pch in Headers */, 01B0E8141108B85A00ACF21B /* ChameleonPrefPane.h in Headers */, - 01B0E8171108B85A00ACF21B /* process.h in Headers */, - 01B0E8191108B85A00ACF21B /* property_list.h in Headers */, + 01B0E8171108B85A00ACF21B /* ShellProcess.h in Headers */, + 01B0E8191108B85A00ACF21B /* PropertyList.h in Headers */, 019930E1110A0CB4003B056E /* BootSetupController.h in Headers */, 019930E8110A0D80003B056E /* BootFlagsController.h in Headers */, 019930FE110A0E6F003B056E /* PeripheralsController.h in Headers */, 01993115110A0EB9003B056E /* AdvancedSetupController.h in Headers */, 01993199110A2C61003B056E /* string_util.h in Headers */, 019931DD110A37FA003B056E /* PreferencesControllerBase.h in Headers */, + 01993567110AA9FA003B056E /* BootPropertyList.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -311,13 +318,14 @@ buildActionMask = 2147483647; files = ( 01B0E8151108B85A00ACF21B /* ChameleonPrefPane.mm in Sources */, - 01B0E8161108B85A00ACF21B /* process.cpp in Sources */, - 01B0E8181108B85A00ACF21B /* property_list.cpp in Sources */, + 01B0E8161108B85A00ACF21B /* ShellProcess.cpp in Sources */, + 01B0E8181108B85A00ACF21B /* PropertyList.cpp in Sources */, 019930E2110A0CB4003B056E /* BootSetupController.mm in Sources */, 019930E9110A0D80003B056E /* BootFlagsController.mm in Sources */, 019930FF110A0E6F003B056E /* PeripheralsController.mm in Sources */, 01993116110A0EB9003B056E /* AdvancedSetupController.mm in Sources */, 019931DE110A37FA003B056E /* PreferencesControllerBase.mm in Sources */, + 01993568110AA9FA003B056E /* BootPropertyList.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; Index: trunk/ChameleonPrefPane/English.lproj/Chameleon.xib =================================================================== --- trunk/ChameleonPrefPane/English.lproj/Chameleon.xib (revision 46) +++ trunk/ChameleonPrefPane/English.lproj/Chameleon.xib (revision 47) @@ -12,7 +12,7 @@ YES - + YES @@ -72,7 +72,7 @@ 1 - + 292 YES @@ -724,7 +724,6 @@ {{10, 33}, {640, 267}} - Boot From ... @@ -733,7 +732,7 @@ 2 - + 256 YES @@ -762,7 +761,7 @@ 1211912703 2 - + NSImage NSSwitch @@ -818,7 +817,7 @@ 1211912703 2 - + @@ -859,7 +858,7 @@ 1211912703 2 - + @@ -913,32 +912,32 @@ 2 NO - + 12 YES - - + + 256 YES - - + + 268 {{12, 13}, {128, 18}} - + 2 YES - + 67239424 0 Swap hd 0<->1 - + 1211912703 2 - + @@ -946,22 +945,22 @@ 25 - - + + 268 {{150, 13}, {124, 18}} - + 2 YES - + 67239424 0 Swap hd 0<->2 - + 1211912703 2 - + @@ -969,22 +968,22 @@ 25 - - + + 268 {{297, 13}, {161, 18}} - + 2 YES - + 67239424 0 Use Freezed Parts List - + 1211912703 2 - + @@ -992,19 +991,19 @@ 25 - - + + 268 {{459, 7}, {159, 28}} - + 2 YES - + 67239424 134348800 Inject Parts in Freeze File - + -2038284033 129 @@ -1015,7 +1014,7 @@ {{1, 1}, {626, 47}} - + 2 @@ -1035,7 +1034,7 @@ MCAwLjgwMDAwMDAxAA - + 1 0 2 @@ -1043,6 +1042,7 @@ {{10, 33}, {640, 267}} + Boot Setup @@ -1079,7 +1079,7 @@ 1211912703 2 - + @@ -1101,7 +1101,7 @@ 1211912703 2 - + @@ -1123,7 +1123,7 @@ 1211912703 2 - + @@ -1145,7 +1145,7 @@ 1211912703 2 - + @@ -1184,7 +1184,7 @@ 1211912703 2 - + @@ -1206,7 +1206,7 @@ 1211912703 2 - + @@ -1228,7 +1228,7 @@ 1211912703 2 - + @@ -1236,21 +1236,21 @@ 25 - + 268 {{141, 75}, {109, 18}} YES - + 67239424 0 Safe Boot (-x) - + 1211912703 2 - + @@ -1307,7 +1307,7 @@ 1211912703 2 - + @@ -1329,7 +1329,7 @@ 1211912703 2 - + @@ -1351,7 +1351,7 @@ 1211912703 2 - + @@ -1422,7 +1422,7 @@ 1211912703 2 - + @@ -1444,7 +1444,7 @@ 1211912703 2 - + @@ -1483,7 +1483,7 @@ 1211912703 2 - + @@ -1505,7 +1505,7 @@ 1211912703 2 - + @@ -1544,7 +1544,7 @@ 1211912703 2 - + @@ -1552,21 +1552,21 @@ 25 - + 268 {{316, 44}, {98, 18}} YES - + 67239424 0 Video ROM - + 1211912703 2 - + @@ -1623,7 +1623,7 @@ 1211912703 2 - + @@ -1645,7 +1645,7 @@ 1211912703 2 - + @@ -1667,7 +1667,7 @@ 1211912703 2 - + @@ -1724,7 +1724,7 @@ 1211912703 2 - + @@ -1795,7 +1795,7 @@ 1211912703 2 - + @@ -1817,7 +1817,7 @@ 1211912703 2 - + @@ -1839,7 +1839,7 @@ 1211912703 2 - + @@ -1878,7 +1878,7 @@ 1211912703 2 - + @@ -1917,7 +1917,7 @@ 1211912703 2 - + @@ -1939,7 +1939,7 @@ 1211912703 2 - + @@ -1978,7 +1978,7 @@ 1211912703 2 - + @@ -2054,21 +2054,21 @@ - + 268 {{307, 15}, {184, 18}} YES - + 67239424 0 Disable kexts blacklisting - + 1211912703 2 - + @@ -2125,7 +2125,7 @@ 1211912703 2 - + @@ -2147,7 +2147,7 @@ 1211912703 2 - + @@ -2238,7 +2238,7 @@ 1211912703 2 - + @@ -2260,7 +2260,7 @@ 1211912703 2 - + @@ -2317,7 +2317,7 @@ 1211912703 2 - + @@ -2339,7 +2339,7 @@ 1211912703 2 - + @@ -2364,21 +2364,21 @@ - + 268 {{16, 12}, {63, 18}} YES - + 67239424 0 Wake - + 1211912703 2 - + @@ -2419,14 +2419,14 @@ - + 0 YES YES YES - + @@ -2465,7 +2465,7 @@ {224.664, 32} {1.79769e+308, 1.79769e+308} - + 8223 2 {{235, 265}, {464, 255}} @@ -2473,24 +2473,24 @@ About the Chameleon Preferences Pane NSPanel - + 256 YES - - + + 268 {{245, 218}, {38, 17}} - + YES - + 68288064 272630784 2.0.0 - + 1 @@ -2498,38 +2498,38 @@ - - + + 268 {{182, 218}, {52, 17}} - + YES - + 68288064 272630784 Version - + - - + + 268 {{46, 49}, {373, 154}} - + YES - + -1805517311 272629760 ICBJbml0aWFsIENvbmNlcHRpb24gJiBEZXNpZ246ICAKCVJla3Vyc29yCiAgCiAgQ3JldyBNZW1iZXJz OiAgCglSZWt1cnNvciwgICBEaWVCdWNoZQogIAogIENvbnRyaWJ1dG9ycyAmIFRlc3RlcnM6ICAKCUJs YWNrT1NYLCAgTWFzdGVyQ2hpZWYsICBkaWdpdGFsX2RyZWFtZXIsICBzbWl0aEBAA - + 1 MCAwIDAAA @@ -2548,16 +2548,16 @@ ChameleonPrefPane - + BootSetupController - + BootFlagsController - + PeripheralsController - + AdvancedSetupController @@ -2695,7 +2695,7 @@ mDefaultPartition - + 600 @@ -2703,7 +2703,7 @@ mHidePartition - + 601 @@ -2711,47 +2711,15 @@ mRenamePartition - + 602 - - onSwapHD: - - - - 612 - - - - onSwapHD: - - - - 613 - - - - onUseFrozenParts: - - - - 614 - - - - onInjectPartsToFreeze: - - - - 615 - - mVerbose - + 616 @@ -2759,15 +2727,15 @@ mSafeBoot - - + + 617 mIgnoreBootConfig - + 618 @@ -2775,7 +2743,7 @@ mTimeOut - + 619 @@ -2783,7 +2751,7 @@ mTimeOutText - + 620 @@ -2791,7 +2759,7 @@ mSingleUser - + 621 @@ -2799,7 +2767,7 @@ mQuietBoot - + 622 @@ -2807,7 +2775,7 @@ mInstantMenu - + 623 @@ -2815,7 +2783,7 @@ mWait - + 624 @@ -2823,7 +2791,7 @@ mRescan - + 625 @@ -2831,7 +2799,7 @@ mRescanPrompt - + 626 @@ -2839,7 +2807,7 @@ mRescanSingleDrive - + 627 @@ -2847,7 +2815,7 @@ mLegacyLogo - + 628 @@ -2855,7 +2823,7 @@ mBootBanner - + 629 @@ -2863,7 +2831,7 @@ mVBIOS - + 631 @@ -2871,15 +2839,15 @@ mVideoROM - - + + 632 mGraphicsMode - + 633 @@ -2887,7 +2855,7 @@ mGraphicsModeText - + 634 @@ -2895,7 +2863,7 @@ mGraphicsEnabler - + 635 @@ -2903,7 +2871,7 @@ mUSBBusFix - + 636 @@ -2911,7 +2879,7 @@ mEHCIacquire - + 637 @@ -2919,7 +2887,7 @@ mUHCIreset - + 638 @@ -2927,7 +2895,7 @@ mEthernetBuiltIn - + 639 @@ -2935,7 +2903,7 @@ mKernel - + 640 @@ -2943,7 +2911,7 @@ mKernelText - + 641 @@ -2951,7 +2919,7 @@ mDeviceRd - + 642 @@ -2959,7 +2927,7 @@ mVideoROMText - + 643 @@ -2967,7 +2935,7 @@ mHidePartitionText - + 644 @@ -2975,7 +2943,7 @@ mRenamePartitionText - + 645 @@ -2983,7 +2951,7 @@ mDefaultPartitionText - + 646 @@ -2991,7 +2959,7 @@ mDeviceRdText - + 647 @@ -2999,7 +2967,7 @@ mArch - + 648 @@ -3007,7 +2975,7 @@ mArchText - + 649 @@ -3015,7 +2983,7 @@ mCPU - + 650 @@ -3023,7 +2991,7 @@ mCPUText - + 651 @@ -3031,7 +2999,7 @@ mBusRatio - + 652 @@ -3039,7 +3007,7 @@ mBusRatioText - + 653 @@ -3047,7 +3015,7 @@ mDebug - + 654 @@ -3055,7 +3023,7 @@ mDebugText - + 655 @@ -3063,7 +3031,7 @@ mIO - + 656 @@ -3071,7 +3039,7 @@ mIOText - + 657 @@ -3079,15 +3047,15 @@ mDisableKextsBlacklisting - - + + 658 mDSDTFile - + 659 @@ -3095,7 +3063,7 @@ mDSDTFileText - + 660 @@ -3103,7 +3071,7 @@ mDSDTDrop - + 661 @@ -3111,7 +3079,7 @@ mSMBIOSFile - + 662 @@ -3119,7 +3087,7 @@ mSMBIOSFileText - + 663 @@ -3127,7 +3095,7 @@ mSMBIOSDefaults - + 664 @@ -3135,15 +3103,15 @@ mWake - - + + 665 mForceWake - + 666 @@ -3151,7 +3119,7 @@ mWakeImage - + 667 @@ -3159,7 +3127,7 @@ mWakeImageText - + 668 @@ -3167,7 +3135,7 @@ onCheckButtonChange: - + 669 @@ -3175,7 +3143,7 @@ onTextFiedChange: - + 670 @@ -3183,7 +3151,7 @@ onCheckButtonChange: - + 671 @@ -3191,7 +3159,7 @@ onTextFiedChange: - + 672 @@ -3199,7 +3167,7 @@ onCheckButtonChange: - + 673 @@ -3207,15 +3175,15 @@ onCheckButtonChange: - - + + 674 onTextFiedChange: - + 675 @@ -3223,7 +3191,7 @@ onCheckButtonChange: - + 676 @@ -3231,7 +3199,7 @@ onCheckButtonChange: - + 677 @@ -3239,7 +3207,7 @@ onCheckButtonChange: - + 678 @@ -3247,7 +3215,7 @@ onTextFiedChange: - + 679 @@ -3255,7 +3223,7 @@ onCheckButtonChange: - + 680 @@ -3263,7 +3231,7 @@ onTextFiedChange: - + 681 @@ -3271,7 +3239,7 @@ onCheckButtonChange: - + 682 @@ -3279,7 +3247,7 @@ onTextFiedChange: - + 683 @@ -3287,7 +3255,7 @@ onCheckButtonChange: - + 684 @@ -3295,42 +3263,74 @@ onTextFiedChange: - + 685 + + onCheckButtonChange: + + + + 691 + + + + onCheckButtonChange: + + + + 692 + + + + onCheckButtonChange: + + + + 693 + + + + onCheckButtonChange: + + + + 694 + + mSwapHD01 - - + + - 686 + 695 mSwapHD02 - - + + - 687 + 696 mFreezeParts - - + + - 688 + 697 mInjectFrozenParts - - + + - 689 + 698 @@ -3443,7 +3443,7 @@ YES - + @@ -3644,7 +3644,7 @@ - + @@ -3903,7 +3903,7 @@ - + @@ -4039,7 +4039,7 @@ - + @@ -4436,7 +4436,7 @@ - + @@ -4537,209 +4537,209 @@ 576 - + YES - + 577 - + YES - - - + + + - + 580 - + YES - + - + 581 - - + + 579 - + YES - + - + 582 - - + + 578 - + YES - + - + 583 - - + + 584 - + YES - + 585 - - + + 586 - + YES - + 587 - - + + 588 - + YES - + 589 - - + + 590 - + YES - + 591 - - + + 596 - + 597 - + 598 - + 599 - + 603 - + YES - - - - + + + + 604 - + YES - + - + 605 - + YES - + - + 606 - + YES - + - + 607 - + YES - + - + 608 - - + + 609 - - + + 610 - - + + 611 - - + + @@ -5007,9 +5007,9 @@ com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin - {{107, 164}, {668, 368}} + {{62, 335}, {668, 368}} com.apple.InterfaceBuilder.CocoaPlugin - {{107, 164}, {668, 368}} + {{62, 335}, {668, 368}} {224.664, 10} @@ -5481,7 +5481,7 @@ ToolTip ToolTip - + Define the GFX card video ROM file that should be loaded at boot @@ -5491,7 +5491,7 @@ ToolTip ToolTip - + Disable the blacklist kexts filtering in voodoo based kernels. Has no effect on vanilla kernels. (Enabled by default) @@ -5501,7 +5501,7 @@ ToolTip ToolTip - + Force displaying the partition selection menu (default=No) @@ -5520,7 +5520,7 @@ ToolTip ToolTip - + Use the freezed partitions list in located in the preference file for locking and manual handling purpose @@ -5529,7 +5529,7 @@ ToolTip ToolTip - + Swap disks indexes 0<->2, use this option if your disk sequence in osx does not match the chameleon boot disk sequence @@ -5538,7 +5538,7 @@ ToolTip ToolTip - + Use this feature to initially inject the current dynamically listed partitions. Then you can change manually the partition disk numbers and labels in the preference file @@ -5547,7 +5547,7 @@ ToolTip ToolTip - + Swap disks indexes 0<->1, use this option if your disk sequence in osx does not match the chameleon boot disk sequence @@ -5583,7 +5583,7 @@ - 689 + 698 @@ -5600,8 +5600,8 @@ YES + NSButton id - id @@ -5680,8 +5680,8 @@ YES + NSButton id - id @@ -5734,8 +5734,8 @@ YES + NSButton id - id @@ -5744,19 +5744,27 @@ YES mDefaultPartition mDefaultPartitionText + mFreezeParts mHidePartition mHidePartitionText + mInjectFrozenParts mRenamePartition mRenamePartitionText + mSwapHD01 + mSwapHD02 YES NSButton NSTextField NSButton + NSButton NSTextField NSButton + NSButton NSTextField + NSButton + NSButton @@ -5771,21 +5779,15 @@ YES YES - onInjectPartsToFreeze: onRestart: onShutdown: onSleep: - onSwapHD: - onUseFrozenParts: YES id id id - id - id - id @@ -5794,8 +5796,6 @@ YES authView mFileSystemColumn - mFreezeParts - mInjectFrozenParts mOptions mPartitionIDColumn mPartitionImgColumn @@ -5805,15 +5805,11 @@ mShutDownButton mSleepButton mStatusText - mSwapHD01 - mSwapHD02 YES SFAuthorizationView NSTableColumn - NSButton - NSButton NSBox NSTableColumn NSTableColumn @@ -5823,8 +5819,6 @@ NSButton NSButton NSTextField - NSButton - NSButton @@ -5860,8 +5854,8 @@ YES + NSButton id - id