"Fossies" - the Fresh Open Source Software Archive

Member "VeraCrypt_1.24-Update6/src/Common/Language.c" (11 Mar 2020, 16141 Bytes) of package /linux/misc/VeraCrypt_1.24-Update6.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "Language.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 1.24-Update5_vs_1.24-Update6.

    1 /*
    2  Derived from source code of TrueCrypt 7.1a, which is
    3  Copyright (c) 2008-2012 TrueCrypt Developers Association and which is governed
    4  by the TrueCrypt License 3.0.
    5 
    6  Modifications and additions to the original source code (contained in this file)
    7  and all other portions of this file are Copyright (c) 2013-2017 IDRIX
    8  and are governed by the Apache License 2.0 the full text of which is
    9  contained in the file License.txt included in VeraCrypt binary and source
   10  code distribution packages.
   11 */
   12 
   13 #include "Language.h"
   14 #include "Dlgcode.h"
   15 #include "Dictionary.h"
   16 #include "Tcdefs.h"
   17 #include "Xml.h"
   18 
   19 #include "../Common/Resource.h"
   20 
   21 #ifdef TCMOUNT
   22 #include "../Mount/Resource.h"
   23 #endif
   24 
   25 #ifdef VOLFORMAT
   26 #include "../Format/Resource.h"
   27 #endif
   28 
   29 #ifdef SETUP
   30 #include "../Setup/Resource.h"
   31 #endif
   32 
   33 #include <Strsafe.h>
   34 
   35 BOOL LocalizationActive;
   36 int LocalizationSerialNo;
   37 
   38 wchar_t UnknownString[1024]  = {0};
   39 static char *LanguageFileBuffer = NULL;
   40 static HANDLE LanguageFileFindHandle = INVALID_HANDLE_VALUE;
   41 static char PreferredLangId[6] = {0};
   42 static char *LanguageResource = NULL;
   43 static DWORD LanguageResourceSize = 0;
   44 static char *HeaderResource[2] = {NULL, NULL};
   45 static DWORD HeaderResourceSize[2] = {0, 0};
   46 static char ActiveLangPackVersion[6] = {0};
   47 static int LanguageResourceId = 0;
   48 
   49 static char *MapFirstLanguageFile ()
   50 {
   51     if (LanguageFileFindHandle != INVALID_HANDLE_VALUE)
   52     {
   53         FindClose (LanguageFileFindHandle);
   54         LanguageFileFindHandle = INVALID_HANDLE_VALUE;
   55     }
   56 
   57     if (LanguageFileBuffer != NULL)
   58     {
   59         free (LanguageFileBuffer);
   60         LanguageFileBuffer = NULL;
   61     }
   62 
   63     LanguageResourceId = 0;
   64 
   65     if (LanguageResource == NULL)
   66     {
   67         DWORD size;
   68         LanguageResource = MapResource (L"Xml", IDR_LANGUAGE, &size);
   69         if (LanguageResource)
   70             LanguageResourceSize = size;
   71     }
   72 
   73     if (LanguageResource)
   74     {
   75         LanguageFileBuffer = malloc(LanguageResourceSize + 1);
   76         if (LanguageFileBuffer)
   77         {
   78             memcpy (LanguageFileBuffer, LanguageResource, LanguageResourceSize);
   79             LanguageFileBuffer[LanguageResourceSize] = 0;
   80         }
   81     }
   82 
   83     return LanguageFileBuffer;
   84 }
   85 
   86 
   87 static char *MapNextLanguageFile (int resourceid)
   88 {
   89     wchar_t f[TC_MAX_PATH*2], *t;
   90     WIN32_FIND_DATAW find;
   91     HANDLE file;
   92     DWORD read;
   93     BOOL bStatus;
   94 
   95     /* free memory here to avoid leaks */
   96     if (LanguageFileBuffer != NULL)
   97     {
   98         free (LanguageFileBuffer);
   99         LanguageFileBuffer = NULL;
  100     }
  101 
  102     if (resourceid == 0)
  103     {
  104         if (LanguageFileFindHandle == INVALID_HANDLE_VALUE)
  105         {
  106             GetModuleFileNameW (NULL, f, sizeof (f) / sizeof (f[0]));
  107             t = wcsrchr (f, L'\\');
  108             if (t == NULL) return NULL;
  109 
  110             *t = 0;
  111             StringCbCatW (f, sizeof(f), L"\\Languages\\Language*.xml");
  112 
  113             LanguageFileFindHandle = FindFirstFileW (f, &find);
  114         }
  115         else if (!FindNextFileW (LanguageFileFindHandle, &find))
  116         {
  117             FindClose (LanguageFileFindHandle);
  118             LanguageFileFindHandle = INVALID_HANDLE_VALUE;
  119             return NULL;
  120         }
  121 
  122         if (LanguageFileFindHandle == INVALID_HANDLE_VALUE) return NULL;
  123         if (find.nFileSizeHigh != 0) return NULL;
  124 
  125         LanguageFileBuffer = malloc(find.nFileSizeLow + 1);
  126         if (LanguageFileBuffer == NULL) return NULL;
  127 
  128         GetModuleFileNameW (NULL, f, sizeof (f) / sizeof(f[0]));
  129         t = wcsrchr (f, L'\\');
  130         if (t == NULL)
  131         {
  132             free(LanguageFileBuffer);
  133             LanguageFileBuffer = NULL;
  134             return NULL;
  135         }
  136 
  137         t[1] = 0;
  138         StringCbCatW (f, sizeof(f), L"Languages\\");
  139         StringCbCatW (f, sizeof(f),find.cFileName);
  140 
  141         file = CreateFileW (f, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
  142         if (file == INVALID_HANDLE_VALUE)
  143         {
  144             free(LanguageFileBuffer);
  145             LanguageFileBuffer = NULL;
  146             return NULL;
  147         }
  148 
  149         bStatus = ReadFile (file, LanguageFileBuffer, find.nFileSizeLow, &read, NULL);
  150         CloseHandle (file);
  151         if (!bStatus || (read != find.nFileSizeLow))
  152         {
  153             free(LanguageFileBuffer);
  154             LanguageFileBuffer = NULL;
  155             return NULL;
  156         }
  157 
  158         LanguageFileBuffer [find.nFileSizeLow] = 0; // we have allocated (find.nFileSizeLow + 1) bytes
  159     }
  160     else if (LanguageResourceId != resourceid)
  161     {
  162         DWORD size;
  163 
  164         LanguageResourceId = resourceid;
  165 
  166         LanguageResource = MapResource (L"Languages", LanguageResourceId, &size);
  167         if (LanguageResource)
  168             LanguageResourceSize = size;
  169 
  170         if (LanguageResource)
  171         {
  172             LanguageFileBuffer = malloc(LanguageResourceSize + 1);
  173             if (LanguageFileBuffer)
  174             {
  175                 memcpy (LanguageFileBuffer, LanguageResource, LanguageResourceSize);
  176                 LanguageFileBuffer[LanguageResourceSize] = 0;
  177             }
  178         }
  179     }
  180 
  181     return LanguageFileBuffer;
  182 }
  183 
  184 
  185 static BOOL LoadLanguageData (int resourceid, BOOL bForceSetPreferredLanguage, BOOL bForceSilent)
  186 {
  187     DWORD size;
  188     BYTE *res;
  189     char *xml, *header, *headerPtr;
  190     char langId[6] = "en", attr[32768], key[128];
  191     BOOL defaultLangParsed = FALSE, langFound = FALSE;
  192     WCHAR wattr[32768];
  193     int i, intKey, len;
  194 
  195     char *xmlElements[] = {"entry", 0};
  196 
  197 #ifdef TCMOUNT
  198     int headers[] = { IDR_COMMON_RSRC_HEADER, IDR_MOUNT_RSRC_HEADER, 0 };
  199 #endif
  200 
  201 #ifdef VOLFORMAT
  202     int headers[] = { IDR_COMMON_RSRC_HEADER, IDR_FORMAT_RSRC_HEADER, 0 };
  203 #endif
  204 
  205 #ifdef SETUP
  206     int headers[] = { IDR_COMMON_RSRC_HEADER, IDR_SETUP_RSRC_HEADER, 0 };
  207 #endif
  208 
  209     LocalizationActive = FALSE;
  210     ActiveLangPackVersion[0] = 0;
  211     ClearDictionaryPool ();
  212     LanguageResource = NULL;
  213 
  214     if ((resourceid == 0) && (PreferredLangId[0] != 0))
  215         StringCbCopyA (langId, sizeof(langId), PreferredLangId);
  216 
  217     // Parse all available language files until preferred language is found
  218     for (res = MapFirstLanguageFile (); res != NULL; res = MapNextLanguageFile (resourceid))
  219     {
  220         xml = (char *) res;
  221         xml = XmlFindElement (xml, "localization");
  222         if (!xml)
  223             continue;
  224 
  225         // Required TrueCrypt version
  226         XmlGetAttributeText (xml, "prog-version", attr, sizeof (attr));
  227 
  228         // Check version of external language file
  229         if (defaultLangParsed && strcmp (attr, VERSION_STRING VERSION_STRING_SUFFIX) && strcmp (attr, "DEBUG"))
  230         {
  231             wchar_t m[2048];
  232             StringCbPrintfW (m, sizeof(m), L"The installed language pack is incompatible with this version of VeraCrypt (the language pack is for VeraCrypt %hs). A newer version may be available at www.idrix.fr.\n\nTo prevent this message from being displayed, do any of the following:\n\n- Select 'Settings' > 'Language'; then select 'English' and click 'OK'.\n\n- Remove or replace the language pack with a compatible version (the language pack may reside e.g. in 'C:\\Program Files\\VeraCrypt' or '%%LOCALAPPDATA%%\\VirtualStore\\Program Files\\VeraCrypt', etc.)", attr);
  233             if (!bForceSilent)
  234                 MessageBoxW (NULL, m, L"VeraCrypt", MB_ICONERROR);
  235             continue;
  236         }
  237 
  238         // Search language id in language file
  239         if (defaultLangParsed)
  240         {
  241             while (xml = XmlFindElement (xml, "language"))
  242             {
  243                 XmlGetAttributeText (xml, "langid", attr, sizeof (attr));
  244                 if (resourceid == 0)
  245                 {
  246                     if (strcmp (attr, langId) == 0)
  247                     {
  248                         XmlGetAttributeText (xml++, "version", ActiveLangPackVersion, sizeof (ActiveLangPackVersion));
  249                         langFound = TRUE;
  250                         break;
  251                     }
  252                     xml++;
  253                 }
  254                 else
  255                 {
  256                     StringCbCopyA (langId, sizeof (langId), attr);
  257                     XmlGetAttributeText (xml++, "version", ActiveLangPackVersion, sizeof (ActiveLangPackVersion));
  258                     langFound = TRUE;
  259                     break;
  260                 }
  261             }
  262 
  263             if (!langFound) continue;
  264         }
  265 
  266         // Create font dictionary
  267         xml = (char *) res;
  268         while (xml = XmlFindElement (xml, "font"))
  269         {
  270             XmlGetAttributeText (xml, "lang", attr, sizeof (attr));
  271             if (!defaultLangParsed
  272                 || strcmp (attr, langId) == 0)
  273             {
  274                 Font font;
  275                 memset (&font, 0, sizeof (font));
  276 
  277                 XmlGetAttributeText (xml, "face", attr, sizeof (attr));
  278 
  279                 len = MultiByteToWideChar (CP_UTF8, 0, attr, -1, wattr, sizeof (wattr) / sizeof(wattr[0]));
  280                 font.FaceName = AddPoolData ((void *) wattr, len * 2);
  281 
  282                 XmlGetAttributeText (xml, "size", attr, sizeof (attr));
  283                 sscanf (attr, "%d", &font.Size);
  284 
  285                 StringCbCopyA (attr, sizeof(attr), "font_");
  286                 XmlGetAttributeText (xml, "class", attr + 5, sizeof (attr) - 5);
  287                 AddDictionaryEntry (
  288                     AddPoolData ((void *) attr, strlen (attr) + 1), 0,
  289                     AddPoolData ((void *) &font, sizeof(font)));
  290             }
  291 
  292             xml++;
  293         }
  294 
  295         // Create string and control dictionaries
  296         for (i = 0; xmlElements[i] != 0; i++)
  297         {
  298             xml = (char *) res;
  299             while (xml = XmlFindElement (xml, xmlElements[i]))
  300             {
  301                 void *key;
  302                 void *text;
  303 
  304                 XmlGetAttributeText (xml, "lang", attr, sizeof (attr));
  305                 if (!defaultLangParsed
  306                     || strcmp (attr, langId) == 0)
  307                 {
  308                     if (XmlGetAttributeText (xml, "key", attr, sizeof (attr)))
  309                     {
  310                         key = AddPoolData (attr, strlen (attr) + 1);
  311                         if (key == NULL) return FALSE;
  312 
  313                         XmlGetNodeText (xml, attr, sizeof (attr));
  314 
  315                         // Parse \ escape sequences
  316                         {
  317                             char *in = attr, *out = attr;
  318                             while (*in)
  319                             {
  320                                 if (*in == '\\')
  321                                 {
  322                                     in++;
  323                                     switch (*in++)
  324                                     {
  325                                     case '\\': *out++ = '\\'; break;
  326                                     case 't': *out++ = '\t'; break;
  327                                     case 'n': *out++ = 13; *out++ = 10; break;
  328                                     default:
  329                                         if (!bForceSilent)
  330                                             MessageBoxA (0, key, "VeraCrypt: Unknown '\\' escape sequence in string", MB_ICONERROR);
  331                                         return FALSE;
  332                                     }
  333                                 }
  334                                 else
  335                                     *out++ = *in++;
  336                             }
  337                             *out = 0;
  338                         }
  339 
  340                         // UTF8 => wide char
  341                         len = MultiByteToWideChar (CP_UTF8, 0, attr, -1, wattr, sizeof (wattr) / sizeof(wattr[0]));
  342                         if (len == 0)
  343                         {
  344                             if (!bForceSilent)
  345                                 MessageBoxA (0, key, "VeraCrypt: Error while decoding UTF-8 string", MB_ICONERROR);
  346                             return FALSE;
  347                         }
  348 
  349                         // Add to dictionary
  350                         text = AddPoolData ((void *) wattr, len * 2);
  351                         if (text == NULL) return FALSE;
  352 
  353                         AddDictionaryEntry ((char *) key, 0, text);
  354                     }
  355                 }
  356 
  357                 xml++;
  358             }
  359         }
  360 
  361         if (langFound)
  362             break;
  363 
  364         if (!defaultLangParsed)
  365         {
  366             defaultLangParsed = TRUE;
  367             if ((resourceid == 0) && (langId[0] == 0 || strcmp (langId, "en") == 0))
  368                 break;
  369         }
  370     }
  371 
  372     LocalizationActive = langFound && strcmp (langId, "en") != 0;
  373     LocalizationSerialNo++;
  374 
  375     if (bForceSetPreferredLanguage)
  376         StringCbCopyA (PreferredLangId, sizeof (PreferredLangId), langId);
  377 
  378     // Create control ID dictionary
  379 
  380     // Default controls
  381     AddDictionaryEntry (NULL, 1, GetString ("IDOK"));
  382     AddDictionaryEntry (NULL, 2, GetString ("IDCANCEL"));
  383     AddDictionaryEntry (NULL, 8, GetString ("IDCLOSE"));
  384     AddDictionaryEntry (NULL, 9, GetString ("IDHELP"));
  385 
  386     for (i = 0; headers[i] != 0; i++)
  387     {
  388         if (HeaderResource[i] == NULL)
  389         {
  390             HeaderResource[i] = MapResource (L"Header", headers[i], &size);
  391             if (HeaderResource[i])
  392                 HeaderResourceSize[i] = size;
  393         }
  394 
  395         headerPtr = NULL;
  396         if (HeaderResource[i])
  397         {
  398             headerPtr = (char*) malloc (HeaderResourceSize[i] + 1);
  399             if (headerPtr)
  400             {
  401                 memcpy (headerPtr, HeaderResource[i], HeaderResourceSize[i]);
  402                 headerPtr [HeaderResourceSize[i]] = 0;
  403             }
  404         }
  405 
  406         header = headerPtr;
  407         if (header == NULL) return FALSE;
  408         header--;
  409 
  410         do
  411         {
  412             header++;
  413             if (sscanf (header, "#define %127s %d", key, &intKey) == 2)
  414             {
  415                 WCHAR *str = GetString (key);
  416 
  417                 if (str != UnknownString)
  418                     AddDictionaryEntry (NULL, intKey, str);
  419             }
  420 
  421         } while ((header = strchr (header, '\n')) != NULL);
  422 
  423         free (headerPtr);
  424     }
  425 
  426     return TRUE;
  427 }
  428 
  429 BOOL LoadLanguageFile ()
  430 {
  431     return LoadLanguageData (0, FALSE, FALSE);
  432 }
  433 
  434 BOOL LoadLanguageFromResource (int resourceid, BOOL bSetPreferredLanguage, BOOL bForceSilent)
  435 {
  436     return LoadLanguageData (resourceid, bSetPreferredLanguage, bForceSilent);
  437 }
  438 
  439 // lParam = 1: auto mode
  440 BOOL CALLBACK LanguageDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
  441 {
  442     WORD lw = LOWORD (wParam);
  443     WORD hw = HIWORD (wParam);
  444 
  445     switch (msg)
  446     {
  447     case WM_INITDIALOG:
  448         {
  449             char *xml;
  450             char attr[2048], lastLangId[10];
  451             WCHAR wattr[2048];
  452             int len;
  453             int langCount = 0;
  454             BOOL defaultLangFound = FALSE;
  455 
  456             LocalizeDialog (hwndDlg, "IDD_LANGUAGE");
  457             ToHyperlink (hwndDlg, IDC_GET_LANG_PACKS);
  458 
  459             for (xml = MapFirstLanguageFile (); xml != NULL; xml = MapNextLanguageFile (0))
  460             {
  461                 while (xml = XmlFindElement (xml, "language"))
  462                 {
  463                     XmlGetAttributeText (xml, "name", attr, sizeof (attr));
  464                     len = MultiByteToWideChar (CP_UTF8, 0, attr, -1, wattr, sizeof (wattr) / sizeof(wattr[0]));
  465 
  466                     if (len != 0
  467                         && (!defaultLangFound || wcscmp (wattr, L"English") != 0))
  468                     {
  469                         int i = (int) SendDlgItemMessageW (hwndDlg, IDC_LANGLIST, LB_ADDSTRING, 0, (LPARAM)wattr);
  470                         if (i >= 0)
  471                         {
  472                             int id;
  473 
  474                             // Encode language id in LPARAM
  475                             XmlGetAttributeText (xml, "langid", attr, sizeof (attr));
  476                             switch (strlen (attr))
  477                             {
  478                             case 2: id = attr[0] | attr[1] << 8; break;
  479                             case 5: id = attr[0] | attr[1] << 8 | attr[3] << 16 | attr[4] << 24; break;
  480                             default: continue;
  481                             }
  482 
  483                             if (!defaultLangFound)
  484                                 defaultLangFound = TRUE;
  485 
  486                             SendDlgItemMessage (hwndDlg, IDC_LANGLIST, LB_SETITEMDATA, i, (LPARAM) id);
  487 
  488                             if (strcmp (attr, PreferredLangId) == 0)
  489                             {
  490                                 char credits [10000];
  491                                 WCHAR wcredits [10000];
  492                                 WCHAR wversion [20];
  493                                 wchar_t szVers [200];
  494                                 int nLen;
  495 
  496                                 SendDlgItemMessage (hwndDlg, IDC_LANGLIST, LB_SETCURSEL, i, 0);
  497 
  498                                 // Language pack version
  499                                 if (!ActiveLangPackVersion[0] || memcmp (ActiveLangPackVersion, "0.0.0", 5) == 0)
  500                                 {
  501                                     StringCbPrintfW (szVers, sizeof(szVers), GetString("LANG_PACK_VERSION"), L"--");
  502                                 }
  503                                 else
  504                                 {
  505                                     nLen = MultiByteToWideChar (CP_UTF8, 0, ActiveLangPackVersion, -1, wversion, sizeof (wversion) / sizeof(wversion[0]));
  506                                     if (nLen != 0)
  507                                         StringCbPrintfW (szVers, sizeof(szVers),GetString("LANG_PACK_VERSION"), wversion);
  508                                 }
  509                                 SetWindowTextW (GetDlgItem (hwndDlg, IDC_LANGPACK_VERSION), szVers);
  510 
  511                                 // Translator credits
  512                                 XmlGetAttributeText (xml, "translators", credits, sizeof (credits));
  513                                 nLen = MultiByteToWideChar (CP_UTF8, 0, credits, -1, wcredits, sizeof (wcredits) / sizeof(wcredits[0]));
  514                                 if (nLen != 0)
  515                                 {
  516                                     SetWindowTextW (GetDlgItem (hwndDlg, IDC_LANGPACK_CREDITS), wcredits);
  517                                 }
  518                             }
  519 
  520                             StringCbCopyA (lastLangId, sizeof(lastLangId),attr);
  521                             langCount++;
  522                         }
  523                     }
  524 
  525                     xml++;
  526                 }
  527             }
  528 
  529             if (lParam == 1)
  530             {
  531                 // Auto mode
  532                 if (langCount < 2)
  533                     EndDialog (hwndDlg, IDCANCEL);
  534 
  535                 if (langCount == 2)
  536                     StringCbCopyA (PreferredLangId, sizeof(PreferredLangId), lastLangId);
  537 
  538                 EndDialog (hwndDlg, IDOK);
  539             }
  540 
  541             return 1;
  542         }
  543 
  544     case WM_COMMAND:
  545 
  546         if (lw == IDOK || hw == LBN_DBLCLK)
  547         {
  548             int i = (int) SendDlgItemMessage (hwndDlg, IDC_LANGLIST, LB_GETCURSEL, 0, 0);
  549 
  550             if (i >= 0)
  551             {
  552                 int id = (int) SendDlgItemMessage (hwndDlg, IDC_LANGLIST, LB_GETITEMDATA, i, 0);
  553 
  554                 if (id != LB_ERR)
  555                 {
  556                     char l[6];
  557 
  558                     // Decode language id from LPARAM
  559                     l[0] = (char) id;
  560                     l[1] = (char) (id >> 8);
  561                     l[2] = 0;
  562 
  563                     if ((id & 0xffff0000) != 0)
  564                     {
  565                         l[2] = '-';
  566                         l[3] = (char) (id >> 16);
  567                         l[4] = id >> 24;
  568                         l[5] = 0;
  569                     }
  570 
  571                     if (SendDlgItemMessage (hwndDlg, IDC_LANGLIST, LB_GETCOUNT, 0, 0) > 1)
  572                         StringCbCopyA (PreferredLangId, sizeof(PreferredLangId), l);
  573                 }
  574             }
  575 
  576             EndDialog (hwndDlg, IDOK);
  577             return 1;
  578         }
  579 
  580         if (lw == IDCANCEL)
  581         {
  582             EndDialog (hwndDlg, lw);
  583             return 1;
  584         }
  585 
  586         if (lw == IDC_GET_LANG_PACKS)
  587         {
  588             char tmpstr [256];
  589 
  590             if (strlen (ActiveLangPackVersion) > 0 && strlen (GetPreferredLangId()) > 0)
  591                 StringCbPrintfA (tmpstr, sizeof(tmpstr), "&langpackversion=%s&lang=%s", ActiveLangPackVersion, GetPreferredLangId());
  592             else
  593                 tmpstr[0] = 0;
  594 
  595             Applink ("localizations");
  596 
  597             return 1;
  598         }
  599         return 0;
  600     }
  601 
  602     return 0;
  603 }
  604 
  605 
  606 char *GetPreferredLangId ()
  607 {
  608     return PreferredLangId;
  609 }
  610 
  611 
  612 void SetPreferredLangId (char *langId)
  613 {
  614     StringCbCopyA (PreferredLangId, sizeof(PreferredLangId), langId);
  615 }
  616 
  617 
  618 char *GetActiveLangPackVersion ()
  619 {
  620     return ActiveLangPackVersion;
  621 }
  622 
  623 
  624 wchar_t *GetString (const char *stringId)
  625 {
  626     WCHAR *str = (WCHAR *) GetDictionaryValue (stringId);
  627     if (str != NULL) return str;
  628 
  629     StringCbPrintfW (UnknownString, sizeof(UnknownString), UNKNOWN_STRING_ID L"%hs" UNKNOWN_STRING_ID, stringId);
  630     return UnknownString;
  631 }
  632 
  633 
  634 Font *GetFont (char *fontType)
  635 {
  636     return (Font *) GetDictionaryValue (fontType);
  637 
  638 }