]> git.saurik.com Git - apple/cf.git/blobdiff - String.subproj/CFStringDefaultEncoding.h
CF-368.tar.gz
[apple/cf.git] / String.subproj / CFStringDefaultEncoding.h
diff --git a/String.subproj/CFStringDefaultEncoding.h b/String.subproj/CFStringDefaultEncoding.h
new file mode 100644 (file)
index 0000000..976e06a
--- /dev/null
@@ -0,0 +1,202 @@
+/*
+ * Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ * 
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*     CFStringDefaultEncoding.h
+       Copyright (c) 1998-2005, Apple, Inc. All rights reserved.
+*/
+
+/* This file defines static inline functions used both by CarbonCore & CF. */
+
+#include <CoreFoundation/CFBase.h>
+#if defined(__MACH__)
+#include <stdlib.h>
+#include <fcntl.h>
+#include <pwd.h>
+#include <sys/param.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdio.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#define __kCFUserEncodingEnvVariableName ("__CF_USER_TEXT_ENCODING")
+#define __kCFMaxDefaultEncodingFileLength (24)
+#define __kCFUserEncodingFileName ("/.CFUserTextEncoding")
+
+/* This function is used to obtain users' default script/region code.
+   The function first looks at environment variable __kCFUserEncodingEnvVariableName, then, reads the configuration file in user's home directory.
+*/
+CF_INLINE void __CFStringGetUserDefaultEncoding(UInt32 *oScriptValue, UInt32 *oRegionValue) {
+    char *stringValue;
+    char buffer[__kCFMaxDefaultEncodingFileLength];
+    int uid = getuid();
+
+    if ((stringValue = getenv(__kCFUserEncodingEnvVariableName)) != NULL) {
+        if ((uid == strtol(stringValue, &stringValue, 0)) && (':' == *stringValue)) {
+            ++stringValue;
+        } else {
+            stringValue = NULL;
+        }
+    }
+
+    if ((stringValue == NULL) && ((uid > 0) || getenv("HOME"))) {
+        struct passwd *passwdp;
+
+        if ((passwdp = getpwuid((uid_t)uid))) {
+            char filename[MAXPATHLEN + 1];
+            int fd;
+
+            strcpy(filename, passwdp->pw_dir);
+            strcat(filename, __kCFUserEncodingFileName);
+
+            if ((fd = open(filename, O_RDONLY, 0)) == -1) {
+                // Cannot open the file. Let's fallback to smRoman/verUS
+                snprintf(filename, sizeof(filename), "%s=0x%X:0:0", __kCFUserEncodingEnvVariableName, uid);
+                putenv(filename);
+            } else {
+                int readSize;
+
+               // cjk: We do not turn on F_NOCACHE on the fd here, because
+               // many processes read this file on startup, and caching the
+               // is probably a good thing, for the system as a whole.
+                readSize = read(fd, buffer, __kCFMaxDefaultEncodingFileLength - 1);
+                buffer[(readSize < 0 ? 0 : readSize)] = '\0';
+                close(fd);
+                stringValue = buffer;
+
+                // Well, we already have a buffer, let's reuse it
+                snprintf(filename, sizeof(filename), "%s=0x%X:%s", __kCFUserEncodingEnvVariableName, uid, buffer);
+                putenv(filename);
+            }
+        }
+    }
+
+    if (stringValue) {
+        *oScriptValue = strtol(stringValue, &stringValue, 0);
+        if (*stringValue == ':') {
+            if (oRegionValue) *oRegionValue = strtol(++stringValue, NULL, 0);
+            return;
+        }
+    }
+
+    // Falling back
+    *oScriptValue = 0; // smRoman
+    if (oRegionValue) *oRegionValue = 0; // verUS
+}
+
+CF_INLINE uint32_t __CFStringGetInstallationRegion() {
+    char *stringValue = NULL;
+    char buffer[__kCFMaxDefaultEncodingFileLength];
+    struct passwd *passwdp;
+    
+    if ((passwdp = getpwuid((uid_t)0))) {
+        char filename[MAXPATHLEN + 1];
+        int fd;
+        
+        strcpy(filename, passwdp->pw_dir);
+        strcat(filename, __kCFUserEncodingFileName);
+        
+        if ((fd = open(filename, O_RDONLY, 0)) != -1) {
+            int readSize;
+            
+            // cjk: We do not turn on F_NOCACHE on the fd here, because
+            // many processes read this file on startup, and caching the
+            // is probably a good thing, for the system as a whole.
+            readSize = read(fd, buffer, __kCFMaxDefaultEncodingFileLength - 1);
+            buffer[(readSize < 0 ? 0 : readSize)] = '\0';
+            close(fd);
+            stringValue = buffer;
+        }
+    }
+    
+    if (stringValue) {
+        (void)strtol(stringValue, &stringValue, 0);
+        if (*stringValue == ':') return strtol(++stringValue, NULL, 0);
+    }
+
+    return 0; // verUS
+}
+
+CF_INLINE void __CFStringGetInstallationEncodingAndRegion(uint32_t *encoding, uint32_t *region) {
+    char *stringValue = NULL;
+    char buffer[__kCFMaxDefaultEncodingFileLength];
+    struct passwd *passwdp;
+
+    *encoding = 0; *region = 0;
+
+    if ((passwdp = getpwuid((uid_t)0))) {
+        char filename[MAXPATHLEN + 1];
+        int fd;
+        
+        strcpy(filename, passwdp->pw_dir);
+        strcat(filename, __kCFUserEncodingFileName);
+        
+        if ((fd = open(filename, O_RDONLY, 0)) != -1) {
+            int readSize;
+            
+            // cjk: We do not turn on F_NOCACHE on the fd here, because
+            // many processes read this file on startup, and caching the
+            // is probably a good thing, for the system as a whole.
+            readSize = read(fd, buffer, __kCFMaxDefaultEncodingFileLength - 1);
+            buffer[(readSize < 0 ? 0 : readSize)] = '\0';
+            close(fd);
+            stringValue = buffer;
+        }
+    }
+    
+    if (stringValue) {
+        *encoding = strtol(stringValue, &stringValue, 0);
+        if (*stringValue == ':') *region = strtol(++stringValue, NULL, 0);
+    }
+}
+
+CF_INLINE void __CFStringSaveUserDefaultEncoding(UInt32 iScriptValue, UInt32 iRegionValue) {
+    struct passwd *passwdp;
+
+    if ((passwdp = getpwuid(getuid()))) {
+        char filename[MAXPATHLEN + 1];
+        int fd;
+
+        strcpy(filename, passwdp->pw_dir);
+        strcat(filename, __kCFUserEncodingFileName);
+
+        // In case, file exists
+        (void)unlink(filename);
+
+        if ((fd = open(filename, O_WRONLY|O_CREAT, 0400)) != -1) {
+            char buffer[__kCFMaxDefaultEncodingFileLength];
+            unsigned int writeSize;
+
+            writeSize = snprintf(buffer, __kCFMaxDefaultEncodingFileLength, "0x%X:0x%X", (unsigned int)iScriptValue, (unsigned int)iRegionValue);
+            (void)write(fd, buffer, (writeSize > __kCFMaxDefaultEncodingFileLength ? __kCFMaxDefaultEncodingFileLength : writeSize));
+            close(fd);
+        }
+    }
+}
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* __MACH__ */