diff options
Diffstat (limited to 'lib/libsi18n/acclanglist.c')
-rw-r--r-- | lib/libsi18n/acclanglist.c | 187 |
1 files changed, 187 insertions, 0 deletions
diff --git a/lib/libsi18n/acclanglist.c b/lib/libsi18n/acclanglist.c new file mode 100644 index 00000000..cc985cde --- /dev/null +++ b/lib/libsi18n/acclanglist.c @@ -0,0 +1,187 @@ +/** BEGIN COPYRIGHT BLOCK + * Copyright 2001 Sun Microsystems, Inc. + * Portions copyright 1999, 2001-2003 Netscape Communications Corporation. + * All rights reserved. + * END COPYRIGHT BLOCK **/ + +#include <stdio.h> +#include <string.h> +#include <ctype.h> +#include <stdlib.h> + +#include "i18n.h" + + +/* + * Accept-Language = "Accept-Language" ":" + * 1#( language-range [ ";" "q" "=" qvalue ] ) + * language-range = ( ( 1*8ALPHA *( "-" 1*8ALPHA ) ) | "*" ) + * + * NLS_AccLangList() assumes that "Accept-Language:" has already + * been stripped off. It takes as input + * + * 1#( ( ( 1*8ALPHA *( "-" 1*8ALPHA ) ) | "*" ) [ ";" "q" "=" qvalue ] ) + * + * and returns a list of languages, ordered by qvalues, in + * the array NLS_ACCEPT_LANGUAGE_LIST. + * + * If there are to many languages (>NLS_MAX_ACCEPT_LANGUAGE) the excess + * is ignored. If the language-range is too long (>NLS_MAX_ACCEPT_LENGTH), + * the language-range is ignored. In these cases, NLS_AccLangList() + * will quietly return, perhaps with numLang = 0. numLang is + * returned by the function. + */ + + +static size_t +AcceptLangList(const char* AcceptLanguage, + ACCEPT_LANGUAGE_LIST AcceptLanguageList) +{ + char* input; + char* cPtr; + char* cPtr1; + char* cPtr2; + int i; + int j; + int countLang = 0; + + input = strdup(AcceptLanguage); + if (input == (char*)NULL){ + return 0; + } + + cPtr1 = input-1; + cPtr2 = input; + + /* put in standard form */ + while (*(++cPtr1)) { + if (isalpha(*cPtr1)) *cPtr2++ = tolower(*cPtr1); /* force lower case */ + else if (isspace(*cPtr1)); /* ignore any space */ + else if (*cPtr1=='-') *cPtr2++ = '_'; /* "-" -> "_" */ + else if (*cPtr1=='*'); /* ignore "*" */ + else *cPtr2++ = *cPtr1; /* else unchanged */ + } + *cPtr2 = '\0'; + + countLang = 0; + + if (strchr(input,';')) { + /* deal with the quality values */ + + float qvalue[MAX_ACCEPT_LANGUAGE]; + float qSwap; + float bias = 0.0f; + char* ptrLanguage[MAX_ACCEPT_LANGUAGE]; + char* ptrSwap; + + cPtr = strtok(input,","); + while (cPtr) { + qvalue[countLang] = 1.0f; + if (cPtr1 = strchr(cPtr,';')) { + sscanf(cPtr1,";q=%f",&qvalue[countLang]); + *cPtr1 = '\0'; + } + if (strlen(cPtr)<MAX_ACCEPT_LENGTH) { /* ignore if too long */ + qvalue[countLang] -= (bias += 0.0001f); /* to insure original order */ + ptrLanguage[countLang++] = cPtr; + if (countLang>=MAX_ACCEPT_LANGUAGE) break; /* quit if too many */ + } + cPtr = strtok(NULL,","); + } + + /* sort according to decending qvalue */ + /* not a very good algorithm, but count is not likely large */ + for ( i=0 ; i<countLang-1 ; i++ ) { + for ( j=i+1 ; j<countLang ; j++ ) { + if (qvalue[i]<qvalue[j]) { + qSwap = qvalue[i]; + qvalue[i] = qvalue[j]; + qvalue[j] = qSwap; + ptrSwap = ptrLanguage[i]; + ptrLanguage[i] = ptrLanguage[j]; + ptrLanguage[j] = ptrSwap; + } + } + } + for ( i=0 ; i<countLang ; i++ ) { + strcpy(AcceptLanguageList[i],ptrLanguage[i]); + } + + } else { + /* simple case: no quality values */ + + cPtr = strtok(input,","); + while (cPtr) { + if (strlen(cPtr)<MAX_ACCEPT_LENGTH) { /* ignore if too long */ + strcpy(AcceptLanguageList[countLang++],cPtr); + if (countLang>=MAX_ACCEPT_LANGUAGE) break; /* quit if too many */ + } + cPtr = strtok(NULL,","); + } + } + + free(input); + + return countLang; +} + +/* + * Get prioritized locale list from NLS_AcceptLangList + * + * Add additonal language to the list for fallback if locale + * name is language_region + * + */ + + +int +XP_AccLangList(char* AcceptLanguage, + ACCEPT_LANGUAGE_LIST AcceptLanguageList) +{ + int i; + int n; + char *defaultLanguage = "en"; + ACCEPT_LANGUAGE_LIST curLanguageList; + int index = 0; + char lang[3]; + int k; + + n = AcceptLangList(AcceptLanguage, curLanguageList); + + if (n == 0) + return 0; + + memset(lang, 0, 3); + for (i = 0; i < n; i++) { + if (*lang && (strncmp(lang, curLanguageList[i], 2) != 0)) { + /* add lang if current language is the last occurence in the list */ + for (k = i+1; (k < n) && strncmp(curLanguageList[k],lang,2); k++); + + if (k == n) { + strcpy(AcceptLanguageList[index++], lang); + *lang = '\0'; + } + } + + strcpy(AcceptLanguageList[index++], curLanguageList[i]); + + /* Add current language for future appending.,make sure it's not on list */ + if ((strlen(curLanguageList[i]) > 2) && (curLanguageList[i][2] == '_')) { + strncpy(lang, curLanguageList[i], 2); + for (k = 0; (k < index) && strcmp(AcceptLanguageList[k], lang); k++); + + if (k != index) lang[0] = '\0'; + } + } + + if (lang[0] != '\0') + strcpy(AcceptLanguageList[index++], lang); /* add new lang */ + + /* Append defaultLanguage if it's not in the list */ + for (i = 0; (i < index) && strcmp(AcceptLanguageList[i], defaultLanguage); i++); + + if (i == index) + strcpy(AcceptLanguageList[index++], defaultLanguage); + + return index; +} |