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.
595 lines
19 KiB
595 lines
19 KiB
------------ Structures: -------------
|
|
|
|
What will be stored in the GPD binary file:
|
|
|
|
A Master table of contents with ptrs/offsets
|
|
to all Arrays and heaps.
|
|
|
|
typedef struct
|
|
{
|
|
DWORD size ;
|
|
DWORD parserVersion ;
|
|
DWORD totalBinarySize ;
|
|
DWORD firstSynthesizedFeature ; // zero based index
|
|
ARRAYREF FeaturesAndOptions ; // union of all feature, option and
|
|
// extra option data.
|
|
ARRAYREF AttributeTreeArray ;
|
|
ARRAYREF InvalidComboArray ;
|
|
ARRAYREF UIConstraintArray ;
|
|
ARRAYREF GroupTreeArray ;
|
|
ARRAYREF DCommandMap ;
|
|
ARRAYREF CommandArray ;
|
|
ARRAYREF ParameterArray ;
|
|
ARRAYREF ValueStack ;
|
|
ARRAYREF OperatorStack ;
|
|
ARRAYREF ListArray;
|
|
ARRAYREF FontArray;
|
|
ARRAYREF PriorityArray;
|
|
DGLOBAL_ATTRIBUTES Dglobals ;
|
|
} RAW_INFOHEADER ;
|
|
|
|
|
|
typedef struct
|
|
{
|
|
|
|
} DFEATURE_OPTIONS ;
|
|
|
|
|
|
|
|
String heap
|
|
|
|
|
|
Items that will not be stored:
|
|
|
|
Symbol Table: all symbols will be dereferenced - replaced by
|
|
indicies to structures.
|
|
Macro structures: all macros will have been expanded.
|
|
|
|
|
|
-------------------------------------------------------
|
|
|
|
Operations needed to create a snapshot for
|
|
UI and Control Module:
|
|
|
|
|
|
Take tree type info stored in FeaturesAndOptions and
|
|
distribute it among hundreds of Amanda's Feature and
|
|
option structures and extra option structures.
|
|
|
|
|
|
Synthesize a direct command table which maps
|
|
Unidrv command ID to index in the command array.
|
|
|
|
Create the SEQUENCED_CMDS lists and ptrs to each list
|
|
from OrderDependency data in the command array.
|
|
|
|
Init the actual Global attributes structure.
|
|
|
|
Init some fields in UIINFO and DRIVERINFO structs.
|
|
--
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
----------------------------------
|
|
|
|
priority array: an array of feature indicies, the
|
|
feature index occupying index 0 in the priority array
|
|
has highest priority. If there is a conflict between
|
|
two features the setting of the feature with lower
|
|
priority will be changed to resolve the conflict.
|
|
All synthesized features will have a higher priority
|
|
then any explicitly defined features.
|
|
|
|
|
|
----- installable features and options ----
|
|
|
|
Whenever an installable option or feature is
|
|
specified in the GPD file, the parser will create
|
|
a generic feature with two options "Installed" and
|
|
"Not Installed". This feature is also refered to as
|
|
an "Installable Configuration Feature" or a "synthesized
|
|
feature". These features are considered "printer sticky"
|
|
and the UI may display them at the appropriate time.
|
|
|
|
|
|
Each option or feature structure declared 'installable'
|
|
will have an index (InstallableFeatureIndex) that points to
|
|
the synthesized feature.
|
|
|
|
Correspondingly, each synthesized feature's
|
|
InstallableFeatureIndex will point back to the
|
|
Installable feature or the feature containing the
|
|
Installable option. If it is an installable
|
|
feature, the InstallableOptionIndex is set to -1,
|
|
if its an installable option, it is set to the
|
|
option index of the installable option.
|
|
|
|
|
|
---------------------------------------------
|
|
|
|
Notes:
|
|
|
|
If an option is marked *installable it will appear on
|
|
the selections UI as being enabled or grayed out.
|
|
If grayed out you can select it, else you cannot.
|
|
|
|
If all options in the feature are installable, there must
|
|
be one option that isn't. The default option will be
|
|
overridden if it points to an uninstalled option.
|
|
|
|
If a feature is marked installed, then all the options
|
|
enumerated there will be displayed just as if it were
|
|
a normal feature. If it is marked "Not Installed" then
|
|
the UI should consider the entire feature to be disabled.
|
|
There will still be a slot on the features array reserved
|
|
for its option selection however, but the control module
|
|
code should not access it.
|
|
|
|
|
|
|
|
------- UIConstraints Array --------
|
|
|
|
The GPD source format defines the following keywords
|
|
to express constraints between two or more options.
|
|
The parser stores this information in either a UICONSTRAINT
|
|
or INVALIDCOMBO structure depending on the number of items
|
|
needed to effect a constraint.
|
|
|
|
Note: some helper functions may ignore UICONSTRAINTS between
|
|
synthesized and non-synthesized features. These are generated
|
|
by the *InstalledConstraints and *NotInstalledConstraints
|
|
keywords.
|
|
|
|
|
|
*Constraints: selecting this option prevents/precludes
|
|
the following options from being selected.
|
|
|
|
UICONSTRAINT (mirrored)
|
|
|
|
*InvalidCombinations: some but not all of the following
|
|
options can be selected at the same time.
|
|
|
|
UICONSTRAINT (mirrored) or INVALIDCOMBO
|
|
|
|
*InvalidInstallableCombinations: some but not all of the following
|
|
feature/options can be INSTALLED at the same time.
|
|
|
|
This imposes constraints between 2 or more synthesized
|
|
(printer sticky) features
|
|
|
|
UICONSTRAINT (mirrored) or INVALIDCOMBO
|
|
|
|
*InstalledConstraints: if this synthesized
|
|
(printer sticky) feature is installed, this prevents/precludes
|
|
the following options from being selected.
|
|
|
|
UICONSTRAINT (one way: installed constrains option)
|
|
|
|
*NotInstalledConstraints: if this synthesized
|
|
(printer sticky) feature is NOT installed, this prevents/precludes
|
|
the following options from being selected.
|
|
|
|
UICONSTRAINT (one way: not installed constrains option)
|
|
the definition of an installable feature/option implies
|
|
one *NotInstalledConstraints: the installable option if not
|
|
installed will always constrain the option from being selected.
|
|
|
|
|
|
|
|
Constraints involving just two items are stored
|
|
in an list of UICONSTRAINT structures which is implemented
|
|
within an array. The list is referenced by the array index of
|
|
the first member of the list.
|
|
|
|
If a synthesized feature is set so it disables another
|
|
feature completely, this is indicated by having wOptionIndex
|
|
take on the value FEATURE_DISABLED. wOptionIndex may
|
|
also take on the value NONE_OR_FALSE to indicate
|
|
all options except 'none' or 'false' are disabled for this feature.
|
|
|
|
typedef struct
|
|
{
|
|
WORD wNextConstraintID ; // 0xffff signifies end of constraint list.
|
|
WORD wFeatureIndex; // may reference an installable feature
|
|
WORD wOptionIndex ;
|
|
} UICONSTRAINT ;
|
|
|
|
|
|
The Constraints field in the options structure
|
|
may take on the value 0xffff to indicate this option
|
|
does not constrain any other . Otherwise this field contains
|
|
the index to start of constraints list for this option. The list is
|
|
interpreted as follows: if this option is selected, the following
|
|
list of options CANNOT be selected.
|
|
|
|
|
|
|
|
Lists of INVALIDCOMBO structures are used to express constraints
|
|
involving 3 or more items before taking effect.
|
|
|
|
Each option structure contains an index to the
|
|
InvalidCombo array element which heads one or more
|
|
InvalidCombo lists involving this option. A value of 0xffff
|
|
indicates this option is not involved in any invalidCombinations.
|
|
The entire list of elements generated by following
|
|
the chain of wNextElements is the set of options that forms
|
|
the current invalidcombination. If there are other invalidcombinations
|
|
involving this option, they can be accessed by traversing wNextElements
|
|
until this option is found, then accessing wNewCombination to
|
|
find the start of chain defining a new invalidcombination.
|
|
The first element in the new list is not necessarily the
|
|
sought after option.
|
|
|
|
|
|
typedef struct
|
|
{
|
|
WORD wFeature; // may reference an installable feature
|
|
WORD wOption ;
|
|
WORD wNextElement ; // 0xffff signifies end of elements list.
|
|
WORD wNewCombination ; // 0xffff signifies no more constraints
|
|
// involving this element.
|
|
}INVALIDCOMBO ;
|
|
|
|
|
|
|
|
|
|
----------------------------------------------------
|
|
|
|
UIGroup: allowing the UI to group related features
|
|
together.
|
|
|
|
This is implemented via a tree:
|
|
|
|
typedef struct
|
|
{
|
|
STRINGREF GroupName;
|
|
WORD wNextGroup ; // if -1, indicates no more
|
|
// groups in this level.
|
|
WORD FirstSubGroup ; // index of another
|
|
// grouptree structure or
|
|
// actually contains a Feature index.
|
|
DWORD wFlags ; // UIGROUP_NOSUBGROUP if set
|
|
// FirstSubGroup contains a Feature index.
|
|
} GROUPTREE ;
|
|
|
|
This is a multi-level tree whose leaf nodes contain
|
|
feature indicies. Any UI group may contain a mixture
|
|
of subgroups and individual features.
|
|
|
|
A leaf node has:
|
|
|
|
No GroupName
|
|
wNextGroup contains the index of another Branch or leaf node
|
|
which has the same parent group has this leaf node.
|
|
FirstSubGroups contains a Feature index,
|
|
wFlags = UIGROUP_NOSUBGROUP
|
|
|
|
a branch node describes one UIGroup:
|
|
|
|
GroupName contains the name of the group
|
|
wNextGroup contains the index of another Branch or leaf node
|
|
which has the same parent group has this group
|
|
FirstSubGroup contains the index of a branch or leaf node
|
|
that is contained within this UIGroup.
|
|
wFlags is cleared.
|
|
|
|
|
|
|
|
|
|
lpGroupTree may be NULL if there are no grouping
|
|
constructs.
|
|
|
|
|
|
|
|
---- Attribute Trees ----------
|
|
|
|
A multi-level tree allows the value of an attribute
|
|
to be multi-valued depending on the option selected
|
|
one or more features. The DWORD in each attribute
|
|
points to the root of the tree. The nodes of the tree
|
|
point to the values possible for this attribute for
|
|
each option selected. Each feature occupies a different
|
|
level in the tree. The simplest tree contains one
|
|
element which has offsetmeans = VALUE.
|
|
|
|
|
|
Note: the tree may Not be organized based upon Features of the
|
|
type PICKMANY. This will cause problems if two options
|
|
are selected at the same time.
|
|
|
|
The tree is implemented by an array of structures
|
|
of the form:
|
|
|
|
typedef struct
|
|
{
|
|
WORD feature ;
|
|
WORD option ;
|
|
DWORD nextOption ; // index to another element
|
|
// holding branches to another
|
|
// option.
|
|
enum {NEXT_FEATURE, VALUE} offsetmeans ;
|
|
DWORD offset ; // If value of offsetmeans == NEXT_FEATURE
|
|
// 'offset' constains the
|
|
// index to another element holding branches
|
|
// representing a different feature.
|
|
// This occurs if the value of an attribute
|
|
// depends on the options selected for more
|
|
// than one feature.
|
|
// Otherwise 'offset' constains the offset
|
|
// in the heap to the actual VALUE.
|
|
// The code navigating the tree is
|
|
// responsible for applying the correct
|
|
// typecast when retrieving this data from
|
|
// the heap.
|
|
} TREE_BRANCH ;
|
|
|
|
|
|
Multiple trees may be defined within one array.
|
|
|
|
--- storage of default initializers ----
|
|
|
|
The root of the tree may contain a default initializer that
|
|
may be used by the parser to initialize the values of the attribute
|
|
in the absence of an explict initializer.
|
|
This is indicated by having 'feature' set to -1.
|
|
|
|
Each feature level in the tree may contain a default initializer
|
|
which is used if the current option is not explicitly enumerated
|
|
in the tree.
|
|
This is indicated by having 'option' set to -1.
|
|
The default option nodes reside at the end of the chain
|
|
of options. (nextOption = -1)
|
|
|
|
|
|
--------------------------------------------------------------------
|
|
|
|
Commands:
|
|
|
|
|
|
|
|
|
|
Commands are divided into two groups:
|
|
Synchronous and Asynchronous.
|
|
|
|
Synchronous commands are issued at one well defined point
|
|
in the job (ie paper selection). Asynchronous commands
|
|
are issued by the driver as the need arises (ie cursor movement).
|
|
|
|
Synchronous commands are accessed outside of the parser
|
|
via a linked list of
|
|
SEQUENCED_CMDS structures. Any command containing
|
|
a *OrderDependency keyword in its GPD definition is
|
|
considered a Synchronous command. If such a command
|
|
also happens to be a Unidrv recognized command, it
|
|
can be accessed both Synchronously and Asynchronously.
|
|
|
|
It should be noted since COMMAND constructs are 'relocatable'
|
|
the SEQUENCED_CMDS lists must be built dynamically using the
|
|
orderDependency fields of the commands applicable to the
|
|
current option configuration. If the command is an option
|
|
selection, the proper selection command will be referenced in
|
|
the SEQUENCED_CMDS list.
|
|
If the options are PICKMANY, the SEQUENCED_CMDS list will contain
|
|
all of the selected option invocation commands in the order
|
|
specified by the orderdependency information included with each
|
|
invocation command. If an installable feature is disabled,
|
|
no option selection commands for that feature will be
|
|
present in the list.
|
|
|
|
|
|
typedef struct
|
|
{
|
|
WORD IndexOfCommand ; // index to an element in the CommandArray
|
|
WORD NextInSequence ;
|
|
}
|
|
SEQUENCED_CMDS ;
|
|
|
|
Several linked lists co-exist in one array of SEQUENCED_CMDS.
|
|
Each section of the print job has an associated
|
|
list containing the commands that are to be emitted
|
|
at that time with each command ordered properly
|
|
relative to each other.
|
|
|
|
The fields dwJobSetupIndex ... dwJobFinishIndex in DRIVERINFO
|
|
contain the index to the first element of each
|
|
SEQUENCED_CMDS list corresponding to each section of the
|
|
print job.
|
|
|
|
|
|
|
|
Asynchronous commands are accessed by a command table.
|
|
Each Unidrv recognized command occupies a position (index)
|
|
in the table. The table is simply an array of DWORDS
|
|
where each DWORD points to an attribute tree. The nodes
|
|
of the attribute tree point to indicies in the
|
|
COMMAND_ARRAY.
|
|
|
|
When a 'snapshot' is taken, a new command table is created
|
|
that contains the index of the proper command in the
|
|
COMMAND_ARRAY instead of an index to an attribute tree.
|
|
|
|
DWORD raw_command_table[NUM_OF_UNIDRV_COMMANDS],
|
|
user_command_table[NUM_OF_UNIDRV_COMMANDS];
|
|
|
|
COMMAND CommandArray[num_of_command_variations] ;
|
|
|
|
typedef struct
|
|
{
|
|
STRINGREF invocation;
|
|
ORDERDEPENDENCY order ; // only used in construction of
|
|
// SEQUENCED_CMDS array.
|
|
DWORD dwCmdCallbackID ;
|
|
} COMMAND ;
|
|
|
|
|
|
|
|
typedef struct
|
|
{
|
|
WORD section ; // JOBSETUP, DOCSETUP, PAGESETUP etc.
|
|
WORD order ; // integer denoting relative order within each section.
|
|
}
|
|
ORDERDEPENDENCY
|
|
|
|
-------------------------------
|
|
|
|
Details of Command storage format.
|
|
|
|
|
|
|
|
|
|
The Command invocation is of the form one or more binary strings
|
|
and parameter references concatenated together in any order.
|
|
"binary string" %paramref "more binary string" ...
|
|
White spaces may separate the binary strings from the parameter
|
|
reference.
|
|
(macros will have been resolved before storing the command.)
|
|
|
|
A binary string is of the form: any set of binary bytes
|
|
enclosed by double quotes. Note the % acts to escape itself
|
|
and the " in a binary string. Thus "%%" is really (%)
|
|
"%"" is really (") , "%%%"" is really (%"), "%a" is just (a).
|
|
A % preceeding any other character is ignored. All bytes between
|
|
the opening and closing " are part of the binary string.
|
|
|
|
A paramref is a % followed by one or more decimal digits representing
|
|
an index to the array of PARAMETERS.
|
|
Multiple PARAMETERS may be embedded into a command.
|
|
|
|
typedef struct
|
|
{
|
|
BYTE bFormat; // The first letter after the %
|
|
BYTE bDigits; // only valid if format = 'd' or 'D'
|
|
DWORD dwFlags; // MIN_USED, MAX_USED, MAXREPEAT_USED
|
|
LONG lMin, lMax ; // look here only if dwFlags
|
|
DWORD lMaxRepeat ; // indicates field is used.
|
|
|
|
ARRAYREF ValuesStack; // may contain refs to StandardVariables
|
|
ARRAYREF OperatorStack; (Min, Max, +, -, *, / , MOD, HALT)
|
|
} PARAMETER
|
|
|
|
typedef struct
|
|
{
|
|
DWORD dwValue; // a integer constant or symbol index.
|
|
DWORD dwFlags ; // VALUE_SYMBOL indicates value
|
|
// is index to Control Module's state variable table.
|
|
} VALUE ;
|
|
|
|
|
|
|
|
The value stack is an array of VALUEs.
|
|
The ValueStack field in PARAMETER is an index to the
|
|
an element in the Value stack. This value is considered
|
|
the top of the stack, the value at index n+1 is next on the stack
|
|
and so forth. The count in the array ref indicates how
|
|
many stack elements will be used in the calculation.
|
|
This allows the user to copy the appropriate number of elements
|
|
to a temp working stack since altering the value stack
|
|
will render it unusable for subsequent command processing.
|
|
Also if the user wishes to emit floating pt values, the
|
|
temp stack should be able to hold floating pt formats
|
|
and perform floating pt math.
|
|
|
|
The Operator Stack is simply an array of words.
|
|
Each operator is assigned an enumeration value.
|
|
Each operator starting from the top of the stack is
|
|
used to operate on the contents of the Value stack until
|
|
the HALT operator is encountered. The result on the
|
|
top of the value stack is formatted according to the
|
|
the format specifier and emitted in the command stream.
|
|
|
|
|
|
|
|
|
|
----------------------------
|
|
|
|
Global Attributes: all attributes not stored within
|
|
fields in FEATURE, OPTION or other specialized structures
|
|
are stored in the global attribute structure.
|
|
All elements of the internal global attribute structure
|
|
are DWORDS.
|
|
|
|
The fields for attributes defined by the parser to be
|
|
'relocatable' (ie may appear within a *Switch construct)
|
|
are DWORDS which contain an index to an array of TREE_BRANCH
|
|
structures.
|
|
|
|
|
|
The DWORD for 'non-relocatable' attributes is an offset to the
|
|
actual value stored in the heap. The code reading the structure
|
|
is responsible for applying the correct typecast when retrieving
|
|
this data from the heap.
|
|
|
|
|
|
typedef struct
|
|
{
|
|
DWORD GPDSpecVersion ;
|
|
DWORD MasterUnits ;
|
|
DWORD MaxCopies ;
|
|
....
|
|
DWORD MaxPrintableArea ;
|
|
DWORD DefaultFont ;
|
|
} GLOBAL_ATTRIBUTES ;
|
|
|
|
|
|
In summary, the code accessing attribute structures must
|
|
know whether the attribute is 'relocatable' or not
|
|
and its data type. And whether the data is in a LIST()
|
|
format.
|
|
|
|
|
|
|
|
------------
|
|
|
|
|
|
SYMBOLS, CONSTANTS, and QUALIFIED_NAMES can be stored as a LIST()
|
|
of one or more elements. Since each type is actually stored
|
|
internally as a DWORD, the data type can only be determined
|
|
from the context. This also means all the elements in the LIST()
|
|
must be of the same data type.
|
|
|
|
The list will be implemented as an array of LIST_ELEMENT
|
|
structures. Each attribute that references a list will
|
|
have one DWORD that indexes the first element of the list.
|
|
|
|
Attributes that can take on either a list or single value
|
|
must be stored internally as a list.
|
|
|
|
typedef struct
|
|
{
|
|
DWORD data ;
|
|
DWORD nextItemInList; // -1 means end of list.
|
|
} LIST_ELEMENT ;
|
|
|
|
LIST_ELEMENT listArray[] ;
|
|
|
|
|
|
|
|
-----------------------------------------------
|
|
|
|
|
|
------ implementation details -------------------------------
|
|
|
|
Code emitting option invocations must check that the
|
|
Feature is Installed before emitting the strings.
|
|
|
|
Code checking for UI constraints may ignore entries
|
|
constraining Disabled Features.
|
|
|
|
Code evaluating all UI constraints must ignore effect
|
|
of Uninstalled Features.
|
|
Code displaying features must first check if the feature is
|
|
disabled.
|
|
|
|
|