Index: trunk/ChameleonPrefPane/Sources/AdvancedSetupController.h =================================================================== --- trunk/ChameleonPrefPane/Sources/AdvancedSetupController.h (revision 48) +++ trunk/ChameleonPrefPane/Sources/AdvancedSetupController.h (revision 49) @@ -46,7 +46,7 @@ } - (IBAction) onCheckButtonChange: (NSButton*) sender; -- (IBAction) onTextFiedChange: (id) sender; +- (IBAction) onTextFiedChange: (NSTextField*) sender; + (AdvancedSetupController *)instance; Index: trunk/ChameleonPrefPane/Sources/string_util.cpp =================================================================== --- trunk/ChameleonPrefPane/Sources/string_util.cpp (revision 0) +++ trunk/ChameleonPrefPane/Sources/string_util.cpp (revision 49) @@ -0,0 +1,34 @@ +/* + * string_util.cpp + * ChameleonPrefPane + * + * Created by Rekursor on 1/23/10. + */ + +#include "string_util.h" + +/* + * String Tokenizer + * In: src string and separator + * Out: a list of string tokens + */ +std::list tokenize(const std::string& src, const std::string& sep) +{ + std::list ret; + if (src.length()==0) return ret; + + std::string::size_type left=0, right=0; + std::string token; + std::string::size_type len = sep.length(); + + for (left=0; (right = src.find(sep, left)) != std::string::npos; left = right + len ) + { + token = src.substr (left, right-left); + if (token.length()>0) ret.push_back (token); + } + token = src.substr(left); + if (token.length()>0) ret.push_back (token); + + return ret; +} + Index: trunk/ChameleonPrefPane/Sources/BootPropertyList.cpp =================================================================== --- trunk/ChameleonPrefPane/Sources/BootPropertyList.cpp (revision 48) +++ trunk/ChameleonPrefPane/Sources/BootPropertyList.cpp (revision 49) @@ -14,11 +14,14 @@ std::map::iterator bod; for (bod=_idToDescDict.begin(); bod!=_idToDescDict.end(); bod++) if(bod->second) delete bod->second; + for (bod=_contentIdToDescDict.begin(); bod!=_contentIdToDescDict.end(); bod++) + if(bod->second) delete bod->second; } void BootPropertyList::clearOptionDesc() { deleteOptionDesc(); _idToDescDict.clear(); // now clear the pairs + _contentIdToDescDict.clear(); // now clear the pairs } Index: trunk/ChameleonPrefPane/Sources/BootPropertyList.h =================================================================== --- trunk/ChameleonPrefPane/Sources/BootPropertyList.h (revision 48) +++ trunk/ChameleonPrefPane/Sources/BootPropertyList.h (revision 49) @@ -48,7 +48,10 @@ // 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 : ""); + if (ID) _idToDescDict[ID] = + new BootOptionDesc(ID, cID, t, szName? szName : "", szDefault ? szDefault : ""); + if (cID) _contentIdToDescDict[cID] = + new BootOptionDesc(ID, cID, t, szName? szName : "", szDefault ? szDefault : ""); } // find the desc corresponding to id: @@ -59,6 +62,14 @@ return bod->second; } + // find the option bod corresponding to contentID + const BootOptionDesc* findOptionContent(void *cID) const + { + std::map::const_iterator bod; + if (!cID || (bod=_contentIdToDescDict.find(cID))==_contentIdToDescDict.end()) return NULL; + return bod->second; + } + // opaque enumeration for the map const BootOptionDesc* firstOption() { @@ -80,7 +91,8 @@ void deleteOptionDesc(); private: - std::map _idToDescDict; // dictionary for id -> desc association type + // dictionary for id -> desc and contentID -> desc association type + std::map _idToDescDict, _contentIdToDescDict; std::map::const_iterator _bod; }; Index: trunk/ChameleonPrefPane/Sources/PeripheralsController.mm =================================================================== --- trunk/ChameleonPrefPane/Sources/PeripheralsController.mm (revision 48) +++ trunk/ChameleonPrefPane/Sources/PeripheralsController.mm (revision 49) @@ -55,7 +55,6 @@ { } - //-------------------------------------------------------------------------- -(IBAction) onCheckButtonChange: (NSButton*) sender { Index: trunk/ChameleonPrefPane/Sources/BootSetupController.mm =================================================================== --- trunk/ChameleonPrefPane/Sources/BootSetupController.mm (revision 48) +++ trunk/ChameleonPrefPane/Sources/BootSetupController.mm (revision 49) @@ -62,16 +62,6 @@ } //-------------------------------------------------------------------------- --(void) loadOptionsFromBootFile -{ -// // Get the Partitions options -// [self loadOptionFromBootFile: mDefaultPartition]; -// [self loadOptionFromBootFile: mHidePartition]; -// [self loadOptionFromBootFile: mRenamePartition]; -} - -//-------------------------------------------------------------------------- -//-------------------------------------------------------------------------- - (void) loadFrozenParts { std::vector& partList = partExtractor->editPartList(); //rw @@ -234,24 +224,12 @@ { [self onInjectPartsToFreeze: mInjectFrozenParts]; } - - // Factorize this code by using the options descriptor map: - 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] ) - { - } + // Handle BootOptions generically: + else + [self handleSender:sender]; } - //-------------------------------------------------------------------------- --(IBAction) onTextFiedChange: (id) sender +-(IBAction) onTextFiedChange: (NSTextField*) sender { } Index: trunk/ChameleonPrefPane/Sources/PropertyList.cpp =================================================================== --- trunk/ChameleonPrefPane/Sources/PropertyList.cpp (revision 48) +++ trunk/ChameleonPrefPane/Sources/PropertyList.cpp (revision 49) @@ -175,25 +175,6 @@ } /****************************************************************************/ -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 "" */ @@ -260,10 +241,13 @@ if (_CFURLRef) { + CFRetain(_CFURLRef); _proplistRef = CreatePropertyListFromFile(inURL, errorString); - if (_proplistRef) + if (_proplistRef) { + CFRetain(_proplistRef); ret= true; + } } // restore rights ret= chmodFile(path,"0644", auth, flags); @@ -302,15 +286,13 @@ */ const char * PropertyList::getStringForKey(const char *key) { - if (!_proplistRef) return 0; - CFDictionaryRef myDict = - (CFGetTypeID(_proplistRef) == CFDictionaryGetTypeID()) ? (CFDictionaryRef) _proplistRef : NULL; + if (!_proplistRef) return NULL; CFStringRef cfKey = CFStringCreateWithCString (kCFAllocatorDefault, key, kCFStringEncodingUTF8); CFStringRef myString; - if (myDict && CFDictionaryGetValueIfPresent(myDict, cfKey, (const void **) &myString)) + if (_proplistRef && CFDictionaryGetValueIfPresent((CFMutableDictionaryRef)_proplistRef, + cfKey, (const void **) &myString)) { - // show(CFSTR("Key '%@' found , value = <%@>\n"), cfKey, !myString ? CFSTR("") : myString); CFRelease(cfKey); return CfsToCs(myString); } @@ -327,17 +309,36 @@ { 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); + CFMutableDictionaryRef myDict = (CFMutableDictionaryRef) _proplistRef; - if (myDict) { - CFDictionaryReplaceValue(myDict, cfKey, myString); + if (myDict) + { + CFDictionarySetValue(myDict, cfKey, myString); ret=true; } if(cfKey) CFRelease(cfKey); - if(myString) CFRelease(myString); + //if(myString) CFRelease(myString); return ret; } +/****************************************************************************/ +/** + * delete a key and its value from the dictionary + */ +bool PropertyList::removeKeyAndValue(const char *key) +{ + if (!_proplistRef) return false; + bool ret = false; + + CFStringRef cfKey = CFStringCreateWithCString (kCFAllocatorDefault, key, kCFStringEncodingUTF8); + + if (_proplistRef) { + CFDictionaryRemoveValue((CFMutableDictionaryRef) _proplistRef, cfKey); + ret=true; + } + if(cfKey) CFRelease(cfKey); + return ret; +} + Index: trunk/ChameleonPrefPane/Sources/PropertyList.h =================================================================== --- trunk/ChameleonPrefPane/Sources/PropertyList.h (revision 48) +++ trunk/ChameleonPrefPane/Sources/PropertyList.h (revision 49) @@ -34,15 +34,27 @@ PropertyList() : _proplistRef(0), _CFURLRef(0) { } virtual ~PropertyList(); + bool isValid() const { return _proplistRef!=NULL;} + 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); + const char * getStringForKey(const std::string& key) + { + std::string str= key; + return getStringForKey(str.c_str()); + } bool setStringForKey(const char* key, const char* value); + bool setStringForKey(const std::string& key, const std::string& value) + { + return setStringForKey(key.c_str(), value.c_str()); + } + bool removeKeyAndValue(const char *key); + const char * propFilePath() const { return _propFilePath.c_str(); } - + static bool chmodFile(const char * path, const char * chmodMask, AuthorizationRef auth, AuthorizationFlags flags=kAuthorizationFlagDefaults); protected: Index: trunk/ChameleonPrefPane/Sources/PreferencesControllerBase.mm =================================================================== --- trunk/ChameleonPrefPane/Sources/PreferencesControllerBase.mm (revision 48) +++ trunk/ChameleonPrefPane/Sources/PreferencesControllerBase.mm (revision 49) @@ -67,6 +67,14 @@ } //-------------------------------------------------------------------------- +// get authorisation from main panel lock +- (AuthorizationRef) getAuthorization +{ + AuthorizationRef auth= [[self chameleon] isUnlocked] ? + [[ [self chameleon]->authView authorization] authorizationRef] : NULL; + return auth; +} +//-------------------------------------------------------------------------- + (void) registerPreferencesGroup:(id) myGroup { groupList.push_back(myGroup); @@ -105,7 +113,6 @@ //-------------------------------------------------------------------------- + (void) loadOptionsFromBootFile { - // *** TODO // parse unix like command string: kernelFlags.parseOptions(prop->getStringForKey(kKernelFlags)); @@ -147,9 +154,14 @@ } break; case OptionString: - [(NSButton*)optionID setIntValue: (s.length()>0 ? 1 : 0 ) ]; + { + int val = (s.length()>0 ? 1 : 0 ); + [(NSButton*)optionID setIntValue: val ]; [(NSTextField*) bod->contentID setStringValue: [[NSString alloc] initWithUTF8String: s.c_str()] ]; + [(NSTextField*) bod->contentID setEnabled: val ? true: false]; + [(NSTextField*) bod->contentID setEditable: val ? true : false]; + } break; case OptionUnix: @@ -186,6 +198,7 @@ } } + //-------------------------------------------------------------------------- - (void) refreshLockState: (id) item { @@ -206,6 +219,82 @@ } //-------------------------------------------------------------------------- +// update the boot Config with one option change and its associated desc +- (bool) saveBootConfig: (id) sender withBootOptionDesc: (BootOptionDesc*) bod +{ + if(!bod) + { + return false; + } + // load boot config file so that we don't risk to loose + // externally modified parameters + + int val = [(NSButton*) sender intValue ]; + std::string sDefaultValue = trim(bod->Default ? bod->Default : ""); + bool status = false; + + switch (bod->Type) { + case OptionYesNo: + { + std::string sVal = val ? "Yes" : "No"; + if (sDefaultValue.length()==0) sDefaultValue = "No"; + // Avoid populating bootConfig with unnecessary options: + if (sVal == sDefaultValue) + status = prop->removeKeyAndValue(bod->Name); + else + status = prop->setStringForKey(bod->Name, sVal.c_str()); + } + break; + case OptionUnix: + if (!val) kernelFlags.removeFlag(bod->Name); + else kernelFlags.addFlag(bod->Name); + prop->setStringForKey(kKernelFlags,kernelFlags.options()); + status = true; + break; + case OptionKernel: + { + std::string contentValue = + [ [(NSTextField*) bod->contentID stringValue] UTF8String ]; + if (!val) kernelFlags.removeFlag(kernelFlags.stringFromKey(bod->Name)); + else + { + std::string concat = bod->Name; + concat+= "="; + concat+= trim(contentValue); + kernelFlags.addFlag(concat); + } + prop->setStringForKey(kKernelFlags,kernelFlags.options()); + status = true; + } + break; + case OptionKernel1: + case OptionString: + // Avoid populating bootConfig with unnecessary options: + if (val == 0 && bod->Type!=OptionKernel1) + status = prop->removeKeyAndValue(bod->Name); + else + { + std::string contentValue = + [ [(NSTextField*) bod->contentID stringValue] UTF8String ]; + if (contentValue.length()>0) + status = prop->setStringForKey(bod->Name, contentValue.c_str()); + else { + return false; // no content to save so don't save it + } + + } + break; + default: + break; + } + + // Now save the bootConfig + AuthorizationRef auth = [self getAuthorization ]; + if (status) status = prop->save(auth); + + return status; +} +//-------------------------------------------------------------------------- -(NSMutableDictionary*) preferencesFile { return [[ChameleonPrefPane instance] preferencesFile]; @@ -224,6 +313,7 @@ const BootOptionDesc * bod = prop->findOption(sender); if (!bod) { + bod = prop->findOptionContent(sender); NSTextField* textField = (NSTextField*) sender; std::string content = [[textField stringValue] UTF8String ]; } @@ -243,6 +333,11 @@ break; } } + if(![self saveBootConfig: sender withBootOptionDesc: (BootOptionDesc*) bod] && !bod->contentID ) + { // Couldn't save, so warn user ... + NSRunAlertPanel(@"Error saving bootConfig", @"Could not save com.apple.Boot.plist", + @"OK", nil, nil); + } return true; } Index: trunk/ChameleonPrefPane/Sources/PeripheralsController.h =================================================================== --- trunk/ChameleonPrefPane/Sources/PeripheralsController.h (revision 48) +++ trunk/ChameleonPrefPane/Sources/PeripheralsController.h (revision 49) @@ -32,7 +32,7 @@ } - (IBAction) onCheckButtonChange: (NSButton*) sender; -- (IBAction) onTextFiedChange: (id) sender; +- (IBAction) onTextFiedChange: (NSTextField*) sender; + (PeripheralsController *)instance; Index: trunk/ChameleonPrefPane/Sources/KernOptionsParser.cpp =================================================================== --- trunk/ChameleonPrefPane/Sources/KernOptionsParser.cpp (revision 0) +++ trunk/ChameleonPrefPane/Sources/KernOptionsParser.cpp (revision 49) @@ -0,0 +1,74 @@ +/* + * KernOptionsParser.cpp + * ChameleonPrefPane + * + * Created by Rekursor on 1/23/10. + */ + +#include "KernOptionsParser.h" +#include "string_util.h" + +bool KernOptionsParser::parseOptions(const char* options) +{ + _options = options ? trim(options) : ""; + std::string token, temp=_options; + + // first remove spaces around '=' to simplify parsing + std::string::size_type found = std::string::npos; + while ((found=_options.find(" =")) != std::string::npos) _options.replace(found, 3,"="); + while ((found=_options.find("= ")) != std::string::npos) _options.replace(found, 3,"="); + + // then tokenize the string + _optionsList = tokenize(_options); + + return true; +} + +static const std::string sEmpty=""; + +// get the corresponding kern option "xxxx=yyyy" +const std::string& KernOptionsParser::stringFromKey(const std::string& key) const +{ + for (std::list::const_iterator it=_optionsList.begin(); it!=_optionsList.end(); it++) + if (it->find(key)!=std::string::npos) return *it; + + return sEmpty; +} + +// get the left member of kern option "xxxx=yyyy" +const std::string& KernOptionsParser::leftMember(const std::string& expression) const +{ + static std::string sLeft; + std::string::size_type pos = expression.find('='); + + if (pos!=std::string::npos) + return (sLeft = expression.substr(0, pos)); + return expression; +} + +// get the right member of kern option "xxxx=yyyy" +const std::string& KernOptionsParser::rightMember(const std::string& expression) const +{ + static std::string sLeft; + std::string::size_type pos = expression.find('='); + + if (pos!=std::string::npos) + return (sLeft = expression.substr(pos+1)); + return expression; +} +// remove a flag in the string +void KernOptionsParser::removeFlag(const std::string& flag) +{ + std::string::size_type found = _options.find(flag); + if (found==std::string::npos) return; + _options.erase(found, found+flag.length()); +} + +// remove a flag in the string +void KernOptionsParser::addFlag(const std::string& flag) +{ + std::string::size_type found = _options.find(flag); + if (found!=std::string::npos) return; + _options = " " + _options; + _options = flag + _options; +} Index: trunk/ChameleonPrefPane/Sources/BootFlagsController.h =================================================================== --- trunk/ChameleonPrefPane/Sources/BootFlagsController.h (revision 48) +++ trunk/ChameleonPrefPane/Sources/BootFlagsController.h (revision 49) @@ -31,7 +31,7 @@ } - (IBAction) onCheckButtonChange: (NSButton*) sender; -- (IBAction) onTextFiedChange: (id) sender; +- (IBAction) onTextFiedChange: (NSTextField*) sender; + (BootFlagsController *)instance; Index: trunk/ChameleonPrefPane/Sources/KernOptionsParser.h =================================================================== --- trunk/ChameleonPrefPane/Sources/KernOptionsParser.h (revision 0) +++ trunk/ChameleonPrefPane/Sources/KernOptionsParser.h (revision 49) @@ -0,0 +1,37 @@ +/* + * KernOptionsParser.h + * ChameleonPrefPane + * + * Created by Rekursor on 1/23/10. + */ +#include +#include + +class KernOptionsParser +{ +public: + KernOptionsParser() {} + + // extract from the string all kern options + bool parseOptions(const char* options); + + // get the corresponding kern option "xxxx=yyyy" + const std::string& stringFromKey(const std::string& key) const; + + // get the left member of kern option "xxxx=yyyy" + const std::string& leftMember(const std::string& expression) const; + + // get the right member of kern option "xxxx=yyyy" + const std::string& rightMember(const std::string& expression) const; + + // add / remove a kernel Flags in the string + void addFlag(const std::string& flag); + void removeFlag(const std::string& flag); + + const std::string& options() const { return _options;} + +private: + bool _status; + std::string _options; + std::list _optionsList; +}; \ No newline at end of file Index: trunk/ChameleonPrefPane/Sources/BootSetupController.h =================================================================== --- trunk/ChameleonPrefPane/Sources/BootSetupController.h (revision 48) +++ trunk/ChameleonPrefPane/Sources/BootSetupController.h (revision 49) @@ -34,7 +34,7 @@ } - (IBAction) onCheckButtonChange: (NSButton*) sender; -- (IBAction) onTextFiedChange: (id) sender; +- (IBAction) onTextFiedChange: (NSTextField*) sender; - (void) doSwapHD: (int) val save: (bool) doSave src: (int) isrc dst: (int) idst; Index: trunk/ChameleonPrefPane/English.lproj/Chameleon.xib =================================================================== --- trunk/ChameleonPrefPane/English.lproj/Chameleon.xib (revision 48) +++ trunk/ChameleonPrefPane/English.lproj/Chameleon.xib (revision 49) @@ -12,7 +12,7 @@ YES - + YES @@ -1161,7 +1161,7 @@ -1536033215 272630784 - 8 + YES @@ -3464,6 +3464,174 @@ 715 + + + onCheckButtonChange: + + + + 716 + + + + onCheckButtonChange: + + + + 717 + + + + onCheckButtonChange: + + + + 718 + + + + onCheckButtonChange: + + + + 719 + + + + onCheckButtonChange: + + + + 720 + + + + onCheckButtonChange: + + + + 721 + + + + onCheckButtonChange: + + + + 722 + + + + onCheckButtonChange: + + + + 723 + + + + onCheckButtonChange: + + + + 725 + + + + onCheckButtonChange: + + + + 726 + + + + onCheckButtonChange: + + + + 727 + + + + onCheckButtonChange: + + + + 728 + + + + onCheckButtonChange: + + + + 729 + + + + onCheckButtonChange: + + + + 730 + + + + onCheckButtonChange: + + + + 731 + + + + onCheckButtonChange: + + + + 732 + + + + onCheckButtonChange: + + + + 733 + + + + onCheckButtonChange: + + + + 734 + + + + onTextFiedChange: + + + + 735 + + + + onTextFiedChange: + + + + 736 + + + + onTextFiedChange: + + + + 737 + @@ -4020,9 +4188,9 @@ - + @@ -4150,7 +4318,6 @@ YES - @@ -4165,6 +4332,7 @@ + @@ -5135,9 +5303,9 @@ com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin - {{344, 266}, {668, 368}} + {{326, 204}, {668, 368}} com.apple.InterfaceBuilder.CocoaPlugin - {{344, 266}, {668, 368}} + {{326, 204}, {668, 368}} {224.664, 10} @@ -5707,7 +5875,7 @@ - 715 + 737 @@ -5725,7 +5893,7 @@ YES NSButton - id + NSTextField @@ -5805,7 +5973,7 @@ YES NSButton - id + NSTextField @@ -5859,7 +6027,7 @@ YES NSButton - id + NSTextField @@ -5979,7 +6147,7 @@ YES NSButton - id + NSTextField