/*DDK*************************************************************************/
/*                                                                           */
/* COPYRIGHT    Copyright (C) 1995 IBM Corporation                           */
/*                                                                           */
/*    The following IBM OS/2 WARP source code is provided to you solely for  */
/*    the purpose of assisting you in your development of OS/2 WARP device   */
/*    drivers. You may use this code in accordance with the IBM License      */
/*    Agreement provided in the IBM Device Driver Source Kit for OS/2. This  */
/*    Copyright statement may not be removed.                                */
/*                                                                           */
/*****************************************************************************/
// driver.h

// maximums
#define MAX_DATATYPES            2   // PM_Q_STD and PM_Q_RAW
#define MAX_UNCOLLATEDCOPIES    10   // referenced in DLG.C

// lengths
#define LEN_DEVICENAME          32 // same len as szDeviceName in DRIVDATA in OS2DEF.H
#define LEN_DESCRIPTION         64
#define LEN_SHAREDHEAP       81920 // 20 4K pages
#define LEN_DCHEAP           81920
#define LEN_APPNAME            100

// orientation settings
#define ORIENTATION_PORTRAIT      1
#define ORIENTATION_LANDSCAPE     2

// magic numbers
#define HMTX_CLOSED          (HMTX)0x0DEAD1
#define PM_Q_STD             1              // any magic number not zero
#define PM_Q_RAW             2              // any magic number not zero


// ini file key names
#define KEYNAME_DRIVERDATA        "DRIVERDATA"
#define KEYNAME_SELECTABLEFORMS   "SELECTABLEFORMS"


// defaults
// default font size is 12 point (10 pitch) and 6 lines per inch
#define DEFAULT_POINTSIZE         12
#define DEFAULT_PITCH             10







// CALLING CONVENTIONS

// calling style of driver calling internal driver helper functions
#ifndef NDEBUG
  // debug version: pass args via stack, easier to kernel debug
  #define DRVENTRY  _System
#else
  // retail version: pass args via regs, faster
  #define DRVENTRY  _Optlink
#endif

// calling style of graphics engine and OS/2 when calling into driver
#define ENGENTRY  _System








// exception handling definitions and macros

// FNEH is a typedef for an exception handler function
typedef ULONG _System FNEH( PEXCEPTIONREPORTRECORD, PEXCEPTIONREGISTRATIONRECORD, PCONTEXTRECORD, PVOID );
typedef FNEH *PFNEH;

// typedef for a handler registration record; a link in a list
struct _regrec {
  PEXCEPTIONREGISTRATIONRECORD pnext;       // req'd by os2
  PFNEH                        pfn;         // req'd by os2
  jmp_buf                      jmp;         // additional field for C runtime longjmp support
};
typedef struct _regrec REGREC, *PREGREC;

#define REGISTERHANDLER( regrec ) \
  regrec.pfn = Handler;\
  DosSetExceptionHandler( (PEXCEPTIONREGISTRATIONRECORD) &regrec );

#define UNREGISTERHANDLER( regrec )   DosUnsetExceptionHandler( (PEXCEPTIONREGISTRATIONRECORD)&regrec );

#define XCPT_USER         0xC0C00ABC

#define RAISEEXCEPTION( exnum ) {\
  EXCEPTIONREPORTRECORD err;\
  err.ExceptionNum = exnum;\
  DosRaiseException( &err );\
}





// macros to "enter" and "exit" a DDC
// they ensure that only one thread is using the DDC at any one time
// a thread can successfully request the same sem over and over without error
// a thread has to release it the same number of times it requested it
// the system keeps track of the use count
// error 640 is ERROR_TIMEOUT from bseerr.h

#define ENTERDDC( pddc )  {\
  APIRET rcRequestSem;\
  EXCEPTIONREPORTRECORD err;\
  rcRequestSem = DosRequestMutexSem( pddc->pdb->hmtxDCSem,  SEM_IMMEDIATE_RETURN );\
  assert( 0 == rcRequestSem || 640 == rcRequestSem );\
  if( 640 == rcRequestSem ) {\
    SetErrorInfo( SEVERITY_ERROR, PMERR_HDC_BUSY );\
    err.ExceptionNum = XCPT_USER;\
    DosRaiseException( &err );\
  }\
}

#define EXITDDC( pddc )  {\
  APIRET rcReleaseSem;\
  rcReleaseSem = DosReleaseMutexSem( pddc->pdb->hmtxDCSem );\
  assert( 0 == rcReleaseSem );\
}


















// STRUCTS


