"Fossies" - the Fresh Open Source Software Archive

Member "src/Common/Language.c" (10 Oct 2018, 16093 Bytes) of package /windows/misc/VeraCrypt_1.23-Hotfix-2_Source.zip:


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 last Fossies "Diffs" side-by-side code changes report: 1.22_Source_vs_1.23_Source.

    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 
  213     if ((resourceid == 0) && (PreferredLangId[0] != 0))
  214         StringCbCopyA (langId, sizeof(langId), PreferredLangId);
  215 
  216     // Parse all available language files until preferred language is found
  217     for (res = MapFirstLanguageFile (); res != NULL; res = MapNextLanguageFile (resourceid))
  218     {
  219         xml = (char *) res;
  220         xml = XmlFindElement (xml, "localization");
  221         if (!xml)
  222             continue;
  223 
  224         // Required TrueCrypt version
  225         XmlGetAttributeText (xml, "prog-version", attr, sizeof (attr));
  226 
  227         // Check version of external language file
  228         if (defaultLangParsed && strcmp (attr, VERSION_STRING) && strcmp (attr, "DEBUG"))
  229         {
  230             wchar_t m[2048];
  231             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);
  232             if (!bForceSilent)
  233                 MessageBoxW (NULL, m, L"VeraCrypt", MB_ICONERROR);
  234             continue;
  235         }
  236 
  237         // Search language id in language file
  238         if (defaultLangParsed)
  239         {
  240             while (xml = XmlFindElement (xml, "language"))
  241             {
  242                 XmlGetAttributeText (xml, "langid", attr, sizeof (attr));
  243                 if (resourceid == 0)
  244                 {
  245                     if (strcmp (attr, langId) == 0)
  246                     {
  247                         XmlGetAttributeText (xml++, "version", ActiveLangPackVersion, sizeof (ActiveLangPackVersion));
  248                         langFound = TRUE;
  249                         break;
  250                     }
  251                     xml++;
  252                 }
  253                 else
  254                 {
  255                     StringCbCopyA (langId, sizeof (langId), attr);
  256                     XmlGetAttributeText (xml++, "version", ActiveLangPackVersion, sizeof (ActiveLangPackVersion));
  257                     langFound = TRUE;
  258                     break;
  259                 }
  260             }
  261 
  262             if (!langFound) continue;
  263         }
  264 
  265         // Create font dictionary
  266         xml = (char *) res;
  267         while (xml = XmlFindElement (xml, "font"))
  268         {
  269             XmlGetAttributeText (xml, "lang", attr, sizeof (attr));
  270             if (!defaultLangParsed
  271                 || strcmp (attr, langId) == 0)
  272             {
  273                 Font font;
  274                 memset (&font, 0, sizeof (font));
  275 
  276                 XmlGetAttributeText (xml, "face", attr, sizeof (attr));
  277 
  278                 len = MultiByteToWideChar (CP_UTF8, 0, attr, -1, wattr, sizeof (wattr) / sizeof(wattr[0]));
  279                 font.FaceName = AddPoolData ((void *) wattr, len * 2);
  280 
  281                 XmlGetAttributeText (xml, "size", attr, sizeof (attr));
  282                 sscanf (attr, "%d", &font.Size);
  283 
  284                 StringCbCopyA (attr, sizeof(attr), "font_");
  285                 XmlGetAttributeText (xml, "class", attr + 5, sizeof (attr) - 5);
  286                 AddDictionaryEntry (
  287                     AddPoolData ((void *) attr, strlen (attr) + 1), 0,
  288                     AddPoolData ((void *) &font, sizeof(font)));
  289             }
  290 
  291             xml++;
  292         }
  293 
  294         // Create string and control dictionaries
  295         for (i = 0; xmlElements[i] != 0; i++)
  296         {
  297             xml = (char *) res;
  298             while (xml = XmlFindElement (xml, xmlElements[i]))
  299             {
  300                 void *key;
  301                 void *text;
  302 
  303                 XmlGetAttributeText (xml, "lang", attr, sizeof (attr));
  304                 if (!defaultLangParsed
  305                     || strcmp (attr, langId) == 0)
  306                 {
  307                     if (XmlGetAttributeText (xml, "key", attr, sizeof (attr)))
  308                     {
  309                         key = AddPoolData (attr, strlen (attr) + 1);
  310                         if (key == NULL) return FALSE;
  311 
  312                         XmlGetNodeText (xml, attr, sizeof (attr));
  313 
  314                         // Parse \ escape sequences
  315                         {
  316                             char *in = attr, *out = attr;
  317                             while (*in)
  318                             {
  319                                 if (*in == '\\')
  320                                 {
  321                                     in++;
  322                                     switch (*in++)
  323                                     {
  324                                     case '\\': *out++ = '\\'; break;
  325                                     case 't': *out++ = '\t'; break;
  326                                     case 'n': *out++ = 13; *out++ = 10; break;
  327                                     default:
  328                                         if (!bForceSilent)
  329                                             MessageBoxA (0, key, "VeraCrypt: Unknown '\\' escape sequence in string", MB_ICONERROR);
  330                                         return FALSE;
  331                                     }
  332                                 }
  333                                 else
  334                                     *out++ = *in++;
  335                             }
  336                             *out = 0;
  337                         }
  338 
  339                         // UTF8 => wide char
  340                         len = MultiByteToWideChar (CP_UTF8, 0, attr, -1, wattr, sizeof (wattr) / sizeof(wattr[0]));
  341                         if (len == 0)
  342                         {
  343                             if (!bForceSilent)
  344                                 MessageBoxA (0, key, "VeraCrypt: Error while decoding UTF-8 string", MB_ICONERROR);
  345                             return FALSE;
  346                         }
  347 
  348                         // Add to dictionary
  349                         text = AddPoolData ((void *) wattr, len * 2);
  350                         if (text == NULL) return FALSE;
  351 
  352                         AddDictionaryEntry ((char *) key, 0, text);
  353                     }
  354                 }
  355 
  356                 xml++;
  357             }
  358         }
  359 
  360         if (langFound)
  361             break;
  362 
  363         if (!defaultLangParsed)
  364         {
  365             defaultLangParsed = TRUE;
  366             if ((resourceid == 0) && (langId[0] == 0 || strcmp (langId, "en") == 0))
  367                 break;
  368         }
  369     }
  370 
  371     LocalizationActive = langFound && strcmp (langId, "en") != 0;
  372     LocalizationSerialNo++;
  373 
  374     if (bForceSetPreferredLanguage)
  375         StringCbCopyA (PreferredLangId, sizeof (PreferredLangId), langId);
  376 
  377     // Create control ID dictionary
  378 
  379     // Default controls
  380     AddDictionaryEntry (NULL, 1, GetString ("IDOK"));
  381     AddDictionaryEntry (NULL, 2, GetString ("IDCANCEL"));
  382     AddDictionaryEntry (NULL, 8, GetString ("IDCLOSE"));
  383     AddDictionaryEntry (NULL, 9, GetString ("IDHELP"));
  384 
  385     for (i = 0; headers[i] != 0; i++)
  386     {
  387         if (HeaderResource[i] == NULL)
  388         {
  389             HeaderResource[i] = MapResource (L"Header", headers[i], &size);
  390             if (HeaderResource[i])
  391                 HeaderResourceSize[i] = size;
  392         }
  393 
  394         headerPtr = NULL;
  395         if (HeaderResource[i])
  396         {
  397             headerPtr = (char*) malloc (HeaderResourceSize[i] + 1);
  398             if (headerPtr)
  399             {
  400                 memcpy (headerPtr, HeaderResource[i], HeaderResourceSize[i]);
  401                 headerPtr [HeaderResourceSize[i]] = 0;
  402             }
  403         }
  404 
  405         header = headerPtr;
  406         if (header == NULL) return FALSE;
  407         header--;
  408 
  409         do
  410         {
  411             header++;
  412             if (sscanf (header, "#define %127s %d", key, &intKey) == 2)
  413             {
  414                 WCHAR *str = GetString (key);
  415 
  416                 if (str != UnknownString)
  417                     AddDictionaryEntry (NULL, intKey, str);
  418             }
  419 
  420         } while ((header = strchr (header, '\n')) != NULL);
  421 
  422         free (headerPtr);
  423     }
  424 
  425     return TRUE;
  426 }
  427 
  428 BOOL LoadLanguageFile ()
  429 {
  430     return LoadLanguageData (0, FALSE, FALSE);
  431 }
  432 
  433 BOOL LoadLanguageFromResource (int resourceid, BOOL bSetPreferredLanguage, BOOL bForceSilent)
  434 {
  435     return LoadLanguageData (resourceid, bSetPreferredLanguage, bForceSilent);
  436 }
  437 
  438 // lParam = 1: auto mode
  439 BOOL CALLBACK LanguageDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
  440 {
  441     WORD lw = LOWORD (wParam);
  442     WORD hw = HIWORD (wParam);
  443 
  444     switch (msg)
  445     {
  446     case WM_INITDIALOG:
  447         {
  448             char *xml;
  449             char attr[2048], lastLangId[10];
  450             WCHAR wattr[2048];
  451             int len;
  452             int langCount = 0;
  453             BOOL defaultLangFound = FALSE;
  454 
  455             LocalizeDialog (hwndDlg, "IDD_LANGUAGE");
  456             ToHyperlink (hwndDlg, IDC_GET_LANG_PACKS);
  457 
  458             for (xml = MapFirstLanguageFile (); xml != NULL; xml = MapNextLanguageFile (0))
  459             {
  460                 while (xml = XmlFindElement (xml, "language"))
  461                 {
  462                     XmlGetAttributeText (xml, "name", attr, sizeof (attr));
  463                     len = MultiByteToWideChar (CP_UTF8, 0, attr, -1, wattr, sizeof (wattr) / sizeof(wattr[0]));
  464 
  465                     if (len != 0
  466                         && (!defaultLangFound || wcscmp (wattr, L"English") != 0))
  467                     {
  468                         int i = (int) SendDlgItemMessageW (hwndDlg, IDC_LANGLIST, LB_ADDSTRING, 0, (LPARAM)wattr);
  469                         if (i >= 0)
  470                         {
  471                             int id;
  472 
  473                             // Encode language id in LPARAM
  474                             XmlGetAttributeText (xml, "langid", attr, sizeof (attr));
  475                             switch (strlen (attr))
  476                             {
  477                             case 2: id = attr[0] | attr[1] << 8; break;
  478                             case 5: id = attr[0] | attr[1] << 8 | attr[3] << 16 | attr[4] << 24; break;
  479                             default: continue;
  480                             }
  481 
  482                             if (!defaultLangFound)
  483                                 defaultLangFound = TRUE;
  484 
  485                             SendDlgItemMessage (hwndDlg, IDC_LANGLIST, LB_SETITEMDATA, i, (LPARAM) id);
  486 
  487                             if (strcmp (attr, PreferredLangId) == 0)
  488                             {
  489                                 char credits [10000];
  490                                 WCHAR wcredits [10000];
  491                                 WCHAR wversion [20];
  492                                 wchar_t szVers [200];
  493                                 int nLen;
  494 
  495                                 SendDlgItemMessage (hwndDlg, IDC_LANGLIST, LB_SETCURSEL, i, 0);
  496 
  497                                 // Language pack version
  498                                 if (!ActiveLangPackVersion[0] || memcmp (ActiveLangPackVersion, "0.0.0", 5) == 0)
  499                                 {
  500                                     StringCbPrintfW (szVers, sizeof(szVers), GetString("LANG_PACK_VERSION"), L"--");
  501                                 }
  502                                 else
  503                                 {
  504                                     nLen = MultiByteToWideChar (CP_UTF8, 0, ActiveLangPackVersion, -1, wversion, sizeof (wversion) / sizeof(wversion[0]));
  505                                     if (nLen != 0)
  506                                         StringCbPrintfW (szVers, sizeof(szVers),GetString("LANG_PACK_VERSION"), wversion);
  507                                 }
  508                                 SetWindowTextW (GetDlgItem (hwndDlg, IDC_LANGPACK_VERSION), szVers);
  509 
  510                                 // Translator credits
  511                                 XmlGetAttributeText (xml, "translators", credits, sizeof (credits));
  512                                 nLen = MultiByteToWideChar (CP_UTF8, 0, credits, -1, wcredits, sizeof (wcredits) / sizeof(wcredits[0]));
  513                                 if (nLen != 0)
  514                                 {
  515                                     SetWindowTextW (GetDlgItem (hwndDlg, IDC_LANGPACK_CREDITS), wcredits);
  516                                 }
  517                             }
  518 
  519                             StringCbCopyA (lastLangId, sizeof(lastLangId),attr);
  520                             langCount++;
  521                         }
  522                     }
  523 
  524                     xml++;
  525                 }
  526             }
  527 
  528             if (lParam == 1)
  529             {
  530                 // Auto mode
  531                 if (langCount < 2)
  532                     EndDialog (hwndDlg, IDCANCEL);
  533 
  534                 if (langCount == 2)
  535                     StringCbCopyA (PreferredLangId, sizeof(PreferredLangId), lastLangId);
  536 
  537                 EndDialog (hwndDlg, IDOK);
  538             }
  539 
  540             return 1;
  541         }
  542 
  543     case WM_COMMAND:
  544 
  545         if (lw == IDOK || hw == LBN_DBLCLK)
  546         {
  547             int i = (int) SendDlgItemMessage (hwndDlg, IDC_LANGLIST, LB_GETCURSEL, 0, 0);
  548 
  549             if (i >= 0)
  550             {
  551                 int id = (int) SendDlgItemMessage (hwndDlg, IDC_LANGLIST, LB_GETITEMDATA, i, 0);
  552 
  553                 if (id != LB_ERR)
  554                 {
  555                     char l[6];
  556 
  557                     // Decode language id from LPARAM
  558                     l[0] = (char) id;
  559                     l[1] = (char) (id >> 8);
  560                     l[2] = 0;
  561 
  562                     if ((id & 0xffff0000) != 0)
  563                     {
  564                         l[2] = '-';
  565                         l[3] = (char) (id >> 16);
  566                         l[4] = id >> 24;
  567                         l[5] = 0;
  568                     }
  569 
  570                     if (SendDlgItemMessage (hwndDlg, IDC_LANGLIST, LB_GETCOUNT, 0, 0) > 1)
  571                         StringCbCopyA (PreferredLangId, sizeof(PreferredLangId), l);
  572                 }
  573             }
  574 
  575             EndDialog (hwndDlg, IDOK);
  576             return 1;
  577         }
  578 
  579         if (lw == IDCANCEL)
  580         {
  581             EndDialog (hwndDlg, lw);
  582             return 1;
  583         }
  584 
  585         if (lw == IDC_GET_LANG_PACKS)
  586         {
  587             char tmpstr [256];
  588 
  589             if (strlen (ActiveLangPackVersion) > 0 && strlen (GetPreferredLangId()) > 0)
  590                 StringCbPrintfA (tmpstr, sizeof(tmpstr), "&langpackversion=%s&lang=%s", ActiveLangPackVersion, GetPreferredLangId());
  591             else
  592                 tmpstr[0] = 0;
  593 
  594             Applink ("localizations");
  595 
  596             return 1;
  597         }
  598         return 0;
  599     }
  600 
  601     return 0;
  602 }
  603 
  604 
  605 char *GetPreferredLangId ()
  606 {
  607     return PreferredLangId;
  608 }
  609 
  610 
  611 void SetPreferredLangId (char *langId)
  612 {
  613     StringCbCopyA (PreferredLangId, sizeof(PreferredLangId), langId);
  614 }
  615 
  616 
  617 char *GetActiveLangPackVersion ()
  618 {
  619     return ActiveLangPackVersion;
  620 }
  621 
  622 
  623 wchar_t *GetString (const char *stringId)
  624 {
  625     WCHAR *str = (WCHAR *) GetDictionaryValue (stringId);
  626     if (str != NULL) return str;
  627 
  628     StringCbPrintfW (UnknownString, sizeof(UnknownString), UNKNOWN_STRING_ID L"%hs" UNKNOWN_STRING_ID, stringId);
  629     return UnknownString;
  630 }
  631 
  632 
  633 Font *GetFont (char *fontType)
  634 {
  635     return (Font *) GetDictionaryValue (fontType);
  636 
  637 }