712 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			712 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			C
		
	
	
	
/* $Xorg: PclPrint.c,v 1.3 2000/08/17 19:48:08 cpqbld Exp $ */
 | 
						|
/*******************************************************************
 | 
						|
**
 | 
						|
**    *********************************************************
 | 
						|
**    *
 | 
						|
**    *  File:		PclPrint.c
 | 
						|
**    *
 | 
						|
**    *  Contents:	Print extension code of Pcl driver
 | 
						|
**    *
 | 
						|
**    *  Created:	2/03/95
 | 
						|
**    *
 | 
						|
**    *********************************************************
 | 
						|
** 
 | 
						|
********************************************************************/
 | 
						|
/*
 | 
						|
(c) Copyright 1996 Hewlett-Packard Company
 | 
						|
(c) Copyright 1996 International Business Machines Corp.
 | 
						|
(c) Copyright 1996 Sun Microsystems, Inc.
 | 
						|
(c) Copyright 1996 Novell, Inc.
 | 
						|
(c) Copyright 1996 Digital Equipment Corp.
 | 
						|
(c) Copyright 1996 Fujitsu Limited
 | 
						|
(c) Copyright 1996 Hitachi, Ltd.
 | 
						|
 | 
						|
Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
						|
of this software and associated documentation files (the "Software"), to deal
 | 
						|
in the Software without restriction, including without limitation the rights
 | 
						|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
						|
copies of the Software, and to permit persons to whom the Software is
 | 
						|
furnished to do so, subject to the following conditions:
 | 
						|
 | 
						|
The above copyright notice and this permission notice shall be included in
 | 
						|
all copies or substantial portions of the Software.
 | 
						|
 | 
						|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
						|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
						|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
 | 
						|
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 | 
						|
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 | 
						|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 | 
						|
 | 
						|
Except as contained in this notice, the names of the copyright holders shall
 | 
						|
not be used in advertising or otherwise to promote the sale, use or other
 | 
						|
dealings in this Software without prior written authorization from said
 | 
						|
copyright holders.
 | 
						|
*/
 | 
						|
/* $XFree86: xc/programs/Xserver/Xprint/pcl/PclPrint.c,v 1.7tsi Exp $ */
 | 
						|
 | 
						|
#ifdef HAVE_DIX_CONFIG_H
 | 
						|
#include <dix-config.h>
 | 
						|
#endif
 | 
						|
 | 
						|
#include <stdio.h>
 | 
						|
#include <string.h>
 | 
						|
#include <sys/types.h>
 | 
						|
#include <sys/stat.h>
 | 
						|
#include <sys/wait.h>
 | 
						|
#include <unistd.h>
 | 
						|
#include <X11/Xprotostr.h>
 | 
						|
 | 
						|
#define NEED_EVENTS
 | 
						|
#include <X11/Xproto.h>
 | 
						|
#undef NEED_EVENTS
 | 
						|
 | 
						|
#include "Pcl.h"
 | 
						|
 | 
						|
#include "windowstr.h"
 | 
						|
#include "attributes.h"
 | 
						|
#include "AttrValid.h"
 | 
						|
#include "Oid.h"
 | 
						|
 | 
						|
int
 | 
						|
