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.
 
 
 
 
 
 

808 lines
18 KiB

/*++
Copyright (c) 1995 Microsoft Corporation
Module Name:
formtray.c
Abstract:
Function for handling form-to-tray assignment dialog
[Environment:]
Win32 subsystem, PostScript driver UI
Revision History:
08/29/95 -davidx-
Created it.
mm/dd/yy -author-
description
--*/
#include "psui.h"
POPTTYPE FillFormNameOptType(PUIDATA);
POPTTYPE AdjustFormNameOptType(PUIDATA, POPTTYPE, WORD);
DWORD CollectFormTrayAssignments(PUIDATA, PWSTR);
#define IS_DEFAULT_TRAY OPTIF_ECB_CHECKED
#define DISABLE_CHECKBOX OPTIF_EXT_DISABLED
BOOL
PackItemFormTrayTable(
PPACKINFO pPackInfo,
PPRINTERDATA pPrinterData
)
/*++
Routine Description:
Pack form-to-tray assignment information into treeview item
structures so that we can call common UI library.
Arguments:
pPackInfo - Pointer to PACKINFO structure
pPrinterData - Pointer to PRINTERDATA structure
Return Value:
TRUE if successful, FALSE otherwise
[Note:]
pPackInfo->pOptItem and pPackInfo->pOptType will be NULL
if the caller is interested in counting items only.
--*/
{
PUIDATA pUiData;
POPTITEM pOptItem;
POPTTYPE pOptType;
WORD index, cTrays;
PWSTR pTrayName;
PEXTCHKBOX pExtChkBox;
HHEAP hheap;
// The first bin name is always "Print Manager Setting"
pUiData = pPackInfo->pUiData;
cTrays = (WORD) pUiData->cBinNames - 1;
if (cTrays == 0 || cTrays > MAX_FORM_TRAY_ITEM-MIN_FORM_TRAY_ITEM) {
DBGMSG1(DBG_LEVEL_WARNING,
"Invalid number of tray: %d\n", cTrays);
return TRUE;
}
// Form-to-tray assignment table
// Tray <-> Form
// ...
PackOptItemGroupHeader(pPackInfo, IDS_CPSUI_FORMTRAYASSIGN,
IDI_CPSUI_FORMTRAYASSIGN, HELP_INDEX_FORMTRAYASSIGN);
pUiData->cFormTrayItem = cTrays;
pPackInfo->cOptItem += cTrays;
if (pPackInfo->pOptItem == NULL)
return TRUE;
pUiData->pFormTrayItems = pPackInfo->pOptItem;
// Generate the list of form names
pOptType = FillFormNameOptType(pPackInfo->pUiData);
if (pOptType == NULL) {
DBGERRMSG("FillFormNameOptType");
return FALSE;
}
// Create an EXTCHKBOX structure
hheap = pUiData->hheap;
pExtChkBox = (PEXTCHKBOX) HEAPALLOC(hheap, sizeof(EXTCHKBOX));
if (pExtChkBox == NULL) {
DBGERRMSG("HEAPALLOC");
return FALSE;
}
memset(pExtChkBox, 0, sizeof(EXTCHKBOX));
pExtChkBox->cbSize = sizeof(EXTCHKBOX);
pExtChkBox->pTitle = (PWSTR) IDS_DRAW_ONLY_FROM_SELECTED;
pExtChkBox->pCheckedName = (PWSTR) IDS_DEFAULT_TRAY;
pExtChkBox->IconID = IDI_USE_DEFAULT;
// Create an OPTITEM for each tray
pTrayName = pUiData->pBinNames + CCHBINNAME;
pOptItem = pPackInfo->pOptItem;
for (index=0; index < cTrays; index++) {
// The tray items cannot share OPTTYPE and OPTPARAMs because
// each tray can contain a different list of forms.
pOptType =
AdjustFormNameOptType(pPackInfo->pUiData, pOptType, index);
if (pOptType == NULL) {
DBGERRMSG("AdjustFormNameOptParam");
return FALSE;
}
FILLOPTITEM(pOptItem,
pOptType,
pTrayName,
0,
TVITEM_LEVEL2,
DMPUB_NONE,
MIN_FORM_TRAY_ITEM + index,
HELP_INDEX_TRAY_ITEM);
pOptItem->pExtChkBox = pExtChkBox;
pOptItem++;
pTrayName += CCHBINNAME;
}
pPackInfo->pOptItem = pOptItem;
return TRUE;
}
BOOL
UnpackItemFormTrayTable(
PUIDATA pUiData
)
/*++
Routine Description:
Extract form-to-tray assignment information from treeview items
Arguments:
pUiData - Pointer to UIDATA structure
Return Value:
TRUE if successful, FALSE otherwise
--*/
{
PWSTR pTable;
DWORD tableSize;
// Figure out how much memory we need to store
// the form-to-tray assignment table
tableSize = CollectFormTrayAssignments(pUiData, NULL);
if (tableSize == 0 || (pTable = MEMALLOC(tableSize)) == NULL) {
DBGERRMSG("CollectFormTrayMappings/MEMALLOC");
return FALSE;
}
// Assemble the form-to-tray assignment table
if (tableSize != CollectFormTrayAssignments(pUiData, pTable))
{
DBGERRMSG("CollectFormTrayMappings");
MEMFREE(pTable);
return FALSE;
}
// Save the form-to-tray assignment table to registry
ASSERT(tableSize < 0x10000);
*pTable = (WCHAR) tableSize;
if (! SaveFormTrayTable(pUiData->hPrinter, pTable, tableSize)) {
DBGERRMSG("SaveFormTrayTable");
}
MEMFREE(pTable);
return TRUE;
}
POPTTYPE
FillFormNameOptType(
PUIDATA pUiData
)
/*++
Routine Description:
Initialize an OPTTYPE structure to hold information
about the list of forms 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;
DWORD cFormName, index;
PWSTR pFormName;
// Allocate memory to hold OPTTYPE and OPTPARAM structures
cFormName = pUiData->cFormNames + 1;
pOptType = HEAPALLOC(pUiData->hheap, sizeof(OPTTYPE));
pOptParam = HEAPALLOC(pUiData->hheap, sizeof(OPTPARAM) * cFormName);
if (pOptType == NULL || pOptParam == NULL) {
DBGERRMSG("HEAPALLOC");
return NULL;
}
memset(pOptType, 0, sizeof(OPTTYPE));
memset(pOptParam, 0, sizeof(OPTPARAM) * cFormName);
// Initialize OPTTYPE structure
pOptType->cbSize = sizeof(OPTTYPE);
pOptType->Count = (WORD) cFormName;
pOptType->Type = TVOT_LISTBOX;
pOptType->pOptParam = pOptParam;
pOptType->Style = OTS_LBCB_SORT;
// Initialize OPTPARAM structures
// The first item is always "No Assignment"
pOptParam->cbSize = sizeof(OPTPARAM);
pOptParam->pData = (PWSTR) IDS_NO_ASSIGNMENT;
pOptParam->IconID = IDI_CPSUI_EMPTY;
pOptParam++;
cFormName--;
// Enumerate the list of supported form names
pFormName = pUiData->pFormNames;
for (index=0; index < cFormName; index++, pOptParam++) {
WORD feature, selection;
pOptParam->cbSize = sizeof(OPTPARAM);
pOptParam->pData = pFormName;
pOptParam->IconID = GetFormIconID(pFormName);
pFormName += CCHPAPERNAME;
}
return pOptType;
}
POPTTYPE
AdjustFormNameOptType(
PUIDATA pUiData,
POPTTYPE pOptType,
WORD trayIndex
)
/*++
Routine Description:
Adjust the list of forms for each tray
Arguments:
pUiData - Pointer to our UIDATA structure
pOptType - Pointer to OPTTYPE
trayIndex - Tray index
Return Value:
TRUE if successful, FALSE otherwise
--*/
{
POPTPARAM pOptParam;
WORD cOptParam = pOptType->Count;
WORD trayFeature, formFeature, index;
// Find the index for InputSlot and PageSize features
trayFeature = GetFeatureIndex(pUiData->hppd->pInputSlots);
formFeature = GetFeatureIndex(pUiData->hppd->pPageSizes);
if (trayFeature == OPTION_INDEX_NONE || formFeature == OPTION_INDEX_NONE)
return pOptType;
// Make a copy of the array of formname OPTPARAMs
if (trayIndex > 0) {
POPTTYPE pNewType;
pNewType = HEAPALLOC(pUiData->hheap, sizeof(OPTTYPE));
pOptParam = HEAPALLOC(pUiData->hheap, sizeof(OPTPARAM)*cOptParam);
if (! pNewType || ! pOptParam)
return NULL;
memcpy(pNewType, pOptType, sizeof(OPTTYPE));
memcpy(pOptParam, pOptType->pOptParam, sizeof(OPTPARAM)*cOptParam);
pNewType->pOptParam = pOptParam;
pOptType = pNewType;
} else
pOptParam = pOptType->pOptParam;
// Go through each formname
// Skip the first formname which is always "Print Manager Setting..."
for (index=1; index < cOptParam; index++) {
WORD selection = pUiData->pPaperFeatures[index - 1];
// If the form conflicts with the tray, then don't display it.
if (selection != OPTION_INDEX_ANY &&
SearchUiConstraints(pUiData->hppd,
trayFeature, trayIndex, formFeature, selection))
{
pOptParam[index].Flags |= (OPTPF_HIDE | CONSTRAINED_FLAG);
} else
pOptParam[index].Flags &= ~(OPTPF_HIDE | CONSTRAINED_FLAG);
}
return pOptType;
}
VOID
SetupFormTrayAssignments(
PUIDATA pUiData,
POPTITEM pOptItem,
FORM_TRAY_TABLE pFormTrayTable
)
/*++
Routine Description:
Update the current selection of tray items based on
the specified form-to-tray assignment table
Arguments:
pUiData - Pointer to our UIDATA structure
pOptItem - Pointer to an array of OPTITEMs
pFormTrayTable - Pointer to form-to-tray assignment table
Return Value:
NONE
[Note:]
We assume the form-tray items are in their default states
when this function is called.
--*/
{
FORM_TRAY_TABLE pNextEntry;
PWSTR pTrayName, pFormName, pPrinterForm;
BOOL IsDefTray;
WORD trayIndex, formIndex, cTrays, cOptParam;
POPTPARAM pOptParam;
if ((cTrays = pUiData->cFormTrayItem) == 0)
return;
pOptParam = pOptItem->pOptType->pOptParam;
cOptParam = pOptItem->pOptType->Count;
// If the form-to-tray assignment information doesn't exist,
// set up the default assignments
if ((pNextEntry = pFormTrayTable) == NULL) {
// Get the default formname (Letter or A4) and
// convert it formname to a seleciton index.
formIndex = FindFormNameIndex(
pUiData,
(PWSTR) GetDefaultFormName(IsMetricCountry()));
// Remember to skip the first formname in the list
// which is "No Assignment".
formIndex++;
ASSERT(formIndex < cOptParam);
for (trayIndex=0; trayIndex < cTrays; trayIndex++) {
if (! (pOptItem[trayIndex].Flags & OPTIF_DISABLED) &&
! IS_CONSTRAINED(&pOptItem[trayIndex], formIndex))
{
pOptItem[trayIndex].Sel = formIndex;
}
}
// Save the default form-to-tray assignment table to registry.
if (HasPermission(pUiData)) {
UnpackItemFormTrayTable(pUiData);
}
return;
}
// Iterate thru the form-to-tray assignment table and
// update the current selection of tray items.
while (*pNextEntry != NUL) {
// Get the next entry in the form-to-tray assignment table
pNextEntry =
EnumFormTrayTable(
pNextEntry, &pTrayName, &pFormName, &pPrinterForm, &IsDefTray);
for (trayIndex=0; trayIndex < cTrays; trayIndex++) {
if (wcscmp(pOptItem[trayIndex].pName, pTrayName) == EQUAL_STRING) {
// If the specified tray name is supported, then check
// if the associated form name is supported.
// Skip the first form name in the list which
// should always be "No Assignment".
for (formIndex=1;
formIndex < cOptParam &&
wcscmp(pFormName, pOptParam[formIndex].pData) != EQUAL_STRING;
formIndex++)
{
}
if (formIndex == cOptParam) {
DBGMSG1(DBG_LEVEL_WARNING,
"Unknown form name: %ws\n", pFormName);
} if ((pOptItem[trayIndex].Flags & OPTIF_DISABLED) ||
IS_CONSTRAINED(&pOptItem[trayIndex], formIndex))
{
DBGMSG(DBG_LEVEL_WARNING,
"Conflicting form-tray assignment\n");
} else {
// If the associated form name is supported,
// then remember the form index.
pOptItem[trayIndex].Sel = formIndex;
if (IsDefTray)
pOptItem[trayIndex].Flags |= IS_DEFAULT_TRAY;
}
break;
}
}
if (trayIndex == cTrays) {
DBGMSG1(DBG_LEVEL_WARNING, "Unknown tray name: %ws\n", pTrayName);
}
}
FreeFormTrayTable(pFormTrayTable);
}
DWORD
CollectFormTrayAssignments(
PUIDATA pUiData,
PWSTR pTable
)
/*++
Routine Description:
Collect the form-to-tray assignment information and
save it to registry.
Arguments:
pUiData - Pointer to our UIDATA structure
pTable - Pointer to memory buffer for storing the table
NULL if the caller is only interested in the table size
Return Value:
Size of the table bytes. 0 if there is an error.
--*/
{
DWORD cChars;
LONG length;
WORD index;
POPTPARAM pOptParam;
WORD cOptItem = pUiData->cFormTrayItem;
POPTITEM pOptItem = pUiData->pFormTrayItems;
// Count the first WCHAR (table size)
cChars = 1;
if (pTable != NULL)
pTable++;
for (index=0; index < cOptItem; index++, pOptItem++) {
ASSERT(IsFormTrayItem(pOptItem->UserData));
if (pOptItem->Sel == 0 || (pOptItem->Flags & OPTIF_DISABLED))
continue;
// Tray name
length = wcslen(pOptItem->pName) + 1;
cChars += length;
if (pTable != NULL) {
wcscpy(pTable, pOptItem->pName);
pTable += length;
}
// Form name
pOptParam = pOptItem->pOptType->pOptParam + pOptItem->Sel;
length = wcslen(pOptParam->pData) + 1;
cChars += length;
if (pTable != NULL) {
wcscpy(pTable, pOptParam->pData);
pTable += length;
}
// Printer form name and DefTrayFlag
cChars += 2;
if (pTable != NULL) {
*pTable++ = NUL;
*pTable++ = (pOptItem->Flags & IS_DEFAULT_TRAY) ? TRUE : FALSE;
}
}
// Append a NUL character at the end of the table
cChars++;
if (pTable != NULL)
*pTable = NUL;
// Return the table size in bytes
return cChars * sizeof(WCHAR);
}
VOID
UpdateDefaultTrayFlags(
PUIDATA pUiData,
INT activeTrayIndex
)
/*++
Routine Description:
Collect the form-to-tray assignment information and
save it to registry.
Arguments:
pUiData - Pointer to UIDATA structure
activeTrayIndex - Index of the active tray
-1 if there is no active tray
Return Value:
NONE
--*/
{
INT trayIndex, cTrays;
LONG formIndex;
DWORD flags, permission;
POPTITEM pOptItem;
pOptItem = pUiData->pFormTrayItems;
cTrays = pUiData->cFormTrayItem;
// If an active tray is specified and it's designated as the
// default, then mark every other tray which contains the same
// form as the active tray as non-default.
if ((activeTrayIndex >= 0) &&
(pOptItem[activeTrayIndex].Flags & IS_DEFAULT_TRAY))
{
formIndex = pOptItem[activeTrayIndex].Sel;
ASSERT(formIndex > 0);
for (trayIndex=0; trayIndex < cTrays; trayIndex++) {
if (pOptItem[trayIndex].Sel == formIndex &&
trayIndex != activeTrayIndex &&
(pOptItem[trayIndex].Flags & IS_DEFAULT_TRAY))
{
pOptItem[trayIndex].Flags &= ~IS_DEFAULT_TRAY;
pOptItem[trayIndex].Flags |= OPTIF_CHANGED;
}
}
}
permission = HasPermission(pUiData) ? 0 : DISABLE_CHECKBOX;
// Go through each tray item and set up the flag bits
for (trayIndex=0; trayIndex < cTrays; trayIndex++) {
ASSERT(IsFormTrayItem(pOptItem[trayIndex].UserData));
flags = pOptItem[trayIndex].Flags;
if ((formIndex = pOptItem[trayIndex].Sel) == 0) {
// The tray doesn't have any assignment, the checkbox
// should be unchecked and disabled.
flags |= DISABLE_CHECKBOX;
flags &= ~IS_DEFAULT_TRAY;
} else {
INT index, wDuplicates;
// The tray has a form assigned to it. Check if there is
// any other tray also contains the same form.
for (index=wDuplicates=0; index < cTrays; index++) {
if (index != trayIndex && pOptItem[index].Sel == formIndex) {
wDuplicates++;
if ((index < trayIndex) &&
(pOptItem[index].Flags & IS_DEFAULT_TRAY))
{
flags &= ~IS_DEFAULT_TRAY;
break;
}
}
}
// If a form is assigned to only one tray, then that
// tray by default must be designated as default.
if (wDuplicates == 0)
flags |= (IS_DEFAULT_TRAY|DISABLE_CHECKBOX);
else
flags &= ~DISABLE_CHECKBOX;
}
// Change the item state in the treeview
flags |= permission;
if (flags != pOptItem[trayIndex].Flags)
pOptItem[trayIndex].Flags = flags | OPTIF_CHANGED;
}
}
WORD
GetFormIconID(
PWSTR pFormName
)
/*++
Routine Description:
Figure out the icon ID corresponding to a specified form name
Arguments:
pFormName - Pointer to a form name string
Return Value:
Icon ID corresponding to the specified form name
[Note:]
This is very klugy but I guess it's better than using the same icon
for all forms. We try to differentiate envelopes from normal forms.
We assume a form name refers an envelope if it contains word Envelope
or Env.
--*/
#define MAXENVLEN 32
{
WCHAR prefix[MAXENVLEN], envelope[MAXENVLEN];
INT prefixLen, envelopeLen;
BOOL bEnvelope = FALSE;
prefixLen = LoadString(ghInstance, IDS_ENV_PREFIX, prefix, MAXENVLEN);
envelopeLen = LoadString(ghInstance, IDS_ENVELOPE, envelope, MAXENVLEN);
if (prefixLen > 0 && envelopeLen > 0) {
while (*pFormName) {
// Do we have a word matching our description?
if (_wcsnicmp(pFormName, prefix, prefixLen) == EQUAL_STRING &&
(pFormName[prefixLen] == L' ' ||
pFormName[prefixLen] == NUL ||
_wcsnicmp(pFormName, envelope, envelopeLen) == EQUAL_STRING))
{
bEnvelope = TRUE;
break;
}
// Move on to the next word
while (*pFormName && *pFormName != L' ')
pFormName++;
while (*pFormName && *pFormName == L' ')
pFormName++;
}
}
return bEnvelope ? IDI_CPSUI_ENVELOPE : IDI_CPSUI_STD_FORM;
}