## Presentation Device Driver Reference for OS/2

[prev][next][parent][TOC]

### Design Overview of DJP

DJP can be applied to two different scenarios. The first scenario applies to applications that query or modify DJP_ITEMs; these events are usually performed asynchronously. In this scenario, the application opens up a OD_ INFO DC, sets up its job property information, and then turns around and opens up a OD_QUEUED DC to print. Setting or querying data uses only the printer property information in the device context (DC) and does not affect the print job in any other way.

In the other scenario for using DJPs, the DC characteristics provided in the DevOpenDC information are changed. This is either accomplished at the start of a document with GreEscape DEVESC_STARTDOC_WPROP or at the beginning of a new page with GreEscape DEVESC_NEWFRAME_WPROP. In this scenario, the application must query the printer driver again and again for DevQueryCaps, DevQueryHardcopyCaps, list of devices fonts, and any other DC information. The driver must use the same code path that DevOpenDC uses ( FillLogicalDeviceBlock, FillPhysicalDeviceBlock, EnableDeviceContext, CompleteOpenDC). After the printer driver resets all of its information, it calls the new Gre call, GreResetDC2 (hdc, 0). This call instructs the graphics engine to query the printer driver again and recalculate its internal state data. This has the side effect of performing a ResetDC.

The DJP_ITEM is the new structure that contains DJP information. The structure DJP_ITEM is used by both applications and device drivers. The format of the structure follows.

    /* Dynamic Job Property Item

    */

    typedef struct _djpItem {

       ULONG       cb;             // size of this structure

       ULONG       ulProperty;     // Type of Property

       LONG        iType;          // INPUT : DJP_ALL - Returns all possible

                                   //         values (placed at ulValue).

                                   //         DJP_ALL is not valid if

                                   //         setting properties.

                                   //

                                   //         DJP_CURRENT - returns current

                                   //         value

                                   //

                                   // OUTPUT: DJP_ERROR_XXX if there was an

                                   //         error

       ULONG       ulNumReturned;  // How many elements are returned in

                                   // ulValue on a query. This should be

                                   // 1 for DEVESC_SETJOBPROPERTIES.

       ULONG       ulValue;        // The start of the types supported by

                                   // this property.

    } DJP_ITEM, *PDJP_ITEM;

Because the individual properties have variable lengths, the properties are broken up into two different categories: simple and complex. The names of these properties are identified by either "_Sx_" for simple or "_Cx_" for complex. In addition, they are sorted into different subcategories such as "_xJ_" for job properties or "_xP_" for printer properties. Simple types are ULONG sized. This is the minimum size for the data. The complex types can be larger and have structures associated with them. All property types, simple and complex, are associated with a type; for example, DJP_SJ_ ORIENTATION is a simple type of type PDJPT_ORIENTATION. The values for DJP_ SJ_ORIENTATION can be DJP_ORI_PORTRAIT or DJP_ORI_LANDSCAPE. DJP_CJ_ RESOLUTION is a complex type of type PDJPT_RESOLUTION; this is a structure composed of two members: x and y resolutions.

The following helper macros have been created to work with DJP_ITEMs: DJP_NEXT_STRUCTP(), DJP_ELEMENTP(), and DJP_SET_ELEMENT().

DJP_NEXT_STRUCTP(): This macro is used for walking the list of item structures. It takes a pointer to the current item and returns a pointer to the next item and depends on the size of the structure set in the variable cb.

    // Bump to the next DJP_ITEM structure

    pDJP = DJP_NEXT_STRUCTP (pDJP);

DJP_ELEMENTP(): This macro takes a pointer to the current item and returns a pointer to the element type passed in. Each job property type has a corresponding element type.

    // Get the pointer to the resolution value

    PDJPT_RESOLUTION    pElm;

    pElm = DJP_ELEMENTP (pDJP, DJPT_RESOLUTION);

DJP_SET_ELEMENT(): This macro will take three parameters: The first is a DJP_ITEM structure, the second is the element type, and the third is the DJP element. This function helps to deal with complex structures, but is not useful for dealing with simple structures. The following example shows how to set DJP_CJ_RESOLUTION (complex property) to use a 720x720 resolution :

    // Structure (from header file DJP.H)

    typedef struct _djpResolution {

       USHORT     usXResolution; // X resolution (in dots per inch)

       USHORT     usYResolution; // Y resolution (in dots per inch)

    } DJPT_RESOLUTION, *PDJPT_RESOLUTION;

    // Set the # of bytes in the structure

    pDJP->cb = DJP_HEADER_SIZE + sizeof (DJPT_RESOLUTION);

    // Set the current property and type

    pDJP->ulProperty = DJP_CJ_RESOLUTION;

    pDJP->iType      = DJP_CURRENT;

    // Set up the resolution structure

    djpResolution.usXResolution = 720;

    djpResolution.usYResolution = 720;

    // Put the data into the DJP_ITEM structure.

    DJP_SET_ELEMENT (*pDJP, DJPT_RESOLUTION, djpResolution);

    To set a simple type such as the color mode use:

    pDJP->cb         = sizeof (DJP_ITEM);

    pDJP->ulProperty = DJP_SJ_COLOR;

    pDJP->lType      = DJP_CURRENT;

    pDJP->ulValue    = DJP_CLR_COLOR;

    /* Move to next element. Either way, you use the same macro.

    ** Dependent on cb having the correct value.

    */

    pDJP = DJP_NEXT_STRUCTP (pDJP);

The parts of the DJP property defines identified by _Sx_ and _Cx_ indicate whether the specified item is a simple item or a complex item. This information helps you to determine the correct strategy for setting the structure size and the data value.