/*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.                                */
/*                                                                           */
/*****************************************************************************/
// query.c

#define INCL_DOS
#define INCL_PM
#define INCL_GPIERRORS
#include <os2.h>


#define INCL_32
#define INCL_VMANDDI
#include <ddi.h>

#define INCL_GRE_DEVICESURFACE
#define INCL_GREALL
#define INCL_DDIMISC
#include <pmddi.h>

// c includes
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <setjmp.h>


#define INCL_GENPLIB_JOURNAL
#define INCL_GENPLIB_MEMORY
#include <genplib.h>



#include "def.h"
#include "driver.h"
#include "funcs.h"


// helper macro that assumes lWork is defined automatically, and a,b are longs
#define swap(a,b) { lWork=a; a=b; b=lWork; }



// -------------------------------------------------------------------------------------------------------------------------
// Mandatory function in GRE22 model.
// Nothing is happening here because this is a monochrome only device.
// If color, provide the printer's hardware palette.

LONG APIENTRY DevicePalette( HDC hdc, PHWPALETTEINFO pHWPaletteInfo, PDDC pddc, ULONG ulFunction )
{
  return TRUE;
}




//----------------------------------------------------------------------------------------

LONG APIENTRY QueryHardcopyCaps(        HDC                        hdc,
                                        LONG                       lStart,
                                        LONG                       cCount,
                                        PHCINFO                    pInfo,
                                        PDDC                       pddc,
                                        ULONG                      ulFunction )
{
  REGREC      regrec;
  ULONG       ulException;
  LONG        lrc;
  LONG        i;
  LONG        lWork;
  PFORMINFO   pfi;



  assert( pddc  );
  assert( pddc->pSupportedDevice );


  REGISTERHANDLER( regrec );
  ulException = setjmp( regrec.jmp );
  if( ulException ) {
    assert( FALSE );
    CheckForTermination( &regrec, ulException, pddc  );
    // error result
    SetErrorInfo( SEVERITY_ERROR, PMERR_INV_LENGTH_OR_COUNT );
    lrc = DQHC_ERROR;
    goto depart;
  }


  if( cCount == 0 ) {
    // return count of hard copy forms supported for this device
    lrc = pddc->pSupportedDevice->cForms;
    goto depart;
  }

  if( lStart >= pddc->pSupportedDevice->cForms ) {
    // request is out of range
    lrc = 0;
    goto depart;
  }


  // copy this many hcinfo structs
  cCount = min( pddc->pSupportedDevice->cForms - lStart, cCount );

  pfi = pddc->pSupportedDevice->paFormInfo + lStart;

  for( i=0; i < cCount; i++ ) {
    *pInfo = pfi->hcinfo;

    if( pddc->DriverData.ulOrientation == ORIENTATION_LANDSCAPE ) {
      // switch x, y around
      swap( pInfo->cx,            pInfo->cy          );
      swap( pInfo->xLeftClip,     pInfo->yTopClip    );
      swap( pInfo->yBottomClip,   pInfo->xLeftClip   );
      swap( pInfo->xPels,         pInfo->yPels       );
    }

    pInfo++;
    pfi++;
  }

  lrc = cCount;

depart:
  UNREGISTERHANDLER( regrec );
  return lrc;
}





// --------------------------------------------------------------------------------------------------------------------
// set the printer's caps into the device info block.
// called from FILL-PHYSICAL at enable time.
// this data is later copied to the surface info structure when GRE calls QuerySurfaceDefinition

