/* ****************************************************************************** * * Copyright (C) 1998-2001, International Business Machines * Corporation and others. All Rights Reserved. * ****************************************************************************** * * File ufile.c * * Modification History: * * Date Name Description * 11/19/98 stephen Creation. * 03/12/99 stephen Modified for new C API. * 06/16/99 stephen Changed T_LocaleBundle to u_locbund * 07/19/99 stephen Fixed to use ucnv's default codepage. ****************************************************************************** */ #include "uhash.h" #include "unicode/ustdio.h" #include "ufile.h" #include "unicode/uloc.h" #include "loccache.h" #include "unicode/ures.h" #include "unicode/ucnv.h" #include #include /* the data in the following two functions should REALLY be somewhere else */ /* convert from a country code (only the first 2 chars are significant) */ /* to an IBM codepage */ /* TODO: We should consider using uprv_defaultCodePageForLocale() instead of this table (less to maintain when the ISO-639 standard changes */ /* thanks to http://czyborra.com/charsets/iso8859.htm for most of this info */ static const char *ufile_locale2codepage[] = { "af", "latin-1", /* Afrikaans */ "ar", "ibm-1256", /* arabic */ "be", "ibm-915" , /* Byelorussian */ "bg", "ibm-915" , /* Bulgarian */ "ca", "latin-1" , /* catalan */ "cs", "ibm-912" , /* Czech */ "da", "latin-1" , /* danish */ "de", "latin-1" , /* german */ "el", "ibm-813" , /* Greek */ "en", "latin-1" , /* English */ "eo", "ibm-913" , /* Esperanto */ "es", "latin-1" , /* Spanish */ "eu", "latin-1" , /* basque */ "et", "ibm-914" , /* Estonian */ "fi", "latin-1" , /* Finnish */ "fo", "latin-1" , /* faroese */ "fr", "latin-1" , /* French */ "ga", "latin-1" , /* Irish (Gaelic) */ "gd", "latin-1" , /* Scottish */ "hr", "ibm-912" , /* Croatian */ "hu", "ibm-912" , /* Hungarian */ "in", "latin-1" , /* Indonesian */ "is", "latin-1" , /* Icelandic */ "it", "latin-1" , /* Italian */ "iw", "ibm-916", /* hebrew */ "ja", "ibm-943", /* Japanese */ "ji", "ibm-916", /* Yiddish */ "kl", "ibm-914", /* Greenlandic */ "ko", "ibm-949", /* korean */ "lt", "ibm-914", /* Lithuanian */ "lv", "ibm-914", /* latvian (lettish) */ "mk", "ibm-915" , /* Macedonian */ "mt", "ibm-1208" , /* Maltese [UTF8] */ "nl", "latin-1" , /* dutch */ "no", "latin-1" , /* Norwegian */ "pl", "ibm-912" , /* Polish */ "pt", "latin-1" , /* Portugese */ "rm", "latin-1" , /* Rhaeto-romanic (?) */ "ro", "ibm-912" , /* Romanian */ "ru", "ibm-878" , /* Russian */ "sk", "ibm-912" , /* Slovak */ "sl", "ibm-912" , /* Slovenian */ "sq", "latin-1" , /* albanian */ "sr", "ibm-915" , /* Serbian */ "sv", "latin-1" , /* Swedish */ "sw", "latin-1" , /* Swahili */ "th", "ibm-1208" , /* Thai - UTF8 */ "tr", "ibm-920", /* Turkish */ "uk", "ibm-915" , /* pre 1990 Ukranian (?) */ "zh", "Big-5", /* Chinese */ 0, 0 }; static const char* ufile_lookup_codepage(const char *locale) { int32_t i; for(i = 0; ufile_locale2codepage[i]; i+= 2) if( ! strncmp(ufile_locale2codepage[i], locale, 2)) return ufile_locale2codepage[i + 1]; return 0; } static UBool hasICUData(const char *cp) { UErrorCode status = U_ZERO_ERROR; UConverter *cnv = NULL; #if 0 UResourceBundle *r = NULL; r = ures_open(NULL, NULL, &status); if(U_FAILURE(status)) { return FALSE; } else { ures_close(r); } #endif cnv = ucnv_open(cp, &status); if(cnv == NULL) { return FALSE; } else { ucnv_close(cnv); } return TRUE; } UFILE* u_fopen(const char *filename, const char *perm, const char *locale, const char *codepage) { UErrorCode status = U_ZERO_ERROR; UBool useSysCP = (UBool)(locale == 0 && codepage == 0); UFILE *result = (UFILE*) malloc(sizeof(UFILE)); if(result == 0) return 0; result->fFile = fopen(filename, perm); if(result->fFile == 0) { free(result); return 0; } result->fOwnFile = TRUE; /* if locale is 0, use the default */ if(locale == 0) locale = uloc_getDefault(); result->fBundle = u_loccache_get(locale); if(result->fBundle == 0) { fclose(result->fFile); free(result); return 0; } result->fOwnBundle = FALSE; result->fUCPos = result->fUCBuffer; result->fUCLimit = result->fUCBuffer; /* if the codepage is 0, use the default for the locale */ if(codepage == 0) { codepage = ufile_lookup_codepage(locale); /* if the codepage is still 0, the default codepage will be used */ } /* if both locale and codepage are 0, use the system default codepage */ else if(useSysCP) codepage = 0; result->fConverter = ucnv_open(codepage, &status); if(U_FAILURE(status) || result->fConverter == 0) { fclose(result->fFile); free(result); return 0; } return result; } UFILE* u_finit(FILE *f, const char *locale, const char *codepage) { UErrorCode status = U_ZERO_ERROR; UBool useSysCP = (UBool)(locale == NULL && codepage == NULL); UFILE *result = (UFILE*) malloc(sizeof(UFILE)); if(result == 0) return 0; #ifdef WIN32 result->fFile = &_iob[_fileno(f)]; #else result->fFile = f; #endif result->fOwnFile = FALSE; result->fOwnBundle = FALSE; result->fUCPos = result->fUCBuffer; result->fUCLimit = result->fUCBuffer; result->fConverter = NULL; result->fBundle = NULL; if(hasICUData(codepage) == TRUE) { /* if locale is 0, use the default */ if(locale == 0) locale = uloc_getDefault(); result->fBundle = u_loccache_get(locale); if(result->fBundle == 0) { /* DO NOT FCLOSE HERE! */ free(result); return 0; } } else { /* bootstrap mode */ return result; } /* if the codepage is 0, use the default for the locale */ if(codepage == 0) { codepage = ufile_lookup_codepage(locale); /* if the codepage is still 0, the default codepage will be used */ if(codepage == 0) { result->fConverter = ucnv_open(0, &status); if(U_FAILURE(status) || result->fConverter == 0) { /* DO NOT fclose here!!!!!! */ free(result); return 0; } } } else if (*codepage != '\0') { result->fConverter = ucnv_open(codepage, &status); if(U_FAILURE(status) || result->fConverter == 0) { /* DO NOT fclose here!!!!!! */ free(result); return 0; } } else if(useSysCP) { /* if both locale and codepage are 0, use the system default codepage */ codepage = 0; } return result; } void u_fclose(UFILE *file) { fflush(file->fFile); if(file->fOwnFile) fclose(file->fFile); if(file->fOwnBundle) u_locbund_delete(file->fBundle); ucnv_close(file->fConverter); free(file); } FILE* u_fgetfile( UFILE *f) { return f->fFile; } const char* u_fgetlocale( UFILE *file) { return file->fBundle->fLocale; } int32_t u_fsetlocale(const char *locale, UFILE *file) { if(file->fOwnBundle) u_locbund_delete(file->fBundle); file->fBundle = u_loccache_get(locale); file->fOwnBundle = FALSE; return file->fBundle == 0 ? -1 : 0; } const char* u_fgetcodepage(UFILE *file) { UErrorCode status = U_ZERO_ERROR; const char *codepage; codepage = ucnv_getName(file->fConverter, &status); if(U_FAILURE(status)) return 0; return codepage; } int32_t u_fsetcodepage( const char *codepage, UFILE *file) { UErrorCode status = U_ZERO_ERROR; /* if the codepage is 0, use the default for the locale */ if(codepage == 0) { codepage = ufile_lookup_codepage(file->fBundle->fLocale); /* if the codepage is still 0, fall back on the default codepage */ } ucnv_close(file->fConverter); file->fConverter = ucnv_open(codepage, &status); if(U_FAILURE(status)) return -1; return 0; } UConverter * u_fgetConverter(UFILE *file) { return file->fConverter; }