< prev index next >

src/java.base/macosx/native/libjava/java_props_macosx.c

Print this page
rev 17428 : [mq]: 8160199


  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?


< prev index next >