mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
410 lines
9.2 KiB
410 lines
9.2 KiB
/*++
|
|
|
|
Copyright (c) 1995 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
forms.c
|
|
|
|
Abstract:
|
|
|
|
Functions for manipulating forms
|
|
|
|
Environment:
|
|
|
|
PCL-XL driver, user and kernel mode
|
|
|
|
Revision History:
|
|
|
|
11/07/95 -davidx-
|
|
Created it.
|
|
|
|
mm/dd/yy -author-
|
|
description
|
|
|
|
--*/
|
|
|
|
#include "xllib.h"
|
|
|
|
|
|
|
|
BOOL
|
|
ValidDevmodeForm(
|
|
HANDLE hPrinter,
|
|
PDEVMODE pdm,
|
|
PFORM_INFO_1 pFormInfo,
|
|
PWSTR pFormName
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Validate the form specification in a devmode
|
|
|
|
Arguments:
|
|
|
|
hPrinter - Handle to the printer object
|
|
pdm - Pointer to the input devmode
|
|
pFormInfo - Pointer to a FORM_INFO_1 structure for returning
|
|
information about the logical form specified by the input devmode
|
|
pFormName - Buffer to storing form name and pFormInfo->pName is set to
|
|
this upon successful return
|
|
|
|
Return Value:
|
|
|
|
TRUE if the input devmode specifies a valid logical form
|
|
FALSE otherwise
|
|
|
|
--*/
|
|
|
|
{
|
|
PFORM_INFO_1 pForm, pFormDB;
|
|
DWORD cForms;
|
|
|
|
Assert(pFormInfo != NULL && pFormName != NULL);
|
|
|
|
//
|
|
// Get a list of forms in the system
|
|
//
|
|
|
|
if (! (pForm = pFormDB = GetFormsDatabase(hPrinter, &cForms))) {
|
|
|
|
Error(("Couldn't get system forms\n"));
|
|
return FALSE;
|
|
}
|
|
|
|
if (CustomDevmodeForm(pdm)) {
|
|
|
|
LONG width, height;
|
|
|
|
//
|
|
// Devmode is specifying a custom form whose width
|
|
// and height are measured in 0.1mm. Convert the unit to micron.
|
|
//
|
|
|
|
width = pdm->dmPaperWidth * 100;
|
|
height = pdm->dmPaperLength * 100;
|
|
|
|
//
|
|
// Go through the forms database and check if
|
|
// one of the forms has the same size as what's
|
|
// being requested. The tolerance is 1mm.
|
|
//
|
|
|
|
while ((cForms != 0) &&
|
|
(abs(width - pForm->Size.cx) > FORMSIZE_TOLERANCE ||
|
|
abs(height - pForm->Size.cy) > FORMSIZE_TOLERANCE))
|
|
{
|
|
cForms--;
|
|
pForm++;
|
|
}
|
|
|
|
//
|
|
// Custom size doesn't match that of any defined forms
|
|
//
|
|
|
|
if (cForms == 0) {
|
|
|
|
pFormInfo->Flags = 0;
|
|
pFormInfo->Size.cx = width;
|
|
pFormInfo->Size.cy = height;
|
|
pFormInfo->ImageableArea.left =
|
|
pFormInfo->ImageableArea.top = 0;
|
|
pFormInfo->ImageableArea.right = width;
|
|
pFormInfo->ImageableArea.bottom = height;
|
|
|
|
pFormInfo->pName = pFormName;
|
|
pFormName[0] = NUL;
|
|
|
|
MemFree(pFormDB);
|
|
return TRUE;
|
|
}
|
|
|
|
} else if (pdm->dmFields & DM_PAPERSIZE && pdm->dmPaperSize >= DMPAPER_FIRST) {
|
|
|
|
//
|
|
// Devmode is specifying a form using paper size index.
|
|
//
|
|
|
|
DWORD index = pdm->dmPaperSize - DMPAPER_FIRST;
|
|
|
|
if (index < cForms)
|
|
pForm = pFormDB + index;
|
|
|
|
} else if (pdm->dmFields & DM_FORMNAME) {
|
|
|
|
//
|
|
// Devmode is specifying a form using form name. Go through the forms database
|
|
// and check if the requested form name matches that of a form in the database.
|
|
//
|
|
|
|
while (cForms && wcscmp(pForm->pName, pdm->dmFormName) != EQUAL_STRING)
|
|
cForms--, pForm++;
|
|
|
|
if (cForms == 0)
|
|
pForm = NULL;
|
|
}
|
|
|
|
//
|
|
// If devmode is specifying a valid logical form, then return the form information
|
|
// in the provided buffer. Also update the devmode fields.
|
|
//
|
|
|
|
if (pForm != NULL) {
|
|
|
|
*pFormInfo = *pForm;
|
|
CopyStringW(pFormName, pForm->pName, CCHFORMNAME);
|
|
pFormInfo->pName = pFormName;
|
|
|
|
//
|
|
// Convert paper size unit from microns to 0.1mm
|
|
//
|
|
|
|
pdm->dmPaperWidth = pForm->Size.cx / 100;
|
|
pdm->dmPaperLength = pForm->Size.cy / 100;
|
|
pdm->dmPaperSize = (SHORT) (pForm - pFormDB);
|
|
pdm->dmFields |= DM_FORMNAME;
|
|
CopyStringW(pdm->dmFormName, pForm->pName, CCHFORMNAME);
|
|
}
|
|
|
|
MemFree(pFormDB);
|
|
return pForm != NULL;
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
MapToPrinterForm(
|
|
PMPD pmpd,
|
|
PFORM_INFO_1 pFormInfo,
|
|
PPRINTERFORM pPrinterForm,
|
|
BOOL bStringent
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Map a logical form to a printer paper size
|
|
|
|
Arguments:
|
|
|
|
pmpd - Pointer to printer description data
|
|
pFormInfo - Pointer to logical form information
|
|
pPrinterForm - Pointer to a buffer for returning printer form information
|
|
bStringent - Whether to use more stringent criteria
|
|
|
|
Return Value:
|
|
|
|
TRUE if the logical form is supported on the printer
|
|
FALSE otherwise
|
|
|
|
--*/
|
|
|
|
{
|
|
LONG width, height;
|
|
WORD selection;
|
|
PFEATURE pFeature;
|
|
PPAPERSIZE pPaperSize, pNext;
|
|
|
|
width = pFormInfo->Size.cx;
|
|
height = pFormInfo->Size.cy;
|
|
|
|
//
|
|
// First check if the logical form name matches the name of a printer form.
|
|
//
|
|
|
|
Assert(pFormInfo->pName != NULL);
|
|
|
|
pFeature = MpdPaperSizes(pmpd);
|
|
Assert(pFeature->size == sizeof(PAPERSIZE));
|
|
|
|
pPaperSize = FindNamedSelection(pFeature, pFormInfo->pName, &selection);
|
|
|
|
if (pPaperSize == NULL && (!bStringent || IsUserDefinedForm(pFormInfo))) {
|
|
|
|
LONG dx, dy, minxy;
|
|
WORD index;
|
|
|
|
//
|
|
// There is no name match. Try to find out if there is a
|
|
// printer form whose size matches that of the logical form.
|
|
//
|
|
|
|
minxy = MAX_LONG;
|
|
|
|
for (index=0; index < pFeature->count; index++) {
|
|
|
|
pNext = FindIndexedSelection(pFeature, index);
|
|
|
|
//
|
|
// Compare the current size with the desired size.
|
|
//
|
|
|
|
dx = pNext->size.cx - width;
|
|
dy = pNext->size.cy - height;
|
|
|
|
//
|
|
// Check if we have an exact size match. Tolerance is 1mm.
|
|
//
|
|
|
|
if (abs(dx) <= FORMSIZE_TOLERANCE && abs(dy) <= FORMSIZE_TOLERANCE) {
|
|
|
|
selection = index;
|
|
pPaperSize = pNext;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Not an exact match, see if we could fit on this form.
|
|
//
|
|
|
|
if (dx >= 0 && dy >= 0) {
|
|
|
|
//
|
|
// Check to see if the current form is smaller than
|
|
// the smallest one we've found so far.
|
|
//
|
|
|
|
if (dx+dy < minxy) {
|
|
|
|
//
|
|
// Tentatively remember it as the smallest size.
|
|
//
|
|
|
|
selection = index;
|
|
pPaperSize = pNext;
|
|
minxy = dx + dy;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// If there is no exact size match and the printer supports
|
|
// custom paper size and the requested size is not too big,
|
|
// then go ahead and select custom paper size on the printer.
|
|
//
|
|
|
|
if (index == pFeature->count && SupportCustomSize(pmpd, width, height)) {
|
|
|
|
if (pPrinterForm) {
|
|
|
|
pPrinterForm->name[0] = NUL;
|
|
pPrinterForm->size = pFormInfo->Size;
|
|
pPrinterForm->imageableArea = pFormInfo->ImageableArea;
|
|
pPrinterForm->selection = SELIDX_ANY;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
//
|
|
// If the logical form is mapped to a printer paper size, then
|
|
// return information about the printer paper size to the caller
|
|
//
|
|
|
|
if (pPaperSize && pPrinterForm) {
|
|
|
|
pPrinterForm->imageableArea = pPaperSize->imageableArea;
|
|
RectIntersect(&pPrinterForm->imageableArea, &pFormInfo->ImageableArea);
|
|
|
|
pPrinterForm->size = pPaperSize->size;
|
|
pPrinterForm->selection = selection;
|
|
CopyStringW(pPrinterForm->name, pPaperSize->pName, CCHFORMNAME);
|
|
}
|
|
|
|
return (pPaperSize != NULL);
|
|
}
|
|
|
|
|
|
|
|
PFORM_INFO_1
|
|
GetFormsDatabase(
|
|
HANDLE hPrinter,
|
|
PDWORD pCount
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Return a collection of forms in the spooler database
|
|
|
|
Arguments:
|
|
|
|
hPrinter - Handle to a printer object
|
|
pCount - Points to a variable for returning total number of forms
|
|
|
|
Return Value:
|
|
|
|
Pointer to an array of FORM_INFO_1 structures if successful
|
|
NULL otherwise
|
|
|
|
--*/
|
|
|
|
{
|
|
PFORM_INFO_1 pFormDB = NULL;
|
|
DWORD cbNeeded;
|
|
|
|
if (!EnumForms(hPrinter, 1, NULL, 0, &cbNeeded, pCount) &&
|
|
GetLastError() == ERROR_INSUFFICIENT_BUFFER &&
|
|
(pFormDB = MemAlloc(cbNeeded)) != NULL &&
|
|
EnumForms(hPrinter, 1, (PBYTE) pFormDB, cbNeeded, &cbNeeded, pCount))
|
|
{
|
|
return pFormDB;
|
|
}
|
|
|
|
MemFree(pFormDB);
|
|
return NULL;
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
FilterFormsDatabase(
|
|
PFORM_INFO_1 pFormDB,
|
|
DWORD cForms,
|
|
PMPD pmpd
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Determine which system forms are supported on the given printer
|
|
|
|
Arguments:
|
|
|
|
pFormDB - Points to a list of forms in the system
|
|
cForms - Number of forms
|
|
pmpd - Points to printer description data
|
|
|
|
Return Value:
|
|
|
|
NONE
|
|
|
|
--*/
|
|
|
|
{
|
|
PRINTERFORM printerForm;
|
|
|
|
while (cForms--) {
|
|
|
|
//
|
|
// Make sure the highest order bits are not used by the spooler
|
|
//
|
|
|
|
Assert(!IsSupportedForm(pFormDB));
|
|
|
|
if (MapToPrinterForm(pmpd, pFormDB, &printerForm, TRUE)) {
|
|
|
|
SetSupportedFormIndex(pFormDB, printerForm.selection);
|
|
}
|
|
|
|
pFormDB++;
|
|
}
|
|
}
|
|
|
|
|