619 lines
13 KiB
C
619 lines
13 KiB
C
/*++
|
||
|
||
Copyright (c) 1995 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
fontsub.c
|
||
|
||
Abstract:
|
||
|
||
Function for handling TrueType font substitution dialog
|
||
|
||
[Environment:]
|
||
|
||
Win32 subsystem, PostScript driver UI
|
||
|
||
[Notes:]
|
||
|
||
Revision History:
|
||
|
||
02/10/97 -davidx-
|
||
Consistent handling of common printer info.
|
||
|
||
09/18/96 - amandan-
|
||
Modified for common binary data and UI
|
||
|
||
08/29/95 -davidx-
|
||
Created it.
|
||
|
||
--*/
|
||
|
||
#include "precomp.h"
|
||
|
||
|
||
VOID
|
||
VSetupTrueTypeFontMappings(
|
||
IN PUIDATA pUiData
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Initialize the font substitution items with the settings from
|
||
current font substitution table.
|
||
|
||
Arguments:
|
||
|
||
pUiData - Points to UIDATA structure
|
||
|
||
Return Value:
|
||
|
||
NONE
|
||
|
||
--*/
|
||
|
||
{
|
||
POPTITEM pOptItem;
|
||
POPTPARAM pOptParam;
|
||
DWORD dwOptItem;
|
||
PWSTR pTTSubstTable;
|
||
|
||
//
|
||
// Get the current font substitution table
|
||
//
|
||
|
||
if ((pTTSubstTable = PGetTTSubstTable(pUiData->ci.hPrinter, NULL)) == NULL &&
|
||
(pTTSubstTable = GET_DEFAULT_FONTSUB_TABLE(&pUiData->ci, pUiData->ci.pUIInfo)) == NULL)
|
||
{
|
||
WARNING(("Font substitution table is not available\n"));
|
||
return;
|
||
}
|
||
|
||
//
|
||
// For each TrueType font, check if there is a device font mapped to it.
|
||
// If there is, find the index of the device font in the selection list.
|
||
//
|
||
|
||
pOptItem = pUiData->pTTFontItems;
|
||
dwOptItem = pUiData->dwTTFontItem;
|
||
|
||
while (dwOptItem--)
|
||
{
|
||
DWORD dwOptParam, dwIndex;
|
||
LPCTSTR pDevFontName;
|
||
|
||
ASSERT(ISFONTSUBSTITEM(pOptItem->UserData));
|
||
|
||
pOptItem->Sel = 0;
|
||
pDevFontName = PtstrSearchTTSubstTable(pTTSubstTable, pOptItem->pName);
|
||
|
||
//
|
||
// Check if we found a match
|
||
//
|
||
|
||
if (pDevFontName != NULL && *pDevFontName != NUL)
|
||
{
|
||
|
||
//
|
||
// Get the total substitution font list
|
||
//
|
||
|
||
dwOptParam = pOptItem->pOptType->Count;
|
||
pOptParam = pOptItem->pOptType->pOptParam;
|
||
|
||
//
|
||
// Skip the first device font name in the list
|
||
// which should always be "Download as Soft Font".
|
||
//
|
||
|
||
for (dwIndex=1; dwIndex < dwOptParam; dwIndex++)
|
||
{
|
||
if (_wcsicmp(pDevFontName, pOptParam[dwIndex].pData) == EQUAL_STRING)
|
||
{
|
||
pOptItem->Sel = dwIndex;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
pOptItem++;
|
||
}
|
||
|
||
//
|
||
// Remember to free the memory occupied by the substitution
|
||
// table after we're done with it.
|
||
//
|
||
|
||
FREE_DEFAULT_FONTSUB_TABLE(pTTSubstTable);
|
||
}
|
||
|
||
|
||
|
||
int __cdecl
|
||
ICompareOptParam(
|
||
const void *p1,
|
||
const void *p2
|
||
)
|
||
|
||
{
|
||
return _wcsicmp(((POPTPARAM) p1)->pData, ((POPTPARAM) p2)->pData);
|
||
}
|
||
|
||
|
||
POPTTYPE
|
||
PFillDevFontOptType(
|
||
IN PUIDATA pUiData
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Initialize an OPTTYPE structure to hold information
|
||
about the list of device fonts supported by a printer
|
||
|
||
Arguments:
|
||
|
||
pUiData - Pointer to UIDATA structure
|
||
|
||
Return Value:
|
||
|
||
Pointer to an OPTTYPE structure
|
||
NULL if there is an error
|
||
|
||
--*/
|
||
|
||
{
|
||
POPTTYPE pOptType;
|
||
POPTPARAM pOptParam;
|
||
HDC hdc;
|
||
DWORD dwCount, dwIndex;
|
||
INT iSize;
|
||
PWSTR pwstrFontNames, pwstr;
|
||
|
||
//
|
||
// Get the list of printer device font names
|
||
//
|
||
|
||
dwCount = 0;
|
||
|
||
if ((hdc = CreateIC(NULL, pUiData->ci.pPrinterName, NULL, NULL)) &&
|
||
(iSize = _IListDevFontNames(hdc, NULL, 0)) > 0 &&
|
||
(pwstrFontNames = HEAPALLOC(pUiData->ci.hHeap, iSize)) &&
|
||
(iSize == _IListDevFontNames(hdc, pwstrFontNames, iSize)))
|
||
{
|
||
//
|
||
// Count the number of device font names
|
||
//
|
||
|
||
for (pwstr=pwstrFontNames; *pwstr; pwstr += wcslen(pwstr)+1)
|
||
dwCount++;
|
||
}
|
||
else
|
||
{
|
||
ERR(("Couldn't enumerate printer device fonts\n"));
|
||
}
|
||
|
||
if (hdc)
|
||
DeleteDC(hdc);
|
||
|
||
//
|
||
// Generate an OPTTYPE structure for device font list
|
||
//
|
||
|
||
pOptType = HEAPALLOC(pUiData->ci.hHeap, sizeof(OPTTYPE));
|
||
pOptParam = HEAPALLOC(pUiData->ci.hHeap, sizeof(OPTPARAM) * (dwCount+1));
|
||
|
||
if (pOptType == NULL || pOptParam == NULL)
|
||
{
|
||
ERR(("Memory allocation failed\n"));
|
||
return NULL;
|
||
}
|
||
|
||
pOptType->cbSize = sizeof(OPTTYPE);
|
||
pOptType->Count = (WORD) (dwCount+1);
|
||
pOptType->Type = TVOT_LISTBOX;
|
||
pOptType->pOptParam = pOptParam;
|
||
|
||
//
|
||
// Initialize OPTPARAM structures.
|
||
// The first item is always "Download as Soft Font".
|
||
//
|
||
|
||
for (dwIndex=0; dwIndex <= dwCount; dwIndex++)
|
||
pOptParam[dwIndex].cbSize = sizeof(OPTPARAM);
|
||
|
||
pOptParam->pData = (PWSTR) IDS_DOWNLOAD_AS_SOFTFONT;
|
||
pOptParam++;
|
||
|
||
// hack to get around a compiler bug
|
||
|
||
dwCount++;
|
||
dwCount--;
|
||
|
||
for (dwIndex=0, pwstr=pwstrFontNames; dwIndex < dwCount; dwIndex++)
|
||
{
|
||
pOptParam[dwIndex].pData = pwstr;
|
||
pwstr += wcslen(pwstr) + 1;
|
||
}
|
||
|
||
//
|
||
// Sort device font names into alphabetical order;
|
||
// Hide any duplicate device font names as well.
|
||
//
|
||
|
||
qsort(pOptParam, dwCount, sizeof(OPTPARAM), ICompareOptParam);
|
||
|
||
for (dwIndex=1; dwIndex < dwCount; dwIndex++)
|
||
{
|
||
if (_wcsicmp(pOptParam[dwIndex].pData, pOptParam[dwIndex-1].pData) == EQUAL_STRING)
|
||
pOptParam[dwIndex].Flags |= OPTPF_HIDE;
|
||
}
|
||
|
||
return pOptType;
|
||
}
|
||
|
||
|
||
|
||
//
|
||
// Data structures and functions for enumerating printer device fonts
|
||
//
|
||
|
||
typedef struct _ENUMTTFONT {
|
||
|
||
DWORD dwCount;
|
||
POPTITEM pOptItem;
|
||
POPTTYPE pOptType;
|
||
HANDLE hHeap;
|
||
WCHAR awchLastFontName[LF_FACESIZE];
|
||
|
||
} ENUMTTFONT, *PENUMTTFONT;
|
||
|
||
INT CALLBACK
|
||
EnumTTFontProc(
|
||
ENUMLOGFONT *pelf,
|
||
NEWTEXTMETRIC *pntm,
|
||
INT FontType,
|
||
LPARAM lParam
|
||
)
|
||
|
||
{
|
||
PENUMTTFONT pEnumData;
|
||
PTSTR pFontName;
|
||
PTSTR pFamilyName;
|
||
|
||
//
|
||
// We only care about the TrueType fonts.
|
||
//
|
||
|
||
if (! (FontType & TRUETYPE_FONTTYPE))
|
||
return 1;
|
||
|
||
pEnumData = (PENUMTTFONT) lParam;
|
||
pFamilyName = pelf->elfLogFont.lfFaceName;
|
||
|
||
if (_tcscmp(pFamilyName, pEnumData->awchLastFontName) == EQUAL_STRING)
|
||
return 1;
|
||
|
||
CopyString(pEnumData->awchLastFontName, pFamilyName, LF_FACESIZE);
|
||
pEnumData->dwCount++;
|
||
|
||
if (pEnumData->pOptItem)
|
||
{
|
||
pFontName = PtstrDuplicateStringFromHeap(pFamilyName, pEnumData->hHeap);
|
||
|
||
if (pFontName == NULL)
|
||
return 0;
|
||
|
||
FILLOPTITEM(pEnumData->pOptItem,
|
||
pEnumData->pOptType,
|
||
pFontName,
|
||
0,
|
||
TVITEM_LEVEL2,
|
||
DMPUB_NONE,
|
||
FONT_SUBST_ITEM,
|
||
HELP_INDEX_TTTODEV);
|
||
|
||
pEnumData->pOptItem++;
|
||
}
|
||
|
||
return 1;
|
||
}
|
||
|
||
|
||
int __cdecl
|
||
ICompareOptItem(
|
||
const void *p1,
|
||
const void *p2
|
||
)
|
||
|
||
{
|
||
return _wcsicmp(((POPTITEM) p1)->pName, ((POPTITEM) p2)->pName);
|
||
}
|
||
|
||
|
||
BOOL
|
||
BPackItemFontSubstTable(
|
||
IN OUT PUIDATA pUiData
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Pack Font Substitution options
|
||
|
||
Arguments:
|
||
|
||
pUiData - Points to UIDATA structure
|
||
|
||
Return Value:
|
||
|
||
TRUE if successful, FALSE if there is an error.
|
||
|
||
--*/
|
||
|
||
{
|
||
ENUMTTFONT EnumData;
|
||
POPTITEM pOptItem;
|
||
HDC hdc;
|
||
INT iResult;
|
||
|
||
//
|
||
// If the printer doesn't support font-substitution,
|
||
// then simply return success here.
|
||
//
|
||
|
||
if (pUiData->ci.pUIInfo->dwFontSubCount == 0)
|
||
return TRUE;
|
||
|
||
//
|
||
// Create a screen IC
|
||
//
|
||
|
||
if ((hdc = CreateIC(TEXT("DISPLAY"), NULL, NULL, NULL)) == NULL)
|
||
{
|
||
ERR(("Cannot create screen IC\n"));
|
||
return FALSE;
|
||
}
|
||
|
||
//
|
||
// Font substitution table
|
||
// TrueType font <-> Device font
|
||
// ....
|
||
//
|
||
// Group Header for Font Substitution Table
|
||
//
|
||
|
||
pOptItem = pUiData->pOptItem;
|
||
|
||
VPackOptItemGroupHeader(
|
||
pUiData,
|
||
IDS_FONTSUB_TABLE,
|
||
IDI_CPSUI_FONTSUB,
|
||
HELP_INDEX_FONTSUB_TABLE);
|
||
|
||
ZeroMemory(&EnumData, sizeof(EnumData));
|
||
EnumData.hHeap = pUiData->ci.hHeap;
|
||
|
||
if (pOptItem == NULL)
|
||
{
|
||
//
|
||
// Count the number of TrueType fonts
|
||
//
|
||
|
||
iResult = EnumFontFamilies(hdc,
|
||
NULL,
|
||
(FONTENUMPROC) EnumTTFontProc,
|
||
(LPARAM) &EnumData);
|
||
}
|
||
else
|
||
{
|
||
//
|
||
// Collapse the group header
|
||
//
|
||
|
||
pOptItem->Flags |= OPTIF_COLLAPSE;
|
||
|
||
pUiData->pTTFontItems = pUiData->pOptItem;
|
||
EnumData.pOptItem = pUiData->pOptItem;
|
||
|
||
//
|
||
// Get the list of printer device fonts
|
||
//
|
||
|
||
EnumData.pOptType = PFillDevFontOptType(pUiData);
|
||
|
||
if (EnumData.pOptType == NULL)
|
||
{
|
||
ERR(("PFillDevFontOptType failed\n"));
|
||
iResult = 0;
|
||
}
|
||
else
|
||
{
|
||
//
|
||
// Enumerate the list of TrueType fonts
|
||
//
|
||
|
||
iResult = EnumFontFamilies(hdc,
|
||
NULL,
|
||
(FONTENUMPROC) EnumTTFontProc,
|
||
(LPARAM) &EnumData);
|
||
|
||
if (iResult == 0 || EnumData.dwCount != pUiData->dwTTFontItem)
|
||
{
|
||
ERR(("Inconsistent number of TrueType fonts\n"));
|
||
iResult = 0;
|
||
}
|
||
else
|
||
{
|
||
//
|
||
// Sort the TrueType font items alphabetically
|
||
//
|
||
|
||
qsort(pUiData->pTTFontItems,
|
||
pUiData->dwTTFontItem,
|
||
sizeof(OPTITEM),
|
||
ICompareOptItem);
|
||
}
|
||
}
|
||
}
|
||
|
||
DeleteDC(hdc);
|
||
|
||
if (iResult == 0)
|
||
{
|
||
ERR(("Failed to enumerate TrueType fonts\n"));
|
||
return FALSE;
|
||
}
|
||
|
||
pUiData->dwTTFontItem = EnumData.dwCount;
|
||
pUiData->dwOptItem += pUiData->dwTTFontItem;
|
||
|
||
if (pUiData->pOptItem)
|
||
{
|
||
pUiData->pOptItem += pUiData->dwTTFontItem;
|
||
VSetupTrueTypeFontMappings(pUiData);
|
||
}
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
|
||
DWORD
|
||
DwCollectTrueTypeMappings(
|
||
IN POPTITEM pOptItem,
|
||
IN DWORD dwOptItem,
|
||
OUT PWSTR pwstrTable
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Assemble TrueType to device font mappings into a table
|
||
|
||
Arguments:
|
||
|
||
pOptItem - Pointer to an array of OPTITEMs
|
||
cOptItem - Number of OPTITEMs
|
||
pwstrTable - Pointer to memory buffer for storing the table.
|
||
NULL if we're only interested in table size.
|
||
|
||
Return Value:
|
||
|
||
Size of the table bytes, 0 if there is an error.
|
||
|
||
--*/
|
||
|
||
{
|
||
DWORD dwChars = 0;
|
||
INT iLength;
|
||
POPTPARAM pOptParam;
|
||
|
||
while (dwOptItem--)
|
||
{
|
||
ASSERT(ISFONTSUBSTITEM(pOptItem->UserData));
|
||
|
||
if (pOptItem->Sel > 0)
|
||
{
|
||
iLength = wcslen(pOptItem->pName) + 1;
|
||
dwChars += iLength;
|
||
|
||
if (pwstrTable != NULL)
|
||
{
|
||
CopyMemory(pwstrTable, pOptItem->pName, iLength*sizeof(WCHAR));
|
||
pwstrTable += iLength;
|
||
}
|
||
|
||
pOptParam = pOptItem->pOptType->pOptParam + pOptItem->Sel;
|
||
|
||
iLength = wcslen(pOptParam->pData) + 1;
|
||
dwChars += iLength;
|
||
|
||
if (pwstrTable != NULL)
|
||
{
|
||
CopyMemory(pwstrTable, pOptParam->pData, iLength*sizeof(WCHAR));
|
||
pwstrTable += iLength;
|
||
}
|
||
}
|
||
|
||
pOptItem++;
|
||
}
|
||
|
||
//
|
||
// Append a NUL character at the end of the table
|
||
//
|
||
|
||
dwChars++;
|
||
|
||
if (pwstrTable != NULL)
|
||
*pwstrTable = NUL;
|
||
|
||
//
|
||
// Return the table size in bytes
|
||
//
|
||
|
||
return dwChars * sizeof(WCHAR);
|
||
}
|
||
|
||
|
||
|
||
BOOL
|
||
BUnpackItemFontSubstTable(
|
||
IN PUIDATA pUiData
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Extract substitution table from treeview items
|
||
|
||
Arguments:
|
||
|
||
pUiData - Pointer to UIDATA structure
|
||
|
||
Return Value:
|
||
|
||
TRUE if successful, FALSE otherwise
|
||
|
||
--*/
|
||
|
||
{
|
||
DWORD dwTableSize;
|
||
PWSTR pwstrTable = NULL;
|
||
POPTITEM pOptItem = pUiData->pTTFontItems;
|
||
DWORD dwOptItem = pUiData->dwTTFontItem;
|
||
|
||
//
|
||
// Check if any changes were made to font-substitution items
|
||
//
|
||
|
||
if (! BOptItemSelectionsChanged(pOptItem, dwOptItem))
|
||
return TRUE;
|
||
|
||
//
|
||
// Figure out how much memory we need to save the font substitution table
|
||
// Assemble the font substitution table
|
||
// Save the TrueType font substitution table to registry
|
||
//
|
||
|
||
if ((dwTableSize = DwCollectTrueTypeMappings(pOptItem, dwOptItem, NULL)) == 0 ||
|
||
(pwstrTable = MemAlloc(dwTableSize)) == NULL ||
|
||
(dwTableSize != DwCollectTrueTypeMappings(pOptItem, dwOptItem, pwstrTable)) ||
|
||
!BSaveTTSubstTable(pUiData->ci.hPrinter, pwstrTable, dwTableSize))
|
||
{
|
||
ERR(("Couldn't save font substitution table\n"));
|
||
MemFree(pwstrTable);
|
||
return FALSE;
|
||
}
|
||
|
||
MemFree(pwstrTable);
|
||
return TRUE;
|
||
}
|
||
|