Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

566 lines
13 KiB

/*++
Copyright (c) 1995 Microsoft Corporation
Module Name:
forms.c
Abstract:
Functions for dealing with paper and forms.
[Environment:]
Win32 subsystem, PostScript driver
Revision History:
07/25/95 -davidx-
Created it.
mm/dd/yy -author-
description
--*/
#include "pslib.h"
PCWSTR
GetDefaultFormName(
BOOL bMetric
)
/*++
Routine Description:
Retrieve a pointer to the default form name
Arguments:
bMetric Whether the system is running in a metric country
Return Value:
Pointer to the default form name string
--*/
{
return bMetric ? STDSTR_A4_FORM_NAME : STDSTR_LETTER_FORM_NAME;
}
PFORM_INFO_1
GetDatabaseForms(
HANDLE hprinter,
DWORD *pcount
)
/*++
Routine Description:
Return list of forms in the forms database
Arguments:
hprinter Handle to printer
pcount Pointer to variable for returning number of forms
Return Value:
Pointer to an array of FORM_INFO_1 structures
NULL if an error occurred
--*/
{
DWORD cbNeeded;
PFORM_INFO_1 pdbForms = NULL;
// Find out how much space we need
if (ENUMFORMS(hprinter, 1, NULL, 0, &cbNeeded, pcount) ||
GETLASTERROR() != ERROR_INSUFFICIENT_BUFFER ||
// Allocate memory
(pdbForms = MEMALLOC(cbNeeded)) == NULL ||
// Retrieve forms info
!ENUMFORMS(hprinter, 1, (PBYTE)pdbForms, cbNeeded, &cbNeeded, pcount))
{
DBGERRMSG("ENUMFORMS");
if (pdbForms != NULL) {
MEMFREE(pdbForms);
pdbForms = NULL;
}
}
return pdbForms;
}
INT
ValidateDevModeForm(
HANDLE hPrinter,
PDEVMODE pDevMode,
PLOGFORM pLogForm
)
/*++
Routine Description:
Find the form specified by the input devmode fields
in the forms database and return the correspond FORM_INFO_1
information in the input buffer
Arguments:
hPrinter - Handle to printer object
pDevMode - Pointer to input devmode
pLogForm - Pointer to LOGFORM buffer
[Note:]
Information in pFormInfo is valid only if return value is
VALID_FORM or CUSTOM_FORM.
Return Value:
VALID_FORM Form specified by input devmode is found
CUSTOM_FORM Specified form is user-defined custom form
FORM_ERROR Cannot find the specified form
--*/
{
PFORM_INFO_1 pForms, pSaved;
DWORD cForms;
INT status = FORM_ERROR;
pSaved = pForms = GetDatabaseForms(hPrinter, &cForms);
if (pForms == NULL || cForms == 0) {
DBGERRMSG("GetDatabaseForms");
return status;
}
if (IsCustomForm(pDevMode) && ValidCustomForm(pDevMode)) {
LONG dmPaperWidth, dmPaperLength;
// Devmode is requesting user-defined custom form.
// 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.
dmPaperWidth = pDevMode->dmPaperWidth * DM_PAPER_UNIT;
dmPaperLength = pDevMode->dmPaperLength * DM_PAPER_UNIT;
while (cForms--) {
if (abs(dmPaperWidth - pForms->Size.cx) <= 1000 &&
abs(dmPaperLength - pForms->Size.cy) <= 1000)
{
status = VALID_FORM;
break;
}
pForms++;
}
// Custom size doesn't match that of any defined forms
if (status != VALID_FORM) {
pLogForm->info.Flags = 0;
pLogForm->info.Size.cx = dmPaperWidth;
pLogForm->info.Size.cy = dmPaperLength;
pLogForm->info.ImageableArea.left =
pLogForm->info.ImageableArea.top = 0;
pLogForm->info.ImageableArea.right = dmPaperWidth;
pLogForm->info.ImageableArea.bottom = dmPaperLength;
pLogForm->name[0] = NUL;
status = CUSTOM_FORM;
}
} else if (pDevMode->dmFields & DM_PAPERSIZE) {
// Devmode is requesting a form using paper size index
if (pDevMode->dmPaperSize >= DMPAPER_FIRST &&
pDevMode->dmPaperSize < DMPAPER_FIRST + (LONG) cForms)
{
pForms += (pDevMode->dmPaperSize - DMPAPER_FIRST);
status = VALID_FORM;
}
} else if (pDevMode->dmFields & DM_FORMNAME) {
// Devmode is requesting 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.
for ( ; cForms--; pForms++) {
if (_wcsicmp(pDevMode->dmFormName, pForms->pName) == 0) {
status = VALID_FORM;
break;
}
}
}
if (status == VALID_FORM) {
pLogForm->info = *pForms;
CopyStringW(pLogForm->name, pForms->pName, CCHFORMNAME);
pDevMode->dmPaperWidth = pForms->Size.cx / DM_PAPER_UNIT;
pDevMode->dmPaperLength = pForms->Size.cy / DM_PAPER_UNIT;
pDevMode->dmPaperSize = DMPAPER_FIRST + (pForms - pSaved);
pDevMode->dmFields |= DM_FORMNAME;
CopyStringW(pDevMode->dmFormName, pForms->pName, CCHFORMNAME);
}
pLogForm->info.pName = pLogForm->name;
MEMFREE(pSaved);
return status;
}
VOID
FillPrinterFormInfoCommon(
PPRINTERFORM pPrinterForm,
PFORM_INFO_1 pFormInfo
)
/*++
Routine Description:
Code shared by FillStandardPrinterFormInfo and FillCustomPrinterFormInfo
Arguments:
pPrinterForm Pointer to PRINTERFORM buffer
pFormInfo Pointer to form information
Return Value:
NONE
--*/
{
// Copy system form name
CopyStringW(pPrinterForm->FormName, pFormInfo->pName, CCHFORMNAME);
// Fill in paper size information
pPrinterForm->PaperSize.width = MicronToPSReal(pFormInfo->Size.cx);
pPrinterForm->PaperSize.height = MicronToPSReal(pFormInfo->Size.cy);
// Fill in imageable area information.
// NOTE: Imageable area is stored in default PostScript
// coordinate system. So we need to flip the y-axis.
pPrinterForm->ImageArea.left =
MicronToPSReal(pFormInfo->ImageableArea.left);
pPrinterForm->ImageArea.top =
MicronToPSReal(pFormInfo->Size.cy - pFormInfo->ImageableArea.top);
pPrinterForm->ImageArea.right =
MicronToPSReal(pFormInfo->ImageableArea.right);
pPrinterForm->ImageArea.bottom =
MicronToPSReal(pFormInfo->Size.cy - pFormInfo->ImageableArea.bottom);
// Default to portrait mode
pPrinterForm->bLandscape = FALSE;
}
VOID
FillStandardPrinterFormInfo(
PPRINTERFORM pPrinterForm,
PFORM_INFO_1 pFormInfo,
PMEDIAOPTION pMediaOption
)
/*++
Routine Description:
Return information about printer form specified by pMediaOption
Arguments:
pPrinterForm Pointer to buffer for receiving printer form info
pFormInfo Pointer to database form info
pMediaOption Pointer to printer form MEDIAOPTION object
Return Value:
NONE
--*/
{
// Copy printer form name
strcpy(pPrinterForm->PaperName, pMediaOption->pName);
// Fill in paper size and imageable area information
FillPrinterFormInfoCommon(pPrinterForm, pFormInfo);
// Intersect the imageable area with physical imageable
// of the printer form
pPrinterForm->ImageArea.left =
max(pMediaOption->imageableArea.left, pPrinterForm->ImageArea.left);
pPrinterForm->ImageArea.top =
min(pMediaOption->imageableArea.top, pPrinterForm->ImageArea.top);
pPrinterForm->ImageArea.right =
min(pMediaOption->imageableArea.right, pPrinterForm->ImageArea.right);
pPrinterForm->ImageArea.bottom =
max(pMediaOption->imageableArea.bottom, pPrinterForm->ImageArea.bottom);
}
VOID
FillCustomPrinterFormInfo(
PPRINTERFORM pPrinterForm,
PFORM_INFO_1 pFormInfo,
HPPD hppd
)
/*++
Routine Description:
Return information about a user-defined custom form
Arguments:
pPrinterForm Pointer to buffer for receiving printer form info
pFormInfo Pointer to database form info
hppd Handle to PPD object
Return Value:
NONE
--*/
{
DBGMSG(DBG_LEVEL_WARNING, "Selecting custom page size.\n");
// Empty printer form name
pPrinterForm->PaperName[0] = NUL;
// Fill in paper size and imageable area information
FillPrinterFormInfoCommon(pPrinterForm, pFormInfo);
// For cut-sheet device, we need to clip the imageable area
// to within the hardware margins. Per PPD spec 4.2, four
// numbers are given for top, bottom, left, and right margins.
// But there is no way to figure out which way paper is feed.
// So to ensure a guranteed imageable area, the largest of
// the four numbers is used.
if (hppd->bCutSheet) {
PSREAL margin;
margin = max(hppd->hwMargins.left,hppd->hwMargins.top);
margin = max(margin, hppd->hwMargins.right);
margin = max(margin, hppd->hwMargins.bottom);
pPrinterForm->ImageArea.left = max(margin, pPrinterForm->ImageArea.left);
pPrinterForm->ImageArea.top =
min(pPrinterForm->PaperSize.height - margin, pPrinterForm->ImageArea.top);
pPrinterForm->ImageArea.right =
min(pPrinterForm->PaperSize.width - margin, pPrinterForm->ImageArea.right);
pPrinterForm->ImageArea.bottom = max(margin, pPrinterForm->ImageArea.bottom);
}
}
BOOL
FormSupportedOnPrinter(
HPPD hppd,
PFORM_INFO_1 pFormInfo,
PPRINTERFORM pPrinterForm,
BOOL bStringent
)
/*++
Routine Description:
Determine whether a form is supported on a printer
Arguments:
hppd Handle to PPD object
pFormInfo Pointer to information about the form in question
pPrinterForm Pointer to a buffer for receiving printer form info
NULL if caller is not interested in printer form info
bStringent Whether to do a more stringent check
Return Value:
TRUE if the requested form is supported on the printer.
FALSE otherwise.
--*/
{
PSREAL width, height;
CHAR formname[CCHFORMNAME];
WORD featureIndex;
PMEDIAOPTION pMediaOption, pNext;
// Sanity check
if (hppd->pPageSizes == NULL)
return FALSE;
// Convert form size from microns to points (24.8 format)
width = MicronToPSReal(pFormInfo->Size.cx);
height = MicronToPSReal(pFormInfo->Size.cy);
// First check if the form name matches the name of a printer form.
// Remember that form name is NULL for custom form.
ASSERT(pFormInfo->pName != NULL);
CopyUnicode2Str(formname, pFormInfo->pName, CCHFORMNAME);
// If doing a stringent check and the form is a printer form,
// then only an exact name match is acceptable.
pMediaOption = (PMEDIAOPTION)
PpdFindUiOptionWithXlation(hppd->pPageSizes->pUiOptions, formname, &featureIndex);
if ((pMediaOption == NULL) &&
(!bStringent || !(pFormInfo->Flags & FORM_PRINTER)))
{
LONG dx, dy, minxy;
WORD index = 0;
// There is no name match. Try to find out if there is a
// printer form whose size matches that of the requested form.
minxy = MAX_LONG;
for (pNext = (PMEDIAOPTION) hppd->pPageSizes->pUiOptions;
pNext != NULL;
pNext = pNext->pNext, index++)
{
// Compare the current size with the desired size.
dx = (LONG) pNext->dimension.width - (LONG) width;
dy = (LONG) pNext->dimension.height - (LONG) height;
// Check if we have an exact size match.
// Tolerance is 1 point.
if (abs(dx) <= ONE_POINT_PSREAL && abs(dy) <= ONE_POINT_PSREAL) {
featureIndex = index;
pMediaOption = 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.
featureIndex = index;
pMediaOption = pNext;
minxy = dx + dy;
}
}
}
//
// Determine whether custom page size support is enabled
//
#ifdef CUSTOM_PAGE_SIZE_ENABLED
// If there is no exact size match, does the printer
// support custom page size?
if (pNext == NULL && PpdSupportCustomPageSize(hppd, width, height)) {
// If the printer supports custom page size and
// the requested form is not too big, then we'll
// invoke the feature on the printer.
if (pPrinterForm != NULL) {
FillCustomPrinterFormInfo(pPrinterForm, pFormInfo, hppd);
pPrinterForm->featureIndex = OPTION_INDEX_ANY;
}
return TRUE;
}
#endif
}
// If the requested form fits on a printer form, then
// return information about the printer form to the caller
if (pMediaOption != NULL && pPrinterForm != NULL) {
FillStandardPrinterFormInfo(pPrinterForm, pFormInfo, pMediaOption);
pPrinterForm->featureIndex = featureIndex;
}
return (pMediaOption != NULL);
}