diff options
Diffstat (limited to 'src/intlemu/intlemu.c')
-rw-r--r-- | src/intlemu/intlemu.c | 251 |
1 files changed, 132 insertions, 119 deletions
diff --git a/src/intlemu/intlemu.c b/src/intlemu/intlemu.c index a8461b7..eaa9252 100644 --- a/src/intlemu/intlemu.c +++ b/src/intlemu/intlemu.c | |||
@@ -15,132 +15,145 @@ | |||
15 | static pthread_mutex_t intlemu_lock; | 15 | static pthread_mutex_t intlemu_lock; |
16 | static CFMutableDictionaryRef intlemu_dict; | 16 | static CFMutableDictionaryRef intlemu_dict; |
17 | 17 | ||
18 | static void intlemu_cstring_release(CFAllocatorRef allocator, const void *value) | 18 | static void |
19 | intlemu_cstring_release (CFAllocatorRef allocator, const void *value) | ||
19 | { | 20 | { |
20 | free((void *)value); | 21 | free ((void *) value); |
21 | } | 22 | } |
22 | 23 | ||
23 | void __attribute__ ((constructor)) intlemu_init_() { | ||
24 | CFDictionaryValueCallBacks cstring_value_callbacks = | ||
25 | { | ||
26 | 0, /* version */ | ||
27 | NULL, /* retain callback */ | ||
28 | &intlemu_cstring_release, /* release callback */ | ||
29 | NULL, /* copy description */ | ||
30 | NULL /* equal */ | ||
31 | }; | ||
32 | if (pthread_mutex_init(&intlemu_lock, NULL) != 0) | ||
33 | abort(); | ||
34 | |||
35 | intlemu_dict = CFDictionaryCreateMutable( | ||
36 | kCFAllocatorDefault, | ||
37 | 0, | ||
38 | &kCFCopyStringDictionaryKeyCallBacks, | ||
39 | &cstring_value_callbacks); | ||
40 | if (intlemu_dict == NULL) | ||
41 | abort(); | ||
42 | } | ||
43 | 24 | ||
44 | void __attribute__ ((destructor)) intlemu_fini_() { | 25 | void __attribute__ ((constructor)) |
45 | if (intlemu_dict) | 26 | intlemu_init_ () |
46 | CFRelease(intlemu_dict); | 27 | { |
28 | CFDictionaryValueCallBacks cstring_value_callbacks = { | ||
29 | 0, /* version */ | ||
30 | NULL, /* retain callback */ | ||
31 | &intlemu_cstring_release, /* release callback */ | ||
32 | NULL, /* copy description */ | ||
33 | NULL /* equal */ | ||
34 | }; | ||
35 | if (pthread_mutex_init (&intlemu_lock, NULL) != 0) | ||
36 | abort (); | ||
47 | 37 | ||
48 | pthread_mutex_destroy(&intlemu_lock); | 38 | intlemu_dict = CFDictionaryCreateMutable ( |
39 | kCFAllocatorDefault, | ||
40 | 0, | ||
41 | &kCFCopyStringDictionaryKeyCallBacks, | ||
42 | &cstring_value_callbacks); | ||
43 | if (intlemu_dict == NULL) | ||
44 | abort (); | ||
49 | } | 45 | } |
50 | 46 | ||
51 | char * intlemu_bgettext (CFBundleRef bundle, const char *msgid) | 47 | |
48 | void __attribute__ ((destructor)) | ||
49 | intlemu_fini_ () | ||
52 | { | 50 | { |
53 | CFStringRef key; | 51 | if (intlemu_dict) |
54 | const char *value; | 52 | CFRelease (intlemu_dict); |
55 | CFStringRef s; | 53 | |
56 | CFRange r; | 54 | pthread_mutex_destroy (&intlemu_lock); |
57 | CFIndex len; | ||
58 | CFIndex clen; | ||
59 | char *buf; | ||
60 | |||
61 | if (msgid == NULL) | ||
62 | return NULL; | ||
63 | if (bundle == NULL) | ||
64 | return msgid; | ||
65 | |||
66 | key = CFStringCreateWithBytes( | ||
67 | kCFAllocatorDefault, | ||
68 | (const UInt8 *)msgid, | ||
69 | (CFIndex)strlen(msgid), | ||
70 | kCFStringEncodingUTF8, | ||
71 | false); | ||
72 | |||
73 | if (pthread_mutex_lock(&intlemu_lock) != 0) | ||
74 | abort(); | ||
75 | value = (char *)CFDictionaryGetValue(intlemu_dict, key); | ||
76 | if (pthread_mutex_unlock(&intlemu_lock) != 0) | ||
77 | abort(); | ||
78 | if (value != NULL) { | ||
79 | CFRelease(key); | ||
80 | return (char *)value; | ||
81 | } | ||
82 | |||
83 | /* no cached translaation, so, find one from the bundle */ | ||
84 | s = CFBundleCopyLocalizedString( | ||
85 | bundle, | ||
86 | key, | ||
87 | NULL, | ||
88 | NULL); | ||
89 | if (s == key) { | ||
90 | CFRelease(key); | ||
91 | return (char *)msgid; | ||
92 | } | ||
93 | /* get the length in bytes */ | ||
94 | r.location = 0; | ||
95 | r.length = CFStringGetLength(s); | ||
96 | len = 0; | ||
97 | clen = CFStringGetBytes( | ||
98 | s, | ||
99 | r, | ||
100 | kCFStringEncodingUTF8, | ||
101 | 0, | ||
102 | false, | ||
103 | NULL, | ||
104 | 0, | ||
105 | &len); | ||
106 | buf = NULL; | ||
107 | if (clen == r.length) { | ||
108 | buf = malloc(len + 1); | ||
109 | } | ||
110 | |||
111 | if (buf == NULL) { | ||
112 | CFRelease(s); | ||
113 | CFRelease(key); | ||
114 | return (char *)msgid; | ||
115 | } | ||
116 | |||
117 | clen = CFStringGetBytes( | ||
118 | s, | ||
119 | r, | ||
120 | kCFStringEncodingUTF8, | ||
121 | 0, | ||
122 | false, | ||
123 | (UInt8 *)buf, | ||
124 | len, | ||
125 | &len); | ||
126 | buf[len] = '\0'; | ||
127 | if (clen == r.length) { | ||
128 | if (pthread_mutex_lock(&intlemu_lock) != 0) | ||
129 | abort(); | ||
130 | CFDictionaryAddValue(intlemu_dict, key, buf); | ||
131 | if (pthread_mutex_unlock(&intlemu_lock) != 0) | ||
132 | abort(); | ||
133 | value = buf; | ||
134 | } | ||
135 | else { | ||
136 | free(buf); | ||
137 | value = msgid; | ||
138 | } | ||
139 | |||
140 | CFRelease(s); | ||
141 | |||
142 | CFRelease(key); | ||
143 | |||
144 | return (char *)value; | ||
145 | } | 55 | } |
146 | 56 | ||
57 | |||
58 | char * | ||
59 | intlemu_bgettext (CFBundleRef bundle, const char *msgid) | ||
60 | { | ||
61 | CFStringRef key; | ||
62 | const char *value; | ||
63 | CFStringRef s; | ||
64 | CFRange r; | ||
65 | CFIndex len; | ||
66 | CFIndex clen; | ||
67 | char *buf; | ||
68 | |||
69 | if (msgid == NULL) | ||
70 | return NULL; | ||
71 | if (bundle == NULL) | ||
72 | return msgid; | ||
73 | |||
74 | key = CFStringCreateWithBytes ( | ||
75 | kCFAllocatorDefault, | ||
76 | (const UInt8 *) msgid, | ||
77 | (CFIndex) strlen (msgid), | ||
78 | kCFStringEncodingUTF8, | ||
79 | false); | ||
80 | |||
81 | if (pthread_mutex_lock (&intlemu_lock) != 0) | ||
82 | abort (); | ||
83 | value = (char *) CFDictionaryGetValue (intlemu_dict, key); | ||
84 | if (pthread_mutex_unlock (&intlemu_lock) != 0) | ||
85 | abort (); | ||
86 | if (value != NULL) | ||
87 | { | ||
88 | CFRelease (key); | ||
89 | return (char *) value; | ||
90 | } | ||
91 | |||
92 | /* no cached translaation, so, find one from the bundle */ | ||
93 | s = CFBundleCopyLocalizedString ( | ||
94 | bundle, | ||
95 | key, | ||
96 | NULL, | ||
97 | NULL); | ||
98 | if (s == key) | ||
99 | { | ||
100 | CFRelease (key); | ||
101 | return (char *) msgid; | ||
102 | } | ||
103 | /* get the length in bytes */ | ||
104 | r.location = 0; | ||
105 | r.length = CFStringGetLength (s); | ||
106 | len = 0; | ||
107 | clen = CFStringGetBytes ( | ||
108 | s, | ||
109 | r, | ||
110 | kCFStringEncodingUTF8, | ||
111 | 0, | ||
112 | false, | ||
113 | NULL, | ||
114 | 0, | ||
115 | &len); | ||
116 | buf = NULL; | ||
117 | if (clen == r.length) | ||
118 | { | ||
119 | buf = malloc (len + 1); | ||
120 | } | ||
121 | |||
122 | if (buf == NULL) | ||
123 | { | ||
124 | CFRelease (s); | ||
125 | CFRelease (key); | ||
126 | return (char *) msgid; | ||
127 | } | ||
128 | |||
129 | clen = CFStringGetBytes ( | ||
130 | s, | ||
131 | r, | ||
132 | kCFStringEncodingUTF8, | ||
133 | 0, | ||
134 | false, | ||
135 | (UInt8 *) buf, | ||
136 | len, | ||
137 | &len); | ||
138 | buf[len] = '\0'; | ||
139 | if (clen == r.length) | ||
140 | { | ||
141 | if (pthread_mutex_lock (&intlemu_lock) != 0) | ||
142 | abort (); | ||
143 | CFDictionaryAddValue (intlemu_dict, key, buf); | ||
144 | if (pthread_mutex_unlock (&intlemu_lock) != 0) | ||
145 | abort (); | ||
146 | value = buf; | ||
147 | } | ||
148 | else | ||
149 | { | ||
150 | free (buf); | ||
151 | value = msgid; | ||
152 | } | ||
153 | |||
154 | CFRelease (s); | ||
155 | |||
156 | CFRelease (key); | ||
157 | |||
158 | return (char *) value; | ||
159 | } | ||