preferences using CoreFoundation API calls:
http://www.purebasic.fr/english/viewtop ... 19&t=37245
But I had to delve still a little bit deeper into the Preferences API
because a member of the German PureBasic Forum had asked me
via PM how to detect which keyboard layout is currently enabled.
On MacOS X you have the option to activate several keyboard
layouts by selecting "System Preferences/Language & Text" and
selecting the tab "Input sources". But how do you determine which
layouts a user has selected?
To solve this problem the first step was to locate where this information
is stored. It is stored in
/Users/YourUserName/Library/Preferences/ByHost/com.apple.HIToolbox.xxx.plist
The xxx denotes a cryptic code of your user name. It is not possible
to utilize the High Level API in Airr's code example because you can't
simply specify an application but you have to use Low Level API calls
and specify the constants for user name and host name and let the OS
find your specified key. For clarity's sake I have taken this snapshot of
my current keyboard layout plist:

As you can see I have activated two keyboard layouts: "German" and
"USInternational PC" and I want to read out these values from the plist.
I had to program these steps:
1. Read out the key "AppleEnabledInputSources" (a CF array) and find out
how many array items (keyboard layouts) are defined.
2. Read out each defined item (as a CF dictionary object).
3. Read the key "KeyboardLayout Name" (a CF string) from each dictionary
and obtain the keyboard layout string.
4. Display the results.
One difficulty was to find out how the constants kCFPreferencesCurrentUser
and kCFPreferencesCurrentHost are defined. In CFPreferences.h they are
exported but I wasn't able to find out where and how they are defined until
I found the solution in the Apple Mailing lists:
Pete Gontier wrote:kCFPreferencesCurrentUser has a string value. I passed it to CFShow and it
turns out to be "kCFPreferencesCurrentUser".
Very tricky: the content of the constant is its own name...

Code: Select all
EnableExplicit
ImportC ""
CFArrayGetCount(CFArrayRef.L)
CFArrayGetTypeID()
CFArrayGetValueAtIndex(CFArrayRef.L, Index.L)
CFDictionaryGetTypeID()
CFDictionaryGetValue(CFDictionaryRef.L, *KeyToFind)
CFStringGetTypeID()
CFGetTypeID(CFTypeRef.L)
CFPreferencesCopyValue(CFKeyRef.L, CFApplicationIDRef, UserName.L, HostName.L)
CFRelease(CFTypeRef.L)
CFStringCreateWithCString(CFAllocatorRef.L, CString, CFStringEncoding.L)
CFStringGetCString(CFStringRef.L, *StringBuffer, BufferSize.L, CFStringEncoding.L)
KLGetCurrentKeyboardLayout(*KeyboardLayoutRef)
KLGetKeyboardLayoutProperty(KeyboardLayoutRef.L, PropertyTag.L, *PropertyValue)
EndImport
#kKLName = 5
Procedure.S ConvertCFStringIntoString(CFStringRef.L)
Protected String.S = Space(256)
CFStringGetCString(CFStringRef, @String, Len(String), 0)
ProcedureReturn Trim(String)
EndProcedure
Define AppIDRef.L
Define ArrayRef.L
Define DictionaryRef.L
Define HostNameRef.L
Define i.L
Define Info.S
Define ItemCount.L
Define KeyboardLayoutRef.L
Define KeyRef.L
Define LanguageNameRef.L
Define LayoutCount.L
Define LayoutList.S
Define StringRef.L
Define UserNameRef.L
; ----- Get current keyboard layout
If KLGetCurrentKeyboardLayout(@KeyboardLayoutRef) = 0
If KLGetKeyboardLayoutProperty(KeyboardLayoutRef, #kKLName, @LanguageNameRef) = 0
Info = "Current keyboard layout: " + ConvertCFStringIntoString(LanguageNameRef) + #CR$ + #CR$
EndIf
EndIf
; ----- Get number of enabled keyboard layouts
KeyRef = CFStringCreateWithCString(0, @"AppleEnabledInputSources", 0)
AppIDRef = CFStringCreateWithCString(0, @"com.apple.HIToolbox", 0)
UserNameRef = CFStringCreateWithCString(0, @"kCFPreferencesCurrentUser", 0)
HostNameRef = CFStringCreateWithCString(0, @"kCFPreferencesCurrentHost", 0)
ArrayRef = CFPreferencesCopyValue(KeyRef, AppIDRef, UserNameRef, HostNameRef)
If ArrayRef
If CFGetTypeID(ArrayRef) = CFArrayGetTypeID()
ItemCount = CFArrayGetCount(ArrayRef)
EndIf
CFRelease(KeyRef)
CFRelease(AppIDRef)
CFRelease(UserNameRef)
CFRelease(HostNameRef)
CFRelease(ArrayRef)
EndIf
; ----- Get the name of each enabled keyboard layout
If ItemCount > 1
For i = 0 To ItemCount - 1
DictionaryRef = CFArrayGetValueAtIndex(ArrayRef, i)
If CFGetTypeID(DictionaryRef) = CFDictionaryGetTypeID()
KeyRef = CFStringCreateWithCString(0, @"KeyboardLayout Name", 0)
StringRef = CFDictionaryGetValue(DictionaryRef, KeyRef)
If StringRef
If CFGetTypeID(StringRef) = CFStringGetTypeID()
LayoutCount + 1
LayoutList + Str(LayoutCount) + ". " + ConvertCFStringIntoString(StringRef) + #CR$
EndIf
CFRelease(StringRef)
EndIf
CFRelease(KeyRef)
EndIf
CFRelease(DictionaryRef)
Next i
EndIf
Info = Info + "Enabled keyboard layouts: " + Str(LayoutCount) + #CR$ + LayoutList
MessageRequester("Preferences-Info", Info)
of "AppleEnabledInputSources" must have a key "KeyboardLayout Name"!