2 * Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
23 /* CFApplicationPreferences.c
24 Copyright 1998-2002, Apple, Inc. All rights reserved.
25 Responsibility: Chris Parker
28 #include <CoreFoundation/CFPreferences.h>
29 #include "CFInternal.h"
30 #include <CoreFoundation/CFUniChar.h>
31 #include <CoreFoundation/CFNumber.h>
33 static Boolean
_CFApplicationPreferencesSynchronizeNoLock(_CFApplicationPreferences
*self
);
34 void _CFPreferencesDomainSetMultiple(CFPreferencesDomainRef domain
, CFDictionaryRef dict
);
35 static void updateDictRep(_CFApplicationPreferences
*self
);
36 Boolean
_CFApplicationPreferencesContainsDomainNoLock(_CFApplicationPreferences
*self
, CFPreferencesDomainRef domain
);
38 static void *__CFInsertionDomain
= NULL
;
39 static CFDictionaryRef __CFInsertion
= NULL
;
42 extern CFSpinLock_t userDefaultsLock
;
43 extern void *userDefaults
;
45 // Management externals
46 extern Boolean _CFPreferencesManagementActive
;
49 #define CF_OBJC_KVO_WILLCHANGE(obj, sel)
50 #define CF_OBJC_KVO_DIDCHANGE(obj, sel)
53 // Right now, nothing is getting destroyed pretty much ever. We probably don't want this to be the case, but it's very tricky - domains live in the cache as well as a given application's preferences, and since they're not CFTypes, there's no reference count. Also, it's not clear we ever want domains destroyed. When they're synchronized, they clear their internal state (to force reading from the disk again), so they're not very big.... REW, 12/17/98
55 CFPropertyListRef
CFPreferencesCopyAppValue(CFStringRef key
, CFStringRef appName
) {
56 _CFApplicationPreferences
*standardPrefs
;
57 CFAssert1(appName
!= NULL
, __kCFLogAssertion
, "%s(): Cannot access application preferences with a NULL application name", __PRETTY_FUNCTION__
);
58 CFAssert1(key
!= NULL
, __kCFLogAssertion
, "%s(): Cannot access preferences with a NULL key", __PRETTY_FUNCTION__
);
60 standardPrefs
= _CFStandardApplicationPreferences(appName
);
61 return standardPrefs
? _CFApplicationPreferencesCreateValueForKey(standardPrefs
, key
) : NULL
;
64 CF_EXPORT Boolean
CFPreferencesAppBooleanValue(CFStringRef key
, CFStringRef appName
, Boolean
*keyExistsAndHasValidFormat
) {
65 CFPropertyListRef value
;
66 Boolean result
, valid
;
68 CFAssert1(appName
!= NULL
, __kCFLogAssertion
, "%s(): Cannot access application preferences with a NULL application name", __PRETTY_FUNCTION__
);
69 CFAssert1(key
!= NULL
, __kCFLogAssertion
, "%s(): Cannot access preferences with a NULL key", __PRETTY_FUNCTION__
);
71 if (!keyExistsAndHasValidFormat
) {
72 keyExistsAndHasValidFormat
= &valid
;
74 value
= CFPreferencesCopyAppValue(key
, appName
);
76 *keyExistsAndHasValidFormat
= false;
79 typeID
= CFGetTypeID(value
);
80 if (typeID
== CFStringGetTypeID()) {
81 if (CFStringCompare(value
, CFSTR("true"), kCFCompareCaseInsensitive
) == kCFCompareEqualTo
|| CFStringCompare(value
, CFSTR("YES"), kCFCompareCaseInsensitive
) == kCFCompareEqualTo
) {
82 *keyExistsAndHasValidFormat
= true;
84 } else if (CFStringCompare(value
, CFSTR("false"), kCFCompareCaseInsensitive
) == kCFCompareEqualTo
|| CFStringCompare(value
, CFSTR("NO"), kCFCompareCaseInsensitive
) == kCFCompareEqualTo
) {
85 *keyExistsAndHasValidFormat
= true;
88 *keyExistsAndHasValidFormat
= false;
91 } else if (typeID
== CFNumberGetTypeID()) {
92 if (CFNumberIsFloatType(value
)) {
93 *keyExistsAndHasValidFormat
= false;
97 *keyExistsAndHasValidFormat
= true;
98 CFNumberGetValue(value
, kCFNumberIntType
, &i
);
99 result
= (i
== 0) ? false : true;
101 } else if (typeID
== CFBooleanGetTypeID()) {
102 result
= (value
== kCFBooleanTrue
);
103 *keyExistsAndHasValidFormat
= true;
107 *keyExistsAndHasValidFormat
= false;
113 __private_extern__ CFIndex
CFPreferencesAppIntegerValue(CFStringRef key
, CFStringRef appName
, Boolean
*keyExistsAndHasValidFormat
) {
114 CFPropertyListRef value
;
118 CFAssert1(appName
!= NULL
, __kCFLogAssertion
, "%s(): Cannot access application preferences with a NULL application name", __PRETTY_FUNCTION__
);
119 CFAssert1(key
!= NULL
, __kCFLogAssertion
, "%s(): Cannot access preferences with a NULL key", __PRETTY_FUNCTION__
);
121 value
= CFPreferencesCopyAppValue(key
, appName
);
122 if (!keyExistsAndHasValidFormat
) {
123 keyExistsAndHasValidFormat
= &valid
;
126 *keyExistsAndHasValidFormat
= false;
129 typeID
= CFGetTypeID(value
);
130 if (typeID
== CFStringGetTypeID()) {
131 CFIndex charIndex
= 0;
133 CFStringInlineBuffer buf
;
135 CFStringInitInlineBuffer(value
, &buf
, CFRangeMake(0, CFStringGetLength(value
)));
136 success
= __CFStringScanInteger(&buf
, NULL
, &charIndex
, false, &intVal
);
137 *keyExistsAndHasValidFormat
= (success
&& charIndex
== CFStringGetLength(value
));
138 result
= (*keyExistsAndHasValidFormat
) ? intVal
: 0;
139 } else if (typeID
== CFNumberGetTypeID()) {
140 *keyExistsAndHasValidFormat
= !CFNumberIsFloatType(value
);
141 if (*keyExistsAndHasValidFormat
) {
142 CFNumberGetValue(value
, kCFNumberCFIndexType
, &result
);
149 *keyExistsAndHasValidFormat
= false;
155 Boolean
CFPreferencesGetAppBooleanValue(CFStringRef key
, CFStringRef appName
, Boolean
*keyExistsAndHasValidFormat
) {
156 CFAssert1(appName
!= NULL
, __kCFLogAssertion
, "%s(): Cannot access application preferences with a NULL application name", __PRETTY_FUNCTION__
);
157 CFAssert1(key
!= NULL
, __kCFLogAssertion
, "%s(): Cannot access preferences with a NULL key", __PRETTY_FUNCTION__
);
158 return CFPreferencesAppBooleanValue(key
, appName
, keyExistsAndHasValidFormat
);
161 CFIndex
CFPreferencesGetAppIntegerValue(CFStringRef key
, CFStringRef appName
, Boolean
*keyExistsAndHasValidFormat
) {
162 CFAssert1(appName
!= NULL
, __kCFLogAssertion
, "%s(): Cannot access application preferences with a NULL application name", __PRETTY_FUNCTION__
);
163 CFAssert1(key
!= NULL
, __kCFLogAssertion
, "%s(): Cannot access preferences with a NULL key", __PRETTY_FUNCTION__
);
164 return CFPreferencesAppIntegerValue(key
, appName
, keyExistsAndHasValidFormat
);
167 void CFPreferencesSetAppValue(CFStringRef key
, CFTypeRef value
, CFStringRef appName
) {
168 _CFApplicationPreferences
*standardPrefs
;
169 CFAssert1(appName
!= NULL
, __kCFLogAssertion
, "%s(): Cannot access application preferences with a NULL application name", __PRETTY_FUNCTION__
);
170 CFAssert1(key
!= NULL
, __kCFLogAssertion
, "%s(): Cannot access preferences with a NULL key", __PRETTY_FUNCTION__
);
172 standardPrefs
= _CFStandardApplicationPreferences(appName
);
174 if (value
) _CFApplicationPreferencesSet(standardPrefs
, key
, value
);
175 else _CFApplicationPreferencesRemove(standardPrefs
, key
);
180 static CFSpinLock_t __CFApplicationPreferencesLock
= 0; // Locks access to __CFStandardUserPreferences
181 static CFMutableDictionaryRef __CFStandardUserPreferences
= NULL
; // Mutable dictionary; keys are app names, values are _CFApplicationPreferences
183 Boolean
CFPreferencesAppSynchronize(CFStringRef appName
) {
184 _CFApplicationPreferences
*standardPrefs
;
186 CFAssert1(appName
!= NULL
, __kCFLogAssertion
, "%s(): Cannot access application preferences with a NULL application name", __PRETTY_FUNCTION__
);
187 __CFPreferencesCheckFormatType();
189 // Do not call _CFStandardApplicationPreferences(), as we do not want to create the preferences only to synchronize
190 __CFSpinLock(&__CFApplicationPreferencesLock
);
191 if (__CFStandardUserPreferences
) {
192 standardPrefs
= (_CFApplicationPreferences
*)CFDictionaryGetValue(__CFStandardUserPreferences
, appName
);
194 standardPrefs
= NULL
;
197 result
= standardPrefs
? _CFApplicationPreferencesSynchronizeNoLock(standardPrefs
) : _CFSynchronizeDomainCache();
198 __CFSpinUnlock(&__CFApplicationPreferencesLock
);
202 void CFPreferencesFlushCaches(void) {
203 CFAllocatorRef alloc
= __CFPreferencesAllocator();
204 __CFSpinLock(&__CFApplicationPreferencesLock
);
205 if (__CFStandardUserPreferences
) {
206 _CFApplicationPreferences
**prefsArray
, *prefsBuf
[32];
207 CFIndex idx
, count
= CFDictionaryGetCount(__CFStandardUserPreferences
);
209 prefsArray
= prefsBuf
;
211 prefsArray
= _CFAllocatorAllocateGC(alloc
, count
* sizeof(_CFApplicationPreferences
*), 0);
213 CFDictionaryGetKeysAndValues(__CFStandardUserPreferences
, NULL
, (const void **)prefsArray
);
215 __CFSpinUnlock(&__CFApplicationPreferencesLock
);
216 // DeallocateApplicationPreferences needs the lock
217 for (idx
= 0; idx
< count
; idx
++) {
218 _CFApplicationPreferences
*appPrefs
= prefsArray
[idx
];
219 _CFApplicationPreferencesSynchronize(appPrefs
);
220 _CFDeallocateApplicationPreferences(appPrefs
);
222 __CFSpinLock(&__CFApplicationPreferencesLock
);
224 CFRelease(__CFStandardUserPreferences
);
225 __CFStandardUserPreferences
= NULL
;
226 if(prefsArray
!= prefsBuf
) _CFAllocatorDeallocateGC(alloc
, prefsArray
);
228 __CFSpinUnlock(&__CFApplicationPreferencesLock
);
229 _CFPreferencesPurgeDomainCache();
232 // quick message to indicate that the given domain has changed, and we should go through and invalidate any dictReps that involve this domain.
233 void _CFApplicationPreferencesDomainHasChanged(CFPreferencesDomainRef changedDomain
) {
234 CFAllocatorRef alloc
= __CFPreferencesAllocator();
235 __CFSpinLock(&__CFApplicationPreferencesLock
);
236 if(__CFStandardUserPreferences
) { // only grovel over the prefs if there's something there to grovel
237 _CFApplicationPreferences
**prefsArray
, *prefsBuf
[32];
238 CFIndex idx
, count
= CFDictionaryGetCount(__CFStandardUserPreferences
);
240 prefsArray
= prefsBuf
;
242 prefsArray
= _CFAllocatorAllocateGC(alloc
, count
* sizeof(_CFApplicationPreferences
*), 0);
244 CFDictionaryGetKeysAndValues(__CFStandardUserPreferences
, NULL
, (const void **)prefsArray
);
245 // For this operation, giving up the lock is the last thing we want to do, so use the modified flavor of _CFApplicationPreferencesContainsDomain
246 for(idx
= 0; idx
< count
; idx
++) {
247 _CFApplicationPreferences
*appPrefs
= prefsArray
[idx
];
248 if(_CFApplicationPreferencesContainsDomainNoLock(appPrefs
, changedDomain
)) {
249 updateDictRep(appPrefs
);
252 if(prefsArray
!= prefsBuf
) _CFAllocatorDeallocateGC(alloc
, prefsArray
);
254 __CFSpinUnlock(&__CFApplicationPreferencesLock
);
258 // Begin ported code from NSUserDefaults.m
260 /*************** Constants ***************/
262 // NSString * const NSUserDefaultsDidChangeNotification = @"NSUserDefaultsDidChangeNotification";
264 static void updateDictRep(_CFApplicationPreferences
*self
) {
265 if (self
->_dictRep
) {
266 CFRelease(self
->_dictRep
);
267 self
->_dictRep
= NULL
;
271 static void __addKeysAndValues(const void *key
, const void *value
, void *context
) {
272 CFDictionarySetValue(context
, key
, value
);
275 static void computeDictRep(_CFApplicationPreferences
*self
) {
276 CFAllocatorRef alloc
= __CFPreferencesAllocator();
277 CFMutableArrayRef searchList
= self
->_search
;
279 CFIndex cnt
= CFArrayGetCount(searchList
);
280 CFDictionaryRef subdomainDict
;
282 if (self
->_dictRep
) {
283 CFRelease(self
->_dictRep
);
285 self
->_dictRep
= CFDictionaryCreateMutable(alloc
, 0, &kCFTypeDictionaryKeyCallBacks
, & kCFTypeDictionaryValueCallBacks
);
286 _CFDictionarySetCapacity(self
->_dictRep
, 160); // avoid lots of rehashing
288 if (!self
->_dictRep
) return;
289 if (0 == cnt
) return;
291 // For each subdomain triplet in the domain, iterate over dictionaries, adding them if necessary to the dictRep
292 for (idx
= cnt
; idx
--;) {
293 CFPreferencesDomainRef domain
= (CFPreferencesDomainRef
)CFArrayGetValueAtIndex(searchList
, idx
);
295 if (!domain
) continue;
297 subdomainDict
= _CFPreferencesDomainDeepCopyDictionary(domain
);
299 CFDictionaryApplyFunction(subdomainDict
, __addKeysAndValues
, self
->_dictRep
);
300 CFRelease(subdomainDict
);
303 if (__CFInsertionDomain
== domain
&& __CFInsertion
) {
304 CFDictionaryApplyFunction(__CFInsertion
, __addKeysAndValues
, self
->_dictRep
);
309 CFTypeRef
_CFApplicationPreferencesSearchDownToDomain(_CFApplicationPreferences
*self
, CFPreferencesDomainRef stopper
, CFStringRef key
) {
310 CFTypeRef value
= NULL
;
311 __CFSpinLock(&__CFApplicationPreferencesLock
);
313 cnt
= CFArrayGetCount(self
->_search
);
314 for (idx
= 0; idx
< cnt
; idx
++) {
315 CFPreferencesDomainRef domain
= (CFPreferencesDomainRef
)CFArrayGetValueAtIndex(self
->_search
, idx
);
316 if (domain
== stopper
) break;
317 value
= _CFPreferencesDomainCreateValueForKey(domain
, key
);
320 __CFSpinUnlock(&__CFApplicationPreferencesLock
);
325 void _CFApplicationPreferencesUpdate(_CFApplicationPreferences
*self
) {
326 __CFSpinLock(&__CFApplicationPreferencesLock
);
328 __CFSpinUnlock(&__CFApplicationPreferencesLock
);
331 __private_extern__ CFDictionaryRef
__CFApplicationPreferencesCopyCurrentState(void) {
332 CFDictionaryRef result
;
333 _CFApplicationPreferences
*self
= _CFStandardApplicationPreferences(kCFPreferencesCurrentApplication
);
334 __CFSpinLock(&__CFApplicationPreferencesLock
);
335 if (!self
->_dictRep
) {
336 computeDictRep(self
);
338 result
= CFDictionaryCreateCopy(kCFAllocatorSystemDefault
, self
->_dictRep
);
339 __CFSpinUnlock(&__CFApplicationPreferencesLock
);
343 // CACHING here - we will only return a value as current as the last time computeDictRep() was called
344 CFTypeRef
_CFApplicationPreferencesCreateValueForKey(_CFApplicationPreferences
*self
, CFStringRef defaultName
) {
346 __CFSpinLock(&__CFApplicationPreferencesLock
);
347 if (!self
->_dictRep
) {
348 computeDictRep(self
);
350 result
= (self
->_dictRep
) ? (CFTypeRef
)CFDictionaryGetValue(self
->_dictRep
, defaultName
) : NULL
;
354 __CFSpinUnlock(&__CFApplicationPreferencesLock
);
358 void _CFApplicationPreferencesSet(_CFApplicationPreferences
*self
, CFStringRef defaultName
, CFTypeRef value
) {
359 CFPreferencesDomainRef applicationDomain
;
361 __CFSpinLock(&userDefaultsLock
);
363 __CFSpinUnlock(&userDefaultsLock
);
365 CF_OBJC_KVO_WILLCHANGE(defs
, defaultName
);
366 __CFSpinLock(&__CFApplicationPreferencesLock
);
367 applicationDomain
= _CFPreferencesStandardDomain(self
->_appName
, kCFPreferencesCurrentUser
, kCFPreferencesAnyHost
);
368 if(applicationDomain
) {
369 _CFPreferencesDomainSet(applicationDomain
, defaultName
, value
);
370 if (CFArrayContainsValue(self
->_search
, CFRangeMake(0, CFArrayGetCount(self
->_search
)), applicationDomain
)) {
371 // Expensive; can't we just check the relevant value throughout the appropriate sets of domains? -- REW, 7/19/99
375 __CFSpinUnlock(&__CFApplicationPreferencesLock
);
376 CF_OBJC_KVO_DIDCHANGE(defs
, defaultName
);
379 void _CFApplicationPreferencesRemove(_CFApplicationPreferences
*self
, CFStringRef defaultName
) {
380 CFPreferencesDomainRef appDomain
;
381 __CFSpinLock(&__CFApplicationPreferencesLock
);
382 appDomain
= _CFPreferencesStandardDomain(self
->_appName
, kCFPreferencesCurrentUser
, kCFPreferencesAnyHost
);
384 _CFPreferencesDomainSet(appDomain
, defaultName
, NULL
);
385 if (CFArrayContainsValue(self
->_search
, CFRangeMake(0, CFArrayGetCount(self
->_search
)), appDomain
)) {
386 // If key exists, it will be in the _dictRep (but possibly overridden)
390 __CFSpinUnlock(&__CFApplicationPreferencesLock
);
393 static Boolean
_CFApplicationPreferencesSynchronizeNoLock(_CFApplicationPreferences
*self
) {
394 Boolean success
= _CFSynchronizeDomainCache();
395 if (self
->_dictRep
) {
396 CFRelease(self
->_dictRep
);
397 self
->_dictRep
= NULL
;
402 Boolean
_CFApplicationPreferencesSynchronize(_CFApplicationPreferences
*self
) {
404 __CFPreferencesCheckFormatType();
405 __CFSpinLock(&__CFApplicationPreferencesLock
);
406 result
= _CFApplicationPreferencesSynchronizeNoLock(self
);
407 __CFSpinUnlock(&__CFApplicationPreferencesLock
);
411 // appName should not be kCFPreferencesCurrentApplication going in to this call
412 _CFApplicationPreferences
*_CFApplicationPreferencesCreateWithUser(CFStringRef userName
, CFStringRef appName
) {
413 CFAllocatorRef alloc
= __CFPreferencesAllocator();
414 _CFApplicationPreferences
*self
= CFAllocatorAllocate(alloc
, sizeof(_CFApplicationPreferences
), 0);
416 self
->_dictRep
= NULL
;
417 self
->_appName
= CFRetain(appName
);
418 self
->_search
= CFArrayCreateMutable(alloc
, 0, &kCFTypeArrayCallBacks
);
419 if (!self
->_search
) {
420 CFAllocatorDeallocate(alloc
, self
);
428 // Do NOT release the domain after adding it to the array; domain_expression should not return a retained object -- REW, 8/26/99
429 #define ADD_DOMAIN(domain_expression) domain = domain_expression; if (domain) {CFArrayAppendValue(search, domain);}
430 void _CFApplicationPreferencesSetStandardSearchList(_CFApplicationPreferences
*appPreferences
) {
431 /* Now we add the standard domains; they are, in order:
432 this user, this app, this host
433 this user, this app, any host
434 this user, any app, this host
435 this user, any app, any host
436 any user, this app, this host
437 any user, this app, any host
438 any user, any app, this host
439 any user, any app, any host
441 note: for MacOS 8, we only add:
442 this user, this app, this host
443 this user, any app, this host
444 any user, this app, this host
445 any user, any app, this host
447 CFPreferencesDomainRef domain
;
448 CFMutableArrayRef search
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
450 // couldn't allocate memory!
454 ADD_DOMAIN(_CFPreferencesStandardDomain(appPreferences
->_appName
, kCFPreferencesCurrentUser
, kCFPreferencesCurrentHost
));
455 ADD_DOMAIN(_CFPreferencesStandardDomain(appPreferences
->_appName
, kCFPreferencesCurrentUser
, kCFPreferencesAnyHost
));
456 __CFInsertionDomain
= _CFPreferencesStandardDomain(kCFPreferencesAnyApplication
, kCFPreferencesCurrentUser
, kCFPreferencesCurrentHost
);
457 ADD_DOMAIN(__CFInsertionDomain
);
458 ADD_DOMAIN(_CFPreferencesStandardDomain(kCFPreferencesAnyApplication
, kCFPreferencesCurrentUser
, kCFPreferencesAnyHost
));
459 ADD_DOMAIN(_CFPreferencesStandardDomain(appPreferences
->_appName
, kCFPreferencesAnyUser
, kCFPreferencesCurrentHost
));
460 ADD_DOMAIN(_CFPreferencesStandardDomain(appPreferences
->_appName
, kCFPreferencesAnyUser
, kCFPreferencesAnyHost
));
461 ADD_DOMAIN(_CFPreferencesStandardDomain(kCFPreferencesAnyApplication
, kCFPreferencesAnyUser
, kCFPreferencesCurrentHost
));
462 ADD_DOMAIN(_CFPreferencesStandardDomain(kCFPreferencesAnyApplication
, kCFPreferencesAnyUser
, kCFPreferencesAnyHost
));
464 _CFApplicationPreferencesSetSearchList(appPreferences
, search
);
470 __private_extern__ _CFApplicationPreferences
*_CFStandardApplicationPreferences(CFStringRef appName
) {
471 _CFApplicationPreferences
*appPreferences
;
472 // CFAssert(appName != kCFPreferencesAnyApplication, __kCFLogAssertion, "Cannot use any of the CFPreferences...App... functions with an appName of kCFPreferencesAnyApplication");
473 __CFSpinLock(&__CFApplicationPreferencesLock
);
474 if (!__CFStandardUserPreferences
) {
475 __CFStandardUserPreferences
= CFDictionaryCreateMutable(NULL
, 0, & kCFTypeDictionaryKeyCallBacks
, NULL
);
477 if (!__CFStandardUserPreferences
) {
479 __CFSpinUnlock(&__CFApplicationPreferencesLock
);
482 if ((appPreferences
= (_CFApplicationPreferences
*)CFDictionaryGetValue(__CFStandardUserPreferences
, appName
)) == NULL
) {
483 appPreferences
= _CFApplicationPreferencesCreateWithUser(kCFPreferencesCurrentUser
, appName
);
484 CFDictionarySetValue(__CFStandardUserPreferences
, appName
, appPreferences
);
485 __CFSpinUnlock(&__CFApplicationPreferencesLock
);
486 _CFApplicationPreferencesSetStandardSearchList(appPreferences
);
488 __CFSpinUnlock(&__CFApplicationPreferencesLock
);
490 return appPreferences
;
493 // Exclusively for Foundation's use
494 void _CFApplicationPreferencesSetCacheForApp(_CFApplicationPreferences
*appPrefs
, CFStringRef appName
) {
495 __CFSpinLock(&__CFApplicationPreferencesLock
);
496 if (!__CFStandardUserPreferences
) {
497 __CFStandardUserPreferences
= CFDictionaryCreateMutable(NULL
, 0, &kCFTypeDictionaryKeyCallBacks
, NULL
);
498 CFDictionarySetValue(__CFStandardUserPreferences
, appName
, appPrefs
);
499 __CFSpinUnlock(&__CFApplicationPreferencesLock
);
501 _CFApplicationPreferences
*oldPrefs
= (_CFApplicationPreferences
*)CFDictionaryGetValue(__CFStandardUserPreferences
, appName
);
502 CFDictionarySetValue(__CFStandardUserPreferences
, appName
, appPrefs
);
503 __CFSpinUnlock(&__CFApplicationPreferencesLock
);
505 _CFDeallocateApplicationPreferences(oldPrefs
);
511 void _CFDeallocateApplicationPreferences(_CFApplicationPreferences
*self
) {
512 CFAllocatorRef alloc
= __CFPreferencesAllocator();
513 _CFApplicationPreferences
*cachedPrefs
= NULL
;
514 __CFSpinLock(&__CFApplicationPreferencesLock
);
516 // Get us out of the cache before destroying!
517 if (__CFStandardUserPreferences
) {
518 cachedPrefs
= (_CFApplicationPreferences
*)CFDictionaryGetValue(__CFStandardUserPreferences
, self
->_appName
);
520 if (cachedPrefs
== self
) {
521 CFDictionaryRemoveValue(__CFStandardUserPreferences
, self
->_appName
);
524 if (self
->_dictRep
) CFRelease(self
->_dictRep
);
525 CFRelease(self
->_search
);
526 CFRelease(self
->_appName
);
527 CFAllocatorDeallocate(alloc
, self
);
528 __CFSpinUnlock(&__CFApplicationPreferencesLock
);
531 // For Foundation's use
532 CFDictionaryRef
_CFApplicationPreferencesCopyRepresentationWithHint(_CFApplicationPreferences
*self
, CFDictionaryRef hint
) {
533 CFDictionaryRef dict
;
534 __CFSpinLock(&__CFApplicationPreferencesLock
);
535 if (!self
->_dictRep
) {
536 computeDictRep(self
);
538 if (self
->_dictRep
&& (self
->_dictRep
!= hint
)) {
539 CFRetain(self
->_dictRep
);
541 dict
= self
->_dictRep
;
542 __CFSpinUnlock(&__CFApplicationPreferencesLock
);
546 // For Foundation's use; does not do what it would seem to from the name
547 CFDictionaryRef
_CFApplicationPreferencesCopyRepresentation3(_CFApplicationPreferences
*self
, CFDictionaryRef hint
, CFDictionaryRef insertion
, CFPreferencesDomainRef afterDomain
) {
548 __CFSpinLock(&__CFApplicationPreferencesLock
);
549 if (0 == self
&& 0 == hint
&& 0 == afterDomain
) {
550 // This is so so gross.
551 if (__CFInsertion
) CFRelease(__CFInsertion
);
552 __CFInsertion
= insertion
? CFRetain(insertion
) : NULL
;
554 __CFSpinUnlock(&__CFApplicationPreferencesLock
);
559 CFDictionaryRef
_CFApplicationPreferencesCopyRepresentation(_CFApplicationPreferences
*self
) {
560 return _CFApplicationPreferencesCopyRepresentationWithHint(self
, NULL
);
563 __private_extern__
void _CFApplicationPreferencesSetSearchList(_CFApplicationPreferences
*self
, CFArrayRef newSearchList
) {
565 __CFSpinLock(&__CFApplicationPreferencesLock
);
566 CFArrayRemoveAllValues(self
->_search
);
567 count
= CFArrayGetCount(newSearchList
);
568 for (idx
= 0; idx
< count
; idx
++) {
569 CFArrayAppendValue(self
->_search
, CFArrayGetValueAtIndex(newSearchList
, idx
));
572 __CFSpinUnlock(&__CFApplicationPreferencesLock
);
575 void CFPreferencesAddSuitePreferencesToApp(CFStringRef appName
, CFStringRef suiteName
) {
576 _CFApplicationPreferences
*appPrefs
;
578 appPrefs
= _CFStandardApplicationPreferences(appName
);
579 _CFApplicationPreferencesAddSuitePreferences(appPrefs
, suiteName
);
582 void _CFApplicationPreferencesAddSuitePreferences(_CFApplicationPreferences
*appPrefs
, CFStringRef suiteName
) {
583 CFPreferencesDomainRef domain
;
587 // Find where to insert the new suite
588 __CFSpinLock(&__CFApplicationPreferencesLock
);
589 domain
= _CFPreferencesStandardDomain(appPrefs
->_appName
, kCFPreferencesCurrentUser
, kCFPreferencesAnyHost
);
591 range
.length
= CFArrayGetCount(appPrefs
->_search
);
592 idx
= domain
? CFArrayGetFirstIndexOfValue(appPrefs
->_search
, range
, domain
) : kCFNotFound
;
593 __CFSpinUnlock(&__CFApplicationPreferencesLock
);
594 idx
++; // We want just below the app domain. Coincidentally, this gives us the top of the list if the app domain has been removed.
595 domain
= _CFPreferencesStandardDomain(suiteName
, kCFPreferencesCurrentUser
, kCFPreferencesAnyHost
);
597 __CFSpinLock(&__CFApplicationPreferencesLock
);
598 CFArrayInsertValueAtIndex(appPrefs
->_search
, idx
, domain
);
599 __CFSpinUnlock(&__CFApplicationPreferencesLock
);
602 domain
= _CFPreferencesStandardDomain(suiteName
, kCFPreferencesCurrentUser
, kCFPreferencesCurrentHost
);
604 __CFSpinLock(&__CFApplicationPreferencesLock
);
605 CFArrayInsertValueAtIndex(appPrefs
->_search
, idx
, domain
);
606 __CFSpinUnlock(&__CFApplicationPreferencesLock
);
610 // Now the AnyUser domains
611 domain
= _CFPreferencesStandardDomain(appPrefs
->_appName
, kCFPreferencesAnyUser
, kCFPreferencesAnyHost
);
612 idx
= domain
? CFArrayGetFirstIndexOfValue(appPrefs
->_search
, range
, domain
) : kCFNotFound
;
613 if (idx
== kCFNotFound
) {
614 // Someone blew away the app domain. Can only happen through -[NSUserDefaults setSearchList:]. For the any user case, we look for right below the global domain
615 // Can this happen anymore? -[NSUserDefaults setSearchList:] is bailing. -- ctp - - 3 Jan 2002
616 domain
= _CFPreferencesStandardDomain(kCFPreferencesAnyApplication
, kCFPreferencesCurrentUser
, kCFPreferencesAnyHost
);
617 idx
= domain
? CFArrayGetFirstIndexOfValue(appPrefs
->_search
, range
, domain
) : kCFNotFound
;
618 if (idx
== kCFNotFound
) {
619 // Try the "any host" choice
620 domain
= _CFPreferencesStandardDomain(kCFPreferencesAnyApplication
, kCFPreferencesCurrentUser
, kCFPreferencesCurrentHost
);
621 idx
= domain
? CFArrayGetFirstIndexOfValue(appPrefs
->_search
, range
, domain
) : kCFNotFound
;
622 if (idx
== kCFNotFound
) {
623 // We give up; put the new domains at the bottom
624 idx
= CFArrayGetCount(appPrefs
->_search
) - 1;
629 domain
= _CFPreferencesStandardDomain(suiteName
, kCFPreferencesAnyUser
, kCFPreferencesAnyHost
);
631 __CFSpinLock(&__CFApplicationPreferencesLock
);
632 CFArrayInsertValueAtIndex(appPrefs
->_search
, idx
, domain
);
633 __CFSpinUnlock(&__CFApplicationPreferencesLock
);
635 domain
= _CFPreferencesStandardDomain(suiteName
, kCFPreferencesAnyUser
, kCFPreferencesCurrentHost
);
637 __CFSpinLock(&__CFApplicationPreferencesLock
);
638 CFArrayInsertValueAtIndex(appPrefs
->_search
, idx
, domain
);
639 __CFSpinUnlock(&__CFApplicationPreferencesLock
);
641 __CFSpinLock(&__CFApplicationPreferencesLock
);
642 updateDictRep(appPrefs
);
643 __CFSpinUnlock(&__CFApplicationPreferencesLock
);
646 void CFPreferencesRemoveSuitePreferencesFromApp(CFStringRef appName
, CFStringRef suiteName
) {
647 _CFApplicationPreferences
*appPrefs
;
649 appPrefs
= _CFStandardApplicationPreferences(appName
);
651 _CFApplicationPreferencesRemoveSuitePreferences(appPrefs
, suiteName
);
654 void _CFApplicationPreferencesRemoveSuitePreferences(_CFApplicationPreferences
*appPrefs
, CFStringRef suiteName
) {
655 CFPreferencesDomainRef domain
;
657 __CFSpinLock(&__CFApplicationPreferencesLock
);
658 domain
= _CFPreferencesStandardDomain(suiteName
, kCFPreferencesCurrentUser
, kCFPreferencesAnyHost
);
659 __CFSpinUnlock(&__CFApplicationPreferencesLock
);
660 if (domain
) _CFApplicationPreferencesRemoveDomain(appPrefs
, domain
);
662 __CFSpinLock(&__CFApplicationPreferencesLock
);
663 domain
= _CFPreferencesStandardDomain(suiteName
, kCFPreferencesCurrentUser
, kCFPreferencesCurrentHost
);
664 __CFSpinUnlock(&__CFApplicationPreferencesLock
);
665 if (domain
) _CFApplicationPreferencesRemoveDomain(appPrefs
, domain
);
667 __CFSpinLock(&__CFApplicationPreferencesLock
);
668 domain
= _CFPreferencesStandardDomain(suiteName
, kCFPreferencesAnyUser
, kCFPreferencesAnyHost
);
669 __CFSpinUnlock(&__CFApplicationPreferencesLock
);
670 if (domain
) _CFApplicationPreferencesRemoveDomain(appPrefs
, domain
);
672 __CFSpinLock(&__CFApplicationPreferencesLock
);
673 domain
= _CFPreferencesStandardDomain(suiteName
, kCFPreferencesAnyUser
, kCFPreferencesCurrentHost
);
674 __CFSpinUnlock(&__CFApplicationPreferencesLock
);
675 if (domain
) _CFApplicationPreferencesRemoveDomain(appPrefs
, domain
);
678 void _CFApplicationPreferencesAddDomain(_CFApplicationPreferences
*self
, CFPreferencesDomainRef domain
, Boolean addAtTop
) {
679 __CFSpinLock(&__CFApplicationPreferencesLock
);
681 CFArrayInsertValueAtIndex(self
->_search
, 0, domain
);
683 CFArrayAppendValue(self
->_search
, domain
);
686 __CFSpinUnlock(&__CFApplicationPreferencesLock
);
689 Boolean
_CFApplicationPreferencesContainsDomain(_CFApplicationPreferences
*self
, CFPreferencesDomainRef domain
) {
691 __CFSpinLock(&__CFApplicationPreferencesLock
);
692 result
= CFArrayContainsValue(self
->_search
, CFRangeMake(0, CFArrayGetCount(self
->_search
)), domain
);
693 __CFSpinUnlock(&__CFApplicationPreferencesLock
);
697 Boolean
_CFApplicationPreferencesContainsDomainNoLock(_CFApplicationPreferences
*self
, CFPreferencesDomainRef domain
) {
699 result
= CFArrayContainsValue(self
->_search
, CFRangeMake(0, CFArrayGetCount(self
->_search
)), domain
);
703 void _CFApplicationPreferencesRemoveDomain(_CFApplicationPreferences
*self
, CFPreferencesDomainRef domain
) {
706 __CFSpinLock(&__CFApplicationPreferencesLock
);
708 range
.length
= CFArrayGetCount(self
->_search
);
709 while ((idx
= CFArrayGetFirstIndexOfValue(self
->_search
, range
, domain
)) != kCFNotFound
) {
710 CFArrayRemoveValueAtIndex(self
->_search
, idx
);
711 range
.location
= idx
;
712 range
.length
= range
.length
- idx
- 1;
715 __CFSpinUnlock(&__CFApplicationPreferencesLock
);