From 1d1f5f3eede8bd6fdbb158acbe23d9a2a83ab7bd Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Tue, 24 Oct 2000 21:29:28 +0000 Subject: [PATCH] Added codepage translation based on the language id (based on a patch by Junichi Kuchinishi ). --- tools/wrc/Makefile.in | 8 +- tools/wrc/genres.c | 20 +++-- tools/wrc/utils.c | 196 ++++++++++++++++++++++++++++++------------ tools/wrc/utils.h | 6 +- tools/wrc/writeres.c | 5 +- 5 files changed, 165 insertions(+), 70 deletions(-) diff --git a/tools/wrc/Makefile.in b/tools/wrc/Makefile.in index ccf7dbba59a..f1441083d7d 100644 --- a/tools/wrc/Makefile.in +++ b/tools/wrc/Makefile.in @@ -3,6 +3,7 @@ TOPSRCDIR = @top_srcdir@ TOPOBJDIR = ../.. SRCDIR = @srcdir@ VPATH = @srcdir@ +LIBEXT = @LIBEXT@ LEXOPT = -Cf #-w -b YACCOPT = #-v @@ -29,8 +30,11 @@ depend: y.tab.h ppy.tab.h @MAKE_RULES@ -wrc: $(OBJS) - $(CC) $(CFLAGS) -o wrc $(OBJS) $(LEXLIB) +wrc: $(OBJS) $(TOPOBJDIR)/libwine_unicode.$(LIBEXT) + $(CC) $(CFLAGS) -o wrc $(OBJS) -L$(TOPOBJDIR) -lwine_unicode $(LEXLIB) + +$(TOPOBJDIR)/libwine_unicode.$(LIBEXT): + cd $(TOPOBJDIR) && $(MAKE) libwine_unicode.$(LIBEXT) y.tab.c y.tab.h: parser.y $(YACC) $(YACCOPT) -d -t $(SRCDIR)/parser.y diff --git a/tools/wrc/genres.c b/tools/wrc/genres.c index 58f01ff9600..14541176cc6 100644 --- a/tools/wrc/genres.c +++ b/tools/wrc/genres.c @@ -257,7 +257,7 @@ void string_to_upper(string_t *str) * Remarks : ***************************************************************************** */ -void put_string(res_t *res, string_t *str, enum str_e type, int isterm) +static void put_string(res_t *res, string_t *str, enum str_e type, int isterm) { int cnt; int c = !0; @@ -269,6 +269,7 @@ void put_string(res_t *res, string_t *str, enum str_e type, int isterm) return; } + str = convert_string(str, type); if(str->type == str_unicode && type == str_unicode) { for(cnt = 0; cnt < str->size; cnt++) @@ -317,6 +318,7 @@ void put_string(res_t *res, string_t *str, enum str_e type, int isterm) if(isterm && (str->size == 0 || (cnt == str->size && c))) put_word(res, 0); } + free(str); } /* @@ -375,6 +377,12 @@ void put_lvc(res_t *res, lvc_t *lvc) put_dword(res, *(lvc->characts)); else put_dword(res, 0); + if(lvc && lvc->language) + set_language( lvc->language->id, lvc->language->sub ); + else if (currentlanguage) + set_language( currentlanguage->id, currentlanguage->sub ); + else + set_language( LANG_NEUTRAL, SUBLANG_NEUTRAL ); } /* @@ -1418,11 +1426,13 @@ static res_t *stringtable2res(stringtable_t *stt) { if(stt->entries[i].str && stt->entries[i].str->size) { - if(win32) - put_word(res, stt->entries[i].str->size); + string_t *str = convert_string(stt->entries[i].str, win32 ? str_unicode : str_char); + if(win32) + put_word(res, str->size); else - put_byte(res, stt->entries[i].str->size); - put_string(res, stt->entries[i].str, win32 ? str_unicode : str_char, FALSE); + put_byte(res, str->size); + put_string(res, str, win32 ? str_unicode : str_char, FALSE); + free(str); } else { diff --git a/tools/wrc/utils.c b/tools/wrc/utils.c index 0812154930a..aadc374d984 100644 --- a/tools/wrc/utils.c +++ b/tools/wrc/utils.c @@ -7,6 +7,7 @@ #include "config.h" +#include #include #include #include @@ -14,6 +15,7 @@ #include #include +#include "wine/unicode.h" #include "wrc.h" #include "utils.h" #include "parser.h" @@ -21,6 +23,7 @@ /* #define WANT_NEAR_INDICATION */ +static const union cptable *current_codepage; #ifdef WANT_NEAR_INDICATION void make_print(char *str) @@ -208,71 +211,29 @@ char *xstrdup(const char *str) return strcpy(s, str); } -int string_compare(const string_t *s1, const string_t *s2) -{ - if(s1->type == str_char && s2->type == str_char) - { - return strcasecmp(s1->str.cstr, s2->str.cstr); - } - else - { - internal_error(__FILE__, __LINE__, "Cannot yet compare unicode strings"); - } - return 0; -} - -int wstrlen(const short *s) -{ - int cnt = 0; - while(*s++) - cnt++; - return cnt; -} - -short *wstrcpy(short *dst, const short *src) -{ - short *d = dst; - while(*src) - *d++ = *src++; - return dst; -} - -int wstricmp(const short *s1, const short *s2) -{ - char *cs1 = dupwstr2cstr(s1); - char *cs2 = dupwstr2cstr(s2); - int retval = strcasecmp(cs1, cs2); - free(cs1); - free(cs2); - warning("Comparing unicode strings without case -> converting to ascii"); - return retval;; -} - short *dupcstr2wstr(const char *str) { - int len = strlen(str) + 1; - short *ws = (short *)xmalloc(len*2); - short *wptr; + int len; + WCHAR *ws; - wptr = ws; - /* FIXME: codepage translation */ - while(*str) - *wptr++ = (short)(*str++ & 0xff); - *wptr = 0; + if (!current_codepage) set_language( LANG_NEUTRAL, SUBLANG_NEUTRAL ); + len = cp_mbstowcs( current_codepage, 0, str, strlen(str), NULL, 0 ); + ws = xmalloc( sizeof(WCHAR) * (len + 1) ); + len = cp_mbstowcs( current_codepage, 0, str, strlen(str), ws, len ); + ws[len] = 0; return ws; } char *dupwstr2cstr(const short *str) { - int len = wstrlen(str) + 1; - char *cs = (char *)xmalloc(len); - char *cptr; + int len; + char *cs; - cptr = cs; - /* FIXME: codepage translation */ - while(*str) - *cptr++ = (char)*str++; - *cptr = 0; + if (!current_codepage) set_language( LANG_NEUTRAL, SUBLANG_NEUTRAL ); + len = cp_wcstombs( current_codepage, 0, str, strlenW(str), NULL, 0, NULL, NULL ); + cs = xmalloc( len + 1 ); + len = cp_wcstombs( current_codepage, 0, str, strlenW(str), cs, len, NULL, NULL ); + cs[len] = 0; return cs; } @@ -302,7 +263,7 @@ int compare_name_id(name_id_t *n1, name_id_t *n2) else if(n1->name.s_name->type == str_unicode && n2->name.s_name->type == str_unicode) { - return wstricmp(n1->name.s_name->str.wstr, n2->name.s_name->str.wstr); + return strcmpiW(n1->name.s_name->str.wstr, n2->name.s_name->str.wstr); } else { @@ -320,3 +281,124 @@ int compare_name_id(name_id_t *n1, name_id_t *n2) return 0; /* Keep the compiler happy */ } +string_t *convert_string(const string_t *str, enum str_e type) +{ + string_t *ret = xmalloc(sizeof(*ret)); + + if((str->type == str_char) && (type == str_unicode)) + { + ret->str.wstr = dupcstr2wstr(str->str.cstr); + ret->type = str_unicode; + ret->size = strlenW(ret->str.wstr); + } + else if((str->type == str_unicode) && (type == str_char)) + { + ret->str.cstr = dupwstr2cstr(str->str.wstr); + ret->type = str_char; + ret->size = strlen(ret->str.cstr); + } + else if(str->type == str_unicode) + { + ret->type = str_unicode; + ret->size = strlenW(str->str.wstr); + ret->str.wstr = xmalloc(sizeof(WCHAR)*(ret->size+1)); + strcpyW(ret->str.wstr, str->str.wstr); + } + else /* str->type == str_char */ + { + ret->type = str_char; + ret->size = strlen(str->str.cstr); + ret->str.cstr = xmalloc( ret->size + 1 ); + strcpy(ret->str.cstr, str->str.cstr); + } + return ret; +} + + +struct lang2cp +{ + unsigned short lang; + unsigned short sublang; + unsigned int cp; +} lang2cp_t; + +/* language to codepage conversion table */ +/* specific sublanguages need only be specified if their codepage */ +/* differs from the default (SUBLANG_NEUTRAL) */ +static const struct lang2cp lang2cps[] = +{ + /* default code page (LANG_NEUTRAL) must be first entry */ + { LANG_NEUTRAL, SUBLANG_NEUTRAL, 1252 }, + { LANG_AFRIKAANS, SUBLANG_NEUTRAL, 1252 }, + { LANG_ALBANIAN, SUBLANG_NEUTRAL, 1250 }, + { LANG_BASQUE, SUBLANG_NEUTRAL, 1252 }, + { LANG_BRETON, SUBLANG_NEUTRAL, 1252 }, + { LANG_BULGARIAN, SUBLANG_NEUTRAL, 1251 }, + { LANG_BYELORUSSIAN, SUBLANG_NEUTRAL, 1251 }, + { LANG_CATALAN, SUBLANG_NEUTRAL, 1252 }, + { LANG_CORNISH, SUBLANG_NEUTRAL, 1252 }, + { LANG_CZECH, SUBLANG_NEUTRAL, 1250 }, + { LANG_DANISH, SUBLANG_NEUTRAL, 1252 }, + { LANG_DUTCH, SUBLANG_NEUTRAL, 1252 }, + { LANG_ENGLISH, SUBLANG_NEUTRAL, 1252 }, + { LANG_ESPERANTO, SUBLANG_NEUTRAL, 1252 }, + { LANG_ESTONIAN, SUBLANG_NEUTRAL, 1257 }, + { LANG_FINNISH, SUBLANG_NEUTRAL, 1252 }, + { LANG_FRENCH, SUBLANG_NEUTRAL, 1252 }, + { LANG_GAELIC, SUBLANG_NEUTRAL, 1252 }, + { LANG_GERMAN, SUBLANG_NEUTRAL, 1252 }, + { LANG_GREEK, SUBLANG_NEUTRAL, 1253 }, + { LANG_HUNGARIAN, SUBLANG_NEUTRAL, 1250 }, + { LANG_ICELANDIC, SUBLANG_NEUTRAL, 1252 }, + { LANG_INDONESIAN, SUBLANG_NEUTRAL, 1252 }, + { LANG_ITALIAN, SUBLANG_NEUTRAL, 1252 }, + { LANG_JAPANESE, SUBLANG_NEUTRAL, 932 }, + { LANG_KOREAN, SUBLANG_NEUTRAL, 949 }, + { LANG_LATVIAN, SUBLANG_NEUTRAL, 1257 }, + { LANG_LITHUANIAN, SUBLANG_NEUTRAL, 1257 }, + { LANG_MACEDONIAN, SUBLANG_NEUTRAL, 1251 }, + { LANG_NORWEGIAN, SUBLANG_NEUTRAL, 1252 }, + { LANG_POLISH, SUBLANG_NEUTRAL, 1250 }, + { LANG_PORTUGUESE, SUBLANG_NEUTRAL, 1252 }, + { LANG_ROMANIAN, SUBLANG_NEUTRAL, 1250 }, + { LANG_RUSSIAN, SUBLANG_NEUTRAL, 1251 }, + { LANG_SERBO_CROATIAN, SUBLANG_NEUTRAL, 1250 }, + { LANG_SERBO_CROATIAN, SUBLANG_SERBIAN_LATIN, 1251 }, + { LANG_SLOVAK, SUBLANG_NEUTRAL, 1250 }, + { LANG_SLOVENIAN, SUBLANG_NEUTRAL, 1250 }, + { LANG_SPANISH, SUBLANG_NEUTRAL, 1252 }, + { LANG_SWEDISH, SUBLANG_NEUTRAL, 1252 }, + { LANG_THAI, SUBLANG_NEUTRAL, 874 }, + { LANG_TURKISH, SUBLANG_NEUTRAL, 1254 }, + { LANG_UKRAINIAN, SUBLANG_NEUTRAL, 1251 }, + { LANG_WALON, SUBLANG_NEUTRAL, 1252 }, + { LANG_WELSH, SUBLANG_NEUTRAL, 1252 } +}; + +void set_language( unsigned short lang, unsigned short sublang ) +{ + int i; + unsigned int cp = 0, defcp = 0; + + for (i = 0; i < sizeof(lang2cps)/sizeof(lang2cps[0]); i++) + { + if (lang2cps[i].lang != lang) continue; + if (lang2cps[i].sublang == sublang) + { + cp = lang2cps[i].cp; + break; + } + if (lang2cps[i].sublang == SUBLANG_NEUTRAL) defcp = lang2cps[i].cp; + } + + if (!cp) cp = defcp; + if (!cp) error( "No codepage value for language %04x", MAKELANGID(lang,sublang) ); + else + { + if ((current_codepage = cp_get_table( cp ))) return; + error( "Bad codepage %d for language %04x", cp, MAKELANGID(lang,sublang) ); + } + /* now find a default code page */ + current_codepage = cp_get_table( lang2cps[0].cp ); + assert( current_codepage ); +} diff --git a/tools/wrc/utils.h b/tools/wrc/utils.h index 1bb9e44cf0b..9d9cfce7f86 100644 --- a/tools/wrc/utils.h +++ b/tools/wrc/utils.h @@ -28,12 +28,10 @@ void warning(const char *s, ...) __attribute__((format (printf, 1, 2))); void chat(const char *s, ...) __attribute__((format (printf, 1, 2))); char *dup_basename(const char *name, const char *ext); -int string_compare(const string_t *s1, const string_t *s2); -int wstrlen(const short *s); -short *wstrcpy(short *dst, const short *src); -int wstricmp(const short *s1, const short *s2); char *dupwstr2cstr(const short *str); short *dupcstr2wstr(const char *str); int compare_name_id(name_id_t *n1, name_id_t *n2); +string_t *convert_string(const string_t *str, enum str_e type); +void set_language(unsigned short lang, unsigned short sublang); #endif diff --git a/tools/wrc/writeres.c b/tools/wrc/writeres.c index d2ea09f7f22..8b6427f4e8c 100644 --- a/tools/wrc/writeres.c +++ b/tools/wrc/writeres.c @@ -12,6 +12,7 @@ #include #include +#include "wine/unicode.h" #include "wrc.h" #include "writeres.h" #include "genres.h" @@ -261,7 +262,7 @@ static void write_name_str(FILE *fp, name_id_t *nid) } else if(win32 && nid->name.s_name->type == str_unicode) { - res.size = wstrlen(nid->name.s_name->str.wstr); + res.size = strlenW(nid->name.s_name->str.wstr); if(res.size > 65534) error("Can't write strings larger than 65534 bytes"); if(res.size == 0) @@ -269,7 +270,7 @@ static void write_name_str(FILE *fp, name_id_t *nid) res.dataidx = 0; res.data = (char *)xmalloc((res.size + 1) * 2); ((short *)res.data)[0] = (short)res.size; - wstrcpy((short *)(res.data+2), nid->name.s_name->str.wstr); + strcpyW((WCHAR *)(res.data+2), nid->name.s_name->str.wstr); res.size *= 2; /* Function writes bytes, not shorts... */ res.size += 2; /* We need to write the length word as well */ write_s_res(fp, &res);