|
|
1.1 ! root 1: /* ! 2: Copyright (c) 2004-2005 TrueCrypt Foundation. All rights reserved. ! 3: ! 4: Covered by TrueCrypt License 2.0 the full text of which is contained in the file ! 5: License.txt included in TrueCrypt binary and source code distribution archives. ! 6: */ ! 7: ! 8: #include "Language.h" ! 9: #include "Dlgcode.h" ! 10: #include "Dictionary.h" ! 11: #include "Tcdefs.h" ! 12: #include "Xml.h" ! 13: ! 14: #include "../Common/Resource.h" ! 15: ! 16: #ifdef TCMOUNT ! 17: #include "../Mount/Resource.h" ! 18: #endif ! 19: ! 20: #ifdef VOLFORMAT ! 21: #include "../Format/Resource.h" ! 22: #endif ! 23: ! 24: #ifdef SETUP ! 25: #include "../Setup/Resource.h" ! 26: #endif ! 27: ! 28: BOOL LocalizationActive; ! 29: int LocalizationSerialNo; ! 30: ! 31: wchar_t UnknownString[1024]; ! 32: static char *LanguageFileBuffer; ! 33: static HANDLE LanguageFileFindHandle = INVALID_HANDLE_VALUE; ! 34: static char PreferredLangId[6]; ! 35: static char *LanguageResource; ! 36: static char *HeaderResource[2]; ! 37: static char ActiveLangPackVersion[6]; ! 38: ! 39: static char *MapFirstLanguageFile () ! 40: { ! 41: if (LanguageFileFindHandle != INVALID_HANDLE_VALUE) ! 42: { ! 43: FindClose (LanguageFileFindHandle); ! 44: LanguageFileFindHandle = INVALID_HANDLE_VALUE; ! 45: } ! 46: ! 47: if (LanguageResource == NULL) ! 48: LanguageResource = MapResource ("Xml", IDR_LANGUAGE, NULL); ! 49: ! 50: return LanguageResource; ! 51: } ! 52: ! 53: ! 54: static char *MapNextLanguageFile () ! 55: { ! 56: wchar_t f[TC_MAX_PATH*2], *t; ! 57: WIN32_FIND_DATAW find; ! 58: HANDLE file; ! 59: DWORD read; ! 60: ! 61: if (LanguageFileFindHandle == INVALID_HANDLE_VALUE) ! 62: { ! 63: GetModuleFileNameW (NULL, f, sizeof (f)); ! 64: t = wcsrchr (f, L'\\'); ! 65: if (t == NULL) return NULL; ! 66: ! 67: wcscpy (t, L"\\Language*.xml"); ! 68: ! 69: LanguageFileFindHandle = FindFirstFileW (f, &find); ! 70: } ! 71: else if (!FindNextFileW (LanguageFileFindHandle, &find)) ! 72: { ! 73: FindClose (LanguageFileFindHandle); ! 74: LanguageFileFindHandle = INVALID_HANDLE_VALUE; ! 75: return NULL; ! 76: } ! 77: ! 78: if (find.nFileSizeHigh != 0) return NULL; ! 79: ! 80: if (LanguageFileBuffer != NULL) free (LanguageFileBuffer); ! 81: LanguageFileBuffer = malloc(find.nFileSizeLow); ! 82: if (LanguageFileBuffer == NULL) return NULL; ! 83: ! 84: GetModuleFileNameW (NULL, f, sizeof (f)); ! 85: t = wcsrchr (f, L'\\'); ! 86: wcscpy (t + 1, find.cFileName); ! 87: ! 88: file = CreateFileW (f, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL); ! 89: if (file == INVALID_HANDLE_VALUE) return NULL; ! 90: ! 91: ReadFile (file, LanguageFileBuffer, find.nFileSizeLow, &read, NULL); ! 92: CloseHandle (file); ! 93: if (read != find.nFileSizeLow) return NULL; ! 94: ! 95: return LanguageFileBuffer; ! 96: } ! 97: ! 98: ! 99: BOOL LoadLanguageFile () ! 100: { ! 101: DWORD size; ! 102: BYTE *res; ! 103: char *xml, *header; ! 104: char langId[6] = "en", attr[2048], key[128]; ! 105: BOOL defaultLangParsed = FALSE, langFound = FALSE; ! 106: WCHAR wattr[2048]; ! 107: int i, intKey, len; ! 108: ! 109: char *xmlElements[] = {"control", "string", 0}; ! 110: ! 111: #ifdef TCMOUNT ! 112: int headers[] = { IDR_COMMON_RSRC_HEADER, IDR_MOUNT_RSRC_HEADER, 0 }; ! 113: #endif ! 114: ! 115: #ifdef VOLFORMAT ! 116: int headers[] = { IDR_COMMON_RSRC_HEADER, IDR_FORMAT_RSRC_HEADER, 0 }; ! 117: #endif ! 118: ! 119: #ifdef SETUP ! 120: int headers[] = { IDR_COMMON_RSRC_HEADER, IDR_SETUP_RSRC_HEADER, 0 }; ! 121: #endif ! 122: ! 123: LocalizationActive = FALSE; ! 124: ClearDictionaryPool (); ! 125: ! 126: if (PreferredLangId[0] != 0) ! 127: strcpy (langId, PreferredLangId); ! 128: ! 129: // Parse all available language files until preferred language is found ! 130: for (res = MapFirstLanguageFile (); res != NULL; res = MapNextLanguageFile ()) ! 131: { ! 132: xml = (char *) res; ! 133: xml = XmlFindElement (xml, "localization"); ! 134: // Required TrueCrypt version ! 135: XmlAttribute (xml, "prog-version", attr, sizeof (attr)); ! 136: ! 137: // Check version of external language file ! 138: if (defaultLangParsed && strcmp (attr, VERSION_STRING)) ! 139: { ! 140: wchar_t m[1024]; ! 141: swprintf (m, L"The installed language pack is incompatible with this version of TrueCrypt\n(this language pack is for TrueCrypt %hs).\n\nA newer version may be available at www.truecrypt.org.\n\nTo prevent this message from being displayed, do any of the following:\n- Update the language pack\n- Remove the language pack file from the TrueCrypt folder", attr); ! 142: MessageBoxW (NULL, m, L"TrueCrypt", MB_ICONERROR); ! 143: continue; ! 144: } ! 145: ! 146: // Search language id in language file ! 147: if (defaultLangParsed) ! 148: { ! 149: while (xml = XmlFindElement (xml, "language")) ! 150: { ! 151: XmlAttribute (xml++, "langid", attr, sizeof (attr)); ! 152: if (strcmp (attr, langId) == 0) ! 153: { ! 154: langFound = TRUE; ! 155: break; ! 156: } ! 157: } ! 158: ! 159: if (!langFound) continue; ! 160: } ! 161: ! 162: // Create font dictionary ! 163: xml = (char *) res; ! 164: while (xml = XmlFindElement (xml, "font")) ! 165: { ! 166: XmlAttribute (xml, "lang", attr, sizeof (attr)); ! 167: if (!defaultLangParsed ! 168: || strcmp (attr, langId) == 0) ! 169: { ! 170: Font font; ! 171: ! 172: XmlAttribute (xml, "face", attr, sizeof (attr)); ! 173: ! 174: len = MultiByteToWideChar (CP_UTF8, 0, attr, -1, wattr, sizeof (wattr)); ! 175: font.FaceName = AddPoolData ((void *) wattr, len * 2); ! 176: ! 177: XmlAttribute (xml, "size", attr, sizeof (attr)); ! 178: sscanf (attr, "%d", &font.Size); ! 179: ! 180: strcpy (attr, "font_"); ! 181: XmlAttribute (xml, "class", attr + 5, sizeof (attr) - 5); ! 182: AddDictionaryEntry (AddPoolData ((void *) attr, sizeof (attr)), 0, ! 183: AddPoolData ((void *) &font, sizeof(font))); ! 184: } ! 185: ! 186: xml++; ! 187: } ! 188: ! 189: // Create string and control dictionaries ! 190: for (i = 0; xmlElements[i] != 0; i++) ! 191: { ! 192: xml = (char *) res; ! 193: while (xml = XmlFindElement (xml, xmlElements[i])) ! 194: { ! 195: void *key; ! 196: void *text; ! 197: ! 198: XmlAttribute (xml, "lang", attr, sizeof (attr)); ! 199: if (!defaultLangParsed ! 200: || strcmp (attr, langId) == 0) ! 201: { ! 202: if (XmlAttribute (xml, "key", attr, sizeof (attr))) ! 203: { ! 204: key = AddPoolData (attr, strlen (attr) + 1); ! 205: if (key == NULL) return FALSE; ! 206: ! 207: XmlNodeText (xml, attr, sizeof (attr)); ! 208: ! 209: // Parse \ escape sequences ! 210: { ! 211: char *in = attr, *out = attr; ! 212: while (*in) ! 213: { ! 214: if (*in == '\\') ! 215: { ! 216: in++; ! 217: switch (*in++) ! 218: { ! 219: case '\\': *out++ = '\\'; break; ! 220: case 't': *out++ = '\t'; break; ! 221: case 'n': *out++ = 13; *out++ = 10; break; ! 222: default: ! 223: MessageBox (0, key, "TrueCrypt: Unknown '\\' escape sequence in string", MB_ICONERROR); ! 224: return FALSE; ! 225: } ! 226: } ! 227: else ! 228: *out++ = *in++; ! 229: } ! 230: *out = 0; ! 231: } ! 232: ! 233: // UTF8 => wide char ! 234: len = MultiByteToWideChar (CP_UTF8, 0, attr, -1, wattr, sizeof (wattr)); ! 235: if (len == 0 || len == ERROR_NO_UNICODE_TRANSLATION) ! 236: { ! 237: MessageBox (0, key, "TrueCrypt: Error while decoding UTF-8 string", MB_ICONERROR); ! 238: return FALSE; ! 239: } ! 240: ! 241: // Add to dictionary ! 242: text = AddPoolData ((void *) wattr, len * 2); ! 243: if (text == NULL) return FALSE; ! 244: ! 245: AddDictionaryEntry ((char *) key, 0, text); ! 246: } ! 247: } ! 248: ! 249: xml++; ! 250: } ! 251: } ! 252: ! 253: if (langFound) ! 254: break; ! 255: ! 256: if (!defaultLangParsed) ! 257: { ! 258: defaultLangParsed = TRUE; ! 259: if (langId[0] == 0 || strcmp (langId, "en") == 0) ! 260: break; ! 261: } ! 262: } ! 263: ! 264: LocalizationActive = langFound && strcmp (langId, "en") != 0; ! 265: LocalizationSerialNo++; ! 266: ! 267: // Create control ID dictionary ! 268: ! 269: // Default controls ! 270: AddDictionaryEntry (NULL, 1, GetString ("IDOK")); ! 271: AddDictionaryEntry (NULL, 2, GetString ("IDCANCEL")); ! 272: AddDictionaryEntry (NULL, 8, GetString ("IDCLOSE")); ! 273: AddDictionaryEntry (NULL, 9, GetString ("IDHELP")); ! 274: ! 275: for (i = 0; headers[i] != 0; i++) ! 276: { ! 277: if (HeaderResource[i] == NULL) ! 278: HeaderResource[i] = MapResource ("Header", headers[i], &size); ! 279: ! 280: header = HeaderResource[i]; ! 281: if (header == NULL) return FALSE; ! 282: ! 283: do ! 284: { ! 285: if (sscanf (header, "#define %s %d", key, &intKey) == 2) ! 286: { ! 287: WCHAR *str = GetString (key); ! 288: ! 289: if (str != UnknownString) ! 290: AddDictionaryEntry (NULL, intKey, str); ! 291: } ! 292: ! 293: } while ((header = strchr (header, '\n') + 1) != (char *) 1); ! 294: } ! 295: ! 296: return TRUE; ! 297: } ! 298: ! 299: ! 300: // lParam = 1: auto mode ! 301: BOOL WINAPI LanguageDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) ! 302: { ! 303: WORD lw = LOWORD (wParam); ! 304: WORD hw = HIWORD (wParam); ! 305: ! 306: switch (msg) ! 307: { ! 308: case WM_INITDIALOG: ! 309: { ! 310: char *xml; ! 311: char attr[2048], lastLangId[10]; ! 312: WCHAR wattr[2048]; ! 313: int len; ! 314: int langCount = 0; ! 315: BOOL defaultLangFound = FALSE; ! 316: ! 317: LocalizeDialog (hwndDlg, "IDD_LANGUAGE"); ! 318: ! 319: SendMessage (GetDlgItem (hwndDlg, IDC_GET_LANG_PACKS), WM_SETFONT, (WPARAM) hUserUnderlineFont, 0); ! 320: ! 321: for (xml = MapFirstLanguageFile (); xml != NULL; xml = MapNextLanguageFile ()) ! 322: { ! 323: while (xml = XmlFindElement (xml, "language")) ! 324: { ! 325: XmlAttribute (xml, "name", attr, sizeof (attr)); ! 326: len = MultiByteToWideChar (CP_UTF8, 0, attr, -1, wattr, sizeof (wattr)); ! 327: ! 328: if (len != 0 && len != ERROR_NO_UNICODE_TRANSLATION ! 329: && (!defaultLangFound || wcscmp (wattr, L"English") != 0)) ! 330: { ! 331: int i = SendDlgItemMessageW (hwndDlg, IDC_LANGLIST, LB_ADDSTRING, 0, (LPARAM)wattr); ! 332: if (i >= 0) ! 333: { ! 334: int id; ! 335: ! 336: // Encode language id in LPARAM ! 337: XmlAttribute (xml, "langid", attr, sizeof (attr)); ! 338: switch (strlen (attr)) ! 339: { ! 340: case 2: id = attr[0] | attr[1] << 8; break; ! 341: case 5: id = attr[0] | attr[1] << 8 | attr[3] << 16 | attr[4] << 24; break; ! 342: default: continue; ! 343: } ! 344: ! 345: if (!defaultLangFound) ! 346: defaultLangFound = TRUE; ! 347: ! 348: SendDlgItemMessage (hwndDlg, IDC_LANGLIST, LB_SETITEMDATA, i, (LPARAM) id); ! 349: ! 350: if (strcmp (attr, PreferredLangId) == 0) ! 351: { ! 352: char credits [10000]; ! 353: WCHAR wcredits [10000]; ! 354: WCHAR wversion [20]; ! 355: wchar_t szVers [200]; ! 356: int nLen; ! 357: ! 358: SendDlgItemMessage (hwndDlg, IDC_LANGLIST, LB_SETCURSEL, i, 0); ! 359: ! 360: // Language pack version ! 361: XmlAttribute (xml, "version", ActiveLangPackVersion, sizeof (ActiveLangPackVersion)); ! 362: if (memcmp (ActiveLangPackVersion, "0.0.0", 5) == 0) ! 363: { ! 364: swprintf (szVers, GetString("LANG_PACK_VERSION"), L"--"); ! 365: } ! 366: else ! 367: { ! 368: nLen = MultiByteToWideChar (CP_UTF8, 0, ActiveLangPackVersion, -1, wversion, sizeof (ActiveLangPackVersion)); ! 369: if (nLen != 0 && nLen != ERROR_NO_UNICODE_TRANSLATION) ! 370: swprintf (szVers, GetString("LANG_PACK_VERSION"), wversion); ! 371: } ! 372: SetWindowTextW (GetDlgItem (hwndDlg, IDC_LANGPACK_VERSION), szVers); ! 373: ! 374: // Translator credits ! 375: XmlAttribute (xml, "translators", credits, sizeof (credits)); ! 376: nLen = MultiByteToWideChar (CP_UTF8, 0, credits, -1, wcredits, sizeof (wcredits)); ! 377: if (nLen != 0 && nLen != ERROR_NO_UNICODE_TRANSLATION) ! 378: { ! 379: SetWindowTextW (GetDlgItem (hwndDlg, IDC_LANGPACK_CREDITS), wcredits); ! 380: } ! 381: } ! 382: ! 383: strcpy (lastLangId, attr); ! 384: langCount++; ! 385: } ! 386: } ! 387: ! 388: xml++; ! 389: } ! 390: } ! 391: ! 392: if (lParam == 1) ! 393: { ! 394: // Auto mode ! 395: if (langCount < 2) ! 396: EndDialog (hwndDlg, IDCANCEL); ! 397: ! 398: if (langCount == 2) ! 399: { ! 400: strcpy (PreferredLangId, lastLangId); ! 401: EndDialog (hwndDlg, IDOK); ! 402: } ! 403: } ! 404: ! 405: return 1; ! 406: } ! 407: ! 408: ! 409: case WM_COMMAND: ! 410: ! 411: if (lw == IDOK || hw == LBN_DBLCLK) ! 412: { ! 413: int i = SendDlgItemMessage (hwndDlg, IDC_LANGLIST, LB_GETCURSEL, 0, 0); ! 414: ! 415: if (i >= 0) ! 416: { ! 417: int id = SendDlgItemMessage (hwndDlg, IDC_LANGLIST, LB_GETITEMDATA, i, 0); ! 418: ! 419: if (id != LB_ERR) ! 420: { ! 421: char l[6]; ! 422: ! 423: // Decode language id from LPARAM ! 424: l[0] = id; ! 425: l[1] = id >> 8; ! 426: l[2] = 0; ! 427: ! 428: if ((id & 0xffff0000) != 0) ! 429: { ! 430: l[2] = '-'; ! 431: l[3] = id >> 16; ! 432: l[4] = id >> 24; ! 433: l[5] = 0; ! 434: } ! 435: ! 436: if (SendDlgItemMessage (hwndDlg, IDC_LANGLIST, LB_GETCOUNT, 0, 0) > 1) ! 437: strcpy (PreferredLangId, l); ! 438: } ! 439: } ! 440: ! 441: EndDialog (hwndDlg, IDOK); ! 442: return 1; ! 443: } ! 444: ! 445: if (lw == IDCANCEL) ! 446: { ! 447: EndDialog (hwndDlg, lw); ! 448: return 1; ! 449: } ! 450: ! 451: if (lw == IDC_GET_LANG_PACKS) ! 452: { ! 453: char tmpstr [256]; ! 454: ! 455: ArrowWaitCursor (); ! 456: if (strlen(ActiveLangPackVersion) > 0 && strlen(PreferredLangId) > 0) ! 457: sprintf (tmpstr, "http://www.truecrypt.org/applink.php?version=%s&dest=localizations&langpackversion=%s&lang=%s", VERSION_STRING, ActiveLangPackVersion, PreferredLangId); ! 458: else ! 459: sprintf (tmpstr, "http://www.truecrypt.org/applink.php?version=%s&dest=localizations", VERSION_STRING); ! 460: ! 461: ShellExecute (NULL, "open", (LPCTSTR) tmpstr, NULL, NULL, SW_SHOWNORMAL); ! 462: Sleep (200); ! 463: NormalCursor (); ! 464: return 1; ! 465: } ! 466: return 0; ! 467: } ! 468: ! 469: return 0; ! 470: } ! 471: ! 472: ! 473: char *GetPreferredLangId () ! 474: { ! 475: return PreferredLangId; ! 476: } ! 477: ! 478: ! 479: void SetPreferredLangId (char *langId) ! 480: { ! 481: strncpy (PreferredLangId, langId, 5); ! 482: } ! 483: ! 484: ! 485: wchar_t *GetString (char *stringId) ! 486: { ! 487: WCHAR *str = (WCHAR *) GetDictionaryValue (stringId); ! 488: if (str != NULL) return str; ! 489: ! 490: wsprintfW (UnknownString, UNKNOWN_STRING_ID L"%hs" UNKNOWN_STRING_ID, stringId); ! 491: return UnknownString; ! 492: } ! 493: ! 494: ! 495: Font *GetFont (char *fontType) ! 496: { ! 497: return (Font *) GetDictionaryValue (fontType); ! 498: ! 499: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.