## Printer Device Driver

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

### Example Code

Starting a Thread With Output to a Printer

Following is an example of starting a thread with output to a printer:

      case DEVESC_STARTDOC:                           // Escape code signals start of document

      {

        // If going to a file or direct to a printer

        if( OD_DIRECT == ulDCType )

        {

          // Open output port (printer-driver version of DosOpen)

          rc  =  PrtOpen( hFile, pszLogAddress );

          // Create/Update the second print thread

          rc = GplThreadStart( hThread,                 // Instance handle

                               0,                       // Handle to spooler

                               hFile,                   // Handle to device

                               0,                       // Default buffer size

                               0,                       // Default number of buffers

                               '\0',                    // Abort character

                               1024,                    // Abort character repeat count

                               sizeof( pszCmdAbort );   // Length of abort command

                               pszCmdAbort,             // Our abort command

                               pszLogAddress,           // For example, LPT1

                               "Error",                 // Error string if write fails

                               pszDeviceName,           // For example, "Epson LQ2550"

                               ulDCType );              // DC type

        } /* end if */

      } /* end case */

Starting a Thread With Output Queuing "Raw" Data

Following is an example of starting a thread with output queuing "raw" printer escapes:

      case DEVESC_STARTDOC:                           // Escape code signals start of document

      {

        // Else DC type is queued, not direct to a printer

        elseif( OD_QUEUED == ulDCType )

        {

          if( ulDataType == PM_Q_RAW )

          {

            if( !hspl )

            {

              // Open appropriate queue (from DevOpenData) for output

              hspl  =  SplQmOpen( "*", 9, (PQMOPENDATA)&DevOpenData );

              SplQmStartDoc( hspl, szDocumentName );

            } /* end if */

            // Create/Update the second print thread

            rc = GplThreadStart( hThread,                 // Instance handle

                                 hspl,                    // Handle to spooler

                                 0,                       // Handle to device

                                 0,                       // Default buffer size

                                 0,                       // Default number of buffers

                                 '\0',                    // Abort character

                                 1024,                    // Abort character repeat count

                                 sizeof( pszCmdAbort );   // Length of abort command

                                 pszCmdAbort,             // Our abort command

                                 pszLogAddress,           // For example, LPT1

                                 "Error",                 // Error string if write fails

                                 pszDeviceName,           // For example, "Epson LQ2550"

                                 ulDCType );                // DC Type

          } /* end if */

        } /* end if */

      } /* end case */

Starting a Thread With Output Queuing "Standard" Data

Following is an example of starting a thread with output queuing "standard" data:

      case DEVESC_STARTDOC:                           // Escape code signals start of document

      {

        // Else DC type is queued, not direct to a printer

        elseif( OD_QUEUED == ulDCType )

        {

          if( ulDataType == PM_Q_STD )

          {

            SplStdStart( pddc->pdb->hdc );

            // Open appropriate queue (from DevOpenData) for output

            hspl = SplQmOpen( "*", 9, (PQMOPENDATA)&DevOpenData );

            // Signal start of document (no thread is started by Omni driver)

            SplQmStartDoc( hspl, szDocumentName );

          } /* end if */

        } /* end if */

      } /* end case */

GplThreadCreateInstance and GplThreadDeleteInstance Usage

The enable and disable subfunctions FILL_PHYSICAL and DISABLE_PHYSICAL are ideal points at which to create and delete a thread instance. Following is an example of GplThreadCreateInstance() and GplThreadDeleteInstance() usage :

    ULONG APIENTRY OS2_PM_DRV_ENABLE( ULONG ulSubFunc, ULONG p1, ULONG p2 )

    {

      switch( ulSubFunc )                                 // Determine enable subfunction

      {

          case FILL_PHYSICAL:                             // An enable subfunction

          {

            // Only create a thread if we expect to output data

            if( (OD_QUEUED == pdb->ulType )  ||  (OD_DIRECT == pdb->ulType ) )

            {

              // Create an output thread instance (do not start thread yet)

              bRC = GplThreadCreateInstance( hmcbHeap, globals.hmod, &hThread, pddc );

            } /* end if */

          } /* end case */

          break;

          case DISABLE_PHYSICAL:                          // A disable subfunction

          {

            // Delete the output thread instance if allocated

            if( hThread )

            {

              bRC = GplThreadDeleteInstance( &hThread );

            } /* end if */

          } /* end case */

          break;

      } /* end switch */

    } /* end OS2_PM_DRV_ENABLE */