PclStartJob(
 | 
						|
     XpContextPtr pCon,
 | 
						|
     Bool sendClientData,
 | 
						|
     ClientPtr client)
 | 
						|
{
 | 
						|
    PclContextPrivPtr pConPriv = 
 | 
						|
      (PclContextPrivPtr)pCon->devPrivates[PclContextPrivateIndex].ptr;
 | 
						|
    PclPaletteMap *pal;
 | 
						|
    
 | 
						|
    /*
 | 
						|
     * Check for existing page file, and delete it if it exists.
 | 
						|
     */
 | 
						|
    if(pConPriv->pageFileName != (char *)NULL)
 | 
						|
    {
 | 
						|
	if(pConPriv->pPageFile != (FILE *)NULL)
 | 
						|
	{
 | 
						|
	    fclose(pConPriv->pPageFile);
 | 
						|
	    pConPriv->pPageFile = (FILE *)NULL;
 | 
						|
	}
 | 
						|
	unlink(pConPriv->pageFileName);
 | 
						|
	xfree(pConPriv->pageFileName);
 | 
						|
	pConPriv->pageFileName = (char *)NULL;
 | 
						|
    }
 | 
						|
 | 
						|
    /* 
 | 
						|
     * Create a temporary file to store the printer output.
 | 
						|
     */
 | 
						|
    if (!XpOpenTmpFile("w+", &pConPriv->jobFileName, &pConPriv->pJobFile))
 | 
						|
	return BadAlloc;
 | 
						|
 | 
						|
    /*
 | 
						|
     * Create/Initialize the SoftFontInfo structure
 | 
						|
     */
 | 
						|
    pConPriv->pSoftFontInfo = PclCreateSoftFontInfo();
 | 
						|
 | 
						|
    /*
 | 
						|
     * Set up the colormap handling
 | 
						|
     */
 | 
						|
    pConPriv->palettes = NULL;
 | 
						|
    pConPriv->nextPaletteId = 4;
 | 
						|
    pConPriv->currentPalette = 0;
 | 
						|
 | 
						|
    pal = &( pConPriv->staticGrayPalette );
 | 
						|
    pal->paletteId = 1;
 | 
						|
    pal->downloaded = 0;
 | 
						|
    
 | 
						|
    pal = &( pConPriv->trueColorPalette );
 | 
						|
    pal->paletteId = 2;
 | 
						|
    pal->downloaded = 0;
 | 
						|
    
 | 
						|
    pal = &( pConPriv->specialTrueColorPalette );
 | 
						|
    pal->paletteId = 3;
 | 
						|
    pal->downloaded = 0;
 | 
						|
 | 
						|
    return Success;
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
PclEndJob(
 | 
						|
     XpContextPtr pCon,
 | 
						|
     Bool cancel)
 | 
						|
{
 | 
						|
    PclContextPrivPtr priv = (PclContextPrivPtr)
 | 
						|
      pCon->devPrivates[PclContextPrivateIndex].ptr;
 | 
						|
 | 
						|
#ifdef CCP_DEBUG
 | 
						|
    FILE *xpoutput;
 | 
						|
#endif
 | 
						|
    FILE *fp;
 | 
						|
    int retVal;
 | 
						|
    char *fileName, *trailer;
 | 
						|
    struct stat statBuf;
 | 
						|
    PclPaletteMapPtr p;
 | 
						|
 | 
						|
    trailer = "\033%-12345X@PJL RESET\n";
 | 
						|
 | 
						|
    if( cancel == True )
 | 
						|
      {
 | 
						|
	  if( priv->getDocClient != (ClientPtr)NULL ) {
 | 
						|
	      XpFinishDocData( priv->getDocClient );
 | 
						|
 | 
						|
	      priv->getDocClient = NULL;
 | 
						|
	      priv->getDocBufSize = 0;
 | 
						|
	  }
 | 
						|
 | 
						|
	  return Success;
 | 
						|
      }
 | 
						|
    
 | 
						|
    if( priv->getDocClient != (ClientPtr)NULL && priv->getDocBufSize > 0  )
 | 
						|
      {
 | 
						|
	  /*
 | 
						|
	   * We need to stash the trailer information somewhere...
 | 
						|
	   */
 | 
						|
	  if (!XpOpenTmpFile("w+", &fileName, &fp))
 | 
						|
	      return BadAlloc;
 | 
						|
 | 
						|
#ifndef XP_PCL_LJ3
 | 
						|
	  SEND_PCL( fp, trailer );
 | 
						|
	  rewind( fp );
 | 
						|
 | 
						|
	  retVal = XpSendDocumentData( priv->getDocClient, fp,
 | 
						|
				      strlen( trailer ),
 | 
						|
				      priv->getDocBufSize );
 | 
						|
#endif /* XP_PCL_LJ3 */
 | 
						|
 | 
						|
	  fclose( fp );
 | 
						|
	  unlink( fileName );
 | 
						|
	  xfree( fileName );
 | 
						|
 | 
						|
	  if( priv->getDocClient != (ClientPtr)NULL ) {
 | 
						|
	      XpFinishDocData( priv->getDocClient );
 | 
						|
 | 
						|
	      priv->getDocClient = NULL;
 | 
						|
	      priv->getDocBufSize = 0;
 | 
						|
	  }
 | 
						|
 | 
						|
	  return retVal;
 | 
						|
      }
 | 
						|
    
 | 
						|
#ifndef XP_PCL_LJ3
 | 
						|
    SEND_PCL( priv->pJobFile, trailer );
 | 
						|
#endif /* XP_PCL_LJ3 */
 | 
						|
    
 | 
						|
    /*
 | 
						|
     * Submit the job to the spooler
 | 
						|
     */
 | 
						|
    fflush( priv->pJobFile );
 | 
						|
    
 | 
						|
    /*
 | 
						|
     * Dump the job file to another output file, for testing
 | 
						|
     * purposes.
 | 
						|
     */
 | 
						|
    rewind( priv->pJobFile );
 | 
						|
    stat( priv->jobFileName, &statBuf );
 | 
						|
    
 | 
						|
#ifdef CCP_DEBUG
 | 
						|
    unlink( "/users/prince/XpOutput" );
 | 
						|
    xpoutput = fopen( "/users/prince/XpOutput", "w" );
 | 
						|
    
 | 
						|
    rewind( priv->pJobFile );
 | 
						|
    TransferBytes( priv->pJobFile, xpoutput,
 | 
						|
		      (int)statBuf.st_size );
 | 
						|
    fclose( xpoutput );
 | 
						|
#endif
 | 
						|
    
 | 
						|
    XpSubmitJob( priv->jobFileName, pCon );
 | 
						|
    fclose( priv->pJobFile );
 | 
						|
    unlink( priv->jobFileName );
 | 
						|
    xfree( priv->jobFileName );
 | 
						|
    priv->jobFileName = NULL;
 | 
						|
 | 
						|
    PclDestroySoftFontInfo(priv->pSoftFontInfo);
 | 
						|
    priv->pSoftFontInfo = (PclSoftFontInfoPtr) NULL;
 | 
						|
 | 
						|
    /*
 | 
						|
     * Clear out the colormap cache
 | 
						|
     */
 | 
						|
    p = priv->palettes;
 | 
						|
    while( p )
 | 
						|
      {
 | 
						|
	  p->downloaded = 0;
 | 
						|
	  p = p->next;
 | 
						|
      }
 | 
						|
 | 
						|
    return Success;
 | 
						|
}
 | 
						|
 | 
						|
/* StartPage 
 | 
						|
 *
 | 
						|
 * If page file exists
 | 
						|
 *     close page file
 | 
						|
 *     set page file pointer = NULL
 | 
						|
 *     unlink page file
 | 
						|
 * Create a new page file
 | 
						|
 *     Send the page header information to the page file
 | 
						|
 * ClearArea the window and all descendant windows
 | 
						|
 */
 | 
						|
int
 | 
						|
PclStartPage(
 | 
						|
     XpContextPtr pCon,
 | 
						|
     WindowPtr pWin)
 | 
						|
{
 | 
						|
    PclContextPrivPtr pConPriv = (PclContextPrivPtr)
 | 
						|
      pCon->devPrivates[PclContextPrivateIndex].ptr;
 | 
						|
    PclWindowPrivPtr pWinPriv =
 | 
						|
      (PclWindowPrivPtr)pWin->devPrivates[PclWindowPrivateIndex].ptr;
 | 
						|
    xRectangle repro;
 | 
						|
    char t[80];
 | 
						|
    XpOid orient, plex, tray, medium;
 | 
						|
    int dir, plexNum, num;
 | 
						|
    
 | 
						|
    /*
 | 
						|
     * Put a pointer to the context in the window private structure
 | 
						|
     */
 | 
						|
    pWinPriv->validContext = 1;
 | 
						|
    pWinPriv->context = pCon;
 | 
						|
    
 | 
						|
    /*
 | 
						|
     * Clear out the old page file, if necessary
 | 
						|
     */
 | 
						|
    if(pConPriv->pPageFile != (FILE *)NULL)
 | 
						|
    {
 | 
						|
	fclose(pConPriv->pPageFile);
 | 
						|
	pConPriv->pPageFile = (FILE *)NULL;
 | 
						|
    }
 | 
						|
    if(pConPriv->pageFileName != (char *)NULL)
 | 
						|
    {
 | 
						|
	unlink(pConPriv->pageFileName);
 | 
						|
	pConPriv->pageFileName = (char *)NULL;
 | 
						|
    }
 | 
						|
 | 
						|
    /*
 | 
						|
     * Make up a new page file.
 | 
						|
     */
 | 
						|
    if (!XpOpenTmpFile("w+", &pConPriv->pageFileName, &pConPriv->pPageFile))
 | 
						|
	return BadAlloc;
 | 
						|
 | 
						|
    /*
 | 
						|
     * Reset the GC cached in the context private struct.
 | 
						|
     */
 | 
						|
    pConPriv->validGC = 0;
 | 
						|
 | 
						|
    /*
 | 
						|
     * Set the page orientation
 | 
						|
     */
 | 
						|
    orient = XpGetContentOrientation( pCon );
 | 
						|
    switch( orient )
 | 
						|
      {
 | 
						|
	case xpoid_val_content_orientation_landscape:
 | 
						|
	  dir = 1;
 | 
						|
	  break;
 | 
						|
	case xpoid_val_content_orientation_reverse_portrait:
 | 
						|
	  dir = 2;
 | 
						|
	  break;
 | 
						|
	case xpoid_val_content_orientation_reverse_landscape:
 | 
						|
	  dir = 3;
 | 
						|
	  break;
 | 
						|
	case xpoid_val_content_orientation_portrait:
 | 
						|
	default:
 | 
						|
	  dir = 0;
 | 
						|
	  break;
 | 
						|
      }
 | 
						|
    sprintf( t, "\033&l%dO", dir );
 | 
						|
    SEND_PCL( pConPriv->pPageFile, t );
 | 
						|
    
 | 
						|
    /*
 | 
						|
     * Set the duplexing method.  Since PCL wants to think of it in
 | 
						|
     * terms of the "binding edge," and the attribute store thinks in
 | 
						|
     * "duplex/tumble," this is a little complicated.
 | 
						|
     *
 | 
						|
     * Actually, this has no bearing on the output, since the HP1600C
 | 
						|
     * will only print on one side of the paper, and ignore all
 | 
						|
     * requests to enable duplexing.  But, in an attempt to keep this
 | 
						|
     * driver somewhat generic, we'll enable it anyway.
 | 
						|
     */
 | 
						|
    plex = XpGetPlex( pCon );
 | 
						|
    
 | 
						|
    if( plex == xpoid_val_plex_duplex )
 | 
						|
      {
 | 
						|
	  if( dir == 0 || dir == 2 )
 | 
						|
	    plexNum = 1;
 | 
						|
	  else
 | 
						|
	    plexNum = 2;
 | 
						|
       }
 | 
						|
    else if( plex == xpoid_val_plex_tumble )
 | 
						|
      {
 | 
						|
	  if( dir == 0 || dir == 2 )
 | 
						|
	    plexNum = 2;
 | 
						|
	  else
 | 
						|
	    plexNum = 1;
 | 
						|
      }
 | 
						|
    else
 | 
						|
      plexNum = 0;
 | 
						|
    sprintf( t, "\033&l%dS", plexNum );
 | 
						|
    SEND_PCL( pConPriv->pPageFile, t );
 | 
						|
 | 
						|
    /*
 | 
						|
     * Set the input tray or medium.  If XpGetPageSize gives us a valid medium,
 | 
						|
     * we can just send that to the printer, and let the printer handle the
 | 
						|
     * details.  Otherwise, we select the tray returned from XpGetPageSize,
 | 
						|
     * which will be either a tray that should contain the correct medium
 | 
						|
     * (possibly with operator intervention), or the default tray from the
 | 
						|
     * config files.
 | 
						|
     */
 | 
						|
    medium = XpGetPageSize( pCon, &tray, NULL );
 | 
						|
    if( medium != xpoid_none )
 | 
						|
      {
 | 
						|
	  switch( medium )
 | 
						|
	    {
 | 
						|
	      case xpoid_val_medium_size_na_legal:
 | 
						|
		num = 3;
 | 
						|
		break;
 | 
						|
	      case xpoid_val_medium_size_iso_a3:
 | 
						|
		num = 27;
 | 
						|
		break;
 | 
						|
	      case xpoid_val_medium_size_iso_a4:
 | 
						|
		num = 26;
 | 
						|
		break;
 | 
						|
	      case xpoid_val_medium_size_executive:
 | 
						|
		num = 1;
 | 
						|
		break;
 | 
						|
	      case xpoid_val_medium_size_ledger:
 | 
						|
		num = 6;
 | 
						|
		break;
 | 
						|
	      case xpoid_val_medium_size_monarch_envelope:
 | 
						|
		num = 80;
 | 
						|
		break;
 | 
						|
	      case xpoid_val_medium_size_na_number_10_envelope:
 | 
						|
		num = 81;
 | 
						|
		break;
 | 
						|
	      case xpoid_val_medium_size_iso_designated_long:
 | 
						|
		num = 90;
 | 
						|
		break;
 | 
						|
	      case xpoid_val_medium_size_iso_c5:
 | 
						|
		num = 91;
 | 
						|
		break;
 | 
						|
	      case xpoid_val_medium_size_iso_b5:
 | 
						|
		num = 100;
 | 
						|
		break;
 | 
						|
	      case xpoid_val_medium_size_jis_b5:
 | 
						|
		num = 45;
 | 
						|
		break;
 | 
						|
	      case xpoid_val_medium_size_na_letter:
 | 
						|
	      default:
 | 
						|
		num = 2;
 | 
						|
		break;
 | 
						|
	    }
 | 
						|
	  sprintf( t, "\033&l%dA", num );
 | 
						|
	  SEND_PCL( pConPriv->pPageFile, t );
 | 
						|
      }
 | 
						|
    else
 | 
						|
      {
 | 
						|
	  switch( tray )
 | 
						|
	    {
 | 
						|
	      case xpoid_val_input_tray_manual:
 | 
						|
		num = 2;
 | 
						|
		break;
 | 
						|
	      case xpoid_val_input_tray_envelope:
 | 
						|
		num = 3;
 | 
						|
		break;
 | 
						|
	      case xpoid_val_input_tray_large_capacity:
 | 
						|
		num = 5;
 | 
						|
		break;
 | 
						|
	      case xpoid_val_input_tray_bottom:
 | 
						|
		num = 4;
 | 
						|
		break;
 | 
						|
	      case xpoid_val_input_tray_main:
 | 
						|
	      default:
 | 
						|
		num = 1;
 | 
						|
		break;
 | 
						|
	    }
 | 
						|
	  sprintf( t, "\033&l%dH", num );
 | 
						|
	  SEND_PCL( pConPriv->pPageFile, t );
 | 
						|
      }
 | 
						|
    
 | 
						|
    /*
 | 
						|
     * Set the scaling factors so that the HP-GL/2 coordinate system
 | 
						|
     * matches the X coordinate system, both in axis orientation and
 | 
						|
     * in unit<->pixel conversion.
 | 
						|
     */
 | 
						|
    XpGetReproductionArea( pCon, &repro );
 | 
						|
 | 
						|
    sprintf( t, "\033&l0E\033*p%dx%dY", repro.x - 75, repro.y );
 | 
						|
    SEND_PCL( pConPriv->pPageFile, t );
 | 
						|
 | 
						|
    sprintf( t, "\033*c%dx%dY\033*c0T", (int)(repro.width / 300.0 * 720.0),
 | 
						|
	    (int)(repro.height / 300.0 * 720.0) );
 | 
						|
    SEND_PCL( pConPriv->pPageFile, t );
 | 
						|
    
 | 
						|
    sprintf( t, "\033%%0BSC%d,%d,%d,%d;\033%%0A", repro.x, repro.x +
 | 
						|
	    repro.width, repro.y + repro.height, repro.y );
 | 
						|
    SEND_PCL( pConPriv->pPageFile, t );
 | 
						|
 | 
						|
    return Success;
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * When sending the generated PCL code back to the client, we send everything
 | 
						|
 * that we have generated so far for the job.  After sending the data, we clean
 | 
						|
 * out the job file, to avoid repeatedly sending the same data.
 | 
						|
 */
 | 
						|
 | 
						|
static int
 | 
						|
SendDocData( PclContextPrivPtr pPriv )
 | 
						|
{
 | 
						|
    struct stat statBuf;
 | 
						|
    int ret;
 | 
						|
    
 | 
						|
    rewind( pPriv->pJobFile );
 | 
						|
    if( stat( pPriv->jobFileName, &statBuf ) < 0 )
 | 
						|
      return BadAlloc;
 | 
						|
    
 | 
						|
    ret = XpSendDocumentData( pPriv->getDocClient, pPriv->pJobFile,
 | 
						|
			     (int)statBuf.st_size, pPriv->getDocBufSize );
 | 
						|
 | 
						|
    /*
 | 
						|
     * Clean out the job file
 | 
						|
     */
 | 
						|
    fclose( pPriv->pJobFile );
 | 
						|
    unlink( pPriv->jobFileName );
 | 
						|
 | 
						|
    xfree(pPriv->jobFileName);
 | 
						|
 | 
						|
    if (!XpOpenTmpFile("w+", &pPriv->jobFileName, &pPriv->pJobFile))
 | 
						|
	return BadAlloc;
 | 
						|
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * EndPage:
 | 
						|
 *
 | 
						|
 * Write page trailer to page file
 | 
						|
 * Write page file to job file
 | 
						|
 */
 | 
						|
int
 | 
						|
PclEndPage(
 | 
						|
     XpContextPtr pCon,
 | 
						|
     WindowPtr pWin)
 | 
						|
{
 | 
						|
    PclContextPrivPtr pConPriv = (PclContextPrivPtr)
 | 
						|
      pCon->devPrivates[PclContextPrivateIndex].ptr;
 | 
						|
 | 
						|
    struct stat statBuf;
 | 
						|
 | 
						|
    /*
 | 
						|
     * Send the page trailer to the page file.
 | 
						|
     */
 | 
						|
    SEND_PCL( pConPriv->pPageFile, "\014" );
 | 
						|
    fflush( pConPriv->pPageFile );
 | 
						|
    
 | 
						|
    /*
 | 
						|
     * Write the page file contents to the job file, or to the
 | 
						|
     * whatever client has called GetDocumentData.
 | 
						|
     *
 | 
						|
     * pWinPriv->pPageFile must first be set to the start of the page file.
 | 
						|
     */
 | 
						|
    rewind(pConPriv->pPageFile);
 | 
						|
    if(stat(pConPriv->pageFileName, &statBuf) < 0)
 | 
						|
      return BadAlloc;
 | 
						|
 | 
						|
    if(TransferBytes(pConPriv->pPageFile, pConPriv->pJobFile, 
 | 
						|
       (int)statBuf.st_size) != (int)statBuf.st_size)
 | 
						|
      return BadAlloc;
 | 
						|
 | 
						|
    if( pConPriv->getDocClient != (ClientPtr)NULL &&
 | 
						|
       pConPriv->getDocBufSize > 0 )
 | 
						|
      {
 | 
						|
	  return SendDocData( pConPriv );
 | 
						|
      }
 | 
						|
    
 | 
						|
    return Success;
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * The PclStartDoc() and PclEndDoc() functions serve basically as NOOP
 | 
						|
 * placeholders.  This driver doesn't deal with the notion of multiple
 | 
						|
 * documents per page.
 | 
						|
 */
 | 
						|
 | 
						|
int
 | 
						|
PclStartDoc(XpContextPtr pCon,
 | 
						|
	    XPDocumentType type)
 | 
						|
{
 | 
						|
    PclContextPrivPtr pConPriv = (PclContextPrivPtr)
 | 
						|
      pCon->devPrivates[PclContextPrivateIndex].ptr;
 | 
						|
    
 | 
						|
#ifndef XP_PCL_LJ3
 | 
						|
    /*
 | 
						|
     * Set the printer resolution for the page.  Since we can only
 | 
						|
     * render color at 300dpi, we just hard-code this.
 | 
						|
     */
 | 
						|
    SEND_PCL( pConPriv->pJobFile, 
 | 
						|
	     "\033%-12345X@PJL SET RESOLUTION = 300\r\n" );
 | 
						|
#endif /* XP_PCL_LJ3 */
 | 
						|
    
 | 
						|
    /*
 | 
						|
     * Initialize HP-GL/2
 | 
						|
     */
 | 
						|
    SEND_PCL( pConPriv->pJobFile, "\033E\033%0BIN,SP1,TR0;\033%0A" );
 | 
						|
 | 
						|
    /*
 | 
						|
     * Stash the type of the document (used by PutDocumentData operation)
 | 
						|
     */
 | 
						|
    pConPriv->isRaw = (type == XPDocRaw);
 | 
						|
    
 | 
						|
    return Success;
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
PclEndDoc(
 | 
						|
     XpContextPtr pCon,
 | 
						|
     Bool cancel)
 | 
						|
{
 | 
						|
    /*
 | 
						|
     * XXX What should I do if I get cancel == TRUE?
 | 
						|
     */
 | 
						|
    return Success;
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * PclDocumentData()
 | 
						|
 *
 | 
						|
 * Hand any pre-generated PDL down to the spool files, formatting it
 | 
						|
 * as necessary to fit the given window.
 | 
						|
 *
 | 
						|
 */
 | 
						|
 | 
						|
#define DOC_PCL 1
 | 
						|
#define DOC_HPGL 2
 | 
						|
 | 
						|
int
 | 
						|
PclDocumentData(
 | 
						|
     XpContextPtr pCon,
 | 
						|
     DrawablePtr pDraw,
 | 
						|
     char *pData,
 | 
						|
     int len_data,
 | 
						|
     char *pFmt,
 | 
						|
     int len_fmt,
 | 
						|
     char *pOpt,
 | 
						|
     int len_opt,
 | 
						|
     ClientPtr client)
 | 
						|
{
 | 
						|
    int type = 0;
 | 
						|
    PclContextPrivPtr pPriv = (PclContextPrivPtr)
 | 
						|
      pCon->devPrivates[PclContextPrivateIndex].ptr;
 | 
						|
    XpOidDocFmtList *formats;
 | 
						|
    XpOidDocFmt *f;
 | 
						|
    char t[80];
 | 
						|
    xRectangle repro;
 | 
						|
    
 | 
						|
    /*
 | 
						|
     * Verify the input format
 | 
						|
     */
 | 
						|
    formats = XpGetDocFmtListAttr( pCon, XPPrinterAttr,
 | 
						|
				  (pPriv->isRaw) ?
 | 
						|
				  xpoid_att_xp_raw_formats_supported :
 | 
						|
				  xpoid_att_xp_embedded_formats_supported, 
 | 
						|
				  NULL );
 | 
						|
    f = XpOidDocFmtNew( pFmt );
 | 
						|
    if( !XpOidDocFmtListHasFmt( formats, f ) )
 | 
						|
      {
 | 
						|
	  XpOidDocFmtListDelete( formats );
 | 
						|
	  XpOidDocFmtDelete( f );
 | 
						|
	  return BadMatch;
 | 
						|
      }
 | 
						|
    XpOidDocFmtListDelete( formats );
 | 
						|
    
 | 
						|
    if( !(pPriv->isRaw) )
 | 
						|
      {
 | 
						|
	  if( !strcmp( f->format, "PCL" ) )
 | 
						|
	    type = DOC_PCL;
 | 
						|
	  else if( !strcmp( f->format, "HPGL" ) )
 | 
						|
	    type = DOC_HPGL;
 | 
						|
	  else
 | 
						|
	    {
 | 
						|
		XpOidDocFmtDelete( f );
 | 
						|
		return BadMatch;
 | 
						|
	    }
 | 
						|
	  
 | 
						|
	  switch( type )
 | 
						|
	    {
 | 
						|
	      case DOC_HPGL:
 | 
						|
		/*
 | 
						|
		 * Move the picture frame to the appropriate place on the page,
 | 
						|
		 * then assume that the embedded code will scale it properly.
 | 
						|
		 */
 | 
						|
		sprintf( t, "\033&l0E\033*p%dx%dY", 
 | 
						|
			pDraw->x - 75,
 | 
						|
			pDraw->y );
 | 
						|
		SEND_PCL( pPriv->pPageFile, t );
 | 
						|
		
 | 
						|
		sprintf( t, "\033*c%dx%dY\033*coT",
 | 
						|
			(int)( pDraw->width / 300.0 * 720.0 ),
 | 
						|
			(int)( pDraw->height / 300.0 * 720.0 ) );
 | 
						|
		SEND_PCL( pPriv->pPageFile, t );
 | 
						|
		break;
 | 
						|
	    }
 | 
						|
      }
 | 
						|
    
 | 
						|
    
 | 
						|
    /*
 | 
						|
     * Send the data down the pipe
 | 
						|
     */
 | 
						|
    SEND_PCL_COUNT( pPriv->pPageFile, pData, len_data );
 | 
						|
    
 | 
						|
    /*
 | 
						|
     * If it's not a raw document, clean up the embedding
 | 
						|
     */
 | 
						|
    if( !(pPriv->isRaw) )
 | 
						|
      switch( type )
 | 
						|
	{
 | 
						|
	  case DOC_HPGL:
 | 
						|
	    /*
 | 
						|
	     * Reset the picture frame
 | 
						|
	     */
 | 
						|
	    XpGetReproductionArea( pCon, &repro );
 | 
						|
	    
 | 
						|
	    sprintf( t, "\033&l0E\033*p%dx%dY", repro.x - 75, repro.y );
 | 
						|
	    SEND_PCL( pPriv->pPageFile, t );
 | 
						|
	    
 | 
						|
	    sprintf( t, "\033*c%dx%dY\033*c0T",
 | 
						|
		    (int)(repro.width / 300.0 * 720.0),
 | 
						|
		    (int)(repro.height / 300.0 * 720.0) );
 | 
						|
	    SEND_PCL( pPriv->pPageFile, t );
 | 
						|
	    
 | 
						|
	    sprintf( t, "\033%%0BSC%d,%d,%d,%d;\033%%0A", repro.x, repro.x +
 | 
						|
		    repro.width, repro.y + repro.height, repro.y );
 | 
						|
	    SEND_PCL( pPriv->pPageFile, t );
 | 
						|
	    break;
 | 
						|
	}
 | 
						|
    
 | 
						|
    XpOidDocFmtDelete( f );
 | 
						|
    return Success;
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * 
 | 
						|
 * PclGetDocumentData()
 | 
						|
 *
 | 
						|
 * This function allows the driver to send the generated PCL back to
 | 
						|
 * the client.
 | 
						|
 *
 | 
						|
 * XXX This function is barely spec'ed, much less implemented!
 | 
						|
 */
 | 
						|
 | 
						|
int
 | 
						|
PclGetDocumentData(
 | 
						|
     XpContextPtr pCon,
 | 
						|
     ClientPtr client,
 | 
						|
     int maxBufferSize)
 | 
						|
{
 | 
						|
    PclContextPrivPtr pPriv = (PclContextPrivPtr)
 | 
						|
      pCon->devPrivates[PclContextPrivateIndex].ptr;
 | 
						|
    
 | 
						|
    pPriv->getDocClient = client;
 | 
						|
    pPriv->getDocBufSize = maxBufferSize;
 | 
						|
    
 | 
						|
    return Success;
 | 
						|
}
 |