LONG DRVENTRY SetCapabilities( PDDC pddc )
{
  int i;
  LONG       xPelsOnPage;
  LONG       yPelsOnPage;



  // prepare the array of device capabilties,
  // store it in the per-DC heap,
  // and supply it to the GRE during QuerySurfaceDefinition


  // setup form size given portrait or landscape
  // determine x and y pels on the page

  assert( pddc->pSupportedDevice );
  assert( pddc->pFormInfo );

  switch( pddc->DriverData.ulOrientation ) {
  case ORIENTATION_PORTRAIT:
    xPelsOnPage = pddc->pFormInfo->hcinfo.xPels;
    yPelsOnPage = pddc->pFormInfo->hcinfo.yPels;
    break;
  case ORIENTATION_LANDSCAPE:
    xPelsOnPage = pddc->pFormInfo->hcinfo.yPels;
    yPelsOnPage = pddc->pFormInfo->hcinfo.xPels;
    break;
  default:
    assert( FALSE );
    break;
  }



  // CAPS_MAX_CAPS is defined by the GRE
  assert( CAPS_MAX_CAPS > 0 );

  for( i = 0; i < CAPS_MAX_CAPS; i++ ) {

    // these cases are in the order that FONTTEST32 (ft32.exe) program lists them
    switch( i ) {
    case CAPS_FAMILY:
      // customary to return OD_DIRECT (5) for this
      pddc->aDeviceCaps[ i ] = OD_DIRECT;
      break;

    case CAPS_IO_CAPS:
      // device supports output
      pddc->aDeviceCaps[ i ] = CAPS_IO_SUPPORTS_OP;
      break;

    case CAPS_TECHNOLOGY:
      pddc->aDeviceCaps[ i ] = CAPS_TECH_RASTER_PRINTER;
      break;

    case CAPS_DRIVER_VERSION:
      // this driver is generally targeted for 2.2
      pddc->aDeviceCaps[ i ] = 0x00000220;
      break;

    case CAPS_WIDTH:
      // current form width in pels
      pddc->aDeviceCaps[ i ] = xPelsOnPage;
      break;

    case CAPS_HEIGHT:
      // current form height in pels
      pddc->aDeviceCaps[ i ] = yPelsOnPage;
      break;

    case CAPS_WIDTH_IN_CHARS:
      // assume 80 chars per line of 12 point text on Letter
      pddc->aDeviceCaps[ i ] = 80;
      break;

    case CAPS_HEIGHT_IN_CHARS:
      // assume 6 lines per inch of 12 point text on Letter
      pddc->aDeviceCaps[ i ] = 66;
      break;

    case CAPS_VERTICAL_RESOLUTION:
    case CAPS_HORIZONTAL_RESOLUTION:
      // compute value in pels per meter; there are 39.37 inches per meter
      // DEVICE_SPECIFIC: square pixels -- may not be the case
      assert( pddc->pSupportedDevice->ulXResolution == pddc->pSupportedDevice->ulYResolution );
      pddc->aDeviceCaps[ i ] = ( pddc->pSupportedDevice->ulXResolution * 3937 ) / 100;
      break;

    case CAPS_CHAR_WIDTH:
    case CAPS_GRAPHICS_CHAR_WIDTH:
      // default char width in pels
      pddc->aDeviceCaps[ i ] = pddc->pSupportedDevice->ulXResolution / DEFAULT_PITCH;
      break;

    case CAPS_CHAR_HEIGHT:
    case CAPS_GRAPHICS_CHAR_HEIGHT:
      // default char height in pels
      pddc->aDeviceCaps[ i ] = ( DEFAULT_POINTSIZE * pddc->pSupportedDevice->ulXResolution ) / 72;
      break;

    case CAPS_SMALL_CHAR_HEIGHT:
    case CAPS_SMALL_CHAR_WIDTH:
      // none
      pddc->aDeviceCaps[ i ] = 0;
      break;


    case CAPS_COLORS:
      // depends on current device; simulated "logical" color count
      assert( pddc->pSupportedDevice );
      pddc->aDeviceCaps[ i ] = pddc->pSupportedDevice->cColors;
      break;

    case CAPS_COLOR_PLANES:
      // depends on currently selected supported device
      assert( pddc->pSupportedDevice );
      pddc->aDeviceCaps[ i ] = pddc->pSupportedDevice->cColorPlanes;
      break;

    case CAPS_COLOR_BITCOUNT:
      // bpp for simulated "logical" colors
      pddc->aDeviceCaps[ i ] = pddc->pSupportedDevice->cBitsPerPel;
      break;

    case CAPS_FOREGROUND_MIX_SUPPORT:
      pddc->aDeviceCaps[ i ] = CAPS_FM_OR                |
                               CAPS_FM_OVERPAINT         |
                               CAPS_FM_XOR               |
                               CAPS_FM_LEAVEALONE        |
                               CAPS_FM_AND               |
                               CAPS_FM_GENERAL_BOOLEAN;
      break;


    case CAPS_BACKGROUND_MIX_SUPPORT:
      pddc->aDeviceCaps[ i ] = CAPS_BM_OVERPAINT | CAPS_BM_LEAVEALONE;
      break;


    case CAPS_BITMAP_FORMATS:
      pddc->aDeviceCaps[ i ] = 2;
      break;


    case CAPS_RASTER_CAPS:
      pddc->aDeviceCaps[ i ] = CAPS_RASTER_BITBLT | CAPS_RASTER_SET_PEL | CAPS_RASTER_FONTS;
      break;



    case CAPS_MARKER_HEIGHT:
    case CAPS_MARKER_WIDTH:
      assert( pddc->pSupportedDevice );
      assert( pddc->pSupportedDevice->ulXResolution == pddc->pSupportedDevice->ulYResolution );
      pddc->aDeviceCaps[ i ] = pddc->pSupportedDevice->ulYResolution / DEFAULT_PITCH;
      break;



    case CAPS_PHYS_COLORS:
      assert( pddc->pSupportedDevice );
      pddc->aDeviceCaps[ i ] = pddc->pSupportedDevice->cPhysicalColors;
      break;


    case CAPS_DEVICE_FONTS:
      // count of device fonts
      pddc->aDeviceCaps[ i ] = 0;
      break;


    case CAPS_COLOR_INDEX:
      // maximum logical color table index supported for this device
      // simulated "logical" colors
      pddc->aDeviceCaps[ i ] = pddc->pSupportedDevice->cColors - 1;
      break;


    case CAPS_HORIZONTAL_FONT_RES:
    case CAPS_VERTICAL_FONT_RES:
      assert( pddc->pSupportedDevice );
      assert( pddc->pSupportedDevice->ulXResolution == pddc->pSupportedDevice->ulYResolution );
      pddc->aDeviceCaps[ i ] = pddc->pSupportedDevice->ulYResolution;
      break;


    // unsupported device capabilities
    case CAPS_COLOR_TABLE_SUPPORT:
    case CAPS_DEVICE_FONT_SIM:
    case CAPS_DEVICE_POLYSET_POINTS:
    case CAPS_DEVICE_WINDOWING:
    case CAPS_GRAPHICS_SUBSET:
    case CAPS_GRAPHICS_VECTOR_SUBSET:
    case CAPS_GRAPHICS_VERSION:
    case CAPS_LINEWIDTH_THICK:
    case CAPS_MOUSE_BUTTONS:
    case CAPS_WINDOW_BYTE_ALIGNMENT:
    case CAPS_VIO_LOADABLE_FONTS:
    case CAPS_ADDITIONAL_GRAPHICS:
    default:
      pddc->aDeviceCaps[ i ] = 0;
      break;
    }
  }

  return 1;
}