//---------------------------------------------------------------------------------------------------------------------
// form info needed in addition to that contained in HCINFO
// DEVICE_SPECIFIC: pszSelectEscape is specific to supported device; see also DRIVER.C for assignment of the escape

struct _forminfo {
  HCINFO  hcinfo;
  PSZ     pszSelectEscape;
};
typedef struct _forminfo  FORMINFO, *PFORMINFO;


// --------------------------------------------------------------------------------------------------------------------
// per process data; there is one of these structures allocated in private process memory
// for each process that loads this DLL.  It has the NONSHARED segment attribute defined
// in the DEF file because it is declared after a #pragma data_seg ( PerProcess ) in driver.c


struct _procdata   {
  char         szAssert[ 64 ];               // expression asserted
  char         szFilename[ 64 ];             // filename where assertion failed
  ULONG        ulLine;                       // line number where assertion failed
  ULONG        ulLastError;                  // error id from WinGetLastError
  PID          pid;                          // process id
  HMTX         hmtxGlobalSem;                // handle to shared, global, named, system-wide mutex sem
  HMTX         hmtxProcessSem;               // handle to private, process sem for serialization
};
typedef struct _procdata  PROCDATA, *PPROCDATA;



// --------------------------------------------------------------------------------------------------------------------
// DRIVERDATA structure

/*

The DRIVERDATA structure is driver-specific data.  The driver uses its
contents to control the printing of a job.  The items contained are often
called job properties.  This driver calls the structure DRIVERDATA.  It is
extended from the structure DRIVDATA in OS2DEF.H.

PM application programmers know this structure as DRIVDATA, and they are
required to handle it.  Application programmers should make no assumptions
about the contents of DRIVDATA other than what is defined in OS2DEF.H.  Only
the device drivers know the extended format and content.

Applications get copies of DRIVDATA from calling SplEnumQueue().
The DRIVDATA returned is used in calls to DevPostDeviceModes() and
DevOpenDC().  Applications rely on the device driver to massage the data in
DRIVDATA.  DevPostDeviceModes() is the best way to massage job properties
whose settings are contained in DRIVDATA.

Print driver code modifications over time will affect the data structure
DRIVERDATA.  As the DRIVERDATA structure morphs, then a new version number
for the DRIVERDATA structure must be assigned so the driver can distinguish
different versions of DRIVERDATA.  Versioning is of little concern on a
single, standalone OS/2 system because there is only one driver, and it is
not required to interact with other versions.  However, in the LAN
environment, versioning is an important concern.  In the field, expect your
customers to install different versions of your printer driver on LAN
requestors and servers.

A copy of DRIVERDATA travels over the LAN when an OS/2 LAN requestor prints
PM_Q_STD jobs to an OS/2 LAN server.  A printer server should be able to
understand DRIVERDATA structures submitted from any requestor -- even from
requestors that have a newer version of the driver than the server!

This version number should not be confused with the version number reported
at QueryDeviceCaps() time.  That version number is examined by the graphics
engine.  The version number in DRIVERDATA is meant to be interpreted by the
printer driver only.

Rules of thumb:

 . when assigning a new version number, raise the old version number by one
 . when morphing the DRIVERDATA structure, never collapse it, just grow it

*/

// version number(s) for DRIVERDATA structure
#define DRIVERDATA_VERSION  0x0100

struct _driverdata  {
  LONG    cb;                          // length of the overall structure in bytes
  LONG    lVersion;                    // driver data version
  CHAR    szDeviceName[32];            // name of supported device
  ULONG   ulOrientation;               // orientation of form is a job property
  CHAR    szFormName[ 32 ];            // size of form is a job property
  LONG    cCopies;                     // count of uncollated copies; see NEWFRAME.C
};
typedef struct _driverdata DRIVERDATA, *PDRIVERDATA;


// --------------------------------------------------------------------------------------------------------------------
// physical traits of printers supported by this driver

struct _supporteddevice {
  CHAR                    szDeviceName[ LEN_DEVICENAME ];
  ULONG                   cForms;
  PFORMINFO               paFormInfo;
  ULONG                   ulXResolution;
  ULONG                   ulYResolution;
};
typedef struct _supporteddevice SUPPORTEDDEVICE, *PSUPPORTEDDEVICE;



// ----------------------------------------------------------------------------------------------
// dialog instance data; allocated in OS2_PM_DRV_DEVMODE when presenting a dialog to the user

