/** FILE: font2.c ********** Module Header ******************************** * * Control panel applet for Font configuration. This file holds code for * the items concerning fonts. * * History: * 12:30 on Tues 23 Apr 1991 -by- Steve Cathcart [stevecat] * Took base code from Win 3.1 source * 10:30 on Tues 04 Feb 1992 -by- Steve Cathcart [stevecat] * Updated code to latest Win 3.1 sources * 04 April 1994 -by- Steve Cathcart [stevecat] * Added support for PostScript Type 1 fonts * * Copyright (C) 1990-1994 Microsoft Corporation * *************************************************************************/ //========================================================================== // Include files //========================================================================== // C Runtime #include #include #include // Application specific #include "main.h" #undef IN #include "t1instal.h" #undef COLOR #define CONST const //typedef WCHAR *PWCHAR; // Windows SDK - private #include // For private GDI entry point: GetFontResourceInfo() //========================================================================== // Local Definitions //========================================================================== #define GWL_PROGRESS 0 #define SET_PROGRESS WM_USER // Progress Control color indices #define PROGRESSCOLOR_FACE 0 #define PROGRESSCOLOR_ARROW 1 #define PROGRESSCOLOR_SHADOW 2 #define PROGRESSCOLOR_HIGHLIGHT 3 #define PROGRESSCOLOR_FRAME 4 #define PROGRESSCOLOR_WINDOW 5 #define CCOLORS 6 #define CHAR_BACKSLASH TEXT('\\') #define CHAR_COLON TEXT(':') #define CHAR_NULL TEXT('\0') #define CHAR_TRUE TEXT('T') #define CHAR_FALSE TEXT('F') //========================================================================== // External Declarations //========================================================================== extern TCHAR szTTF[]; extern TCHAR szFON[]; extern TCHAR szPFM[]; extern TCHAR szPFB[]; extern TCHAR szPostScript[]; extern HWND hLBoxInstalled; //========================================================================== // Local Data Declarations //========================================================================== BOOL bYesAll_PS = FALSE; // Use global state for all PS fonts BOOL bConvertPS = TRUE; // Convert Type1 files to TT BOOL bInstallPS = TRUE; // Install PS files BOOL bCopyPS = TRUE; // Copy PS files to Windows dir BOOL bCancelInstall = FALSE; // Global installation cancel TCHAR szTrue[] = TEXT("T"); TCHAR szFalse[] = TEXT("F"); TCHAR szHash[] = TEXT("#"); BOOL bProgMsgDisplayed; // Used by Progress to avoid msg flicker BOOL bProg2MsgDisplayed; // Used by Progress2 to avoid msg flicker HWND hDlgProgress = NULL; // // Used to determine Foreground/Backgnd colors for progress bar control // Global values are set at RegisterClass time // DWORD rgbFG; DWORD rgbBG; // Registry location for installing PostScript printer font info TCHAR szType1Key[] = TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Type 1 Installer\\Type 1 Fonts"); //Array of default colors, matching the order of PROGRESSCOLOR_* values. DWORD rgColorPro[CCOLORS]={ COLOR_BTNFACE, // PROGRESSCOLOR_FACE COLOR_BTNTEXT, // PROGRESSCOLOR_ARROW COLOR_BTNSHADOW, // PROGRESSCOLOR_SHADOW COLOR_BTNHIGHLIGHT, // PROGRESSCOLOR_HIGHLIGHT COLOR_WINDOWFRAME, // PROGRESSCOLOR_FRAME COLOR_WINDOW // PROGRESSCOLOR_WINDOW }; typedef struct _T1_INSTALL_OPTIONS { BOOL bMatchingTT; BOOL bOnlyPSInstalled; int iFontType; LPTSTR szDesc; } T1_INSTALL_OPTIONS, *PT1_INSTALL_OPTIONS; // // Linked-list structure used for copyright Vendors // typedef struct _psvendor { struct _psvendor *pNext; LPTSTR pszCopyright; // Copyright string int iResponse; // User's response to YES/NO MsgBox } PSVENDOR; PSVENDOR *pFirstVendor = NULL; // ptr to linked list for PS vendors //========================================================================== // Local Function Prototypes //========================================================================== BOOL CheckT1Install (LPTSTR pszDesc, LPTSTR pszData); BOOL CheckTTInstall (LPTSTR szDesc); void Draw3DRect (HDC hDC, HBRUSH hBrushFace, HPEN hPenFrame, HPEN hPenHigh, HPEN hPenShadow, int x1, int y1, int x2, int y2); BOOL APIENTRY InstallPSDlg (HWND hDlg, UINT nMsg, DWORD wParam, LONG lParam); void Progress (short PercentDone, void* UniqueValue); LRESULT APIENTRY ProgressBarCtlProc(HWND hTest, UINT message, WPARAM wParam, LONG lParam); BOOL APIENTRY ProgressDlg (HWND hDlg, UINT nMsg, DWORD wParam, LONG lParam); LONG ProgressPaint (HWND hWnd, DWORD dwProgress); BOOL WriteType1RegistryEntry (HWND hDlg, LPTSTR szDesc, LPTSTR szPfmName, LPTSTR szPfbName); //========================================================================== // Functions //========================================================================== ///////////////////////////////////////////////////////////////////////////// // // InspectFontFile // // This routine is called to set up all fonts from the FON file passed. // The handle returned is a handle to global memory containing LOGFONT // structures, the number of structures contained is returned in the // integer pointed to by the second parameter. // // in: // szFontFile font file name // out: // pNumFonts // // NOTE: there must be matching pairs of InspectFontFile () and // PassedInspection () on each font so module counts don't // get out of sync. // ///////////////////////////////////////////////////////////////////////////// HANDLE InspectFontFile (LPTSTR szFontFile, int *pNumFonts) { HANDLE hlpLOGFONT; int nFonts; DWORD dwBufSize; LPTSTR lpFontBuffer; BOOL bStatus; nFonts = 0; if (MyOpenFile (szFontFile, NULL, OF_EXIST) != INVALID_HANDLE_VALUE) { if (nFonts = AddFontResource (szFontFile)) { dwBufSize = (DWORD) (nFonts * sizeof (LOGFONT)); if (hlpLOGFONT = GlobalAlloc (GMEM_MOVEABLE, dwBufSize)) { lpFontBuffer = GlobalLock(hlpLOGFONT); bStatus = GetFontResourceInfoW (szFontFile, &dwBufSize, lpFontBuffer, GFRI_LOGFONTS); GlobalUnlock(hlpLOGFONT); if (bStatus == 0) { GlobalFree (hlpLOGFONT); nFonts = 0; // DbgPrint ("CPanel.Fonts::InspectFontFile - GetFontResourceInfo(LOGFONTS) failed!\n"); } } } } return ((*pNumFonts = nFonts) ? hlpLOGFONT : 0); } ///////////////////////////////////////////////////////////////////////////// // // PassedInspection // // This function takes a handle to memory containing the information // obtained through a call to InspectFontFile, as well as the filename // where the information was retrieved. If the handle is null, // InspectFontFile did not increase the reference count and as such the // count should not be decreased. // ///////////////////////////////////////////////////////////////////////////// HANDLE PassedInspection (HANDLE hLogicalFont, LPTSTR szFileName) { if (hLogicalFont) { GlobalFree (hLogicalFont); RemoveFontResource (szFileName); } return (hLogicalFont); } ///////////////////////////////////////////////////////////////////////////// // // AddBackslash // // Add a Backslash character to the end of a path, if necessary. // ///////////////////////////////////////////////////////////////////////////// void AddBackslash (LPTSTR pszFile) { LPTSTR psz; if (*CharPrev(pszFile, psz = pszFile + lstrlen (pszFile)) != TEXT('\\')) { *psz = TEXT('\\'); *(psz+1) = TEXT('\0'); } } ///////////////////////////////////////////////////////////////////////////// // // StripFilespec // // Remove the filespec portion from a path (including the backslash). // ///////////////////////////////////////////////////////////////////////////// VOID StripFilespec (LPTSTR lpszPath) { LPTSTR p; p = lpszPath + lstrlen(lpszPath); while ((*p != CHAR_BACKSLASH) && (*p != CHAR_COLON) && (p != lpszPath)) p--; if (*p == CHAR_COLON) p++; // // Don't strip backslash from root directory entry. // if (p != lpszPath) { if ((*p == CHAR_BACKSLASH) && (*(p-1) == CHAR_COLON)) p++; } *p = CHAR_NULL; } ///////////////////////////////////////////////////////////////////////////// // // StripPath // // Extract only the filespec portion from a path. // ///////////////////////////////////////////////////////////////////////////// VOID StripPath (LPTSTR lpszPath) { LPTSTR p; p = lpszPath + lstrlen(lpszPath); while ((*p != CHAR_BACKSLASH) && (*p != CHAR_COLON) && (p != lpszPath)) p--; if (p != lpszPath) p++; if (p != lpszPath) lstrcpy(lpszPath, p); } ///////////////////////////////////////////////////////////////////////////// // // AddVendorCopyright // // Add a PostScript Vendor's Copyright and User response to "MAYBE" list. // This linked-list is used to keep track of a user's prior response to // message about converting this vendor's fonts to TrueType. If a vendor // is not in the registry, we cannot automatically assume that the font // can be converted. We must present the User with a message, asking them // to get permission from the vendor before converting the font to TrueType. // // However, we do allow them to continue the installation and convert the // font to TrueType by selecting the YES button on the Message box. This // routine keeps track of each vendor and the User's response for that // vendor. This way we do not continually ask them about the same vendor // during installation of a large number of fonts. // // (Insert item into linked list) // // ///////////////////////////////////////////////////////////////////////////// BOOL AddVendorCopyright (LPTSTR pszCopyright, int iResponse) { PSVENDOR *pVendor; // temp pointer to linked list // // Make the new PSVENDOR node and add it to the linked list. // if (pFirstVendor) { pVendor = (PSVENDOR *) AllocMem (sizeof(PSVENDOR)); if (pVendor) { pVendor->pNext = pFirstVendor; pFirstVendor = pVendor; } else return FALSE; } else // First time thru { pFirstVendor = (PSVENDOR *) AllocMem (sizeof(PSVENDOR)); if (pFirstVendor) pFirstVendor->pNext = NULL; else return FALSE; } // // Save User response and Copyright string // pFirstVendor->iResponse = iResponse; pFirstVendor->pszCopyright = AllocStr (pszCopyright); // // Return success. // return TRUE; } ///////////////////////////////////////////////////////////////////////////// // // CheckVendorCopyright // // Check if a Vendor Copyright is already in the "MAYBE" linked-list and // and return User response if it is found. // // Returns: // IDYES - User wants to convert typeface anyway // IDNO - User does not want to convert typeface // -1 - Entry not found // ///////////////////////////////////////////////////////////////////////////// int CheckVendorCopyright (LPTSTR pszCopyright) { PSVENDOR *pVendor; // temp pointer to linked list // // Traverse the list, testing each node for matching copyright string // pVendor = pFirstVendor; while (pVendor) { if (!lstrcmpi (pVendor->pszCopyright, pszCopyright)) return (pVendor->iResponse); pVendor = pVendor->pNext; } // // "Did not find matching copyright" return // return (-1); } ///////////////////////////////////////////////////////////////////////////// // // IsPSFont // // Check validity of font file passed in and get paths to .pfm/.pfb // files, determine if it can be converted to TT. // // in: // lpszPfm .pfm file name to validate // out: // lpszDesc on succes Font Name of Type1 // lpszPfm on succes the path to .pfm file // lpszPfb on succes the path to .pfb file // pbCreatedPFM on succes whether a PFM file was created or not // lpiFontType set to a value based on Font type 1 == TT, 2 == Type1 // // NOTE: Assumes that lpszPfm and lpszPfb are of size PATHMAX & lpszDesc is // of size DESCMAX // // returns: // TRUE success, FALSE failure // ///////////////////////////////////////////////////////////////////////////// BOOL IsPSFont (HWND hDlg, // if NULL, HWND_DESKTOP used LPTSTR lpszKey, LPTSTR lpszDesc, // Optional LPTSTR lpszPfm, // Optional LPTSTR lpszPfb, // Optional BOOL *pbCreatedPFM, // Optional int *lpiFontType) { BOOL bRet = FALSE; TCHAR strbuf[PATHMAX]; TCHAR szCopyright[PATHMAX]; BOOL bPFM; int iResponse; HWND hwndParent; // // ANSI buffers for use with ANSI only API's // char *desc, Descbuf[PATHMAX]; char Keybuf[PATHMAX]; char *pfb, Pfbbuf[PATHMAX]; char *pfm, Pfmbuf[PATHMAX]; char Vendorbuf[PATHMAX]; DWORD iDesc, iPfb, iPfm; if (!lpiFontType) return bRet; if (lpszDesc) *lpszDesc = (TCHAR) 0; desc = Descbuf; iDesc = PATHMAX; pfb = Pfbbuf; iPfb = PATHMAX; if (lpszPfm) { pfm = Pfmbuf; iPfm = PATHMAX; } else { pfm = NULL; iPfm = 0; } if (pbCreatedPFM) *pbCreatedPFM = FALSE; *lpiFontType = NOT_TT_OR_T1; WideCharToMultiByte (CP_ACP, 0, lpszKey, -1, Keybuf, PATHMAX, NULL, NULL); // // The CheckType1A routine accepts either a .INF or .PFM file name as // the Keybuf (i.e. Key file) input parameter. If the input is a .INF // file, a .PFM file will be created in the SYSTEM directory if (and // only if) the .PFM file name parameter is non-NULL. Otherwise, it // will just check to see if a valid .INF, .AFM and .PFB file exist for // the font. // // The bPFM BOOL value is an output parameter that tells me if the routine // created a .PFM file from the .INF/.AFM file for this font. If the // pfm input parameter is non-NULL, it will always receive the proper // path for the .PFM file. // if (CheckType1A (Keybuf, iDesc, desc, iPfm, pfm, iPfb, pfb, &bPFM, szFontsDirA)) { if (pbCreatedPFM) *pbCreatedPFM = bPFM; // // Check convertability of this font from Type1 to TrueType. // // Returns: SUCCESS, FAILURE, MAYBE // switch (CheckCopyrightA (Pfbbuf, PATHMAX, Vendorbuf)) { case FAILURE: *lpiFontType = TYPE1_FONT_NC; // // Put up a message box stating that this Type1 font vendor // does not allow us to Convert their fonts to TT. This will // let the user know that it is not Microsoft's fault that the // font is not converted to TT, but the vendor's fault. // // NOTE: This is only done if the User has NOT selected the // YesToAll_PS install option. Otherwise it will be very // annoying to see message repeated over and over. // // HACK: The lpszPfb arg is used in the conditional to determine // when the message box should be displayed. If the // IsPSFont routine is called from ValidFontFile routine, // this arg will be NULL. If this routine is called from // InstallPSFont routine it will be non-NULL. It is only // during actual installation that we want the message // displayed. // if (!bYesAll_PS && lpszPfb) { // // Convert ANSI buffers to UNICODE for our use // MultiByteToWideChar (CP_ACP, MB_PRECOMPOSED, Vendorbuf, -1, szCopyright, PATHMAX); MultiByteToWideChar (CP_ACP, MB_PRECOMPOSED, Descbuf, -1, strbuf, PATHMAX); hwndParent = (hDlg == NULL) ? HWND_DESKTOP : hDlg; MyMessageBox (hwndParent, MYFONT+14, INITS+1, MB_OK | MB_ICONEXCLAMATION, (LPTSTR) szCopyright, (LPTSTR) strbuf); } break; case SUCCESS: *lpiFontType = TYPE1_FONT; break; case MAYBE: // // Check font copyright and ask for user response if necessary // // // Convert ANSI buffers to UNICODE for our use // MultiByteToWideChar (CP_ACP, MB_PRECOMPOSED, Vendorbuf, -1, szCopyright, PATHMAX); MultiByteToWideChar (CP_ACP, MB_PRECOMPOSED, Descbuf, -1, strbuf, PATHMAX); switch (CheckVendorCopyright (szCopyright)) { case IDYES: *lpiFontType = TYPE1_FONT; break; case IDNO: *lpiFontType = TYPE1_FONT_NC; break; case -1: default: *lpiFontType = TYPE1_FONT; // HACK: The lpszPfb arg is used in the conditional to determine // when the message box should be displayed. If the // IsPSFont routine is called from ValidFontFile routine, // this arg will be NULL. If this routine is called from // InstallPSFont routine it will be non-NULL. It is only // during actual installation that we want the message // displayed. // if (lpszPfb) { hwndParent = (hDlg == NULL) ? HWND_DESKTOP : hDlg; iResponse = MyMessageBox (hwndParent, MYFONT+41, INITS+1, MB_YESNO | MB_ICONEXCLAMATION | MB_DEFBUTTON2, (LPTSTR) strbuf, (LPTSTR) szCopyright); AddVendorCopyright (szCopyright, iResponse); *lpiFontType = (iResponse == IDYES) ? TYPE1_FONT : TYPE1_FONT_NC; } break; } break; default: // // ERROR! from routine - assume worst case // *lpiFontType = TYPE1_FONT_NC; break; } // // Return Font description // if (lpszDesc) { // Convert Descbuf to UNICODE since IsType1 is ANSI MultiByteToWideChar (CP_ACP, MB_PRECOMPOSED, Descbuf, -1, strbuf, PATHMAX); wsprintf(lpszDesc, TEXT("%s (%s)"), strbuf, szPostScript); } // // Return PFM file name // if (lpszPfm) { // Return PFM file name - convert to UNICODE since IsType1 is ANSI MultiByteToWideChar (CP_ACP, MB_PRECOMPOSED, Pfmbuf, -1, lpszPfm, PATHMAX); } // // Return PFB file name // if (lpszPfb) { // Return PFB file name - convert to UNICODE since IsType1 is ANSI MultiByteToWideChar (CP_ACP, MB_PRECOMPOSED, Pfbbuf, -1, lpszPfb, PATHMAX); } bRet = TRUE; } return bRet; } ///////////////////////////////////////////////////////////////////////////// // // InitPSInstall // // Initialize PostScript install routine global variables. // ///////////////////////////////////////////////////////////////////////////// void InitPSInstall () { // // Initialize linked list variables for "MAYBE" copyright vendor list // pFirstVendor = NULL; // // Other installation globals // bYesAll_PS = FALSE; bConvertPS = TRUE; bInstallPS = TRUE; bCopyPS = TRUE; return; } ///////////////////////////////////////////////////////////////////////////// // // TermPSInstall // // Initialize PostScript install routine global variables. // ///////////////////////////////////////////////////////////////////////////// void TermPSInstall () { PSVENDOR *pVendor; // // Traverse the list, freeing list memory and strings. // pVendor = pFirstVendor; while (pVendor) { pFirstVendor = pVendor; pVendor = pVendor->pNext; if (pFirstVendor->pszCopyright) FreeStr ((LPVOID) pFirstVendor->pszCopyright); FreeMem ((LPVOID) pFirstVendor, sizeof(PSVENDOR)); } // // Reset global to be safe // pFirstVendor = NULL; return; } ///////////////////////////////////////////////////////////////////////////// // // InstallT1Font // // Install PostScript Type1 font, possibly converting the Type1 font to a // TrueType font in the process. Write registry entries so the PostScript // printer driver can find these files either in their original source // directory or locally in the 'shared' or system directory. // ///////////////////////////////////////////////////////////////////////////// int InstallT1Font (HWND hDlg, HWND hListFonts, // Installed fonts listbox BOOL bCopyTTFile, // Copy TT file? BOOL bInSharedDir, // Files in Shared Directory? LPTSTR szKeyName, // IN: PFM/INF Source File name & dir // OUT: Destination file name LPTSTR szDesc) // INOUT: Font description { int iFontType; // Enumerated Font type int rc, iRet; WORD wMsg; BOOL bCreatedPfm = FALSE; TCHAR szTemp[PATHMAX]; TCHAR szTemp2[PATHMAX]; TCHAR szPfbName[PATHMAX]; TCHAR szPfmName[PATHMAX]; TCHAR szSrcDir[PATHMAX]; TCHAR szDstName[PATHMAX]; TCHAR szTTFName[PATHMAX]; TCHAR *pszArg1, *pszArg2; T1_INSTALL_OPTIONS t1ops; // // ASCII Buffers for use in ASCII-only api calls // char pfb[PATHMAX]; char pfm[PATHMAX]; char ttf[PATHMAX]; if (!IsPSFont (hDlg, szKeyName, NULL, szPfmName, szPfbName, &bCreatedPfm, &iFontType)) { MyMessageBox (hDlg, ERRORS+1, INITS+1, MB_OK | MB_ICONEXCLAMATION, (LPTSTR) szDesc); iRet = TYPE1_INSTALL_IDNO; goto InstallPSFailure; } t1ops.szDesc = szDesc; t1ops.iFontType = iFontType; // // Keep a copy of source directory // lstrcpy (szSrcDir, szKeyName); StripFilespec (szSrcDir); AddBackslash (szSrcDir); ////////////////////////////////////////////////////////////////////// // Check if font is already loaded on the system ////////////////////////////////////////////////////////////////////// t1ops.bOnlyPSInstalled = FALSE; t1ops.bMatchingTT = FALSE; // // Check both Type1 & Fonts registry location for prior font installation // if (CheckT1Install (szDesc, NULL)) { if (CheckTTInstall (szDesc)) { // // "Font is already loaded" // iRet = MyMessageBox (hDlg, MYFONT+21, INITS+1, MB_OKCANCEL|MB_ICONEXCLAMATION, (LPTSTR)szDesc); goto InstallPSFailure; } else t1ops.bOnlyPSInstalled = TRUE; } else if (CheckTTInstall (szDesc)) { t1ops.bMatchingTT = TRUE; if (!bYesAll_PS) { // // "The TrueType version of this font is already installed." // switch (MyMessageBox(hDlg, MYFONT+17, INITS+1, MB_YESNOCANCEL|MB_ICONEXCLAMATION, (LPTSTR)szDesc)) { case IDYES: break; case IDNO: iRet = TYPE1_INSTALL_IDNO; goto InstallPSFailure; case IDCANCEL: default: iRet = TYPE1_INSTALL_IDCANCEL; goto InstallPSFailure; } } } // // The global state of // // bConvertPS - Convert Type1 files to TT // bInstallPS - Install PS files // // is only effective for the last time the "Install Type 1 fonts" // dialog was displayed. Check the state of these globals against // what we know about the current font to determine if the dialog // should be redisplayed. // // 5/31/94 [stevecat] DO NOT redisplay the dialog after "YesToAll" // selected once. Instead, display messages about 'exceptions' to // their initial choices and give user the option to continue // installation. // if (bYesAll_PS) { // // If the PS version of this font is already installed AND the // global bInstall == TRUE, then the globals are out-of-sync // with this font. Let user know and continue installation. // if (t1ops.bOnlyPSInstalled && bInstallPS) { // // "The Type 1 version of this font is already installed." // switch (MyMessageBox(hDlg, MYFONT+15, INITS+1, MB_YESNOCANCEL|MB_ICONEXCLAMATION, (LPTSTR)szDesc)) { case IDYES: break; case IDNO: iRet = TYPE1_INSTALL_IDNO; goto InstallPSFailure; case IDCANCEL: default: iRet = TYPE1_INSTALL_IDCANCEL; goto InstallPSFailure; } } // // If the matching TT font is already installed AND the global // bConvertPS == TRUE, then the globals are out-of-sync with // this font. Let the user know and continue installation. // if (t1ops.bMatchingTT && bConvertPS) { // // "The TrueType version of this font is already installed." // switch (MyMessageBox(hDlg, MYFONT+17, INITS+1, MB_YESNOCANCEL|MB_ICONEXCLAMATION, (LPTSTR)szDesc)) { case IDYES: break; case IDNO: iRet = TYPE1_INSTALL_IDNO; goto InstallPSFailure; case IDCANCEL: default: iRet = TYPE1_INSTALL_IDCANCEL; goto InstallPSFailure; } } } // // Get user options for PostScript font installation: // - TT conversion // - Type1 installation // - Copying Type1 files // // State returned in globals: // // bConvertPS - Convert Type1 files to TT // bInstallPS - Install PS files // bCopyPS - Copy PS files to Windows\System dir if (!bYesAll_PS) { HourGlass (FALSE); switch (DoDialogBoxParam(DLG_INSTALL_PS, hDlg, (DLGPROC)InstallPSDlg, IDH_DLG_INSTALL_PS, (LPARAM) &t1ops)) { case IDNO: // // Note that we do not do HourGlass (TRUE), but that // should be harmless, since we are either going to come // right back here, or we are going to exit // return IDNO; case IDD_YESALL: bYesAll_PS = TRUE; // // Fall thru... // case IDYES: // // Give a warning here about installing from a non-local // directory and not copying files, as necessary. // if (bInstallPS && !bCopyPS) { lstrcpy (szTemp, szPfbName); StripFilespec (szTemp); AddBackslash (szTemp); switch (GetDriveType (szTemp)) { case DRIVE_REMOTE: case DRIVE_REMOVABLE: case DRIVE_CDROM: case DRIVE_RAMDISK: if (MyMessageBox (hDlg, ERRORS+6, INITS+1, MB_YESNO|MB_ICONEXCLAMATION) != IDYES) { iRet = TYPE1_INSTALL_IDCANCEL; goto InstallPSFailure; } } } break; default: // CANCEL and NOMEM (user already warned) iRet = TYPE1_INSTALL_IDCANCEL; goto InstallPSFailure; } HourGlass (TRUE); } // // szDstName should already have the full source file name // // Only convert the Type1 font to TT if: // // a) The user asked us to do it; // b) The font can be converted, AND; // c) There is not a matching TT font already installed // if (bConvertPS && (iFontType != TYPE1_FONT_NC) && !t1ops.bMatchingTT) { ////////////////////////////////////////////////////////////////// // Convert Type1 files to TrueType // // Copy converted TT file, if necessary, to "fonts" directory // // NOTE: We are using the ConvertTypeface api to do the copying // and it is an ASCII only api. ////////////////////////////////////////////////////////////////// // // Create destination name with .ttf // lstrcpy (szTemp, szPfmName); StripPath (szTemp); ConvertExtension (szTemp, szTTF); // // Build destination file pathname based on bCopyTTFile // if (bCopyTTFile || bInSharedDir) { // // Copy file to local directory // lstrcpy (szDstName, szSharedDir); } else { // // Create converted file in source directory // lstrcpy (szDstName, szSrcDir); } // // Check new filename for uniqueness // if (!(UniqueFilename (szTemp, szTemp, szDstName))) { iRet = MyMessageBox (hDlg, MYFONT+19, MYFONT+7, MB_OKCANCEL | MB_ICONEXCLAMATION, (LPTSTR)szDesc); goto InstallPSFailure; } lstrcat (szDstName, szTemp); // // Save destination filename for return to caller // if (bCopyTTFile || bInSharedDir) lstrcpy (szTTFName, szTemp); else lstrcpy (szTTFName, szDstName); // // We will convert and copy the Type1 font in the same api // WideCharToMultiByte (CP_ACP, 0, szPfbName, -1, pfb, PATHMAX, NULL, NULL); WideCharToMultiByte (CP_ACP, 0, szPfmName, -1, pfm, PATHMAX, NULL, NULL); WideCharToMultiByte (CP_ACP, 0, szDstName, -1, ttf, PATHMAX, NULL, NULL); ResetProgress (); // // Remove "PostScript" postfix string from description // RemoveDecoration (szDesc, TRUE); if ((rc = (int) ConvertTypefaceA (pfb, pfm, ttf, Progress, (void *) szDesc)) < 0) { pszArg1 = szPfmName; pszArg2 = szPfbName; switch (rc) { case ARGSTACK: case TTSTACK: case NOMEM: wMsg = ERRORS+11; break; case NOMETRICS: case BADMETRICS: case UNSUPPORTEDFORMAT: // // Something is wrong with the .pfm metrics file // pszArg1 = szDstName; pszArg2 = szPfmName; wMsg = MYFONT+43; break; case BADT1HYBRID: case BADT1HEADER: case BADCHARSTRING: case NOCOPYRIGHT: // // Bad .pfb input file - format, or corruption // pszArg1 = szDstName; pszArg2 = szPfbName; wMsg = MYFONT+44; break; case BADINPUTFILE: // // Bad input file names, or formats or file errors // or file read errors // pszArg1 = szDstName; pszArg2 = szPfbName; wMsg = MYFONT+45; break; case BADOUTPUTFILE: // // No diskspace for copy, read-only share, etc. // pszArg1 = szDstName; wMsg = MYFONT+46; break; default: // // Cannot convert szDesc to TrueType - general failure // pszArg1 = szDstName; pszArg2 = szDesc; wMsg = MYFONT + 47; break; } iRet = MyMessageBox (hDlg, wMsg, INITS+1, MB_OKCANCEL | MB_ICONEXCLAMATION, pszArg1, pszArg2, szPfmName); goto InstallPSFailure; } // // Change font description to have "TrueType" now // wsprintf(szDesc, TEXT("%s (%s)"), szDesc, szTrueType); } iRet = TYPE1_INSTALL_IDNO; if (bInstallPS && !t1ops.bOnlyPSInstalled) { // // Remove "PostScript" postfix string from description // lstrcpy (szTemp2, szDesc); RemoveDecoration (szTemp2, TRUE); // // Now reset per font install progress // ResetProgress (); Progress2 (0, szTemp2); // // Only copy the files if the User asked us to AND they are NOT // already in the Shared directory. // if (bCopyPS && !bInSharedDir) { // // Copy file progress // Progress2 (10, szTemp2); ///////////////////////////////////////////////////////////////// // COPY files to "system" directory ///////////////////////////////////////////////////////////////// // // For .inf/.afm file install:: Check .pfm pathname to see if // it is the same as the destination file pathname we built. // Make this check before we test/create a UniqueFilename. // // Build Destination file pathname for .PFM file lstrcpy (szTemp, szPfmName); StripPath (szTemp); lstrcpy (szDstName, szSharedDir); lstrcat (szDstName, szTemp); // // Check to see if the .pfm file already exists in the "system" // directory. If it does, then just copy the .pfb over. // if (!lstrcmpi (szPfmName, szDstName)) goto CopyPfbFile; if (!(UniqueFilename (szTemp, szTemp, szSharedDir))) { iRet = MyMessageBox (hDlg, MYFONT+19, MYFONT+7, MB_OKCANCEL | MB_ICONEXCLAMATION, (LPTSTR)szDesc); goto InstallPSFailure; } lstrcpy (szDstName, szSharedDir); lstrcat (szDstName, szTemp); if ((rc = Copy (hDlg, szPfmName, szDstName)) <= 0) { switch (rc) { // On these two return codes, the USER has effectively // "Cancelled" the copy operation for the fonts case COPY_CANCEL: case COPY_DRIVEOPEN: return IDCANCEL; case COPY_SELF: wMsg = ERRORS+10; break; case COPY_NOCREATE: wMsg = ERRORS+13; break; case COPY_NODISKSPACE: wMsg = ERRORS+12; break; case COPY_NOMEMORY: wMsg = ERRORS+11; break; default: wMsg = ERRORS+14; break; } iRet = MyMessageBox (hDlg, wMsg, INITS+1, MB_OKCANCEL | MB_ICONEXCLAMATION, szDstName, szPfmName); goto InstallPSFailure; } CopyPfbFile: // // Copying pfm file was small portion of install // Progress2 (30, szTemp2); // Build Destination file pathname for .PFB file lstrcpy (szTemp, szPfbName); StripPath (szTemp); if (!(UniqueFilename (szTemp, szTemp, szSharedDir))) { iRet = MyMessageBox (hDlg, MYFONT+19, MYFONT+7, MB_OKCANCEL | MB_ICONEXCLAMATION, (LPTSTR)szDesc); goto InstallPSFailure; } lstrcpy (szDstName, szSharedDir); lstrcat (szDstName, szTemp); if ((rc = Copy (hDlg, szPfbName, szDstName)) <= 0) { switch (rc) { // On these two return codes, the USER has effectively // "Cancelled" the copy operation for the fonts case COPY_CANCEL: case COPY_DRIVEOPEN: return IDCANCEL; case COPY_SELF: wMsg = ERRORS+10; break; case COPY_NOCREATE: wMsg = ERRORS+13; break; case COPY_NODISKSPACE: wMsg = ERRORS+12; break; case COPY_NOMEMORY: wMsg = ERRORS+11; break; default: wMsg = ERRORS+14; break; } iRet = MyMessageBox (hDlg, wMsg, INITS+1, MB_OKCANCEL | MB_ICONEXCLAMATION, szDstName, szPfbName); goto InstallPSFailure; } } // // Copying pfb file was large portion of install // Progress2 (85, szTemp2); // // Write registry entry to "install" font for use by the // PostScript driver, but only after successfully copying // files (if copy was necessary). // iRet = WriteType1RegistryEntry (hDlg, szDesc, szPfmName, szPfbName); // // Final registry write completes install, except for listbox munging. // Note that TrueType file install is handled separately. // Progress2 (100, szTemp2); } // // Determine correct return code based on installation options and // current installed state of font. // if (bConvertPS && (iFontType != TYPE1_FONT_NC)) { // // Handle the special case of when the matching TTF font is already // installed. // if (t1ops.bMatchingTT) goto Type1InstallCheck; lstrcpy (szKeyName, szTTFName); if (t1ops.bOnlyPSInstalled) { // // There is already a Lbox entry for the PS version of this font // that needs to be deleted because the TT installation will // add a new Lbox entry. // iRet = TYPE1_INSTALL_TT_AND_MPS; // // Funnel all exits thru 1 point to check for Install Cancellation // goto MasterExit; } else if (bInstallPS) { iRet = (iRet == IDOK) ? TYPE1_INSTALL_TT_AND_PS : TYPE1_INSTALL_TT_ONLY; // // Funnel all exits thru 1 point to check for Install Cancellation // goto MasterExit; } else { iRet = TYPE1_INSTALL_TT_ONLY; goto CheckPfmDeletion; } } Type1InstallCheck: if (bInstallPS) { if (iRet != IDOK) { iRet = TYPE1_INSTALL_IDNO; goto InstallPSFailure; } iRet = TYPE1_INSTALL_IDNO; if (t1ops.bMatchingTT) { // // If we previously found the Matching TT font for this Type1 // font and installed the PostScript font in this session, set // the font type for the Matching TT font to IF_TYPE1_TT. // // Also, do not add a new entry in listbox for the Type1 font. // // Find matching "xxxxx (TrueType)" entry and change its // ItemData to IF_TYPE1_TT // // Change font description to have "(TrueType)" now // RemoveDecoration (szDesc, TRUE); wsprintf (szDesc, TEXT("%s (%s)"), szDesc, szTrueType); rc= SendMessage (hListFonts, LB_FINDSTRINGEXACT, (WPARAM) -1, (LONG)szDesc); if (rc != LB_ERR) { SendMessage (hListFonts, LB_SETITEMDATA, rc, (LONG) IF_TYPE1_TT); SendMessage (hListFonts, LB_SETSEL, 1, rc); UpdateWindow (hListFonts); iRet = TYPE1_INSTALL_PS_AND_MTT; } } else { rc = SendMessage (hListFonts, LB_ADDSTRING, 0, (LONG)(LPTSTR)szDesc); // // Attach font type to each listed font // if (rc != LB_ERR) { SendMessage (hListFonts, LB_SETITEMDATA, rc, IF_TYPE1); SendMessage (hListFonts, LB_SETSEL, 1, rc); UpdateWindow (hListFonts); iRet = TYPE1_INSTALL_PS_ONLY; } } } if (!bInstallPS) goto CheckPfmDeletion; // // Funnel all exits thru 1 point to check for Install Cancellation // goto MasterExit; ///////////////////////////////////////////////////////////////////////// // // Install failure exit AND Delete extraneously created PFM file // // NOTE: For the installation scenario where we based installation on // the .INF/.AFM file and the Type1 font was NOT installed, we // need to delete the .FPM file that was created by the // CheckType1A routine in the IsPSFont routine. // ///////////////////////////////////////////////////////////////////////// InstallPSFailure: CheckPfmDeletion: if (bCreatedPfm) DeleteFile (szPfmName); MasterExit: return (bCancelInstall ? IDCANCEL : iRet); } ///////////////////////////////////////////////////////////////////////////// // // InstallPSDlg // // This dialog proc manages the Install PostScript font dialog which allows // the user several options for the installation, including converting the // file to a TrueType font. // // Globals munged: // // bConvertPS - Convert Type1 files to TT // bInstallPS - Install PS files // bCopyPS - Copy PS files to Windows dir // ///////////////////////////////////////////////////////////////////////////// BOOL APIENTRY InstallPSDlg (HWND hDlg, UINT nMsg, DWORD wParam, LONG lParam) { TCHAR szFormat[PATHMAX]; TCHAR szTemp[PATHMAX]; TCHAR szTemp2[PATHMAX]; int iButtonChecked; int wMsg; static HWND hwndActive = NULL; T1_INSTALL_OPTIONS *pt1ops; switch (nMsg) { case WM_INITDIALOG: pt1ops = (PT1_INSTALL_OPTIONS) lParam; // // Remove all "PostScript" or "TrueType" postfix to font name // lstrcpy (szTemp2, (LPTSTR)pt1ops->szDesc); RemoveDecoration (szTemp2, FALSE); LoadString (hModule, MYFONT + 34, szFormat, CharSizeOf(szFormat)); wsprintf (szTemp, szFormat, szTemp2); SetWindowLong (hDlg, DWL_USER, lParam); SetDlgItemText (hDlg, FONT_INSTALLMSG, szTemp); EnableWindow (hDlg, TRUE); if (pt1ops->bOnlyPSInstalled && pt1ops->bMatchingTT) { // // ERROR! Both of these options should not be set at // this point. It means that the font is // already installed. This should have been // handled before calling this dialog. // wMsg = MYFONT+21; InstallError: MyMessageBox (hDlg, wMsg, INITS+1, MB_OK | MB_ICONEXCLAMATION, pt1ops->szDesc); EndDialog (hDlg, IDNO); break; } if ((pt1ops->iFontType == TYPE1_FONT_NC) && pt1ops->bOnlyPSInstalled) { // // ERROR! This case is when I have detected only the PS // version of font installed, and the font CANNOT // be converted to TT for some reason. // wMsg = MYFONT+37; goto InstallError; } ///////////////////////////////////////////////////////////////////// // // Setup user options depending on install state of font and // convertibility to TT of T1 font and on previous user choices. // ///////////////////////////////////////////////////////////////////// if ((pt1ops->iFontType == TYPE1_FONT) && (!pt1ops->bMatchingTT)) { // // This one can be converted // CheckDlgButton(hDlg, FONT_CONVERT_PS, bConvertPS); } else { // // Do not allow conversion to TT because, either the font // type is TYPE1_FONT_NC (i.e. it cannot be converted) OR // the TT version of font is already installed. // CheckDlgButton(hDlg, FONT_CONVERT_PS, FALSE); EnableWindow (GetDlgItem (hDlg, FONT_CONVERT_PS), FALSE); } if (pt1ops->bOnlyPSInstalled) { // // If the PostScript version of this font is already // installed, then we gray out the options to re-install // the PostScript version of font, but continue to allow // the User to convert it to TT. // CheckDlgButton(hDlg, FONT_INSTALL_PS, 0); EnableWindow (GetDlgItem (hDlg, FONT_INSTALL_PS), FALSE); CheckDlgButton(hDlg, FONT_COPY_PS, 0); EnableWindow (GetDlgItem (hDlg, FONT_COPY_PS), FALSE); } else { // // PostScript version of font is not installed. Set // state of "INSTALL" and "COPY" checkboxes based on // global state of "INSTALL" // CheckDlgButton(hDlg, FONT_INSTALL_PS, bInstallPS); CheckDlgButton(hDlg, FONT_COPY_PS, bCopyPS); EnableWindow (GetDlgItem (hDlg, FONT_COPY_PS), bInstallPS); } // // Save the modeless dlg window handle for reactivation // hwndActive = GetActiveWindow (); break; case WM_COMMAND: switch (LOWORD(wParam)) { case FONT_INSTALL_PS: if (HIWORD(wParam) != BN_CLICKED) break; // // Get state of "INSTALL" checkbox // iButtonChecked = IsDlgButtonChecked (hDlg, LOWORD(wParam)); // // A disabled checkbox is same as "No Install" selection // if (iButtonChecked != 1) iButtonChecked = 0; // // Enable or disable "COPY" control based on state of // "INSTALL" checkbox. Also, initialize it. // EnableWindow (GetDlgItem (hDlg, FONT_COPY_PS), iButtonChecked); if (iButtonChecked) CheckDlgButton(hDlg, FONT_COPY_PS, bCopyPS); break; case IDD_HELP: goto DoHelp; case IDYES: case IDD_YESALL: bConvertPS = bInstallPS = FALSE; if (IsDlgButtonChecked (hDlg, FONT_CONVERT_PS) == 1) bConvertPS = TRUE; if (IsDlgButtonChecked (hDlg, FONT_INSTALL_PS) == 1) bInstallPS = TRUE; // // This is checked twice because it could be disabled, // in which case we leave the previous state alone. // if (IsDlgButtonChecked (hDlg, FONT_COPY_PS) == 1) bCopyPS = TRUE; if (IsDlgButtonChecked (hDlg, FONT_COPY_PS) == 0) bCopyPS = FALSE; // // Fall thru... // case IDNO: case IDCANCEL: // // Reset the active window to "Install Font Progress" modeless dlg // if (hwndActive) { SetActiveWindow (hwndActive); hwndActive = NULL; } EndDialog (hDlg, LOWORD(wParam)); break; default: return FALSE; } break; default: if (nMsg == wHelpMessage) { DoHelp: CPHelp (hDlg); return TRUE; } else return FALSE; } return TRUE; } ///////////////////////////////////////////////////////////////////////////// // // RemoveDecoration // // Deletes the "(TrueType)" or "(PostScript)" postfix string from the end // of a font name. Optionally it will also remove the trailing space. // // NOTE: This function modifies the string passed into the function. // ///////////////////////////////////////////////////////////////////////////// void RemoveDecoration (LPTSTR pszDesc, BOOL bDeleteTrailingSpace) { LPTSTR lpch; // // Remove any postfix strings like "(PostScript)" or "(TrueType)" // if (lpch = _tcschr (pszDesc, TEXT('('))) { // // End string at before "(" // if (bDeleteTrailingSpace) lpch--; *lpch = CHAR_NULL; } return ; } ///////////////////////////////////////////////////////////////////////////// // // CheckT1Install // // Checks the Type1 fonts location in registry to see if this font is or // has been previously installed as a "PostScript" font. Optionally, it // will return the data for the "szDesc" value if it finds a matching entry. // // Assumes "szData" buffer is of least size T1_MAX_DATA. // ///////////////////////////////////////////////////////////////////////////// BOOL CheckT1Install (LPTSTR pszDesc, LPTSTR pszData) { TCHAR szTemp[PATHMAX]; DWORD dwSize; DWORD dwType; HKEY hkey; BOOL bRet = FALSE; hkey = NULL; if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, // Root key szType1Key, // Subkey to open 0L, // Reserved KEY_READ, // SAM &hkey) // return handle == ERROR_SUCCESS) { // // Remove any postfix strings like "PostScript" or "TrueType" // lstrcpy (szTemp, pszDesc); RemoveDecoration (szTemp, TRUE); dwSize = pszData ? T1_MAX_DATA * sizeof(TCHAR) : 0; if (RegQueryValueEx (hkey, szTemp, NULL, &dwType, (LPBYTE) pszData, &dwSize) == ERROR_SUCCESS) { bRet = (dwType == REG_MULTI_SZ); } else { bRet = FALSE; } RegCloseKey (hkey); } return bRet; } ///////////////////////////////////////////////////////////////////////////// // // AddSystemPath // // Add "System" path to a naked file name, if no path currently exists // on the filename. Assumes pszFile buffer is at least PATHMAX chars in // length. // ///////////////////////////////////////////////////////////////////////////// void AddSystemPath (LPTSTR pszFile) { TCHAR szPath[PATHMAX]; // // Add "system" path, if no path present on file // lstrcpy (szPath, pszFile); StripFilespec (szPath); if (szPath[0] == CHAR_NULL) { lstrcpy (szPath, szSharedDir); AddBackslash (szPath); lstrcat (szPath, pszFile); lstrcpy (pszFile, szPath); } return ; } ///////////////////////////////////////////////////////////////////////////// // // ExtractT1Files // // Extracts file names from a REG_MULTI_SZ (multi-string) array that is // passed into this routine. The output strings are expected to be at // least PATHMAX in size. A "" (NULL string) indicates that a filename // string was not present. This should only happen for the PFB filename // argument. // ///////////////////////////////////////////////////////////////////////////// BOOL ExtractT1Files (LPTSTR pszMulti, LPTSTR pszPfmFile, LPTSTR pszPfbFile) { LPTSTR pszPfm; LPTSTR pszPfb; if (!pszMulti) return FALSE; if ((pszMulti[0] != CHAR_TRUE) && (pszMulti[0] != CHAR_FALSE)) return FALSE; // // .Pfm file should always be present // pszPfm = pszMulti + lstrlen(pszMulti) + 1; lstrcpy (pszPfmFile, pszPfm); // // Add "system" path, if no path present on files // AddSystemPath (pszPfmFile); // // Check to see if .pfb filename is present // if (pszMulti[0] == CHAR_TRUE) { pszPfb = pszPfm + lstrlen(pszPfm) + 1; lstrcpy (pszPfbFile, pszPfb); // // Add "system" path, if no path present on files // AddSystemPath (pszPfbFile); } else { pszPfbFile[0] = CHAR_NULL; } return TRUE; } ///////////////////////////////////////////////////////////////////////////// // // DeleteT1Install // // Deletes a Type1 entry from the registry and optionally the files pointed // to in the data strings. // ///////////////////////////////////////////////////////////////////////////// BOOL DeleteT1Install (HWND hDlg, LPTSTR pszDesc, BOOL bDeleteFiles) { TCHAR szTemp[PATHMAX]; TCHAR szTemp2[T1_MAX_DATA]; TCHAR szPfmFile[PATHMAX]; TCHAR szPfbFile[PATHMAX]; TCHAR szPath[PATHMAX]; DWORD dwSize; DWORD dwType; HKEY hkey; BOOL bRet = FALSE; hkey = NULL; if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, // Root key szType1Key, // Subkey to open 0L, // Reserved (KEY_READ | KEY_WRITE), // SAM &hkey) // return handle == ERROR_SUCCESS) { // // Remove any postfix strings like "PostScript" or "TrueType" // lstrcpy (szTemp, pszDesc); RemoveDecoration (szTemp, TRUE); if (bDeleteFiles) { dwSize = sizeof(szTemp2); if (RegQueryValueEx (hkey, szTemp, NULL, &dwType, (LPBYTE) szTemp2, &dwSize) == ERROR_SUCCESS) { if (ExtractT1Files (szTemp2, szPfmFile, szPfbFile)) { // // Delete the files // if (DelSharedFile (hDlg, szTemp, szPfbFile, szPath, TRUE)) DelSharedFile (hDlg, szTemp, szPfmFile, szPath, FALSE); } else { // ERROR! Cannot get file names from string goto RemoveT1Error; } } else { RemoveT1Error: MyMessageBox (hDlg, MYFONT+4, INITS+1, MB_ICONEXCLAMATION|MB_OKCANCEL, szTemp); bRet = FALSE; } } if (RegDeleteValue (hkey, szTemp) != ERROR_SUCCESS) { // // ERROR! Put up message box // MyMessageBox (hDlg, MYFONT+4, INITS+1, MB_ICONEXCLAMATION|MB_OKCANCEL, szTemp); bRet = FALSE; } else { bRet = TRUE; } RegCloseKey (hkey); } return bRet; } ///////////////////////////////////////////////////////////////////////////// // // GetT1Install // // Gets a Type1 entry information from the registry into the files pointed // to in the data strings. // ///////////////////////////////////////////////////////////////////////////// BOOL GetT1Install (HWND hDlg, LPTSTR pszDesc, LPTSTR pszPfmFile, LPTSTR pszPfbFile) { TCHAR szTemp2[T1_MAX_DATA]; BOOL bRet = FALSE; if (CheckT1Install (pszDesc, szTemp2)) { bRet = ExtractT1Files (szTemp2, pszPfmFile, pszPfbFile); } return bRet; } ///////////////////////////////////////////////////////////////////////////// // // CheckTTInstall // // Check FONTS location in registry to see if this font has already // been installed. // ///////////////////////////////////////////////////////////////////////////// BOOL CheckTTInstall (LPTSTR szDesc) { TCHAR szTemp[PATHMAX]; TCHAR szTemp2[PATHMAX]; // // Change description string to have TrueType instead of // PostScript and then check if it is already installed. // lstrcpy (szTemp, szDesc); RemoveDecoration (szTemp, FALSE); wsprintf(szTemp, TEXT("%s(%s)"), szTemp, szTrueType); if (GetProfileString(szFonts, szTemp, szNull, szTemp2, CharSizeOf(szTemp2))) return TRUE; return FALSE; } ///////////////////////////////////////////////////////////////////////////// // // WriteType1RegistryEntry // // Create registry entry for this PostScript font by writing the path of // both the .PFM and .PFB files. // // NOTE: Checks global "bCopyPS" to determine if files have been copied // to the local shared directory. In that case, the path info is // stripped from the file names passed into routine. // ///////////////////////////////////////////////////////////////////////////// int WriteType1RegistryEntry (HWND hDlg, LPTSTR szDesc, // Font name description LPTSTR szPfmName, // .PFM filename LPTSTR szPfbName) // .PFB filename { TCHAR szTemp[2*PATHMAX+6]; TCHAR szTemp2[PATHMAX]; TCHAR szClass[PATHMAX]; DWORD dwSize; DWORD dwDisposition; HKEY hkey = NULL; // // Must have a Font description to store information in registry // if (!szDesc || !szPfmName) return TYPE1_INSTALL_IDNO; // // Try to create the key if it does not exist or open existing key. // if (RegCreateKeyEx (HKEY_LOCAL_MACHINE, // Root key szType1Key, // Subkey to open/create 0L, // Reserved szClass, // Class string 0L, // Options KEY_WRITE, // SAM NULL, // ptr to Security struct &hkey, // return handle &dwDisposition) // return disposition == ERROR_SUCCESS) { // // Create REG_MULTI_SZ string to save in registry // // X [path]zzzz.pfm [path]xxxxx.pfb // // Where X == T(rue) if .pfb file present // lstrcpy (szTemp, szPfbName ? szTrue : szFalse); lstrcat (szTemp, szHash); if (bCopyPS) StripPath (szPfmName); lstrcat (szTemp, szPfmName); lstrcat (szTemp, szHash); if (szPfbName) { if (bCopyPS) StripPath (szPfbName); lstrcat (szTemp, szPfbName); lstrcat (szTemp, szHash); } lstrcat (szTemp, szHash); dwSize = ByteCountOf(lstrlen(szTemp)); // // Now convert string to multi-string // FixupNulls (szTemp); // // Create Registry Value name to store info under by // removing any postfix strings like "PostScript" or // "TrueType" from Font description string. // lstrcpy (szTemp2, szDesc); RemoveDecoration (szTemp2, TRUE); if (RegSetValueEx (hkey, szTemp2, 0L, REG_MULTI_SZ, (LPBYTE) szTemp, dwSize) != ERROR_SUCCESS) { goto WriteRegError; } RegCloseKey (hkey); } else { WriteRegError: // // Put up a message box error stating that the USER does // not have the permission necessary to install type1 // fonts. // if (hkey) RegCloseKey (hkey); return (MyMessageBox (hDlg, MYFONT+38, INITS+1, MB_OKCANCEL | MB_ICONEXCLAMATION, (LPTSTR)szDesc, (LPTSTR)szType1Key)); } return TYPE1_INSTALL_IDOK; } ///////////////////////////////////////////////////////////////////////////// // // EnumType1Fonts // // List all of the Type 1 fonts installed in the registry, check for // TrueType installation and put Postscript-only installed fonts in // the "Installed Fonts" list box. // // This routine assumes that the TrueType descriptions are already // displayed in the "Installed Fonts" listbox. // ///////////////////////////////////////////////////////////////////////////// BOOL EnumType1Fonts (HWND hLBox) { int i, j; DWORD dwSize; DWORD dwPathMax; DWORD dwType; HKEY hkey; LPTSTR pszDesc; LPTSTR pszFontName; BOOL bRet = FALSE; ////////////////////////////////////////////////////////////////////// // Get some storage ////////////////////////////////////////////////////////////////////// pszFontName = pszDesc = NULL; dwPathMax = PATHMAX * sizeof(TCHAR); pszFontName = (LPTSTR) AllocMem (dwPathMax); pszDesc = (LPTSTR) AllocMem (dwPathMax); if (!pszDesc || !pszFontName) goto EnumType1Exit; ////////////////////////////////////////////////////////////////////// // Get list of installed Type 1 fonts ////////////////////////////////////////////////////////////////////// hkey = NULL; if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, // Root key szType1Key, // Subkey to open 0L, // Reserved KEY_READ, // SAM &hkey) // return handle == ERROR_SUCCESS) { dwSize = dwPathMax; i = 0; while (RegEnumValue (hkey, i++, pszFontName, &dwSize, NULL, &dwType, (LPBYTE) NULL, NULL) == ERROR_SUCCESS) { if (dwType != REG_MULTI_SZ) continue; wsprintf(pszDesc, TEXT("%s (%s)"), pszFontName, szPostScript); // // Check to see if TrueType version is already installed // if (CheckTTInstall (pszDesc)) { // // Find matching "xxxxx (TrueType)" entry and change its // ItemData to IF_TYPE1_TT // wsprintf(pszDesc, TEXT("%s (%s)"), pszFontName, szTrueType); j = SendMessage (hLBox, LB_FINDSTRINGEXACT, (WPARAM) -1, (LONG)pszDesc); if (j != LB_ERR) SendMessage (hLBox, LB_SETITEMDATA, j, (LONG) IF_TYPE1_TT); // else // ERROR! We should have found a matching LB entry for this // font based on TT name. } else { // // Put Font name string in ListBox // j = SendMessage (hLBox, LB_ADDSTRING, 0, (LONG)pszDesc); if (j != LB_ERR) SendMessage (hLBox, LB_SETITEMDATA, j, (LONG) IF_TYPE1); // else // ERROR! We found an installed Type1 font but cannot show // it in listbox because of USER error. } dwSize = dwPathMax; } bRet = TRUE; RegCloseKey (hkey); } EnumType1Exit: if (pszDesc) FreeMem (pszDesc, dwPathMax); if (pszFontName) FreeMem (pszFontName, dwPathMax); return bRet; } ///////////////////////////////////////////////////////////////////////////// // // InitProgress // // Create and initialize the Progress dialog. Initial state is visible. // ///////////////////////////////////////////////////////////////////////////// BOOL InitProgress (HWND hwnd) { if (hDlgProgress) return TRUE; hDlgProgress = CreateDialog (hModule, MAKEINTRESOURCE(DLG_PROGRESS), hwnd, (DLGPROC)ProgressDlg); return (hDlgProgress != NULL); } ///////////////////////////////////////////////////////////////////////////// // // TermProgress // // Remove and cleanup after the Progress dialog. // ///////////////////////////////////////////////////////////////////////////// void TermProgress () { if (hDlgProgress) DestroyWindow (hDlgProgress); hDlgProgress = NULL; return; } ///////////////////////////////////////////////////////////////////////////// // // cpProgressYield // // Allow other messages including Dialog messages for Modeless dialog to be // processed while we are converting Type1 files to TrueType. // // Since the font conversion is done on a single thread (in order to keep it // synchronous with installation of all fonts) we need to provide a mechanism // that will allow a user to Cancel out of the operation and also allow // window messages, like WM_PAINT, to be processed by other Window Procedures. // ///////////////////////////////////////////////////////////////////////////// VOID cpProgressYield() { MSG msg; while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) { // if (!hDlgProgress || !IsDialogMessage (hDlgProgress, &msg)) if (!IsDialogMessage (hDlgProgress, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } } } ///////////////////////////////////////////////////////////////////////////// // // UpdateProgress // // Set the overall progress control in Progress Dialog, along with a // message describing installation progress. // ///////////////////////////////////////////////////////////////////////////// void UpdateProgress (int iTotalCount, int iFontInstalling, int iProgress) { TCHAR szTemp[120]; wsprintf (szTemp, szGenErr, iFontInstalling, iTotalCount); SetDlgItemText (hDlgProgress, ID_INSTALLMSG, szTemp); SendDlgItemMessage (hDlgProgress, ID_OVERALL, SET_PROGRESS, (int) iProgress, 0L); // // Process outstanding messages // cpProgressYield(); } ///////////////////////////////////////////////////////////////////////////// // // ResetProgress // // Clear the progress bar control and reset message to NULL // ///////////////////////////////////////////////////////////////////////////// void ResetProgress () { SetDlgItemText (hDlgProgress, ID_PROGRESSMSG, szNull); SendDlgItemMessage(hDlgProgress, ID_BAR, SET_PROGRESS, (int) 0, 0L); bProgMsgDisplayed = FALSE; bProg2MsgDisplayed = FALSE; // // Process outstanding messages // cpProgressYield(); } ///////////////////////////////////////////////////////////////////////////// // // Progress // // Progress function for ConvertTypefaceA - Adobe Type1 to TrueType font // file converter. Put up progress in converting font and message // describing font being converted. // ///////////////////////////////////////////////////////////////////////////// void Progress (short PercentDone, void* UniqueValue) { TCHAR szTemp[120]; TCHAR szTemp2[120]; DWORD err = GetLastError(); // save whatever t1instal may have set // // UniqueValue is a pointer to the string name of the file being // converted. Only put this message up if not previously displayed. // if (!bProgMsgDisplayed) { LoadString (hModule, MYFONT + 32, szTemp2, CharSizeOf(szTemp2)); wsprintf (szTemp, szTemp2, (LPTSTR) UniqueValue); SetDlgItemText (hDlgProgress, ID_PROGRESSMSG, szTemp); bProgMsgDisplayed = TRUE; } SendDlgItemMessage (hDlgProgress, ID_BAR, SET_PROGRESS, (int) PercentDone, 0L); // // Process outstanding messages // cpProgressYield(); // // reset last error to whatever t1instal set it to: // SetLastError(err); } ///////////////////////////////////////////////////////////////////////////// // // Progress2 // // Progress function for updating progress dialog controls on a per font // install basis. // ///////////////////////////////////////////////////////////////////////////// void Progress2 (int PercentDone, LPTSTR pszDesc) { TCHAR szTemp[PATHMAX]; TCHAR szTemp2[240]; // // szDesc is a pointer to the string name of the file being installed. // Only put this message up if not previously displayed. if (!bProg2MsgDisplayed) { LoadString (hModule, MYFONT + 40, szTemp2, CharSizeOf(szTemp2)); wsprintf (szTemp, szTemp2, pszDesc); SetDlgItemText (hDlgProgress, ID_PROGRESSMSG, szTemp); bProg2MsgDisplayed = TRUE; } SendDlgItemMessage (hDlgProgress, ID_BAR, SET_PROGRESS, (int) PercentDone, 0L); // // Process outstanding messages // cpProgressYield(); } ///////////////////////////////////////////////////////////////////////////// // // ProgressDlg // // Display progress messages to user based on progress in converting // font files to TrueType // ///////////////////////////////////////////////////////////////////////////// BOOL APIENTRY ProgressDlg (HWND hDlg, UINT nMsg, DWORD wParam, LONG lParam) { switch (nMsg) { case WM_INITDIALOG: CentreWindow (hDlg); // // Load in Progress messages // LoadString (hModule, MYFONT + 39, szGenErr, CharSizeOf(szGenErr)); EnableWindow (hDlg, TRUE); break; case WM_COMMAND: switch (LOWORD(wParam)) { case IDOK: case IDCANCEL: bCancelInstall = (LOWORD(wParam) == IDCANCEL); EndDialog (hDlg, LOWORD(wParam)); break; default: return FALSE; } break; default: return FALSE; } return TRUE; } ///////////////////////////////////////////////////////////////////////////// // // ProgressBarCtlProc // // Window Procedure for the Progress Bar custom control. Handles all // messages like WM_PAINT just as a normal application window would. // ///////////////////////////////////////////////////////////////////////////// LRESULT APIENTRY ProgressBarCtlProc(HWND hWnd, UINT message, WPARAM wParam, LONG lParam) { DWORD dwProgress; dwProgress = (DWORD) GetWindowLong (hWnd, GWL_PROGRESS); switch (message) { case WM_CREATE: dwProgress = 0; SetWindowLong (hWnd, GWL_PROGRESS, (LONG) dwProgress); break; case SET_PROGRESS: SetWindowLong (hWnd, GWL_PROGRESS, (LONG) wParam); InvalidateRect(hWnd, NULL, FALSE); UpdateWindow(hWnd); break; case WM_ENABLE: // Force a repaint since the control will look different. InvalidateRect (hWnd, NULL, TRUE); UpdateWindow (hWnd); break; case WM_PAINT: return ProgressPaint (hWnd, dwProgress); default: return (DefWindowProc (hWnd, message, wParam, lParam)); break; } return(0L); } ///////////////////////////////////////////////////////////////////////////// // // RegisterProgressClass // // ///////////////////////////////////////////////////////////////////////////// BOOL RegisterProgressClass (HANDLE hModule) { WNDCLASS wcTest; wcTest.lpszClassName = TEXT("cpProgress"); wcTest.hInstance = hModule; wcTest.lpfnWndProc = ProgressBarCtlProc; wcTest.hCursor = LoadCursor(NULL, IDC_WAIT); wcTest.hIcon = NULL; wcTest.lpszMenuName = NULL; wcTest.hbrBackground = (HBRUSH) (rgColorPro[PROGRESSCOLOR_WINDOW]); wcTest.style = CS_HREDRAW | CS_VREDRAW; wcTest.cbClsExtra = 0; wcTest.cbWndExtra = sizeof(DWORD); // // Set Bar color to Blue and text color to white // rgbBG = RGB( 0, 0, 255); rgbFG = RGB(255, 255, 255); return (RegisterClass((LPWNDCLASS) &wcTest)); } ///////////////////////////////////////////////////////////////////////////// // // UnRegisterProgressClass // // ///////////////////////////////////////////////////////////////////////////// VOID UnRegisterProgressClass (HANDLE hModule) { UnregisterClass(TEXT("cpProgress"), hModule); } ///////////////////////////////////////////////////////////////////////////// // // ProgressPaint // // Description: // // Handles all WM_PAINT messages for the control and paints // the control for the progress state. // // Parameters: // hWnd HWND Handle to the control. // dwProgress DWORD Progress amount - between 1 and 100 // // Return Value: // LONG 0L. // // // This is an alternate way to do the progress bar in the control. Instead // of drawing a rectangle, it uses ExtTextOut to draw the opagueing rect // based on the percentage complete. Clever. // ///////////////////////////////////////////////////////////////////////////// LONG ProgressPaint (HWND hWnd, DWORD dwProgress) { PAINTSTRUCT ps; HDC hDC; TCHAR szTemp[20]; int dx, dy, len; RECT rc1, rc2; SIZE Size; hDC = BeginPaint (hWnd, &ps); GetClientRect (hWnd, &rc1); FrameRect (hDC, &rc1, GetStockObject(BLACK_BRUSH)); InflateRect (&rc1, -2, -2); rc2 = rc1; dx = rc1.right; dy = rc1.bottom; rc1.right = rc2.left = (dwProgress * dx / 100) + 1; // // Boundary condition testing // if (rc2.left > rc2.right) rc2.left = rc2.right; len = wsprintf (szTemp, TEXT("%3d%%"), dwProgress); GetTextExtentPoint32 (hDC, szTemp, len, &Size); SetBkColor (hDC, rgbBG); SetTextColor (hDC, rgbFG); ExtTextOut (hDC, (dx-Size.cx)/2, (dy-Size.cy)/2, ETO_OPAQUE | ETO_CLIPPED, &rc1, szTemp, len, NULL); SetBkColor (hDC, rgbFG); SetTextColor (hDC, rgbBG); ExtTextOut (hDC, (dx-Size.cx)/2, (dy-Size.cy)/2, ETO_OPAQUE | ETO_CLIPPED, &rc2, szTemp, len, NULL); EndPaint (hWnd, &ps); return 0L; } #ifdef LATER ///////////////////////////////////////////////////////////////////////////// // // ProgressPaint // // Description: // // Handles all WM_PAINT messages for the control and paints // the control for the progress state. // // Parameters: // hWnd HWND Handle to the control. // dwProgress DWORD Progress amount - between 1 and 100 // // Return Value: // LONG 0L. // ///////////////////////////////////////////////////////////////////////////// LONG ProgressPaint (HWND hWnd, DWORD dwProgress) { PAINTSTRUCT ps; LPRECT lpRect; RECT rect; // RECT rc2; HDC hDC; COLORREF rgCr[CCOLORS]; HPEN rgHPen[CCOLORS]; int iColor, len; TCHAR szTemp[20]; SIZE Size; HBRUSH hBrushFace; HBRUSH hBrushCtl; int x1, x2, y1, y2; if (dwProgress > 100) return 0L; lpRect = ▭ hDC = BeginPaint (hWnd, &ps); // // Get colors that we'll need. We do not want to cache these // items since we may our top-level parent window may have // received a WM_WININICHANGE message at which time the control // is repainted. Since this control never sees that message, // we cannot assume that colors will remain the same throughout // the life of the control. // for (iColor = 0; iColor < CCOLORS; iColor++) { rgCr[iColor] = GetSysColor (rgColorPro[iColor]); rgHPen[iColor] = CreatePen (PS_SOLID, 1, rgCr[iColor]); } // // Draw outer frame of Control and adjust size // GetClientRect (hWnd, lpRect); FrameRect(hDC, lpRect, GetStockObject (BLACK_BRUSH)); hBrushFace = CreateSolidBrush (rgCr[PROGRESSCOLOR_FACE]); InflateRect (lpRect, -1, -1); #ifdef OLD // // Draw the face color and the outer frame // SelectObject (hDC, hBrushFace); SelectObject (hDC, rgHPen[PROGRESSCOLOR_FRAME]); #endif // OLD // // Draw 3D Progress bar within the control // Draw3DRect (hDC, hBrushFace, rgHPen[PROGRESSCOLOR_FRAME], rgHPen[PROGRESSCOLOR_HIGHLIGHT], rgHPen[PROGRESSCOLOR_SHADOW], lpRect->left, lpRect->top, lpRect->right * dwProgress / 100, lpRect->bottom); // // Now draw the rest of the control rectangle in Window color // (this will erase any text from last call) // x1 = (lpRect->right * dwProgress / 100)+ 1; if (x1 > lpRect->right) x1= lpRect->right; y1 = lpRect->top + 1; x2 = lpRect->right - 1; y2 = lpRect->bottom - 1; hBrushCtl = CreateSolidBrush (rgCr[PROGRESSCOLOR_WINDOW]); SelectObject (hDC, hBrushCtl); SelectObject (hDC, rgHPen[PROGRESSCOLOR_WINDOW]); Rectangle (hDC, x1, y1, x2, y2); // // Now draw text % centered with-in the rectangle // len = wsprintf (szTemp, TEXT("%3d%%"), dwProgress); GetTextExtentPoint32 (hDC, szTemp, len, &Size); #ifdef OLD rc2.left = (lpRect->right - Size.cx) / 2; rc2.top = (lpRect->bottom - Size.cy) / 2; rc2.right = rc2.left + Size.cx; rc2.bottom = rc2.top + Size.cy; #endif // OLD SetBkMode (hDC, TRANSPARENT); SetTextColor (hDC, GetSysColor(COLOR_BTNTEXT)); ExtTextOut (hDC, (lpRect->right-Size.cx)/2, (lpRect->bottom-Size.cy)/2, 0L, lpRect, szTemp, len, NULL); // // Clean up // EndPaint(hWnd, &ps); DeleteObject (hBrushFace); DeleteObject (hBrushCtl); for (iColor = 0; iColor < CCOLORS; iColor++) { if (rgHPen[iColor]) DeleteObject (rgHPen[iColor]); } return 0L; } ///////////////////////////////////////////////////////////////////////////// // // Draw3DRect // // Description: // Draws the 3D button look within a given rectangle. This rectangle // is assumed to be bounded by a one pixel black border, so everything // is bumped in by one. // // Parameters: // hDC DC to draw to. // hBrushFace HBRUSH rectangle fill color brush. // hPenFrame HPEN rectangle frame color pen. // hPenHigh HPEN highlight color pen. // hPenShadow HPEN shadow color pen. // x1 int Upper left corner x. // y1 int Upper left corner y. // x2 int Lower right corner x. // y2 int Lower right corner y. // // NOTE: hBrushFace and hPenFrame are usually the same color, only one // is a Pen used to draw the rectangle frame and the brush color // is used to fill the rectangle. Then the highlight and shadow // pens are used to create the 3D effect. // // Return Value: // void // ///////////////////////////////////////////////////////////////////////////// void Draw3DRect (HDC hDC, HBRUSH hBrushFace, HPEN hPenFrame, HPEN hPenHigh, HPEN hPenShadow, int x1, int y1, int x2, int y2) { HPEN hPenOrg; RECT rect; if (x1 < 0) x1 = 0; if (x2 < 1) x2 = 1; if (y1 < 1) y1 = 1; if (y2 < 0) y2 = 0; if (!(x1 < x2)) x1 = x2; if (!(y1 < y2)) y1 = y2; // // Draw the face color and the rectangle frame // SelectObject (hDC, hBrushFace); hPenOrg = SelectObject (hDC, hPenFrame); Rectangle (hDC, x1, y1, x2, y2); // // Shrink the rectangle to account for borders. // x1+=1; x2-=1; y1+=1; y2-=1; if (x2 < 1) x2 = 1; if (y2 < 1) y2 = 1; if (!(x1 < x2)) x1 = x2; if (!(y1 < y2)) y1 = y2; SelectObject (hDC, hPenShadow); // // Lowest shadow line. // MoveToEx (hDC, x1, y2, NULL); LineTo (hDC, x2, y2); LineTo (hDC, x2, y1-1); // // Upper shadow line. // MoveToEx (hDC, x1+1, y2-1, NULL); LineTo (hDC, x2-1, y2-1); LineTo (hDC, x2-1, y1); SelectObject (hDC, hPenHigh); // // Upper highlight line. // MoveToEx (hDC, x1, y2-1, NULL); LineTo (hDC, x1, y1); LineTo (hDC, x2, y1); if (hPenOrg) SelectObject (hDC, hPenOrg); return; } // If using the ExtTextOut method for progress ctl, these globals are needed DWORD rgbFG; DWORD rgbBG; ///////////////////////////////////////////////////////////////////////////// // // ProgressPaint2 // // Description: // // Handles all WM_PAINT messages for the control and paints // the control for the progress state. // // Parameters: // hWnd HWND Handle to the control. // dwProgress DWORD Progress amount - between 1 and 100 // // Return Value: // LONG 0L. // // // This is an alternate way to do the progress bar in the control. Instead // of drawing a rectangle, it uses ExtTextOut to draw the opagueing rect // based on the percentage complete. Clever. // ///////////////////////////////////////////////////////////////////////////// LONG ProgressPaint2 (HWND hWnd, DWORD dwProgress) { PAINTSTRUCT ps; HDC hDC; TCHAR szTemp[20]; int dx, dy, len; RECT rc1, rc2; SIZE Size; DWORD rgbFG; DWORD rgbBG; rgbBG = RGB( 0, 0, 255); rgbFG = RGB(255, 255, 255); hDC = BeginPaint (hWnd, &ps); GetClientRect (hWnd, &rc1); FrameRect (hDC, &rc1, GetStockObject(BLACK_BRUSH)); InflateRect (&rc1, -1, -1); rc2 = rc1; dx = rc1.right; dy = rc1.bottom; rc1.right = rc2.left = (dwProgress * dx / 100) + 1; len = wsprintf (szTemp, TEXT("%3d%%"), dwProgress); GetTextExtentPoint32 (hDC, szTemp, len, &Size); SetBkColor (hDC, rgbBG); SetTextColor (hDC, rgbFG); ExtTextOut (hDC, (dx-Size.cx)/2, (dy-Size.cy)/2, ETO_OPAQUE | ETO_CLIPPED, &rc1, szTemp, len, NULL); SetBkColor (hDC, rgbFG); SetTextColor (hDC, rgbBG); ExtTextOut (hDC, (dx-Size.cx)/2, (dy-Size.cy)/2, ETO_OPAQUE | ETO_CLIPPED, &rc2, szTemp, len, NULL); EndPaint (hWnd, &ps); return 0L; } ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// #endif // LATER