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>
34 static Boolean
_CFApplicationPreferencesSynchronizeNoLock(_CFApplicationPreferences
*self
);
35 void _CFPreferencesDomainSetMultiple(CFPreferencesDomainRef domain
, CFDictionaryRef dict
);
36 static void updateDictRep(_CFApplicationPreferences
*self
);
37 Boolean
_CFApplicationPreferencesContainsDomainNoLock(_CFApplicationPreferences
*self
, CFPreferencesDomainRef domain
);
39 static void *__CFInsertionDomain
= NULL
;
40 static CFDictionaryRef __CFInsertion
= NULL
;
43 extern CFSpinLock_t userDefaultsLock
;
44 extern void *userDefaults
;
46 // Management externals
47 extern Boolean _CFPreferencesManagementActive
;
50 #define CF_OBJC_KVO_WILLCHANGE(obj, sel)
51 #define CF_OBJC_KVO_DIDCHANGE(obj, sel)
54 // 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
56 CFPropertyListRef
CFPreferencesCopyAppValue(CFStringRef key
, CFStringRef appName
) {
57 _CFApplicationPreferences
*standardPrefs
;
58 CFAssert1(appName
!= NULL
, __kCFLogAssertion
, "%s(): Cannot access application preferences with a NULL application name", __PRETTY_FUNCTION__
);
59 CFAssert1(key
!= NULL
, __kCFLogAssertion
, "%s(): Cannot access preferences with a NULL key", __PRETTY_FUNCTION__
);
61 standardPrefs
= _CFStandardApplicationPreferences(appName
);
62 return standardPrefs
? _CFApplicationPreferencesCreateValueForKey(standardPrefs
, key
) : NULL
;
65 CF_EXPORT Boolean
CFPreferencesAppBooleanValue(CFStringRef key
, CFStringRef appName
, Boolean
*keyExistsAndHasValidFormat
) {
66 CFPropertyListRef value
;
67 Boolean result
, valid
;
69 CFAssert1(appName
!= NULL
, __kCFLogAssertion
, "%s(): Cannot access application preferences with a NULL application name", __PRETTY_FUNCTION__
);
70 CFAssert1(key
!= NULL
, __kCFLogAssertion
, "%s(): Cannot access preferences with a NULL key", __PRETTY_FUNCTION__
);
72 if (!keyExistsAndHasValidFormat
) {
73 keyExistsAndHasValidFormat
= &valid
;
75 value
= CFPreferencesCopyAppValue(key
, appName
);
77 *keyExistsAndHasValidFormat
= false;
80 typeID
= CFGetTypeID(value
);
81 if (typeID
== CFStringGetTypeID()) {
82 if (CFStringCompare(value
, CFSTR("true"), kCFCompareCaseInsensitive
) == kCFCompareEqualTo
|| CFStringCompare(value
, CFSTR("YES"), kCFCompareCaseInsensitive
) == kCFCompareEqualTo
) {
83 *keyExistsAndHasValidFormat
= true;
85 } else if (CFStringCompare(value
, CFSTR("false"), kCFCompareCaseInsensitive
) == kCFCompareEqualTo
|| CFStringCompare(value
, CFSTR("NO"), kCFCompareCaseInsensitive
) == kCFCompareEqualTo
) {
86 *keyExistsAndHasValidFormat
= true;
89 *keyExistsAndHasValidFormat
= false;
92 } else if (typeID
== CFNumberGetTypeID()) {
93 if (CFNumberIsFloatType(value
)) {
94 *keyExistsAndHasValidFormat
= false;
98 *keyExistsAndHasValidFormat
= true;
99 CFNumberGetValue(value
, kCFNumberIntType
, &i
);
100 result
= (i
== 0) ? false : true;
102 } else if (typeID
== CFBooleanGetTypeID()) {
103 result
= (value
== kCFBooleanTrue
);
104 *keyExistsAndHasValidFormat
= true;
108 *keyExistsAndHasValidFormat
= false;
114 __private_extern__ CFIndex
CFPreferencesAppIntegerValue(CFStringRef key
, CFStringRef appName
, Boolean
*keyExistsAndHasValidFormat
) {
115 CFPropertyListRef value
;
119 CFAssert1(appName
!= NULL
, __kCFLogAssertion
, "%s(): Cannot access application preferences with a NULL application name", __PRETTY_FUNCTION__
);
120 CFAssert1(key
!= NULL
, __kCFLogAssertion
, "%s(): Cannot access preferences with a NULL key", __PRETTY_FUNCTION__
);
122 value
= CFPreferencesCopyAppValue(key
, appName
);
123 if (!keyExistsAndHasValidFormat
) {
124 keyExistsAndHasValidFormat
= &valid
;
127 *keyExistsAndHasValidFormat
= false;
130 typeID
= CFGetTypeID(value
);
131 if (typeID
== CFStringGetTypeID()) {
132 CFIndex charIndex
= 0;
134 CFStringInlineBuffer buf
;
136 CFStringInitInlineBuffer(value
, &buf
, CFRangeMake(0, CFStringGetLength(value
)));
137 success
= __CFStringScanInteger(&buf
, NULL
, &charIndex
, false, &intVal
);
138 *keyExistsAndHasValidFormat
= (success
&& charIndex
== CFStringGetLength(value
));
139 result
= (*keyExistsAndHasValidFormat
) ? intVal
: 0;
140 } else if (typeID
== CFNumberGetTypeID()) {
141 *keyExistsAndHasValidFormat
= !CFNumberIsFloatType(value
);
142 if (*keyExistsAndHasValidFormat
) {
143 CFNumberGetValue(value
, kCFNumberCFIndexType
, &result
);
150 *keyExistsAndHasValidFormat
= false;
156 Boolean
CFPreferencesGetAppBooleanValue(CFStringRef key
, CFStringRef appName
, Boolean
*keyExistsAndHasValidFormat
) {
157 CFAssert1(appName
!= NULL
, __kCFLogAssertion
, "%s(): Cannot access application preferences with a NULL application name", __PRETTY_FUNCTION__
);
158 CFAssert1(key
!= NULL
, __kCFLogAssertion
, "%s(): Cannot access preferences with a NULL key", __PRETTY_FUNCTION__
);
159 return CFPreferencesAppBooleanValue(key
, appName
, keyExistsAndHasValidFormat
);
162 CFIndex
CFPreferencesGetAppIntegerValue(CFStringRef key
, CFStringRef appName
, Boolean
*keyExistsAndHasValidFormat
) {
163 CFAssert1(appName
!= NULL
, __kCFLogAssertion
, "%s(): Cannot access application preferences with a NULL application name", __PRETTY_FUNCTION__
);
164 CFAssert1(key
!= NULL
, __kCFLogAssertion
, "%s(): Cannot access preferences with a NULL key", __PRETTY_FUNCTION__
);
165 return CFPreferencesAppIntegerValue(key
, appName
, keyExistsAndHasValidFormat
);
168 void CFPreferencesSetAppValue(CFStringRef key
, CFTypeRef value
, CFStringRef appName
) {
169 _CFApplicationPreferences
*standardPrefs
;
170 CFAssert1(appName
!= NULL
, __kCFLogAssertion
, "%s(): Cannot access application preferences with a NULL application name", __PRETTY_FUNCTION__
);
171 CFAssert1(key
!= NULL
, __kCFLogAssertion
, "%s(): Cannot access preferences with a NULL key", __PRETTY_FUNCTION__
);
173 standardPrefs
= _CFStandardApplicationPreferences(appName
);
175 if (value
) _CFApplicationPreferencesSet(standardPrefs
, key
, value
);
176 else _CFApplicationPreferencesRemove(standardPrefs
, key
);
181 static CFSpinLock_t __CFApplicationPreferencesLock
= 0; // Locks access to __CFStandardUserPreferences
182 static CFMutableDictionaryRef __CFStandardUserPreferences
= NULL
; // Mutable dictionary; keys are app names, values are _CFApplicationPreferences
184 Boolean
CFPreferencesAppSynchronize(CFStringRef appName
) {
185 _CFApplicationPreferences
*standardPrefs
;
187 CFAssert1(appName
!= NULL
, __kCFLogAssertion
, "%s(): Cannot access application preferences with a NULL application name", __PRETTY_FUNCTION__
);
188 __CFPreferencesCheckFormatType();
190 // Do not call _CFStandardApplicationPreferences(), as we do not want to create the preferences only to synchronize
191 __CFSpinLock(&__CFApplicationPreferencesLock
);
192 if (__CFStandardUserPreferences
) {
193 standardPrefs
= (_CFApplicationPreferences
*)CFDictionaryGetValue(__CFStandardUserPreferences
, appName
);
195 standardPrefs
= NULL
;
198 result
= standardPrefs
? _CFApplicationPreferencesSynchronizeNoLock(standardPrefs
) : _CFSynchronizeDomainCache();
199 __CFSpinUnlock(&__CFApplicationPreferencesLock
);
203 void CFPreferencesFlushCaches(void) {
204 CFAllocatorRef alloc
= __CFPreferencesAllocator();
205 __CFSpinLock(&__CFApplicationPreferencesLock
);
206 if (__CFStandardUserPreferences
) {
207 _CFApplicationPreferences
**prefsArray
, *prefsBuf
[32];
208 CFIndex idx
, count
= CFDictionaryGetCount(__CFStandardUserPreferences
);
210 prefsArray
= prefsBuf
;
212 prefsArray
= _CFAllocatorAllocateGC(alloc
, count
* sizeof(_CFApplicationPreferences
*), 0);
214 CFDictionaryGetKeysAndValues(__CFStandardUserPreferences
, NULL
, (const void **)prefsArray
);
216 __CFSpinUnlock(&__CFApplicationPreferencesLock
);
217 // DeallocateApplicationPreferences needs the lock
218 for (idx
= 0; idx
< count
; idx
++) {
219 _CFApplicationPreferences
*appPrefs
= prefsArray
[idx
];
220 _CFApplicationPreferencesSynchronize(appPrefs
);
221 _CFDeallocateApplicationPreferences(appPrefs
);
223 __CFSpinLock(&__CFApplicationPreferencesLock
);
225 CFRelease(__CFStandardUserPreferences
);
226 __CFStandardUserPreferences
= NULL
;
227 if(prefsArray
!= prefsBuf
) _CFAllocatorDeallocateGC(alloc
, prefsArray
);
229 __CFSpinUnlock(&__CFApplicationPreferencesLock
);
230 _CFPreferencesPurgeDomainCache();
233 // quick message to indicate that the given domain has changed, and we should go through and invalidate any dictReps that involve this domain.
234 void _CFApplicationPreferencesDomainHasChanged(CFPreferencesDomainRef changedDomain
) {
235 CFAllocatorRef alloc
= __CFPreferencesAllocator();
236 __CFSpinLock(&__CFApplicationPreferencesLock
);
237 if(__CFStandardUserPreferences
) { // only grovel over the prefs if there's something there to grovel
238 _CFApplicationPreferences
**prefsArray
, *prefsBuf
[32];
239 CFIndex idx
, count
= CFDictionaryGetCount(__CFStandardUserPreferences
);
241 prefsArray
= prefsBuf
;
243 prefsArray
= _CFAllocatorAllocateGC(alloc
, count
* sizeof(_CFApplicationPreferences
*), 0);
245 CFDictionaryGetKeysAndValues(__CFStandardUserPreferences
, NULL
, (const void **)prefsArray
);
246 // For this operation, giving up the lock is the last thing we want to do, so use the modified flavor of _CFApplicationPreferencesContainsDomain
247 for(idx
= 0; idx
< count
; idx
++) {
248 _CFApplicationPreferences
*appPrefs
= prefsArray
[idx
];
249 if(_CFApplicationPreferencesContainsDomainNoLock(appPrefs
, changedDomain
)) {
250 updateDictRep(appPrefs
);
253 if(prefsArray
!= prefsBuf
) _CFAllocatorDeallocateGC(alloc
, prefsArray
);
255 __CFSpinUnlock(&__CFApplicationPreferencesLock
);
259 // Begin ported code from NSUserDefaults.m
261 /*************** Constants ***************/
263 // NSString * const NSUserDefaultsDidChangeNotification = @"NSUserDefaultsDidChangeNotification";
265 static void updateDictRep(_CFApplicationPreferences
*self
) {
266 if (self
->_dictRep
) {
267 CFRelease(self
->_dictRep
);
268 self
->_dictRep
= NULL
;
272 static void __addKeysAndValues(const void *key
, const void *value
, void *context
) {
273 CFDictionarySetValue(context
, key
, value
);
276 static void computeDictRep(_CFApplicationPreferences
*self
) {
277 CFAllocatorRef alloc
= __CFPreferencesAllocator();
278 CFMutableArrayRef searchList
= self
->_search
;
280 CFIndex cnt
= CFArrayGetCount(searchList
);
281 CFDictionaryRef subdomainDict
;
283 if (self
->_dictRep
) {
284 CFRelease(self
->_dictRep
);
286 self
->_dictRep
= CFDictionaryCreateMutable(alloc
, 0, &kCFTypeDictionaryKeyCallBacks
, & kCFTypeDictionaryValueCallBacks
);
287 _CFDictionarySetCapacity(self
->_dictRep
, 160); // avoid lots of rehashing
289 if (!self
->_dictRep
) return;
290 if (0 == cnt
) return;
292 // For each subdomain triplet in the domain, iterate over dictionaries, adding them if necessary to the dictRep
293 for (idx
= cnt
; idx
--;) {
294 CFPreferencesDomainRef domain
= (CFPreferencesDomainRef
)CFArrayGetValueAtIndex(searchList
, idx
);
296 if (!domain
) continue;
298 subdomainDict
= _CFPreferencesDomainDeepCopyDictionary(domain
);
300 CFDictionaryApplyFunction(subdomainDict
, __addKeysAndValues
, self
->_dictRep
);
301 CFRelease(subdomainDict
);
304 if (__CFInsertionDomain
== domain
&& __CFInsertion
) {
305 CFDictionaryApplyFunction(__CFInsertion
, __addKeysAndValues
, self
->_dictRep
);
310 CFTypeRef
_CFApplicationPreferencesSearchDownToDomain(_CFApplicationPreferences
*self
, CFPreferencesDomainRef stopper
, CFStringRef key
) {
311 CFTypeRef value
= NULL
;
312 __CFSpinLock(&__CFApplicationPreferencesLock
);
314 cnt
= CFArrayGetCount(self
->_search
);
315 for (idx
= 0; idx
< cnt
; idx
++) {
316 CFPreferencesDomainRef domain
= (CFPreferencesDomainRef
)CFArrayGetValueAtIndex(self
->_search
, idx
);
317 if (domain
== stopper
) break;
318 value
= _CFPreferencesDomainCreateValueForKey(domain
, key
);
321 __CFSpinUnlock(&__CFApplicationPreferencesLock
);
326 void _CFApplicationPreferencesUpdate(_CFApplicationPreferences
*self
) {
327 __CFSpinLock(&__CFApplicationPreferencesLock
);
329 __CFSpinUnlock(&__CFApplicationPreferencesLock
);
332 __private_extern__ CFDictionaryRef
__CFApplicationPreferencesCopyCurrentState(void) {
333 CFDictionaryRef result
;
334 _CFApplicationPreferences
*self
= _CFStandardApplicationPreferences(kCFPreferencesCurrentApplication
);
335 __CFSpinLock(&__CFApplicationPreferencesLock
);
336 if (!self
->_dictRep
) {
337 computeDictRep(self
);
339 result
= CFDictionaryCreateCopy(kCFAllocatorSystemDefault
, self
->_dictRep
);
340 __CFSpinUnlock(&__CFApplicationPreferencesLock
);
344 // CACHING here - we will only return a value as current as the last time computeDictRep() was called
345 CFTypeRef
_CFApplicationPreferencesCreateValueForKey(_CFApplicationPreferences
*self
, CFStringRef defaultName
) {
347 __CFSpinLock(&__CFApplicationPreferencesLock
);
348 if (!self
->_dictRep
) {
349 computeDictRep(self
);
351 result
= (self
->_dictRep
) ? (CFTypeRef
)CFDictionaryGetValue(self
->_dictRep
, defaultName
) : NULL
;
355 __CFSpinUnlock(&__CFApplicationPreferencesLock
);
359 void _CFApplicationPreferencesSet(_CFApplicationPreferences
*self
, CFStringRef defaultName
, CFTypeRef value
) {
360 CFPreferencesDomainRef applicationDomain
;
362 __CFSpinLock(&userDefaultsLock
);
364 __CFSpinUnlock(&userDefaultsLock
);
366 CF_OBJC_KVO_WILLCHANGE(defs
, defaultName
);
367 __CFSpinLock(&__CFApplicationPreferencesLock
);
368 applicationDomain
= _CFPreferencesStandardDomain(self
->_appName
, kCFPreferencesCurrentUser
, kCFPreferencesAnyHost
);
369 if(applicationDomain
) {
370 _CFPreferencesDomainSet(applicationDomain
, defaultName
, value
);
371 if (CFArrayContainsValue(self
->_search
, CFRangeMake(0, CFArrayGetCount(self
->_search
)), applicationDomain
)) {
372 // Expensive; can't we just check the relevant value throughout the appropriate sets of domains? -- REW, 7/19/99
376 __CFSpinUnlock(&__CFApplicationPreferencesLock
);
377 CF_OBJC_KVO_DIDCHANGE(defs
, defaultName
);
380 void _CFApplicationPreferencesRemove(_CFApplicationPreferences
*self
, CFStringRef defaultName
) {
381 CFPreferencesDomainRef appDomain
;
383 __CFSpinLock(&userDefaultsLock
);
385 __CFSpinUnlock(&userDefaultsLock
);
386 CF_OBJC_KVO_WILLCHANGE(defs
, defaultName
);
387 __CFSpinLock(&__CFApplicationPreferencesLock
);
388 appDomain
= _CFPreferencesStandardDomain(self
->_appName
, kCFPreferencesCurrentUser
, kCFPreferencesAnyHost
);
390 _CFPreferencesDomainSet(appDomain
, defaultName
, NULL
);
391 if (CFArrayContainsValue(self
->_search
, CFRangeMake(0, CFArrayGetCount(self
->_search
)), appDomain
)) {
392 // If key exists, it will be in the _dictRep (but possibly overridden)
396 __CFSpinUnlock(&__CFApplicationPreferencesLock
);
397 CF_OBJC_KVO_DIDCHANGE(defs
, defaultName
);
400 static Boolean
_CFApplicationPreferencesSynchronizeNoLock(_CFApplicationPreferences
*self
) {
401 Boolean success
= _CFSynchronizeDomainCache();
402 if (self
->_dictRep
) {
403 CFRelease(self
->_dictRep
);
404 self
->_dictRep
= NULL
;
409 Boolean
_CFApplicationPreferencesSynchronize(_CFApplicationPreferences
*self
) {
411 __CFPreferencesCheckFormatType();
412 __CFSpinLock(&__CFApplicationPreferencesLock
);
413 result
= _CFApplicationPreferencesSynchronizeNoLock(self
);
414 __CFSpinUnlock(&__CFApplicationPreferencesLock
);
418 // appName should not be kCFPreferencesCurrentApplication going in to this call
419 _CFApplicationPreferences
*_CFApplicationPreferencesCreateWithUser(CFStringRef userName
, CFStringRef appName
) {
420 CFAllocatorRef alloc
= __CFPreferencesAllocator();
421 _CFApplicationPreferences
*self
= CFAllocatorAllocate(alloc
, sizeof(_CFApplicationPreferences
), 0);
423 self
->_dictRep
= NULL
;
424 self
->_appName
= CFRetain(appName
);
425 self
->_search
= CFArrayCreateMutable(alloc
, 0, &kCFTypeArrayCallBacks
);
426 if (!self
->_search
) {
427 CFAllocatorDeallocate(alloc
, self
);
435 // Do NOT release the domain after adding it to the array; domain_expression should not return a retained object -- REW, 8/26/99
436 #define ADD_DOMAIN(domain_expression) domain = domain_expression; if (domain) {CFArrayAppendValue(search, domain);}
437 void _CFApplicationPreferencesSetStandardSearchList(_CFApplicationPreferences
*appPreferences
) {
438 /* Now we add the standard domains; they are, in order:
439 this user, this app, this host
440 this user, this app, any host
441 this user, any app, this host
442 this user, any app, any host
443 any user, this app, this host
444 any user, this app, any host
445 any user, any app, this host
446 any user, any app, any host
448 note: for MacOS 8, we only add:
449 this user, this app, this host
450 this user, any app, this host
451 any user, this app, this host
452 any user, any app, this host
454 CFPreferencesDomainRef domain
;
455 CFMutableArrayRef search
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
457 // couldn't allocate memory!
461 ADD_DOMAIN(_CFPreferencesStandardDomain(appPreferences
->_appName
, kCFPreferencesCurrentUser
, kCFPreferencesCurrentHost
));
462 ADD_DOMAIN(_CFPreferencesStandardDomain(appPreferences
->_appName
, kCFPreferencesCurrentUser
, kCFPreferencesAnyHost
));
463 __CFInsertionDomain
= _CFPreferencesStandardDomain(kCFPreferencesAnyApplication
, kCFPreferencesCurrentUser
, kCFPreferencesCurrentHost
);
464 ADD_DOMAIN(__CFInsertionDomain
);
465 ADD_DOMAIN(_CFPreferencesStandardDomain(kCFPreferencesAnyApplication
, kCFPreferencesCurrentUser
, kCFPreferencesAnyHost
));
466 ADD_DOMAIN(_CFPreferencesStandardDomain(appPreferences
->_appName
, kCFPreferencesAnyUser
, kCFPreferencesCurrentHost
));
467 ADD_DOMAIN(_CFPreferencesStandardDomain(appPreferences
->_appName
, kCFPreferencesAnyUser
, kCFPreferencesAnyHost
));
468 ADD_DOMAIN(_CFPreferencesStandardDomain(kCFPreferencesAnyApplication
, kCFPreferencesAnyUser
, kCFPreferencesCurrentHost
));
469 ADD_DOMAIN(_CFPreferencesStandardDomain(kCFPreferencesAnyApplication
, kCFPreferencesAnyUser
, kCFPreferencesAnyHost
));
471 _CFApplicationPreferencesSetSearchList(appPreferences
, search
);
477 __private_extern__ _CFApplicationPreferences
*_CFStandardApplicationPreferences(CFStringRef appName
) {
478 _CFApplicationPreferences
*appPreferences
;
479 // CFAssert(appName != kCFPreferencesAnyApplication, __kCFLogAssertion, "Cannot use any of the CFPreferences...App... functions with an appName of kCFPreferencesAnyApplication");
480 __CFSpinLock(&__CFApplicationPreferencesLock
);
481 if (!__CFStandardUserPreferences
) {
482 __CFStandardUserPreferences
= CFDictionaryCreateMutable(NULL
, 0, & kCFTypeDictionaryKeyCallBacks
, NULL
);
484 if (!__CFStandardUserPreferences
) {
486 __CFSpinUnlock(&__CFApplicationPreferencesLock
);
489 if ((appPreferences
= (_CFApplicationPreferences
*)CFDictionaryGetValue(__CFStandardUserPreferences
, appName
)) == NULL
) {
490 appPreferences
= _CFApplicationPreferencesCreateWithUser(kCFPreferencesCurrentUser
, appName
);
491 CFDictionarySetValue(__CFStandardUserPreferences
, appName
, appPreferences
);
492 __CFSpinUnlock(&__CFApplicationPreferencesLock
);
493 _CFApplicationPreferencesSetStandardSearchList(appPreferences
);
495 __CFSpinUnlock(&__CFApplicationPreferencesLock
);
497 return appPreferences
;
500 // Exclusively for Foundation's use
501 void _CFApplicationPreferencesSetCacheForApp(_CFApplicationPreferences
*appPrefs
, CFStringRef appName
) {
502 __CFSpinLock(&__CFApplicationPreferencesLock
);
503 if (!__CFStandardUserPreferences
) {
504 __CFStandardUserPreferences
= CFDictionaryCreateMutable(NULL
, 0, &kCFTypeDictionaryKeyCallBacks
, NULL
);
505 CFDictionarySetValue(__CFStandardUserPreferences
, appName
, appPrefs
);
506 __CFSpinUnlock(&__CFApplicationPreferencesLock
);
508 _CFApplicationPreferences
*oldPrefs
= (_CFApplicationPreferences
*)CFDictionaryGetValue(__CFStandardUserPreferences
, appName
);
509 CFDictionarySetValue(__CFStandardUserPreferences
, appName
, appPrefs
);
510 __CFSpinUnlock(&__CFApplicationPreferencesLock
);
512 _CFDeallocateApplicationPreferences(oldPrefs
);
518 void _CFDeallocateApplicationPreferences(_CFApplicationPreferences
*self
) {
519 CFAllocatorRef alloc
= __CFPreferencesAllocator();
520 _CFApplicationPreferences
*cachedPrefs
= NULL
;
521 __CFSpinLock(&__CFApplicationPreferencesLock
);
523 // Get us out of the cache before destroying!
524 if (__CFStandardUserPreferences
) {
525 cachedPrefs
= (_CFApplicationPreferences
*)CFDictionaryGetValue(__CFStandardUserPreferences
, self
->_appName
);
527 if (cachedPrefs
== self
) {
528 CFDictionaryRemoveValue(__CFStandardUserPreferences
, self
->_appName
);
531 if (self
->_dictRep
) CFRelease(self
->_dictRep
);
532 CFRelease(self
->_search
);
533 CFRelease(self
->_appName
);
534 CFAllocatorDeallocate(alloc
, self
);
535 __CFSpinUnlock(&__CFApplicationPreferencesLock
);
538 // For Foundation's use
539 CFDictionaryRef
_CFApplicationPreferencesCopyRepresentationWithHint(_CFApplicationPreferences
*self
, CFDictionaryRef hint
) {
540 CFDictionaryRef dict
;
541 __CFSpinLock(&__CFApplicationPreferencesLock
);
542 if (!self
->_dictRep
) {
543 computeDictRep(self
);
545 if (self
->_dictRep
&& (self
->_dictRep
!= hint
)) {
546 CFRetain(self
->_dictRep
);
548 dict
= self
->_dictRep
;
549 __CFSpinUnlock(&__CFApplicationPreferencesLock
);
553 // For Foundation's use; does not do what it would seem to from the name
554 CFDictionaryRef
_CFApplicationPreferencesCopyRepresentation3(_CFApplicationPreferences
*self
, CFDictionaryRef hint
, CFDictionaryRef insertion
, CFPreferencesDomainRef afterDomain
) {
555 __CFSpinLock(&__CFApplicationPreferencesLock
);
556 if (0 == self
&& 0 == hint
&& 0 == afterDomain
) {
557 // This is so so gross.
558 if (__CFInsertion
) CFRelease(__CFInsertion
);
559 __CFInsertion
= insertion
? CFRetain(insertion
) : NULL
;
561 __CFSpinUnlock(&__CFApplicationPreferencesLock
);
566 CFDictionaryRef
_CFApplicationPreferencesCopyRepresentation(_CFApplicationPreferences
*self
) {
567 return _CFApplicationPreferencesCopyRepresentationWithHint(self
, NULL
);
570 __private_extern__
void _CFApplicationPreferencesSetSearchList(_CFApplicationPreferences
*self
, CFArrayRef newSearchList
) {
572 __CFSpinLock(&__CFApplicationPreferencesLock
);
573 CFArrayRemoveAllValues(self
->_search
);
574 count
= CFArrayGetCount(newSearchList
);
575 for (idx
= 0; idx
< count
; idx
++) {
576 CFArrayAppendValue(self
->_search
, CFArrayGetValueAtIndex(newSearchList
, idx
));
579 __CFSpinUnlock(&__CFApplicationPreferencesLock
);
582 void CFPreferencesAddSuitePreferencesToApp(CFStringRef appName
, CFStringRef suiteName
) {
583 _CFApplicationPreferences
*appPrefs
;
585 appPrefs
= _CFStandardApplicationPreferences(appName
);
586 _CFApplicationPreferencesAddSuitePreferences(appPrefs
, suiteName
);
589 void _CFApplicationPreferencesAddSuitePreferences(_CFApplicationPreferences
*appPrefs
, CFStringRef suiteName
) {
590 CFPreferencesDomainRef domain
;
594 // Find where to insert the new suite
595 __CFSpinLock(&__CFApplicationPreferencesLock
);
596 domain
= _CFPreferencesStandardDomain(appPrefs
->_appName
, kCFPreferencesCurrentUser
, kCFPreferencesAnyHost
);
598 range
.length
= CFArrayGetCount(appPrefs
->_search
);
599 idx
= domain
? CFArrayGetFirstIndexOfValue(appPrefs
->_search
, range
, domain
) : kCFNotFound
;
600 __CFSpinUnlock(&__CFApplicationPreferencesLock
);
601 idx
++; // We want just below the app domain. Coincidentally, this gives us the top of the list if the app domain has been removed.
602 domain
= _CFPreferencesStandardDomain(suiteName
, kCFPreferencesCurrentUser
, kCFPreferencesAnyHost
);
604 __CFSpinLock(&__CFApplicationPreferencesLock
);
605 CFArrayInsertValueAtIndex(appPrefs
->_search
, idx
, domain
);
606 __CFSpinUnlock(&__CFApplicationPreferencesLock
);
609 domain
= _CFPreferencesStandardDomain(suiteName
, kCFPreferencesCurrentUser
, kCFPreferencesCurrentHost
);
611 __CFSpinLock(&__CFApplicationPreferencesLock
);
612 CFArrayInsertValueAtIndex(appPrefs
->_search
, idx
, domain
);
613 __CFSpinUnlock(&__CFApplicationPreferencesLock
);
617 // Now the AnyUser domains
618 domain
= _CFPreferencesStandardDomain(appPrefs
->_appName
, kCFPreferencesAnyUser
, kCFPreferencesAnyHost
);
619 idx
= domain
? CFArrayGetFirstIndexOfValue(appPrefs
->_search
, range
, domain
) : kCFNotFound
;
620 if (idx
== kCFNotFound
) {
621 // 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
622 // Can this happen anymore? -[NSUserDefaults setSearchList:] is bailing. -- ctp - - 3 Jan 2002
623 domain
= _CFPreferencesStandardDomain(kCFPreferencesAnyApplication
, kCFPreferencesCurrentUser
, kCFPreferencesAnyHost
);
624 idx
= domain
? CFArrayGetFirstIndexOfValue(appPrefs
->_search
, range
, domain
) : kCFNotFound
;
625 if (idx
== kCFNotFound
) {
626 // Try the "any host" choice
627 domain
= _CFPreferencesStandardDomain(kCFPreferencesAnyApplication
, kCFPreferencesCurrentUser
, kCFPreferencesCurrentHost
);
628 idx
= domain
? CFArrayGetFirstIndexOfValue(appPrefs
->_search
, range
, domain
) : kCFNotFound
;
629 if (idx
== kCFNotFound
) {
630 // We give up; put the new domains at the bottom
631 idx
= CFArrayGetCount(appPrefs
->_search
) - 1;
636 domain
= _CFPreferencesStandardDomain(suiteName
, kCFPreferencesAnyUser
, kCFPreferencesAnyHost
);
638 __CFSpinLock(&__CFApplicationPreferencesLock
);
639 CFArrayInsertValueAtIndex(appPrefs
->_search
, idx
, domain
);
640 __CFSpinUnlock(&__CFApplicationPreferencesLock
);
642 domain
= _CFPreferencesStandardDomain(suiteName
, kCFPreferencesAnyUser
, kCFPreferencesCurrentHost
);
644 __CFSpinLock(&__CFApplicationPreferencesLock
);
645 CFArrayInsertValueAtIndex(appPrefs
->_search
, idx
, domain
);
646 __CFSpinUnlock(&__CFApplicationPreferencesLock
);
648 __CFSpinLock(&__CFApplicationPreferencesLock
);
649 updateDictRep(appPrefs
);
650 __CFSpinUnlock(&__CFApplicationPreferencesLock
);
653 void CFPreferencesRemoveSuitePreferencesFromApp(CFStringRef appName
, CFStringRef suiteName
) {
654 _CFApplicationPreferences
*appPrefs
;
656 appPrefs
= _CFStandardApplicationPreferences(appName
);
658 _CFApplicationPreferencesRemoveSuitePreferences(appPrefs
, suiteName
);
661 void _CFApplicationPreferencesRemoveSuitePreferences(_CFApplicationPreferences
*appPrefs
, CFStringRef suiteName
) {
662 CFPreferencesDomainRef domain
;
664 __CFSpinLock(&__CFApplicationPreferencesLock
);
665 domain
= _CFPreferencesStandardDomain(suiteName
, kCFPreferencesCurrentUser
, kCFPreferencesAnyHost
);
666 __CFSpinUnlock(&__CFApplicationPreferencesLock
);
667 if (domain
) _CFApplicationPreferencesRemoveDomain(appPrefs
, domain
);
669 __CFSpinLock(&__CFApplicationPreferencesLock
);
670 domain
= _CFPreferencesStandardDomain(suiteName
, kCFPreferencesCurrentUser
, kCFPreferencesCurrentHost
);
671 __CFSpinUnlock(&__CFApplicationPreferencesLock
);
672 if (domain
) _CFApplicationPreferencesRemoveDomain(appPrefs
, domain
);
674 __CFSpinLock(&__CFApplicationPreferencesLock
);
675 domain
= _CFPreferencesStandardDomain(suiteName
, kCFPreferencesAnyUser
, kCFPreferencesAnyHost
);
676 __CFSpinUnlock(&__CFApplicationPreferencesLock
);
677 if (domain
) _CFApplicationPreferencesRemoveDomain(appPrefs
, domain
);
679 __CFSpinLock(&__CFApplicationPreferencesLock
);
680 domain
= _CFPreferencesStandardDomain(suiteName
, kCFPreferencesAnyUser
, kCFPreferencesCurrentHost
);
681 __CFSpinUnlock(&__CFApplicationPreferencesLock
);
682 if (domain
) _CFApplicationPreferencesRemoveDomain(appPrefs
, domain
);
685 void _CFApplicationPreferencesAddDomain(_CFApplicationPreferences
*self
, CFPreferencesDomainRef domain
, Boolean addAtTop
) {
686 __CFSpinLock(&__CFApplicationPreferencesLock
);
688 CFArrayInsertValueAtIndex(self
->_search
, 0, domain
);
690 CFArrayAppendValue(self
->_search
, domain
);
693 __CFSpinUnlock(&__CFApplicationPreferencesLock
);
696 Boolean
_CFApplicationPreferencesContainsDomain(_CFApplicationPreferences
*self
, CFPreferencesDomainRef domain
) {
698 __CFSpinLock(&__CFApplicationPreferencesLock
);
699 result
= CFArrayContainsValue(self
->_search
, CFRangeMake(0, CFArrayGetCount(self
->_search
)), domain
);
700 __CFSpinUnlock(&__CFApplicationPreferencesLock
);
704 Boolean
_CFApplicationPreferencesContainsDomainNoLock(_CFApplicationPreferences
*self
, CFPreferencesDomainRef domain
) {
706 result
= CFArrayContainsValue(self
->_search
, CFRangeMake(0, CFArrayGetCount(self
->_search
)), domain
);
710 void _CFApplicationPreferencesRemoveDomain(_CFApplicationPreferences
*self
, CFPreferencesDomainRef domain
) {
713 __CFSpinLock(&__CFApplicationPreferencesLock
);
715 range
.length
= CFArrayGetCount(self
->_search
);
716 while ((idx
= CFArrayGetFirstIndexOfValue(self
->_search
, range
, domain
)) != kCFNotFound
) {
717 CFArrayRemoveValueAtIndex(self
->_search
, idx
);
718 range
.location
= idx
;
719 range
.length
= range
.length
- idx
- 1;
722 __CFSpinUnlock(&__CFApplicationPreferencesLock
);