struct _dlginstance {
  PDRIVERDATA          pddSupplied;                 // driver data supplied on the call
  PSZ                  pszDriverName;               // DRV module name supplied on the call
  PSZ                  pszDeviceName;               // supported device name supplied on the call
  PSZ                  pszPrinterName;              // logical printer name per printer object
  ULONG                ulOption;                    // DPDM_* option
  DRIVERDATA           ddScratch;                   // DRIVERDATA scratch pad for dialog proc
  ULONG                ulDismissalCode;             // scratch pad data is good if DID_OK dismissal code
  PSUPPORTEDDEVICE     pSupportedDevice;            // pointer to physical traits of the printer
  CHAR                 achSelectableForms[ 120 ];   // of the format "Letter;Legal;A4;" etc.
};
typedef struct _dlginstance DLGINSTANCE, *PDLGINSTANCE;




// ----------------------------------------------------------------------------------------------
// global data; there is only one copy of this structure in memory and every process that uses the
// driver will have this global data mapped into their virtual process' address space
// It has the SHARED attribute in the def file.  Pragma'd and declared in DRIVER.C.

struct _globals  {
  HMODULE               hModule;                      // supplied on first load in INITTERM.C
  ULONG                 ulGreVersion;                 // on fill logical, graphics engine version
  ULONG                 cDispatchEntries;             // on fill logical, count of entries in the dispatch table
  PFN*                  ppfnDispatchTableCopy;        // points to a copy of the original, unmodified dispatch table
  PSZ                   pszSemName;                   // pointer to string containing the name of the global sem
  ULONG                 ulDeviceCount;                // count of supported devices
  PSUPPORTEDDEVICE      paDevice;                     // pointer to the first of the array of supported devices
  PVOID                 pvSharedHeap;                 // pointer to base of shared heap
  ULONG                 cInstances;                   // count of times this driver is instantiated
  CHAR                  szModule[ 600 ];              // module name as supplied on DLL_initterm() call
};
typedef struct _globals  GLOBALS, *PGLOBALS;





// -----------------------------------------------------------------------------------------------
// device block filled in at FILL_PHYSICAL time

struct _deviceblock {
  CHAR               szLogAddress[ CCHMAXPATH ];       // holds a copy of DEVOPENSTRUC contents passed into FILL_PHYSICAL
  CHAR               szDriverName[ CCHMAXPATH ];       // ditto
  DRIVERDATA         DriverData;                       // ditto
  CHAR               szDataType[ 16 ];                 // ditto
  CHAR               szComment[ 80 ];                  // ditto
  CHAR               szSpoolerParams[ 64 ];            // ditto
  DEVOPENSTRUC       dop;                              // dop whose pointers point to above items; used on SplQmOpen
  ULONG              ulStateInfo;                      // assigned at FILL_PHYSICAL time, but otherwise unused
  ULONG              ulType;                           // OD_ type DIRECT/QUEUE/INFO/META
  HDC                hdc;                              // current DC handle
  PVOID              pvHeap;                           // base of DC heap; see also #define LEN_DCHEAP
  HMTX               hmtxDCSem;                        // sem to serialize access to the ddc
  ULONG              ulDataType;                       // integer value for PM_Q_STD or PM_Q_RAW
  BOOL               fStartDocCalled;                  // application sent a DEVESC_STARTDOC
  BOOL               fAbortDocCalled;                  // application sent a DEVESC_ABORTDOC
  HSPL               hspl;                             // result of SplQmOpen; only need one of these for life of DC
  CHAR               szDocumentName[ 36 ];             // document name supplied on DEVESC_STARTDOC
  ULONG              ulPage;                           // page number; first page is page number zero
  PSUPPORTEDDEVICE   pSupportedDevice;                 // pointer to the supported device structure
  PFORMINFO          pFormInfo;                        // pointer to the form information for this job's form
};
typedef struct _deviceblock  DEVICEBLOCK, *PDEVICEBLOCK;







// -----------------------------------------------------------------------------------------------
// DDC: device drawing context


struct _ddc {
  PDEVICEBLOCK pdb;                   // pointer to physical device block
  BOOL         fComplete;             // complete open DC has been called
  HDC          hdcShadow;             // display OD_MEMORY DC created at printer DC enable time
  HRGN         hrgnShadow;            // rectangular clipping region for shadow DC
  HBITMAP      hbmShadow;             // bitmap for shadow DC
  POINTL       ptlDCOrigin;           // initialized to 0, 0 at enable time; will be used for banding in future version
  BOOL         fGenerateOutput;       // OD_DIRECT or OD_QUEUED+PM_Q_RAW
};
typedef struct _ddc DDC, *PDDC;





// externs for public, static structures
// they are pragma'd and declared in driver.c
extern GLOBALS      globals;
extern PROCDATA     procdata;

