30
31 #include <Security/AuthSession.h>
32 #include <CoreFoundation/CoreFoundation.h>
33 #include <SystemConfiguration/SystemConfiguration.h>
34 #include <Foundation/Foundation.h>
35
36 #include "java_props_macosx.h"
37
38 char *getPosixLocale(int cat) {
39 char *lc = setlocale(cat, NULL);
40 if ((lc == NULL) || (strcmp(lc, "C") == 0)) {
41 lc = getenv("LANG");
42 }
43 if (lc == NULL) return NULL;
44 return strdup(lc);
45 }
46
47 #define LOCALEIDLENGTH 128
48 char *getMacOSXLocale(int cat) {
49 const char* retVal = NULL;
50
51 switch (cat) {
52 case LC_MESSAGES:
53 {
54 // get preferred language code
55 CFArrayRef languages = CFLocaleCopyPreferredLanguages();
56 if (languages == NULL) {
57 return NULL;
58 }
59 if (CFArrayGetCount(languages) <= 0) {
60 CFRelease(languages);
61 return NULL;
62 }
63
64 CFStringRef primaryLanguage = (CFStringRef)CFArrayGetValueAtIndex(languages, 0);
65 if (primaryLanguage == NULL) {
66 CFRelease(languages);
67 return NULL;
68 }
69 char languageString[LOCALEIDLENGTH];
70 if (CFStringGetCString(primaryLanguage, languageString,
71 LOCALEIDLENGTH, CFStringGetSystemEncoding()) == false) {
72 CFRelease(languages);
73 return NULL;
74 }
75 CFRelease(languages);
76
77 retVal = languageString;
78
79 // Special case for Portuguese in Brazil:
80 // The language code needs the "_BR" region code (to distinguish it
81 // from Portuguese in Portugal), but this is missing when using the
82 // "Portuguese (Brazil)" language.
83 // If language is "pt" and the current locale is pt_BR, return pt_BR.
84 char localeString[LOCALEIDLENGTH];
85 if (strcmp(retVal, "pt") == 0 &&
86 CFStringGetCString(CFLocaleGetIdentifier(CFLocaleCopyCurrent()),
87 localeString, LOCALEIDLENGTH, CFStringGetSystemEncoding()) &&
88 strcmp(localeString, "pt_BR") == 0) {
89 retVal = localeString;
90 }
91 }
92 break;
93 default:
94 {
95 char localeString[LOCALEIDLENGTH];
96 if (!CFStringGetCString(CFLocaleGetIdentifier(CFLocaleCopyCurrent()),
97 localeString, LOCALEIDLENGTH, CFStringGetSystemEncoding())) {
98 return NULL;
99 }
100 retVal = localeString;
101 }
102 break;
103 }
104
105 if (retVal != NULL) {
106 // Language IDs use the language designators and (optional) region
107 // and script designators of BCP 47. So possible formats are:
108 //
109 // "en" (language designator only)
110 // "haw" (3-letter lanuage designator)
111 // "en-GB" (language with alpha-2 region designator)
112 // "es-419" (language with 3-digit UN M.49 area code)
113 // "zh-Hans" (language with ISO 15924 script designator)
114 // "zh-Hans-US" (language with ISO 15924 script designator and region)
115 // "zh-Hans-419" (language with ISO 15924 script designator and UN M.49)
116 //
117 // In the case of region designators (alpha-2 and/or UN M.49), we convert
118 // to our locale string format by changing '-' to '_'. That is, if
119 // the '-' is followed by fewer than 4 chars.
120 char* scriptOrRegion = strchr(retVal, '-');
121 if (scriptOrRegion != NULL) {
122 int length = strlen(scriptOrRegion);
123 if (length > 5) {
124 // Region and script both exist. Honor the script for now
125 scriptOrRegion[5] = '\0';
126 } else if (length < 5) {
127 *scriptOrRegion = '_';
128
129 assert((length == 3 &&
130 // '-' followed by a 2 character region designator
131 isalpha(scriptOrRegion[1]) &&
132 isalpha(scriptOrRegion[2])) ||
133 (length == 4 &&
134 // '-' followed by a 3-digit UN M.49 area code
135 isdigit(scriptOrRegion[1]) &&
136 isdigit(scriptOrRegion[2]) &&
137 isdigit(scriptOrRegion[3])));
138 }
139 }
140
141 return strdup(retVal);
142 }
143 return NULL;
144 }
145
146 char *setupMacOSXLocale(int cat) {
147 char * ret = getMacOSXLocale(cat);
148
149 if (ret == NULL) {
150 return getPosixLocale(cat);
151 } else {
152 return ret;
153 }
154 }
155
156 int isInAquaSession() {
157 // environment variable to bypass the aqua session check
158 char *ev = getenv("AWT_FORCE_HEADFUL");
159 if (ev && (strncasecmp(ev, "true", 4) == 0)) {
160 // if "true" then tell the caller we're in an Aqua session without actually checking
161 return 1;
162 }
163 // Is the WindowServer available?
|
30
31 #include <Security/AuthSession.h>
32 #include <CoreFoundation/CoreFoundation.h>
33 #include <SystemConfiguration/SystemConfiguration.h>
34 #include <Foundation/Foundation.h>
35
36 #include "java_props_macosx.h"
37
38 char *getPosixLocale(int cat) {
39 char *lc = setlocale(cat, NULL);
40 if ((lc == NULL) || (strcmp(lc, "C") == 0)) {
41 lc = getenv("LANG");
42 }
43 if (lc == NULL) return NULL;
44 return strdup(lc);
45 }
46
47 #define LOCALEIDLENGTH 128
48 char *getMacOSXLocale(int cat) {
49 const char* retVal = NULL;
50 char localeString[LOCALEIDLENGTH];
51
52 switch (cat) {
53 case LC_MESSAGES:
54 {
55 // get preferred language code
56 CFArrayRef languages = CFLocaleCopyPreferredLanguages();
57 if (languages == NULL) {
58 return NULL;
59 }
60 if (CFArrayGetCount(languages) <= 0) {
61 CFRelease(languages);
62 return NULL;
63 }
64
65 CFStringRef primaryLanguage = (CFStringRef)CFArrayGetValueAtIndex(languages, 0);
66 if (primaryLanguage == NULL) {
67 CFRelease(languages);
68 return NULL;
69 }
70 char languageString[LOCALEIDLENGTH];
71 if (CFStringGetCString(primaryLanguage, languageString,
72 LOCALEIDLENGTH, CFStringGetSystemEncoding()) == false) {
73 CFRelease(languages);
74 return NULL;
75 }
76 CFRelease(languages);
77
78 // Explicitly supply region, if there is none
79 CFStringGetCString(CFLocaleGetIdentifier(CFLocaleCopyCurrent()),
80 localeString, LOCALEIDLENGTH, CFStringGetSystemEncoding());
81 char *hyphenPos = strchr(languageString, '-');
82 int langStrLen = strlen(languageString);
83
84 if (hyphenPos == NULL || // languageString contains ISO639 only, e.g., "en"
85 languageString + langStrLen - hyphenPos == 5) { // ISO639-ScriptCode, e.g., "en-Latn"
86 char *underscorePos = strrchr(localeString, '_');
87 char *region = NULL;
88
89 if (underscorePos != NULL) {
90 region = underscorePos + 1;
91 }
92
93 if (region != NULL) {
94 strcat(languageString, "-");
95 strcat(languageString, region);
96 }
97 }
98
99 retVal = languageString;
100 }
101 break;
102
103 default:
104 {
105 if (!CFStringGetCString(CFLocaleGetIdentifier(CFLocaleCopyCurrent()),
106 localeString, LOCALEIDLENGTH, CFStringGetSystemEncoding())) {
107 return NULL;
108 }
109
110 retVal = localeString;
111 }
112 break;
113 }
114
115 if (retVal != NULL) {
116 return strdup(convertToPOSIXLocale(retVal));
117 }
118
119 return NULL;
120 }
121
122 /* Language IDs use the language designators and (optional) region
123 * and script designators of BCP 47. So possible formats are:
124 *
125 * "en" (language designator only)
126 * "haw" (3-letter lanuage designator)
127 * "en-GB" (language with alpha-2 region designator)
128 * "es-419" (language with 3-digit UN M.49 area code)
129 * "zh-Hans" (language with ISO 15924 script designator)
130 * "zh-Hans-US" (language with ISO 15924 script designator and region)
131 * "zh-Hans-419" (language with ISO 15924 script designator and UN M.49)
132 *
133 * convert these tags into POSIX conforming locale string, i.e.,
134 * lang{_region}{@script}. e.g.,
135 * for "zh-Hans-US" into "zh_US@Hans"
136 */
137 const char * convertToPOSIXLocale(const char* src) {
138 char* scriptRegion = strchr(src, '-');
139 if (scriptRegion != NULL) {
140 int length = strlen(scriptRegion);
141 char* region = strchr(scriptRegion + 1, '-');
142 char* atMark = NULL;
143
144 if (region == NULL) {
145 // CFLocaleGetIdentifier() returns '_' before region
146 region = strchr(scriptRegion + 1, '_');
147 }
148
149 *scriptRegion = '_';
150 if (length > 5) {
151 // Region and script both exist.
152 char tmp[4];
153 int regionLength = length - 6;
154 atMark = scriptRegion + 1 + regionLength;
155 memcpy(tmp, scriptRegion + 1, 4);
156 memmove(scriptRegion + 1, region + 1, regionLength);
157 memcpy(atMark + 1, tmp, 4);
158 } else if (length == 5) {
159 // script only
160 atMark = scriptRegion;
161 }
162
163 if (atMark != NULL) {
164 *atMark = '@';
165
166 // assert script code
167 assert(isalpha(atMark[1]) &&
168 isalpha(atMark[2]) &&
169 isalpha(atMark[3]) &&
170 isalpha(atMark[4]));
171 }
172
173 assert((length == 3 || length == 8) &&
174 // '_' followed by a 2 character region designator
175 isalpha(scriptRegion[1]) &&
176 isalpha(scriptRegion[2]) ||
177 (length == 4 || length == 9) &&
178 // '_' followed by a 3-digit UN M.49 area code
179 isdigit(scriptRegion[1]) &&
180 isdigit(scriptRegion[2]) &&
181 isdigit(scriptRegion[3]) ||
182 // '@' followed by a 4 character script code (already validated above)
183 length == 5);
184 }
185
186 return src;
187 }
188
189 char *setupMacOSXLocale(int cat) {
190 char * ret = getMacOSXLocale(cat);
191
192 if (ret == NULL) {
193 return getPosixLocale(cat);
194 } else {
195 return ret;
196 }
197 }
198
199 int isInAquaSession() {
200 // environment variable to bypass the aqua session check
201 char *ev = getenv("AWT_FORCE_HEADFUL");
202 if (ev && (strncasecmp(ev, "true", 4) == 0)) {
203 // if "true" then tell the caller we're in an Aqua session without actually checking
204 return 1;
205 }
206 // Is the WindowServer available?
|