From f22ba0560dd87eefe899c1fb59e35581b9f90d85 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Thu, 15 Aug 2002 21:57:36 +0000 Subject: [PATCH] Added support for #pragma code_page. Fixed a few bugs in language handling. Added error message when Ansi->Unicode conversion in the current codepage loses information. --- dlls/commdlg/cdlg_Zh.rc | 3 + dlls/shell32/shell32_Zh.rc | 3 + dlls/user/resources/user32_Zh.rc | 3 + include/winnt.h | 381 ++++++++++++++++--------------- tools/wpp/ppy.y | 2 +- tools/wrc/genres.c | 245 +++++++++----------- tools/wrc/parser.l | 90 +++++--- tools/wrc/parser.y | 7 +- tools/wrc/utils.c | 180 +++++++++------ tools/wrc/utils.h | 10 +- tools/wrc/wrc.c | 2 + tools/wrc/wrctypes.h | 2 +- tools/wrc/writeres.c | 16 +- 13 files changed, 507 insertions(+), 437 deletions(-) diff --git a/dlls/commdlg/cdlg_Zh.rc b/dlls/commdlg/cdlg_Zh.rc index e601d387917..a89d75407b4 100644 --- a/dlls/commdlg/cdlg_Zh.rc +++ b/dlls/commdlg/cdlg_Zh.rc @@ -17,6 +17,7 @@ */ LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL +#pragma code_page(936) /* FIXME: default for CHINESE_TRADITIONAL is 950 */ OPEN_FILE DIALOG LOADONCALL MOVEABLE DISCARDABLE 36, 24, 275, 134 STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU @@ -220,3 +221,5 @@ STRINGTABLE DISCARDABLE IDS_REPORTVIEW "詳細資料" IDS_TODESKTOP "顯示桌面" } + +#pragma code_page(default) diff --git a/dlls/shell32/shell32_Zh.rc b/dlls/shell32/shell32_Zh.rc index 50de503dc91..44a8c8f87cb 100644 --- a/dlls/shell32/shell32_Zh.rc +++ b/dlls/shell32/shell32_Zh.rc @@ -17,6 +17,7 @@ */ LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL +#pragma code_page(936) /* FIXME: default for CHINESE_TRADITIONAL is 950 */ SHELL_ABOUT_MSGBOX DIALOG LOADONCALL MOVEABLE DISCARDABLE 15, 40, 210, 152 STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU @@ -55,3 +56,5 @@ BEGIN IDS_SHV_COLUMN6 "使用空間" IDS_SHV_COLUMN7 "剩餘空間" END + +#pragma code_page(default) diff --git a/dlls/user/resources/user32_Zh.rc b/dlls/user/resources/user32_Zh.rc index 0b16927c3cf..af13ace0b05 100644 --- a/dlls/user/resources/user32_Zh.rc +++ b/dlls/user/resources/user32_Zh.rc @@ -76,6 +76,7 @@ STRINGTABLE DISCARDABLE } LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL +#pragma code_page(936) /* FIXME: default for CHINESE_TRADITIONAL is 950 */ SYSMENU MENU LOADONCALL MOVEABLE DISCARDABLE { @@ -133,3 +134,5 @@ STRINGTABLE DISCARDABLE { MDI_IDS_MOREWINDOWS "更多視窗(&M)..." /* defined in mdi.h */ } + +#pragma code_page(default) diff --git a/include/winnt.h b/include/winnt.h index 08fb64c405e..dd495a4c02d 100644 --- a/include/winnt.h +++ b/include/winnt.h @@ -385,6 +385,7 @@ typedef LPCSTR PCTSTR, LPCTSTR; #endif /* __WINE__ */ /* Misc common WIN32 types */ +typedef char CCHAR; typedef LONG HRESULT; typedef DWORD LCID, *PLCID; typedef WORD LANGID; @@ -1236,92 +1237,102 @@ static DWORD __builtin_return_address(int p_iDepth) #define LOCALE_USER_DEFAULT (MAKELCID(LANG_USER_DEFAULT, SORT_DEFAULT)) #define LOCALE_NEUTRAL (MAKELCID(MAKELANGID(LANG_NEUTRAL,SUBLANG_NEUTRAL),SORT_DEFAULT)) -/* FIXME: are the symbolic names correct for LIDs: 0x17, 0x20, 0x28, - * 0x2a, 0x2b, 0x2c, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, - * 0x37, 0x39, 0x3a, 0x3b, 0x3c, 0x3e, 0x3f, 0x41, 0x43, 0x44, - * 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, - * 0x4f, 0x57 +/* FIXME: are the symbolic names correct for LIDs: 0x17, 0x28, + * 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x3a, 0x3b, 0x3c */ -#define LANG_NEUTRAL 0x00 -#define LANG_AFRIKAANS 0x36 -#define LANG_ALBANIAN 0x1c -#define LANG_ARABIC 0x01 -#define LANG_ARMENIAN 0x2b -#define LANG_ASSAMESE 0x4d -#define LANG_AZERI 0x2c -#define LANG_BASQUE 0x2d -#define LANG_BENGALI 0x45 -#define LANG_BULGARIAN 0x02 -#define LANG_BYELORUSSIAN 0x23 -#define LANG_CATALAN 0x03 -#define LANG_CHINESE 0x04 -#define LANG_SERBO_CROATIAN 0x1a -#define LANG_CROATIAN LANG_SERBO_CROATIAN -#define LANG_SERBIAN LANG_SERBO_CROATIAN -#define LANG_CZECH 0x05 -#define LANG_DANISH 0x06 -#define LANG_DUTCH 0x13 -#define LANG_ENGLISH 0x09 -#define LANG_ESTONIAN 0x25 -#define LANG_FAEROESE 0x38 -#define LANG_FARSI 0x29 -#define LANG_FINNISH 0x0b -#define LANG_FRENCH 0x0c -#define LANG_GAELIC 0x3c -#define LANG_GEORGIAN 0x37 -#define LANG_GERMAN 0x07 -#define LANG_GREEK 0x08 -#define LANG_GUJARATI 0x47 -#define LANG_HEBREW 0x0D -#define LANG_HINDI 0x39 -#define LANG_HUNGARIAN 0x0e -#define LANG_ICELANDIC 0x0f -#define LANG_INDONESIAN 0x21 -#define LANG_ITALIAN 0x10 -#define LANG_JAPANESE 0x11 -#define LANG_KANNADA 0x4b -#define LANG_KAZAKH 0x3f -#define LANG_KONKANI 0x57 -#define LANG_KOREAN 0x12 -#define LANG_LATVIAN 0x26 -#define LANG_LITHUANIAN 0x27 -#define LANG_MACEDONIAN 0x2f -#define LANG_MALAY 0x3e -#define LANG_MALAYALAM 0x4c -#define LANG_MALTESE 0x3a -#define LANG_MAORI 0x28 -#define LANG_MARATHI 0x4e -#define LANG_NORWEGIAN 0x14 -#define LANG_ORIYA 0x48 -#define LANG_POLISH 0x15 -#define LANG_PORTUGUESE 0x16 -#define LANG_PUNJABI 0x46 -#define LANG_RHAETO_ROMANCE 0x17 -#define LANG_ROMANIAN 0x18 -#define LANG_RUSSIAN 0x19 -#define LANG_SAAMI 0x3b -#define LANG_SANSKRIT 0x4f -#define LANG_SLOVAK 0x1b -#define LANG_SLOVENIAN 0x24 -#define LANG_SORBIAN 0x2e -#define LANG_SPANISH 0x0a -#define LANG_SUTU 0x30 -#define LANG_SWAHILI 0x41 -#define LANG_SWEDISH 0x1d -#define LANG_TAMIL 0x49 -#define LANG_TATAR 0x44 -#define LANG_TELUGU 0x4a -#define LANG_THAI 0x1e -#define LANG_TSONGA 0x31 -#define LANG_TSWANA 0x32 -#define LANG_TURKISH 0x1f -#define LANG_UKRAINIAN 0x22 -#define LANG_URDU 0x20 -#define LANG_UZBEK 0x43 -#define LANG_VENDA 0x33 -#define LANG_VIETNAMESE 0x2a -#define LANG_XHOSA 0x34 -#define LANG_ZULU 0x35 +#define LANG_NEUTRAL 0x00 +#define LANG_INVARIANT 0x7f + +#define LANG_AFRIKAANS 0x36 +#define LANG_ALBANIAN 0x1c +#define LANG_ARABIC 0x01 +#define LANG_ARMENIAN 0x2b +#define LANG_ASSAMESE 0x4d +#define LANG_AZERI 0x2c +#define LANG_BASQUE 0x2d +#define LANG_BELARUSIAN 0x23 +#define LANG_BENGALI 0x45 +#define LANG_BULGARIAN 0x02 +#define LANG_CATALAN 0x03 +#define LANG_CHINESE 0x04 +#define LANG_CROATIAN 0x1a +#define LANG_CZECH 0x05 +#define LANG_DANISH 0x06 +#define LANG_DIVEHI 0x65 +#define LANG_DUTCH 0x13 +#define LANG_ENGLISH 0x09 +#define LANG_ESTONIAN 0x25 +#define LANG_FAEROESE 0x38 +#define LANG_FARSI 0x29 +#define LANG_FINNISH 0x0b +#define LANG_FRENCH 0x0c +#define LANG_GALICIAN 0x56 +#define LANG_GEORGIAN 0x37 +#define LANG_GERMAN 0x07 +#define LANG_GREEK 0x08 +#define LANG_GUJARATI 0x47 +#define LANG_HEBREW 0x0d +#define LANG_HINDI 0x39 +#define LANG_HUNGARIAN 0x0e +#define LANG_ICELANDIC 0x0f +#define LANG_INDONESIAN 0x21 +#define LANG_ITALIAN 0x10 +#define LANG_JAPANESE 0x11 +#define LANG_KANNADA 0x4b +#define LANG_KASHMIRI 0x60 +#define LANG_KAZAK 0x3f +#define LANG_KONKANI 0x57 +#define LANG_KOREAN 0x12 +#define LANG_KYRGYZ 0x40 +#define LANG_LATVIAN 0x26 +#define LANG_LITHUANIAN 0x27 +#define LANG_MACEDONIAN 0x2f +#define LANG_MALAY 0x3e +#define LANG_MALAYALAM 0x4c +#define LANG_MANIPURI 0x58 +#define LANG_MARATHI 0x4e +#define LANG_MONGOLIAN 0x50 +#define LANG_NEPALI 0x61 +#define LANG_NORWEGIAN 0x14 +#define LANG_ORIYA 0x48 +#define LANG_POLISH 0x15 +#define LANG_PORTUGUESE 0x16 +#define LANG_PUNJABI 0x46 +#define LANG_ROMANIAN 0x18 +#define LANG_RUSSIAN 0x19 +#define LANG_SANSKRIT 0x4f +#define LANG_SERBIAN 0x1a +#define LANG_SINDHI 0x59 +#define LANG_SLOVAK 0x1b +#define LANG_SLOVENIAN 0x24 +#define LANG_SPANISH 0x0a +#define LANG_SWAHILI 0x41 +#define LANG_SWEDISH 0x1d +#define LANG_SYRIAC 0x5a +#define LANG_TAMIL 0x49 +#define LANG_TATAR 0x44 +#define LANG_TELUGU 0x4a +#define LANG_THAI 0x1e +#define LANG_TURKISH 0x1f +#define LANG_UKRAINIAN 0x22 +#define LANG_URDU 0x20 +#define LANG_UZBEK 0x43 +#define LANG_VIETNAMESE 0x2a + +/* FIXME: these are not in the Windows header */ +#define LANG_GAELIC 0x3c +#define LANG_MALTESE 0x3a +#define LANG_MAORI 0x28 +#define LANG_RHAETO_ROMANCE 0x17 +#define LANG_SAAMI 0x3b +#define LANG_SORBIAN 0x2e +#define LANG_SUTU 0x30 +#define LANG_TSONGA 0x31 +#define LANG_TSWANA 0x32 +#define LANG_VENDA 0x33 +#define LANG_XHOSA 0x34 +#define LANG_ZULU 0x35 + /* non standard; keep the number high enough (but < 0xff) */ #define LANG_ESPERANTO 0x8f #define LANG_WALON 0x90 @@ -1334,106 +1345,108 @@ static DWORD __builtin_return_address(int p_iDepth) #define SUBLANG_DEFAULT 0x01 /* user default */ #define SUBLANG_SYS_DEFAULT 0x02 /* system default */ -#define SUBLANG_ARABIC 0x01 -#define SUBLANG_ARABIC_SAUDI_ARABIA 0x01 -#define SUBLANG_ARABIC_IRAQ 0x02 -#define SUBLANG_ARABIC_EGYPT 0x03 -#define SUBLANG_ARABIC_LIBYA 0x04 -#define SUBLANG_ARABIC_ALGERIA 0x05 -#define SUBLANG_ARABIC_MOROCCO 0x06 -#define SUBLANG_ARABIC_TUNISIA 0x07 -#define SUBLANG_ARABIC_OMAN 0x08 -#define SUBLANG_ARABIC_YEMEN 0x09 -#define SUBLANG_ARABIC_SYRIA 0x0a -#define SUBLANG_ARABIC_JORDAN 0x0b -#define SUBLANG_ARABIC_LEBANON 0x0c -#define SUBLANG_ARABIC_KUWAIT 0x0d -#define SUBLANG_ARABIC_UAE 0x0e -#define SUBLANG_ARABIC_BAHRAIN 0x0f -#define SUBLANG_ARABIC_QATAR 0x10 -#define SUBLANG_CHINESE_TRADITIONAL 0x01 -#define SUBLANG_CHINESE_SIMPLIFIED 0x02 -#define SUBLANG_CHINESE_HONGKONG 0x03 -#define SUBLANG_CHINESE_SINGAPORE 0x04 -#define SUBLANG_CHINESE_MACAU 0x05 -#define SUBLANG_DUTCH 0x01 -#define SUBLANG_DUTCH_BELGIAN 0x02 -#define SUBLANG_DUTCH_SURINAM 0x03 -#define SUBLANG_ENGLISH_US 0x01 -#define SUBLANG_ENGLISH_UK 0x02 -#define SUBLANG_ENGLISH_AUS 0x03 -#define SUBLANG_ENGLISH_CAN 0x04 -#define SUBLANG_ENGLISH_NZ 0x05 -#define SUBLANG_ENGLISH_EIRE 0x06 -#define SUBLANG_ENGLISH_SAFRICA 0x07 -#define SUBLANG_ENGLISH_JAMAICA 0x08 -#define SUBLANG_ENGLISH_CARRIBEAN 0x09 -#define SUBLANG_ENGLISH_BELIZE 0x0a -#define SUBLANG_ENGLISH_TRINIDAD 0x0b -#define SUBLANG_ENGLISH_ZIMBABWE 0x0c -#define SUBLANG_ENGLISH_PHILIPPINES 0x0d -#define SUBLANG_FRENCH 0x01 -#define SUBLANG_FRENCH_BELGIAN 0x02 -#define SUBLANG_FRENCH_CANADIAN 0x03 -#define SUBLANG_FRENCH_SWISS 0x04 -#define SUBLANG_FRENCH_LUXEMBOURG 0x05 -#define SUBLANG_FRENCH_MONACO 0x06 -#define SUBLANG_GERMAN 0x01 -#define SUBLANG_GERMAN_SWISS 0x02 -#define SUBLANG_GERMAN_AUSTRIAN 0x03 -#define SUBLANG_GERMAN_LUXEMBOURG 0x04 -#define SUBLANG_GERMAN_LIECHTENSTEIN 0x05 -#define SUBLANG_ITALIAN 0x01 -#define SUBLANG_ITALIAN_SWISS 0x02 -#define SUBLANG_KOREAN 0x01 -#define SUBLANG_KOREAN_JOHAB 0x02 -#define SUBLANG_NORWEGIAN_BOKMAL 0x01 -#define SUBLANG_NORWEGIAN_NYNORSK 0x02 -#define SUBLANG_PORTUGUESE 0x02 -#define SUBLANG_PORTUGUESE_BRAZILIAN 0x01 -#define SUBLANG_SPANISH 0x01 -#define SUBLANG_SPANISH_MEXICAN 0x02 -#define SUBLANG_SPANISH_MODERN 0x03 -#define SUBLANG_SPANISH_GUATEMALA 0x04 -#define SUBLANG_SPANISH_COSTARICA 0x05 -#define SUBLANG_SPANISH_PANAMA 0x06 -#define SUBLANG_SPANISH_DOMINICAN 0x07 -#define SUBLANG_SPANISH_VENEZUELA 0x08 -#define SUBLANG_SPANISH_COLOMBIA 0x09 -#define SUBLANG_SPANISH_PERU 0x0a -#define SUBLANG_SPANISH_ARGENTINA 0x0b -#define SUBLANG_SPANISH_ECUADOR 0x0c -#define SUBLANG_SPANISH_CHILE 0x0d -#define SUBLANG_SPANISH_URUGUAY 0x0e -#define SUBLANG_SPANISH_PARAGUAY 0x0f -#define SUBLANG_SPANISH_BOLIVIA 0x10 -#define SUBLANG_SPANISH_EL_SALVADOR 0x11 -#define SUBLANG_SPANISH_HONDURAS 0x12 -#define SUBLANG_SPANISH_NICARAGUA 0x13 -#define SUBLANG_SPANISH_PUERTO_RICO 0x14 -/* FIXME: I don't know the symbolic names for those */ -#define SUBLANG_ROMANIAN 0x01 -#define SUBLANG_ROMANIAN_MOLDAVIA 0x02 -#define SUBLANG_RUSSIAN 0x01 -#define SUBLANG_RUSSIAN_MOLDAVIA 0x02 -#define SUBLANG_CROATIAN 0x01 -#define SUBLANG_SERBIAN 0x02 -#define SUBLANG_SERBIAN_LATIN 0x03 -#define SUBLANG_SWEDISH 0x01 -#define SUBLANG_SWEDISH_FINLAND 0x02 -#define SUBLANG_LITHUANIAN 0x01 -#define SUBLANG_LITHUANIAN_CLASSIC 0x02 -#define SUBLANG_AZERI 0x01 -#define SUBLANG_AZERI_CYRILLIC 0x02 -#define SUBLANG_GAELIC 0x01 -#define SUBLANG_GAELIC_SCOTTISH 0x02 -#define SUBLANG_GAELIC_MANX 0x03 -#define SUBLANG_MALAY 0x01 -#define SUBLANG_MALAY_BRUNEI_DARUSSALAM 0x02 -#define SUBLANG_UZBEK 0x01 -#define SUBLANG_UZBEK_CYRILLIC 0x02 -#define SUBLANG_URDU_PAKISTAN 0x01 +#define SUBLANG_ARABIC_SAUDI_ARABIA 0x01 +#define SUBLANG_ARABIC_IRAQ 0x02 +#define SUBLANG_ARABIC_EGYPT 0x03 +#define SUBLANG_ARABIC_LIBYA 0x04 +#define SUBLANG_ARABIC_ALGERIA 0x05 +#define SUBLANG_ARABIC_MOROCCO 0x06 +#define SUBLANG_ARABIC_TUNISIA 0x07 +#define SUBLANG_ARABIC_OMAN 0x08 +#define SUBLANG_ARABIC_YEMEN 0x09 +#define SUBLANG_ARABIC_SYRIA 0x0a +#define SUBLANG_ARABIC_JORDAN 0x0b +#define SUBLANG_ARABIC_LEBANON 0x0c +#define SUBLANG_ARABIC_KUWAIT 0x0d +#define SUBLANG_ARABIC_UAE 0x0e +#define SUBLANG_ARABIC_BAHRAIN 0x0f +#define SUBLANG_ARABIC_QATAR 0x10 +#define SUBLANG_AZERI_LATIN 0x01 +#define SUBLANG_AZERI_CYRILLIC 0x02 +#define SUBLANG_CHINESE_TRADITIONAL 0x01 +#define SUBLANG_CHINESE_SIMPLIFIED 0x02 +#define SUBLANG_CHINESE_HONGKONG 0x03 +#define SUBLANG_CHINESE_SINGAPORE 0x04 +#define SUBLANG_CHINESE_MACAU 0x05 +#define SUBLANG_DUTCH 0x01 +#define SUBLANG_DUTCH_BELGIAN 0x02 +#define SUBLANG_ENGLISH_US 0x01 +#define SUBLANG_ENGLISH_UK 0x02 +#define SUBLANG_ENGLISH_AUS 0x03 +#define SUBLANG_ENGLISH_CAN 0x04 +#define SUBLANG_ENGLISH_NZ 0x05 +#define SUBLANG_ENGLISH_EIRE 0x06 +#define SUBLANG_ENGLISH_SOUTH_AFRICA 0x07 +#define SUBLANG_ENGLISH_JAMAICA 0x08 +#define SUBLANG_ENGLISH_CARIBBEAN 0x09 +#define SUBLANG_ENGLISH_BELIZE 0x0a +#define SUBLANG_ENGLISH_TRINIDAD 0x0b +#define SUBLANG_ENGLISH_ZIMBABWE 0x0c +#define SUBLANG_ENGLISH_PHILIPPINES 0x0d +#define SUBLANG_FRENCH 0x01 +#define SUBLANG_FRENCH_BELGIAN 0x02 +#define SUBLANG_FRENCH_CANADIAN 0x03 +#define SUBLANG_FRENCH_SWISS 0x04 +#define SUBLANG_FRENCH_LUXEMBOURG 0x05 +#define SUBLANG_FRENCH_MONACO 0x06 +#define SUBLANG_GERMAN 0x01 +#define SUBLANG_GERMAN_SWISS 0x02 +#define SUBLANG_GERMAN_AUSTRIAN 0x03 +#define SUBLANG_GERMAN_LUXEMBOURG 0x04 +#define SUBLANG_GERMAN_LIECHTENSTEIN 0x05 +#define SUBLANG_ITALIAN 0x01 +#define SUBLANG_ITALIAN_SWISS 0x02 +#define SUBLANG_KASHMIRI_SASIA 0x02 +#define SUBLANG_KASHMIRI_INDIA 0x02 +#define SUBLANG_KOREAN 0x01 +#define SUBLANG_LITHUANIAN 0x01 +#define SUBLANG_MALAY_MALAYSIA 0x01 +#define SUBLANG_MALAY_BRUNEI_DARUSSALAM 0x02 +#define SUBLANG_NEPALI_INDIA 0x02 +#define SUBLANG_NORWEGIAN_BOKMAL 0x01 +#define SUBLANG_NORWEGIAN_NYNORSK 0x02 +#define SUBLANG_PORTUGUESE 0x02 +#define SUBLANG_PORTUGUESE_BRAZILIAN 0x01 +#define SUBLANG_SERBIAN_LATIN 0x02 +#define SUBLANG_SERBIAN_CYRILLIC 0x03 +#define SUBLANG_SPANISH 0x01 +#define SUBLANG_SPANISH_MEXICAN 0x02 +#define SUBLANG_SPANISH_MODERN 0x03 +#define SUBLANG_SPANISH_GUATEMALA 0x04 +#define SUBLANG_SPANISH_COSTA_RICA 0x05 +#define SUBLANG_SPANISH_PANAMA 0x06 +#define SUBLANG_SPANISH_DOMINICAN_REPUBLIC 0x07 +#define SUBLANG_SPANISH_VENEZUELA 0x08 +#define SUBLANG_SPANISH_COLOMBIA 0x09 +#define SUBLANG_SPANISH_PERU 0x0a +#define SUBLANG_SPANISH_ARGENTINA 0x0b +#define SUBLANG_SPANISH_ECUADOR 0x0c +#define SUBLANG_SPANISH_CHILE 0x0d +#define SUBLANG_SPANISH_URUGUAY 0x0e +#define SUBLANG_SPANISH_PARAGUAY 0x0f +#define SUBLANG_SPANISH_BOLIVIA 0x10 +#define SUBLANG_SPANISH_EL_SALVADOR 0x11 +#define SUBLANG_SPANISH_HONDURAS 0x12 +#define SUBLANG_SPANISH_NICARAGUA 0x13 +#define SUBLANG_SPANISH_PUERTO_RICO 0x14 +#define SUBLANG_SWEDISH 0x01 +#define SUBLANG_SWEDISH_FINLAND 0x02 +#define SUBLANG_URDU_PAKISTAN 0x01 +#define SUBLANG_URDU_INDIA 0x02 +#define SUBLANG_UZBEK_LATIN 0x01 +#define SUBLANG_UZBEK_CYRILLIC 0x02 +/* FIXME: these are not in the Windows header */ +#define SUBLANG_DUTCH_SURINAM 0x03 +#define SUBLANG_ROMANIAN 0x01 +#define SUBLANG_ROMANIAN_MOLDAVIA 0x02 +#define SUBLANG_RUSSIAN 0x01 +#define SUBLANG_RUSSIAN_MOLDAVIA 0x02 +#define SUBLANG_CROATIAN 0x01 +#define SUBLANG_LITHUANIAN_CLASSIC 0x02 +#define SUBLANG_GAELIC 0x01 +#define SUBLANG_GAELIC_SCOTTISH 0x02 +#define SUBLANG_GAELIC_MANX 0x03 /* diff --git a/tools/wpp/ppy.y b/tools/wpp/ppy.y index 8186be5bfb7..54b3aa4a967 100644 --- a/tools/wpp/ppy.y +++ b/tools/wpp/ppy.y @@ -284,7 +284,7 @@ preprocessor | tGCCLINE tNL /* The null-token */ | tERROR opt_text tNL { pperror("#error directive: '%s'", $2); if($2) free($2); } | tWARNING opt_text tNL { ppwarning("#warning directive: '%s'", $2); if($2) free($2); } - | tPRAGMA opt_text tNL { if(pp_status.pedantic) ppwarning("#pragma ignored (arg: '%s')", $2); if($2) free($2); } + | tPRAGMA opt_text tNL { fprintf(ppout, "#pragma %s\n", $2 ? $2 : ""); if ($2) free($2); } | tPPIDENT opt_text tNL { if(pp_status.pedantic) ppwarning("#ident ignored (arg: '%s')", $2); if($2) free($2); } | tRCINCLUDE tRCINCLUDEPATH { int nl=strlen($2) +3; diff --git a/tools/wrc/genres.c b/tools/wrc/genres.c index ca5b4ef2d36..23e724e9121 100644 --- a/tools/wrc/genres.c +++ b/tools/wrc/genres.c @@ -40,6 +40,7 @@ #include "winbase.h" #include "wingdi.h" #include "winuser.h" +#include "wine/unicode.h" #define SetResSize(res, tag) set_dword((res), (tag), (res)->size - get_dword((res), (tag))) @@ -278,32 +279,29 @@ DWORD get_dword(res_t *res, int ofs) * Remarks : FIXME: codepages... ***************************************************************************** */ -void string_to_upper(string_t *str) +static void string_to_upper(string_t *str) { - if(str->type == str_char) - { - char *cptr = str->str.cstr; - for(; *cptr; cptr++) - *cptr = (char)toupper(*cptr); - } - else if(str->type == str_unicode) - { - short *sptr = str->str.wstr; - for(; *sptr; sptr++) - if(isalpha(*sptr)) - *sptr = (short)toupper(*sptr); - } - else - { - internal_error(__FILE__, __LINE__, "Invalid string type %d", str->type); - } + int i; + + if(str->type == str_char) + { + for (i = 0; i < str->size; i++) str->str.cstr[i] = toupper((unsigned char)str->str.cstr[i]); + } + else if(str->type == str_unicode) + { + for (i = 0; i < str->size; i++) str->str.wstr[i] = toupperW(str->str.wstr[i]); + } + else + { + internal_error(__FILE__, __LINE__, "Invalid string type %d", str->type); + } } /* ***************************************************************************** * Function : put_string * Syntax : void put_string(res_t *res, string_t *str, enum str_e type, - * int isterm) + * int isterm, const language_t *lang) * Input : * res - Binary resource to put the data in * str - String to put @@ -315,81 +313,63 @@ void string_to_upper(string_t *str) * Remarks : ***************************************************************************** */ -static void put_string(res_t *res, string_t *str, enum str_e type, int isterm) +static void put_string(res_t *res, const string_t *str, enum str_e type, int isterm, + const language_t *lang) { - int cnt; - int c = !0; - assert(res != NULL); - assert(str != NULL); - if(!isterm && str->size == 0) - { - warning("String length is zero, not written"); - return; - } + int cnt, codepage; + string_t *newstr; - str = convert_string(str, type); - if(str->type == str_unicode && type == str_unicode) - { - for(cnt = 0; cnt < str->size; cnt++) - { - c = str->str.wstr[cnt]; - put_word(res, c); - if(isterm && !c) - break; - } - if(isterm && (str->size == 0 || (cnt == str->size && c))) - put_word(res, 0); - } - else if(str->type == str_char && type == str_char) - { - for(cnt = 0; cnt < str->size; cnt++) - { - c = str->str.cstr[cnt]; - put_byte(res, c); - if(isterm && !c) - break; - } - if(isterm && (str->size == 0 || (cnt == str->size && c))) - put_byte(res, 0); - } - else if(str->type == str_unicode && type == str_char) - { - for(cnt = 0; cnt < str->size; cnt++) - { - c = str->str.wstr[cnt]; - put_byte(res, c); - if(isterm && !c) - break; - } - if(isterm && (str->size == 0 || (cnt == str->size && c))) - put_byte(res, 0); - } - else /* str->type == str_char && type == str_unicode */ - { - for(cnt = 0; cnt < str->size; cnt++) - { - c = str->str.cstr[cnt]; - put_word(res, c & 0xff); - if(isterm && !c) - break; - } - if(isterm && (str->size == 0 || (cnt == str->size && c))) - put_word(res, 0); - } - free(str); + assert(res != NULL); + assert(str != NULL); + + if (lang) codepage = get_language_codepage( lang->id, lang->sub ); + else codepage = get_language_codepage( 0, 0 ); + + assert( codepage != -1 ); + + newstr = convert_string(str, type, codepage); + if (type == str_unicode) + { + if (str->type == str_char) + { + if (!check_unicode_conversion( str, newstr, codepage )) + error( "String %s does not convert identically to Unicode and back in codepage %d. " + "Try using a Unicode string instead.", str->str.cstr, codepage ); + } + if (!isterm) put_word(res, newstr->size); + for(cnt = 0; cnt < newstr->size; cnt++) + { + WCHAR c = newstr->str.wstr[cnt]; + if (isterm && !c) break; + put_word(res, c); + } + if (isterm) put_word(res, 0); + } + else /* str_char */ + { + if (!isterm) put_byte(res, newstr->size); + for(cnt = 0; cnt < newstr->size; cnt++) + { + char c = newstr->str.cstr[cnt]; + if (isterm && !c) break; + put_byte(res, c); + } + if (isterm) put_byte(res, 0); + } + free_string(newstr); } /* ***************************************************************************** * Function : put_name_id - * Syntax : void put_name_id(res_t *res, name_id_t *nid, int upcase) + * Syntax : void put_name_id(res_t *res, name_id_t *nid, int upcase, const language_t *lang) * Input : * Output : * Description : * Remarks : ***************************************************************************** */ -void put_name_id(res_t *res, name_id_t *nid, int upcase) +static void put_name_id(res_t *res, name_id_t *nid, int upcase, const language_t *lang) { if(nid->type == name_ord) { @@ -403,7 +383,7 @@ void put_name_id(res_t *res, name_id_t *nid, int upcase) { if(upcase) string_to_upper(nid->name.s_name); - put_string(res, nid->name.s_name, win32 ? str_unicode : str_char, TRUE); + put_string(res, nid->name.s_name, win32 ? str_unicode : str_char, TRUE, lang); } else { @@ -421,7 +401,7 @@ void put_name_id(res_t *res, name_id_t *nid, int upcase) * Remarks : ***************************************************************************** */ -void put_lvc(res_t *res, lvc_t *lvc) +static void put_lvc(res_t *res, lvc_t *lvc) { if(lvc && lvc->language) put_word(res, MAKELANGID(lvc->language->id, lvc->language->sub)); @@ -435,12 +415,6 @@ 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 ); } /* @@ -494,8 +468,8 @@ int put_res_header(res_t *res, int type, name_id_t *ntype, name_id_t *name, put_word(res, type); } else - put_name_id(res, ntype, TRUE); - put_name_id(res, name, TRUE); /* ResName */ + put_name_id(res, ntype, TRUE, lvc->language); + put_name_id(res, name, TRUE, lvc->language); /* ResName */ put_pad(res); put_dword(res, 0); /* DataVersion */ put_word(res, memopt); /* Memory options */ @@ -514,8 +488,8 @@ int put_res_header(res_t *res, int type, name_id_t *ntype, name_id_t *name, put_word(res, type); } else - put_name_id(res, ntype, TRUE); - put_name_id(res, name, TRUE); /* ResName */ + put_name_id(res, ntype, TRUE, NULL); + put_name_id(res, name, TRUE, NULL); /* ResName */ put_word(res, memopt); /* Memory options */ tag = res->size; put_dword(res, 0); /* ResSize overwritten later*/ @@ -613,21 +587,21 @@ static res_t *dialog2res(name_id_t *name, dialog_t *dlg) put_word(res, dlg->width); put_word(res, dlg->height); if(dlg->menu) - put_name_id(res, dlg->menu, TRUE); + put_name_id(res, dlg->menu, TRUE, dlg->lvc.language); else put_word(res, 0); if(dlg->dlgclass) - put_name_id(res, dlg->dlgclass, TRUE); + put_name_id(res, dlg->dlgclass, TRUE, dlg->lvc.language); else put_word(res, 0); if(dlg->title) - put_string(res, dlg->title, str_unicode, TRUE); + put_string(res, dlg->title, str_unicode, TRUE, dlg->lvc.language); else put_word(res, 0); if(dlg->font) { put_word(res, dlg->font->size); - put_string(res, dlg->font->name, str_unicode, TRUE); + put_string(res, dlg->font->name, str_unicode, TRUE, dlg->lvc.language); } put_pad(res); @@ -642,11 +616,11 @@ static res_t *dialog2res(name_id_t *name, dialog_t *dlg) put_word(res, ctrl->height); put_word(res, ctrl->id); if(ctrl->ctlclass) - put_name_id(res, ctrl->ctlclass, TRUE); + put_name_id(res, ctrl->ctlclass, TRUE, dlg->lvc.language); else internal_error(__FILE__, __LINE__, "Control has no control-class"); if(ctrl->title) - put_name_id(res, ctrl->title, FALSE); + put_name_id(res, ctrl->title, FALSE, dlg->lvc.language); else put_word(res, 0); if(ctrl->extra) @@ -678,21 +652,21 @@ static res_t *dialog2res(name_id_t *name, dialog_t *dlg) put_word(res, dlg->width); put_word(res, dlg->height); if(dlg->menu) - put_name_id(res, dlg->menu, TRUE); + put_name_id(res, dlg->menu, TRUE, NULL); else put_byte(res, 0); if(dlg->dlgclass) - put_name_id(res, dlg->dlgclass, TRUE); + put_name_id(res, dlg->dlgclass, TRUE, NULL); else put_byte(res, 0); if(dlg->title) - put_string(res, dlg->title, str_char, TRUE); + put_string(res, dlg->title, str_char, TRUE, NULL); else put_byte(res, 0); if(dlg->font) { put_word(res, dlg->font->size); - put_string(res, dlg->font->name, str_char, TRUE); + put_string(res, dlg->font->name, str_char, TRUE, NULL); } while(ctrl) @@ -710,14 +684,14 @@ static res_t *dialog2res(name_id_t *name, dialog_t *dlg) && ctrl->ctlclass->name.i_name <= 0x85) put_byte(res, ctrl->ctlclass->name.i_name); else if(ctrl->ctlclass->type == name_str) - put_name_id(res, ctrl->ctlclass, FALSE); + put_name_id(res, ctrl->ctlclass, FALSE, NULL); else error("Unknown control-class %04x", ctrl->ctlclass->name.i_name); } else internal_error(__FILE__, __LINE__, "Control has no control-class"); if(ctrl->title) - put_name_id(res, ctrl->title, FALSE); + put_name_id(res, ctrl->title, FALSE, NULL); else put_byte(res, 0); @@ -781,15 +755,15 @@ static res_t *dialogex2res(name_id_t *name, dialogex_t *dlgex) put_word(res, dlgex->width); put_word(res, dlgex->height); if(dlgex->menu) - put_name_id(res, dlgex->menu, TRUE); + put_name_id(res, dlgex->menu, TRUE, dlgex->lvc.language); else put_word(res, 0); if(dlgex->dlgclass) - put_name_id(res, dlgex->dlgclass, TRUE); + put_name_id(res, dlgex->dlgclass, TRUE, dlgex->lvc.language); else put_word(res, 0); if(dlgex->title) - put_string(res, dlgex->title, str_unicode, TRUE); + put_string(res, dlgex->title, str_unicode, TRUE, dlgex->lvc.language); else put_word(res, 0); if(dlgex->font) @@ -801,7 +775,7 @@ static res_t *dialogex2res(name_id_t *name, dialogex_t *dlgex) * I just copy it here, and hope for the best. */ put_word(res, dlgex->font->italic ? 0x0101 : 0); - put_string(res, dlgex->font->name, str_unicode, TRUE); + put_string(res, dlgex->font->name, str_unicode, TRUE, dlgex->lvc.language); } put_pad(res); @@ -819,11 +793,11 @@ static res_t *dialogex2res(name_id_t *name, dialogex_t *dlgex) /* FIXME: Pad is _NOT_ documented!?! */ put_pad(res); if(ctrl->ctlclass) - put_name_id(res, ctrl->ctlclass, TRUE); + put_name_id(res, ctrl->ctlclass, TRUE, dlgex->lvc.language); else internal_error(__FILE__, __LINE__, "Control has no control-class"); if(ctrl->title) - put_name_id(res, ctrl->title, FALSE); + put_name_id(res, ctrl->title, FALSE, dlgex->lvc.language); else put_word(res, 0); if(ctrl->extra) @@ -865,7 +839,7 @@ static res_t *dialogex2res(name_id_t *name, dialogex_t *dlgex) * Remarks : Self recursive ***************************************************************************** */ -static void menuitem2res(res_t *res, menu_item_t *menitem) +static void menuitem2res(res_t *res, menu_item_t *menitem, const language_t *lang) { menu_item_t *itm = menitem; if(win32) @@ -876,11 +850,11 @@ static void menuitem2res(res_t *res, menu_item_t *menitem) if(!itm->popup) put_word(res, itm->id); if(itm->name) - put_string(res, itm->name, str_unicode, TRUE); + put_string(res, itm->name, str_unicode, TRUE, lang); else put_word(res, 0); if(itm->popup) - menuitem2res(res, itm->popup); + menuitem2res(res, itm->popup, lang); itm = itm->next; } } @@ -892,11 +866,11 @@ static void menuitem2res(res_t *res, menu_item_t *menitem) if(!itm->popup) put_word(res, itm->id); if(itm->name) - put_string(res, itm->name, str_char, TRUE); + put_string(res, itm->name, str_char, TRUE, lang); else put_byte(res, 0); if(itm->popup) - menuitem2res(res, itm->popup); + menuitem2res(res, itm->popup, lang); itm = itm->next; } } @@ -926,7 +900,7 @@ static res_t *menu2res(name_id_t *name, menu_t *men) restag = put_res_header(res, WRC_RT_MENU, NULL, name, men->memopt, win32 ? &(men->lvc) : NULL); put_dword(res, 0); /* Menuheader: Version and HeaderSize */ - menuitem2res(res, men->items); + menuitem2res(res, men->items, win32 ? men->lvc.language : NULL); /* Set ResourceSize */ SetResSize(res, restag); if(win32) @@ -944,7 +918,7 @@ static res_t *menu2res(name_id_t *name, menu_t *men) * Remarks : Self recursive ***************************************************************************** */ -static void menuexitem2res(res_t *res, menuex_item_t *menitem) +static void menuexitem2res(res_t *res, menuex_item_t *menitem, const language_t *lang) { menuex_item_t *itm = menitem; assert(win32 != 0); @@ -955,14 +929,14 @@ static void menuexitem2res(res_t *res, menuex_item_t *menitem) put_dword(res, itm->gotid ? itm->id : 0); /* FIXME: Docu. says word */ put_word(res, (itm->popup ? 0x01 : 0) | (!itm->next ? MF_END : 0)); if(itm->name) - put_string(res, itm->name, str_unicode, TRUE); + put_string(res, itm->name, str_unicode, TRUE, lang); else put_word(res, 0); put_pad(res); if(itm->popup) { put_dword(res, itm->gothelpid ? itm->helpid : 0); - menuexitem2res(res, itm->popup); + menuexitem2res(res, itm->popup, lang); } itm = itm->next; } @@ -997,7 +971,7 @@ static res_t *menuex2res(name_id_t *name, menuex_t *menex) put_word(res, 4); /* Offset */ put_dword(res, 0); /* HelpId */ put_pad(res); - menuexitem2res(res, menex->items); + menuexitem2res(res, menex->items, menex->lvc.language); /* Set ResourceSize */ SetResSize(res, restag); put_pad(res); @@ -1484,17 +1458,12 @@ static res_t *stringtable2res(stringtable_t *stt) { if(stt->entries[i].str && 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, str->size); - put_string(res, str, win32 ? str_unicode : str_char, FALSE); - free(str); + put_string(res, stt->entries[i].str, win32 ? str_unicode : str_char, + FALSE, win32 ? stt->lvc.language : NULL); } else { - if(win32) + if (win32) put_word(res, 0); else put_byte(res, 0); @@ -1550,7 +1519,7 @@ static res_t *user2res(name_id_t *name, user_t *usr) * Remarks : Self recursive ***************************************************************************** */ -static void versionblock2res(res_t *res, ver_block_t *blk, int level) +static void versionblock2res(res_t *res, ver_block_t *blk, int level, const language_t *lang) { ver_value_t *val; int blksizetag; @@ -1564,7 +1533,7 @@ static void versionblock2res(res_t *res, ver_block_t *blk, int level) put_word(res, 0); if(win32) put_word(res, 0); /* level ? */ - put_string(res, blk->name, win32 ? str_unicode : str_char, TRUE); + put_string(res, blk->name, win32 ? str_unicode : str_char, TRUE, lang); put_pad(res); for(val = blk->values; val; val = val->next) { @@ -1578,10 +1547,10 @@ static void versionblock2res(res_t *res, ver_block_t *blk, int level) { put_word(res, level); } - put_string(res, val->key, win32 ? str_unicode : str_char, TRUE); + put_string(res, val->key, win32 ? str_unicode : str_char, TRUE, lang); put_pad(res); tag = res->size; - put_string(res, val->value.str, win32 ? str_unicode : str_char, TRUE); + put_string(res, val->value.str, win32 ? str_unicode : str_char, TRUE, lang); if(win32) set_word(res, valvalsizetag, (WORD)((res->size - tag) >> 1)); else @@ -1599,7 +1568,7 @@ static void versionblock2res(res_t *res, ver_block_t *blk, int level) { put_word(res, level); } - put_string(res, val->key, win32 ? str_unicode : str_char, TRUE); + put_string(res, val->key, win32 ? str_unicode : str_char, TRUE, lang); put_pad(res); tag = res->size; for(i = 0; i < val->value.words->nwords; i++) @@ -1612,7 +1581,7 @@ static void versionblock2res(res_t *res, ver_block_t *blk, int level) } else if(val->type == val_block) { - versionblock2res(res, val->value.block, level+1); + versionblock2res(res, val->value.block, level+1, lang); } else { @@ -1661,7 +1630,8 @@ static res_t *versioninfo2res(name_id_t *name, versioninfo_t *ver) put_word(res, 0); /* ValueSize filled in later*/ if(win32) put_word(res, 0); /* Tree-level ? */ - put_string(res, &vsvi, win32 ? str_unicode : str_char, TRUE); + put_string(res, &vsvi, win32 ? str_unicode : str_char, + TRUE, win32 ? ver->lvc.language : NULL); if(win32) put_pad(res); tag = res->size; @@ -1682,7 +1652,7 @@ static res_t *versioninfo2res(name_id_t *name, versioninfo_t *ver) set_word(res, valsizetag, (WORD)(res->size - tag)); /* Descend into the blocks */ for(blk = ver->blocks; blk; blk = blk->next) - versionblock2res(res, blk, 0); + versionblock2res(res, blk, 0, win32 ? ver->lvc.language : NULL); /* Set root block's size */ set_word(res, rootblocksizetag, (WORD)(res->size - rootblocksizetag)); @@ -2025,4 +1995,3 @@ void resources2res(resource_t *top) top = top->next; } } - diff --git a/tools/wrc/parser.l b/tools/wrc/parser.l index 0e5329cdb8c..d9b689c73c4 100644 --- a/tools/wrc/parser.l +++ b/tools/wrc/parser.l @@ -82,6 +82,9 @@ %x pp_stripp_final /* Set when scanning #line style directives */ %x pp_line +/* Set when scanning #pragma */ +%x pp_pragma +%x pp_code_page %option stack %option never-interactive @@ -100,6 +103,7 @@ cident [a-zA-Z_][0-9a-zA-Z_]* #include #include +#include "wine/unicode.h" #include "wrc.h" #include "utils.h" #include "parser.h" @@ -115,7 +119,7 @@ cident [a-zA-Z_][0-9a-zA-Z_]* #define YY_USER_ACTION char_number+=yyleng; wanted_id = want_id; want_id = 0; static void addcchar(char c); -static void addwchar(short s); +static void addwchar(WCHAR s); static string_t *get_buffered_cstring(void); static string_t *get_buffered_wstring(void); static string_t *make_string(char *s); @@ -123,13 +127,15 @@ static string_t *make_string(char *s); static char *cbuffer; /* Buffers for string collection */ static int cbufidx; static int cbufalloc = 0; -static short *wbuffer; +static WCHAR *wbuffer; static int wbufidx; static int wbufalloc = 0; static int stripslevel = 0; /* Count {} during pp_strips/pp_stripe mode */ static int stripplevel = 0; /* Count () during pp_strips mode */ static int cjunk_tagline; /* Where did we start stripping (helps error tracking) */ +static int current_codepage = -1; /* use language default */ + /* * This one is a bit tricky. * We set 'want_id' in the parser to get the first @@ -316,6 +322,7 @@ static struct keyword *iskeyword(char *kw) * because we only want to know the linenumber and * filename. */ +^{ws}*\#{ws}*pragma{ws}+ yy_push_state(pp_pragma); ^{ws}*\#{ws}* yy_push_state(pp_line); [^\n]* { int lineno; @@ -337,6 +344,23 @@ static struct keyword *iskeyword(char *kw) input_name = xstrdup(fname); } +code_page[^\n]* yyless(9); yy_pop_state(); yy_push_state(pp_code_page); +[^\n]* yy_pop_state(); if (pedantic) yywarning("Unrecognized #pragma directive '%s'",yytext); + +\({ws}*default{ws}*\)[^\n]* current_codepage = -1; yy_pop_state(); +\({ws}*[0-9]+{ws}*\)[^\n]* { + char *p = yytext; + yy_pop_state(); + while (*p < '0' || *p > '9') p++; + current_codepage = strtol( p, NULL, 10 ); + if (current_codepage && !cp_get_table( current_codepage )) + { + yyerror("Codepage %d not supported", current_codepage); + current_codepage = 0; + } + } +[^\n]* yy_pop_state(); yyerror("Malformed #pragma code_page directive"); + /* * Strip everything until a ';' taking * into account braces {} for structures, @@ -418,16 +442,16 @@ L\" { return tSTRING; } \\[0-7]{1,6} { /* octal escape sequence */ - int result; - result = strtol(yytext+1, 0, 8); + unsigned int result; + result = strtoul(yytext+1, 0, 8); if ( result > 0xffff ) yyerror("Character constant out of range"); - addwchar((short)result); + addwchar((WCHAR)result); } \\x[0-9a-fA-F]{4} { /* hex escape sequence */ - int result; - result = strtol(yytext+2, 0, 16); - addwchar((short)result); + unsigned int result; + result = strtoul(yytext+2, 0, 16); + addwchar((WCHAR)result); } \\x[0-9a-fA-F]{1,3} { yyerror("Invalid hex escape sequence '%s'", yytext); } @@ -441,8 +465,8 @@ L\" { \\v addwchar('\v'); \\(\n|.) addwchar(yytext[1]); \\\r\n addwchar(yytext[2]); -\"\" addcchar('\"'); /* "bla""bla" -> "bla\"bla" */ -\\\"\" addcchar('\"'); /* "bla\""bla" -> "bla\"bla" */ +\"\" addwchar('\"'); /* "bla""bla" -> "bla\"bla" */ +\\\"\" addwchar('\"'); /* "bla\""bla" -> "bla\"bla" */ \"{ws}+\" ; /* "bla" "bla" -> "blabla" */ [^\\\n\"]+ { char *yptr = yytext; @@ -596,7 +620,7 @@ static void addcchar(char c) cbuffer[cbufidx++] = c; } -static void addwchar(short s) +static void addwchar(WCHAR s) { if(wbufidx >= wbufalloc) { @@ -605,27 +629,33 @@ static void addwchar(short s) if(wbufalloc > 65536) yywarning("Reallocating wide string buffer larger than 64kB"); } - - /* - * BS 08-Aug-1999 FIXME: The '& 0xff' is probably a bug, but I have - * not experienced it yet and I seem to remember that this was for - * a reason. But, as so many things you tend to forget why. - * I guess that there were problems due to the sign extension of - * shorts WRT chars (e.g. 0x80 becomes 0xff80 instead of 0x0080). - * This should then be fixed in the lexer calling the function. - */ - wbuffer[wbufidx++] = (short)(s & 0xff); + wbuffer[wbufidx++] = s; } static string_t *get_buffered_cstring(void) { - string_t *str = new_string(); - str->size = cbufidx; - str->type = str_char; - str->str.cstr = (char *)xmalloc(cbufidx+1); - memcpy(str->str.cstr, cbuffer, cbufidx); - str->str.cstr[cbufidx] = '\0'; - return str; + string_t *str = new_string(); + + str->size = cbufidx; + str->type = str_char; + str->str.cstr = (char *)xmalloc(cbufidx+1); + memcpy(str->str.cstr, cbuffer, cbufidx); + str->str.cstr[cbufidx] = '\0'; + + if (!current_codepage || current_codepage == -1 || !win32) /* store as ANSI string */ + { + if (!current_codepage) yyerror("Codepage set to Unicode only, cannot use ASCII string here"); + return str; + } + else /* convert to Unicode before storing */ + { + string_t *str_w = convert_string( str, str_unicode, current_codepage ); + if (!check_unicode_conversion( str, str_w, current_codepage )) + yyerror("String %s does not convert identically to Unicode and back in codepage %d. " + "Try using a Unicode string instead.", str->str.cstr, current_codepage ); + free_string( str ); + return str_w; + } } static string_t *get_buffered_wstring(void) @@ -633,8 +663,8 @@ static string_t *get_buffered_wstring(void) string_t *str = new_string(); str->size = wbufidx; str->type = str_unicode; - str->str.wstr = (short *)xmalloc(2*(wbufidx+1)); - memcpy(str->str.wstr, wbuffer, wbufidx); + str->str.wstr = xmalloc((wbufidx+1)*sizeof(WCHAR)); + memcpy(str->str.wstr, wbuffer, wbufidx*sizeof(WCHAR)); str->str.wstr[wbufidx] = 0; return str; } diff --git a/tools/wrc/parser.y b/tools/wrc/parser.y index 942725dbbac..3a7c892d37d 100644 --- a/tools/wrc/parser.y +++ b/tools/wrc/parser.y @@ -531,6 +531,8 @@ resource yywarning("LANGUAGE not supported in 16-bit mode"); if(currentlanguage) free(currentlanguage); + if (get_language_codepage($3, $5) == -1) + yyerror( "Language %04x is not supported", ($5<<10) + $3); currentlanguage = new_language($3, $5); $$ = NULL; chat("Got LANGUAGE %d,%d (0x%04x)", $3, $5, ($5<<10) + $3); @@ -1752,7 +1754,10 @@ opt_lvc : /* Empty */ { $$ = new_lvc(); } * The conflict is now moved to the expression handling below. */ opt_language - : tLANGUAGE expr ',' expr { $$ = new_language($2, $4); } + : tLANGUAGE expr ',' expr { $$ = new_language($2, $4); + if (get_language_codepage($2, $4) == -1) + yyerror( "Language %04x is not supported", ($4<<10) + $2); + } ; opt_characts diff --git a/tools/wrc/utils.c b/tools/wrc/utils.c index ab13429a21b..2e9dfe838de 100644 --- a/tools/wrc/utils.c +++ b/tools/wrc/utils.c @@ -36,8 +36,6 @@ /* #define WANT_NEAR_INDICATION */ -static const union cptable *current_codepage; - #ifdef WANT_NEAR_INDICATION void make_print(char *str) { @@ -202,31 +200,6 @@ char *xstrdup(const char *str) return strcpy(s, str); } -short *dupcstr2wstr(const char *str) -{ - int len; - WCHAR *ws; - - 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; - char *cs; - - 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; -} /* ***************************************************************************** @@ -272,37 +245,84 @@ 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 *convert_string(const string_t *str, enum str_e type, int codepage) { - string_t *ret = xmalloc(sizeof(*ret)); + const union cptable *cptable = codepage ? cp_get_table( codepage ) : NULL; + 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; + if (!cptable && str->type != type) + error( "Current language is Unicode only, cannot convert strings" ); + + if((str->type == str_char) && (type == str_unicode)) + { + ret->type = str_unicode; + ret->size = cp_mbstowcs( cptable, 0, str->str.cstr, str->size, NULL, 0 ); + ret->str.wstr = xmalloc( (ret->size+1) * sizeof(WCHAR) ); + cp_mbstowcs( cptable, 0, str->str.cstr, str->size, ret->str.wstr, ret->size ); + ret->str.wstr[ret->size] = 0; + } + else if((str->type == str_unicode) && (type == str_char)) + { + ret->type = str_char; + ret->size = cp_wcstombs( cptable, 0, str->str.wstr, str->size, + NULL, 0, NULL, NULL ); + ret->str.cstr = xmalloc( ret->size + 1 ); + cp_wcstombs( cptable, 0, str->str.wstr, str->size, ret->str.cstr, ret->size, + NULL, NULL ); + ret->str.cstr[ret->size] = 0; + } + else if(str->type == str_unicode) + { + ret->type = str_unicode; + ret->size = str->size; + ret->str.wstr = xmalloc(sizeof(WCHAR)*(ret->size+1)); + memcpy( ret->str.wstr, str->str.wstr, ret->size * sizeof(WCHAR) ); + ret->str.wstr[ret->size] = 0; + } + else /* str->type == str_char */ + { + ret->type = str_char; + ret->size = str->size; + ret->str.cstr = xmalloc( ret->size + 1 ); + memcpy( ret->str.cstr, str->str.cstr, ret->size ); + ret->str.cstr[ret->size] = 0; + } + return ret; +} + + +void free_string(string_t *str) +{ + if (str->type == str_unicode) free( str->str.wstr ); + else free( str->str.cstr ); + free( str ); +} + + +int check_unicode_conversion( const string_t *str_a, const string_t *str_w, int codepage ) +{ + int ok; + string_t *teststr = convert_string( str_w, str_char, codepage ); + + ok = (teststr->size == str_a->size && !memcmp( teststr->str.cstr, str_a->str.cstr, str_a->size )); + + if (!ok) + { + int i; + + fprintf( stderr, "Source: %s", str_a->str.cstr ); + for (i = 0; i < str_a->size; i++) + fprintf( stderr, " %02x", (unsigned char)str_a->str.cstr[i] ); + fprintf( stderr, "\nUnicode: " ); + for (i = 0; i < str_w->size; i++) + fprintf( stderr, " %04x", str_w->str.wstr[i] ); + fprintf( stderr, "\nBack: %s", teststr->str.cstr ); + for (i = 0; i < teststr->size; i++) + fprintf( stderr, " %02x", (unsigned char)teststr->str.cstr[i] ); + fprintf( stderr, "\n" ); + } + free_string( teststr ); + return ok; } @@ -321,60 +341,88 @@ static const struct lang2cp lang2cps[] = { LANG_AFRIKAANS, SUBLANG_NEUTRAL, 1252 }, { LANG_ALBANIAN, SUBLANG_NEUTRAL, 1250 }, { LANG_ARABIC, SUBLANG_NEUTRAL, 1256 }, + { LANG_ARMENIAN, SUBLANG_NEUTRAL, 0 }, + { LANG_AZERI, SUBLANG_NEUTRAL, 1254 }, + { LANG_AZERI, SUBLANG_AZERI_CYRILLIC, 1251 }, { LANG_BASQUE, SUBLANG_NEUTRAL, 1252 }, + { LANG_BELARUSIAN, SUBLANG_NEUTRAL, 1251 }, { LANG_BRETON, SUBLANG_NEUTRAL, 1252 }, { LANG_BULGARIAN, SUBLANG_NEUTRAL, 1251 }, - { LANG_BYELORUSSIAN, SUBLANG_NEUTRAL, 1251 }, { LANG_CATALAN, SUBLANG_NEUTRAL, 1252 }, - { LANG_CHINESE, SUBLANG_NEUTRAL, 936 }, + { LANG_CHINESE, SUBLANG_NEUTRAL, 950 }, + { LANG_CHINESE, SUBLANG_CHINESE_SINGAPORE, 936 }, + { LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED, 936 }, { LANG_CORNISH, SUBLANG_NEUTRAL, 1252 }, + { LANG_CROATIAN, SUBLANG_NEUTRAL, 1250 }, { LANG_CZECH, SUBLANG_NEUTRAL, 1250 }, { LANG_DANISH, SUBLANG_NEUTRAL, 1252 }, + { LANG_DIVEHI, SUBLANG_NEUTRAL, 0 }, { LANG_DUTCH, SUBLANG_NEUTRAL, 1252 }, { LANG_ENGLISH, SUBLANG_NEUTRAL, 1252 }, { LANG_ESPERANTO, SUBLANG_NEUTRAL, 1252 }, { LANG_ESTONIAN, SUBLANG_NEUTRAL, 1257 }, { LANG_FAEROESE, SUBLANG_NEUTRAL, 1252 }, + { LANG_FARSI, SUBLANG_NEUTRAL, 1256 }, { LANG_FINNISH, SUBLANG_NEUTRAL, 1252 }, { LANG_FRENCH, SUBLANG_NEUTRAL, 1252 }, { LANG_GAELIC, SUBLANG_NEUTRAL, 1252 }, + { LANG_GALICIAN, SUBLANG_NEUTRAL, 1252 }, + { LANG_GEORGIAN, SUBLANG_NEUTRAL, 0 }, { LANG_GERMAN, SUBLANG_NEUTRAL, 1252 }, { LANG_GREEK, SUBLANG_NEUTRAL, 1253 }, + { LANG_GUJARATI, SUBLANG_NEUTRAL, 0 }, { LANG_HEBREW, SUBLANG_NEUTRAL, 1255 }, + { LANG_HINDI, SUBLANG_NEUTRAL, 0 }, { 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_KANNADA, SUBLANG_NEUTRAL, 0 }, + { LANG_KAZAK, SUBLANG_NEUTRAL, 1251 }, + { LANG_KONKANI, SUBLANG_NEUTRAL, 0 }, { LANG_KOREAN, SUBLANG_NEUTRAL, 949 }, + { LANG_KYRGYZ, SUBLANG_NEUTRAL, 1251 }, { LANG_LATVIAN, SUBLANG_NEUTRAL, 1257 }, { LANG_LITHUANIAN, SUBLANG_NEUTRAL, 1257 }, { LANG_MACEDONIAN, SUBLANG_NEUTRAL, 1251 }, { LANG_MALAY, SUBLANG_NEUTRAL, 1252 }, + { LANG_MARATHI, SUBLANG_NEUTRAL, 0 }, + { LANG_MONGOLIAN, SUBLANG_NEUTRAL, 1251 }, { LANG_NEUTRAL, SUBLANG_NEUTRAL, 1252 }, { LANG_NORWEGIAN, SUBLANG_NEUTRAL, 1252 }, { LANG_POLISH, SUBLANG_NEUTRAL, 1250 }, { LANG_PORTUGUESE, SUBLANG_NEUTRAL, 1252 }, + { LANG_PUNJABI, SUBLANG_NEUTRAL, 0 }, { LANG_ROMANIAN, SUBLANG_NEUTRAL, 1250 }, { LANG_RUSSIAN, SUBLANG_NEUTRAL, 1251 }, - { LANG_SERBO_CROATIAN, SUBLANG_NEUTRAL, 1250 }, - { LANG_SERBO_CROATIAN, SUBLANG_SERBIAN, 1251 }, + { LANG_SANSKRIT, SUBLANG_NEUTRAL, 0 }, + { LANG_SERBIAN, SUBLANG_NEUTRAL, 1250 }, + { LANG_SERBIAN, SUBLANG_SERBIAN_CYRILLIC, 1251 }, { LANG_SLOVAK, SUBLANG_NEUTRAL, 1250 }, { LANG_SLOVENIAN, SUBLANG_NEUTRAL, 1250 }, { LANG_SPANISH, SUBLANG_NEUTRAL, 1252 }, + { LANG_SWAHILI, SUBLANG_NEUTRAL, 1252 }, { LANG_SWEDISH, SUBLANG_NEUTRAL, 1252 }, + { LANG_SYRIAC, SUBLANG_NEUTRAL, 0 }, + { LANG_TAMIL, SUBLANG_NEUTRAL, 0 }, + { LANG_TATAR, SUBLANG_NEUTRAL, 1251 }, + { LANG_TELUGU, SUBLANG_NEUTRAL, 0 }, { LANG_THAI, SUBLANG_NEUTRAL, 874 }, { LANG_TURKISH, SUBLANG_NEUTRAL, 1254 }, { LANG_UKRAINIAN, SUBLANG_NEUTRAL, 1251 }, + { LANG_URDU, SUBLANG_NEUTRAL, 1256 }, + { LANG_UZBEK, SUBLANG_NEUTRAL, 1254 }, + { LANG_UZBEK, SUBLANG_UZBEK_CYRILLIC, 1251 }, { LANG_VIETNAMESE, SUBLANG_NEUTRAL, 1258 }, { LANG_WALON, SUBLANG_NEUTRAL, 1252 }, { LANG_WELSH, SUBLANG_NEUTRAL, 1252 } }; -void set_language( unsigned short lang, unsigned short sublang ) +int get_language_codepage( unsigned short lang, unsigned short sublang ) { unsigned int i; - unsigned int cp = 0, defcp = 0; + int cp = -1, defcp = -1; for (i = 0; i < sizeof(lang2cps)/sizeof(lang2cps[0]); i++) { @@ -387,9 +435,7 @@ void set_language( unsigned short lang, unsigned short sublang ) 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) ); - if (!(current_codepage = cp_get_table( cp ))) - error( "Bad codepage %d for language %04x", cp, MAKELANGID(lang,sublang) ); + if (cp == -1) cp = defcp; + assert( cp <= 0 || cp_get_table(cp) ); + return cp; } diff --git a/tools/wrc/utils.h b/tools/wrc/utils.h index 6230c6460ca..afb959776fa 100644 --- a/tools/wrc/utils.h +++ b/tools/wrc/utils.h @@ -37,16 +37,16 @@ char *xstrdup(const char *str); int yyerror(const char *s, ...) __attribute__((format (printf, 1, 2))); int yywarning(const char *s, ...) __attribute__((format (printf, 1, 2))); -void internal_error(const char *file, int line, const char *s, ...) __attribute__((format (printf, 3, 4))); +void internal_error(const char *file, int line, const char *s, ...) __attribute__((format (printf, 3, 4), noreturn)); void error(const char *s, ...) __attribute__((format (printf, 1, 2))); 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); -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); +string_t *convert_string(const string_t *str, enum str_e type, int codepage); +void free_string( string_t *str ); +int check_unicode_conversion( const string_t *str_a, const string_t *str_w, int codepage ); +int get_language_codepage( unsigned short lang, unsigned short sublang ); #endif diff --git a/tools/wrc/wrc.c b/tools/wrc/wrc.c index 378143b6047..463b38cf015 100644 --- a/tools/wrc/wrc.c +++ b/tools/wrc/wrc.c @@ -363,6 +363,8 @@ int main(int argc,char *argv[]) { int lan; lan = strtol(optarg, NULL, 0); + if (get_language_codepage(PRIMARYLANGID(lan), SUBLANGID(lan)) == -1) + error("Language %04x is not supported",lan); currentlanguage = new_language(PRIMARYLANGID(lan), SUBLANGID(lan)); } break; diff --git a/tools/wrc/wrctypes.h b/tools/wrc/wrctypes.h index 0bf6a50b2fd..0f73a1fbac9 100644 --- a/tools/wrc/wrctypes.h +++ b/tools/wrc/wrctypes.h @@ -99,7 +99,7 @@ typedef struct string { enum str_e type; union { char *cstr; - short *wstr; + WCHAR *wstr; } str; } string_t; diff --git a/tools/wrc/writeres.c b/tools/wrc/writeres.c index 756c8db033f..c068d41f6c9 100644 --- a/tools/wrc/writeres.c +++ b/tools/wrc/writeres.c @@ -243,26 +243,22 @@ static void write_name_str(FILE *fp, name_id_t *nid) else if(!win32 && nid->name.s_name->type == str_unicode) { name_id_t lnid; - string_t str; lnid.type = name_str; - lnid.name.s_name = &str; - str.type = str_char; - str.str.cstr = dupwstr2cstr(nid->name.s_name->str.wstr); + lnid.name.s_name = convert_string( nid->name.s_name, str_char, + get_language_codepage(0,0) ); write_name_str(fp, &lnid); - free(str.str.cstr); + free_string( lnid.name.s_name ); } else if(win32 && nid->name.s_name->type == str_char) { name_id_t lnid; - string_t str; lnid.type = name_str; - lnid.name.s_name = &str; - str.type = str_unicode; - str.str.wstr = dupcstr2wstr(nid->name.s_name->str.cstr); + lnid.name.s_name = convert_string( nid->name.s_name, str_unicode, + get_language_codepage(0,0) ); write_name_str(fp, &lnid); - free(str.str.wstr); + free_string( lnid.name.s_name ); } else if(win32 && nid->name.s_name->type == str_unicode) {