GplThreadOutput Usage

Following is an example of GplThreadOutput() usage:

      case DEVESC_NEWFRAME:                            // Page eject requested

      {

         CHAR achRasterCmd[] = "*Esc*r1Q";

         // When getting a DEVESC_NEWFRAME or DEVESC_ENDDOC,

         // The current page's raster image can be retrieved from the

         // device surface and transferred to the printer

         // Enter raster mode by sending down escape code for current device

         bRC = GplThreadOutput( hThread,                 // Thread instance handle

                                achRasterCmd,            // Pointer to data buffer

                                strlen(achRasterCmd),    // Size of data buffer

                                THREAD_DT_BINARY );      // Data type

         // Dither and/or compress raster data and send to output thread

         bRC = GplThreadOutput( hThread,

                                pbRasterData,

                                ulRasterDataLength,

                                THREAD_DT_BINARY );

      } /* end case */

GplThreadEnd Usage

Following is an example of GplThreadEnd usage during OS2_PM_DRV_ENABLE:

    ULONG APIENTRY OS2_PM_DRV_ENABLE( ULONG ulSubFunc, ULONG p1, ULONG p2 )

    {

      switch( ulSubFunc )                              // Determine enable subfunction

      {

        case BEGIN_CLOSE_DC:

        {

          // If we created an output thread

          if( hThread )

          {

            // End   the   second   thread   implied   flush   with   wait

             bRC   =   GplThreadEnd (   hThread   ) ;

           }   / *   end   if   * /

         }   / *   end   case   * /

       }   / *   end   switch   * /

    }   / *   end   OS2 _ PM _ DRV _ ENABLE   * /

GplThreadAbortDoc Usage

Following is an example of GplThreadAbortDoc usage for handling an abort- document escape:

      case DEVESC_ABORTDOC:

      {

        // Tell second thread that an abort doc occurred

        GplThreadAbortDoc( hThread );

        // Store a state flag in our pddc to indicate abort is in effect

        pddc->fAbortDocCalled = TRUE;

      } /* end case */

GplThreadResetAbortDoc Usage

Following is an example of using GplThreadResetAbortDoc:

    case DEVESC_ENDDOC:

    {

      // If we received a DEVESC_ABORTDOC

      if( pddc->fAbortDocCalled )

      {

        // Notify the output thread that the abort condition is over

        GplThreadResetAbortDoc( hThread );

        // Reset the abort state so thread will begin processing data again

        pddc->fAbortDocCalled = FALSE;

      } /* end if */

    } /* end case */

GplThreadFlushBuffer Usage

Following is an example of using GplThreadFlushBuffer:

    case DEVESC_ENDDOC:

    {

      // If going to a file or direct to a printer

      if( OD_DIRECT == ulDCType )

      {

        // Flush all data in second thread; we are done

        GplThreadFlushBuffer( hThread, TRUE );

       } /* end if */

       elseif( OD_QUEUED == ulDCType  &&  PM_Q_RAW == ulDataType )

       {

         // Flush all data in second thread; we are done

         GplThreadFlushBuffer( hThread, TRUE );

       } /* end if */

    } /* end case */

GplThreadHookDeviceWrites Usage

Following is an example of using GplThreadHookDeviceWrites:

    case DEVESC_STARTDOC:

    {

      // We have just called thread Start

      GplThreadStart();

      // We inform the thread that we want to subclass the write of data

      // to the output destination, replacing it with our callback function

      GplThreadHookDeviceWrites( hThread,        // Thread handle

                                 pfnPrtWrite,    // Our "write" function

                                 pddc );         // Parameter to our "write" function

    } /* end case */