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.
 
 
 
 
 
 

803 lines
18 KiB

/*++
Copyright (c) 1995 Microsoft Corporation
Module Name:
formtray.c
Abstract:
Function for dealing with form-to-tray assignment items
Environment:
PCL-XL driver user interface
Revision History:
12/13/95 -davidx-
Created it.
mm/dd/yy -author-
description
--*/
#include "xlui.h"
// Forward declaration of local functions
POPTTYPE
FillFormNameOptType(
PUIDATA pUiData
);
POPTTYPE
AdjustFormNameOptType(
PUIDATA pUiData,
POPTTYPE pOptType,
WORD trayIndex
);
DWORD
CollectFormTrayAssignments(
PUIDATA pUiData,
PFORMTRAYTABLE pTable
);
#define DEFAULT_CHECKED OPTIF_ECB_CHECKED // default tray checkbox is checked
#define DISABLE_CHECKBOX OPTIF_EXT_DISABLED // default tray checkbox is disabled
BOOL
PackItemFormTrayTable(
PPACKINFO pPackInfo
)
/*++
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
Return Value:
TRUE if successful, FALSE otherwise
--*/
{
PFEATURE pFeature;
PUIDATA pUiData;
HANDLE hheap;
WORD index;
POPTITEM pOptItem;
POPTTYPE pOptType;
PEXTCHKBOX pExtChkBox;
//
// Form-to-tray assignment table
// Tray <-> Form
// ...
//
PackOptItemGroupHeader(pPackInfo,
IDS_CPSUI_FORMTRAYASSIGN,
IDI_CPSUI_FORMTRAYASSIGN,
HELP_INDEX_FORMTRAYASSIGN);
//
// Figure out the number of output bins
//
pUiData = pPackInfo->pUiData;
hheap = pUiData->hheap;
pFeature = MpdInputSlots(pUiData->pmpd);
Assert(pFeature != NULL);
pUiData->cFormTrayItem = pFeature->count;
pPackInfo->cOptItem += pFeature->count;
if (pPackInfo->pOptItem == NULL)
return TRUE;
pOptItem = pUiData->pFormTrayItems = pPackInfo->pOptItem;
//
// Generate the list of form names
//
if (! (pOptType = FillFormNameOptType(pUiData))) {
Error(("Couldn't fill out form name list\n"));
return FALSE;
}
//
// Create an EXTCHKBOX structure
//
if (! (pExtChkBox = (PEXTCHKBOX) HeapAlloc(hheap, HEAP_ZERO_MEMORY, sizeof(EXTCHKBOX))))
return FALSE;
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
//
for (index=0; index < pFeature->count; index++) {
POPTION pInputSlot;
//
// The tray items cannot share OPTTYPE and OPTPARAMs because
// each tray can contain a different list of forms.
//
if (! (pOptType = AdjustFormNameOptType(pUiData, pOptType, index)))
return FALSE;
pInputSlot = FindIndexedSelection(pFeature, index);
FILLOPTITEM(pOptItem,
pOptType,
GetXlatedName(pInputSlot),
0,
TVITEM_LEVEL2,
DMPUB_NONE,
FORM_TRAY_ITEM,
HELP_INDEX_TRAY_ITEM);
pOptItem->pExtChkBox = pExtChkBox;
pOptItem++;
}
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
--*/
{
PFORMTRAYTABLE pTable;
DWORD tableSize;
//
// Figure out how much memory we need to store the form-to-tray assignment table
//
if ((tableSize = CollectFormTrayAssignments(pUiData, NULL)) > MAX_WORD) {
Error(("Form-to-tray assignment table is too big\n"));
return FALSE;
}
if (! (pTable = HeapAlloc(pUiData->hheap, HEAP_ZERO_MEMORY, tableSize)))
return FALSE;
//
// Assemble the form-to-tray assignment table
//
CollectFormTrayAssignments(pUiData, pTable);
//
// Save the form-to-tray assignment table to registry
//
if (! SavePrinterRegistryData(pUiData->hPrinter, pTable, REGSTR_TRAYFORMTABLE)) {
Error(("Failed to save form-to-tray assignment table to registry\n"));
}
HeapFree(pUiData->hheap, 0, 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;
PWSTR pFormName;
//
// Allocate memory to hold OPTTYPE and OPTPARAM structures
//
cFormName = pUiData->cFormNames + 1;
pOptType = HeapAlloc(pUiData->hheap, HEAP_ZERO_MEMORY, sizeof(OPTTYPE));
pOptParam = HeapAlloc(pUiData->hheap, HEAP_ZERO_MEMORY, sizeof(OPTPARAM) * cFormName);
if (pOptType == NULL || pOptParam == NULL)
return NULL;
//
// 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++;
//
// Enumerate the list of supported form names
//
for (pFormName = pUiData->pFormNames; --cFormName; pOptParam++, pFormName += CCHPAPERNAME) {
pOptParam->cbSize = sizeof(OPTPARAM);
pOptParam->pData = pFormName;
pOptParam->IconID = GetFormIconID(pFormName);
}
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 trayFeature, formFeature;
INT index, cOptParam = pOptType->Count;
PMPD pmpd = pUiData->pmpd;
//
// Find the index for InputSlot and PageSize features
//
trayFeature = GetFeatureIndex(pmpd, MpdInputSlots(pmpd));
formFeature = GetFeatureIndex(pmpd, MpdPaperSizes(pmpd));
//
// Make a copy of the array of formname OPTPARAMs
//
if (trayIndex > 0) {
POPTTYPE pNewType;
pNewType = HeapAlloc(pUiData->hheap, 0, sizeof(OPTTYPE));
pOptParam = HeapAlloc(pUiData->hheap, 0, 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 "No Assignment"
//
for (index=1; index < cOptParam; index++) {
WORD formIndex = pUiData->pPaperSelections[index - 1];
//
// If the form conflicts with the tray, then don't display it.
//
if (formIndex != SELIDX_ANY &&
SearchUiConstraints(pmpd, trayFeature, trayIndex, formFeature, formIndex))
{
pOptParam[index].Flags |= (OPTPF_HIDE | CONSTRAINED_FLAG);
} else
pOptParam[index].Flags &= ~(OPTPF_HIDE | CONSTRAINED_FLAG);
}
return pOptType;
}
VOID
SetupFormTrayAssignments(
PUIDATA pUiData
)
/*++
Routine Description:
Update the current selection of tray items based on form-to-tray assignment table
Arguments:
pUiData - Pointer to our UIDATA structure
Return Value:
NONE
[Note:]
We assume the form-tray items are in their default states
when this function is called.
--*/
{
PFORMTRAYTABLE pFormTrayTable;
FINDFORMTRAY findData;
POPTITEM pOptItem;
POPTPARAM pOptParam;
DWORD cOptParam, cTrays;
DWORD formIndex, trayIndex;
pOptItem = pUiData->pFormTrayItems;
cTrays = pUiData->cFormTrayItem;
pOptParam = pOptItem->pOptType->pOptParam;
cOptParam = pOptItem->pOptType->Count;
//
// If the form-to-tray assignment information doesn't exist, use the default assignments
//
pFormTrayTable = GetPrinterRegistryData(pUiData->hPrinter, REGSTR_TRAYFORMTABLE);
if (pFormTrayTable == NULL) {
//
// Get the default formname and convert it to a seleciton index.
// Remember to skip the first formname in the list which is "No Assignment".
//
PWSTR pDefaultFormName;
Verbose(("No form-to-tray assignment table exists\n"));
pDefaultFormName = DefaultFormName(IsMetricCountry());
formIndex = FindFormNameIndex(pUiData, pDefaultFormName) + 1;
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.
//
ResetFindData(&findData);
while (FindFormToTrayAssignment(pFormTrayTable, NULL, NULL, &findData)) {
for (trayIndex=0;
trayIndex < cTrays &&
wcscmp(pOptItem[trayIndex].pName, findData.pTrayName) != EQUAL_STRING;
trayIndex++)
{
}
if (trayIndex == cTrays) {
Error(("Unrecognized tray name: %ws\n", findData.pTrayName));
} else {
//
// If the tray name is valid, then check if the associated form name is valid.
// Skip the first form name in the list which should always be "No Assignment".
//
for (formIndex=1;
formIndex < cOptParam &&
wcscmp(pOptParam[formIndex].pData, findData.pFormName) != EQUAL_STRING;
formIndex++)
{
}
if (formIndex == cOptParam) {
Error(("Unrecognized form name: %ws\n", findData.pFormName));
} if ((pOptItem[trayIndex].Flags & OPTIF_DISABLED) ||
IS_CONSTRAINED(&pOptItem[trayIndex], formIndex))
{
Error(("Conflicting form-to-tray assignment\n"));
} else {
//
// If the associated form name is supported,
// then remember the form index.
//
pOptItem[trayIndex].Sel = formIndex;
if (findData.flags & DEFAULT_TRAY)
pOptItem[trayIndex].Flags |= DEFAULT_CHECKED;
}
}
}
MemFree(pFormTrayTable);
}
DWORD
CollectFormTrayAssignments(
PUIDATA pUiData,
PFORMTRAYTABLE pTable
)
/*++
Routine Description:
Collect form-to-tray assignment information
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.
--*/
{
POPTITEM pOptItem = pUiData->pFormTrayItems;
DWORD cOptItem = pUiData->cFormTrayItem;
DWORD length, tableSize, tableIndex = 0;
tableSize = cOptItem * 3 * sizeof(WORD) + sizeof(FORMTRAYTABLE);
while (cOptItem--) {
Assert(IsFormTrayItem(pOptItem->UserData));
if (pOptItem->Sel > 0 && !(pOptItem->Flags & OPTIF_DISABLED)) {
PWSTR pTrayName, pFormName;
//
// Get tray name and form name
//
pTrayName = pOptItem->pName;
pFormName = pOptItem->pOptType->pOptParam[pOptItem->Sel].pData;
length = sizeof(WCHAR) * (wcslen(pTrayName) + 1);
if (pTable) {
pTable->table[tableIndex++] = (WORD) tableSize;
pTable->table[tableIndex++] = (WORD) (tableSize + length);
pTable->table[tableIndex++] =
(pOptItem->Flags & DEFAULT_CHECKED) ? DEFAULT_TRAY : 0;
wcscpy((PWSTR) ((PBYTE) pTable + tableSize), pTrayName);
wcscpy((PWSTR) ((PBYTE) pTable + tableSize + length), pFormName);
}
tableSize += length + sizeof(WCHAR) * (wcslen(pFormName) + 1);
}
pOptItem++;
}
if (pTable) {
pTable->size = (WORD) tableSize;
pTable->version = DRIVER_VERSION;
pTable->count = (WORD) (tableIndex / 3);
pTable->table[tableIndex] = 0;
}
return tableSize;
}
VOID
UpdateDefaultTrayFlags(
PUIDATA pUiData,
INT activeTrayIndex
)
/*++
Routine Description:
Update default tray flags on form-to-tray assignment items
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 & DEFAULT_CHECKED)) {
formIndex = pOptItem[activeTrayIndex].Sel;
Assert(formIndex > 0);
for (trayIndex=0; trayIndex < cTrays; trayIndex++) {
if (pOptItem[trayIndex].Sel == formIndex &&
trayIndex != activeTrayIndex &&
(pOptItem[trayIndex].Flags & DEFAULT_CHECKED))
{
pOptItem[trayIndex].Flags &= ~DEFAULT_CHECKED;
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 &= ~DEFAULT_CHECKED;
flags |= DISABLE_CHECKBOX;
} 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 & DEFAULT_CHECKED)) {
flags &= ~DEFAULT_CHECKED;
break;
}
}
}
//
// If a form is assigned to only one tray, then that
// tray by default must be designated as default.
//
if (wDuplicates == 0)
flags |= (DEFAULT_CHECKED|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;
}