Logo Search packages:      
Sourcecode: wine-unstable version File versions  Download package

escape.c

/*
 *    PostScript driver Escape function
 *
 *    Copyright 1998  Huw D M Davies
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 */
#include <stdarg.h>

#include "windef.h"
#include "winbase.h"
#include "wingdi.h"
#include "wine/wingdi16.h"
#include "wownt32.h"
#include "psdrv.h"
#include "wine/debug.h"
#include "winspool.h"

WINE_DEFAULT_DEBUG_CHANNEL(psdrv);

static const char psbegindocument[] =
"%%BeginDocument: Wine passthrough\n";

/**********************************************************************
 *           ExtEscape  (WINEPS.@)
 */
INT CDECL PSDRV_ExtEscape( PSDRV_PDEVICE *physDev, INT nEscape, INT cbInput, LPCVOID in_data,
                           INT cbOutput, LPVOID out_data )
{
    switch(nEscape)
    {
    case QUERYESCSUPPORT:
        if(cbInput < sizeof(INT))
        {
          WARN("cbInput < sizeof(INT) (=%d) for QUERYESCSUPPORT\n", cbInput);
          return 0;
      } else {
          UINT num = *(const UINT *)in_data;
          TRACE("QUERYESCSUPPORT for %d\n", num);

          switch(num) {
          case NEXTBAND:
          /*case BANDINFO:*/
          case SETCOPYCOUNT:
          case GETTECHNOLOGY:
          case SETLINECAP:
          case SETLINEJOIN:
          case SETMITERLIMIT:
          case SETCHARSET:
          case EXT_DEVICE_CAPS:
          case SET_BOUNDS:
            case EPSPRINTING:
          case POSTSCRIPT_DATA:
            case PASSTHROUGH:
            case POSTSCRIPT_PASSTHROUGH:
          case POSTSCRIPT_IGNORE:
          case BEGIN_PATH:
          case CLIP_TO_PATH:
          case END_PATH:
          /*case DRAWPATTERNRECT:*/
              return TRUE;

          default:
            FIXME("QUERYESCSUPPORT(%d) - not supported.\n", num);
              return FALSE;
          }
      }

    case MFCOMMENT:
    {
      FIXME("MFCOMMENT(%p, %d)\n", in_data, cbInput);
      return 1;
    }
    case DRAWPATTERNRECT:
    {
      DRAWPATRECT *dpr = (DRAWPATRECT*)in_data;

      FIXME("DRAWPATTERNRECT(pos (%d,%d), size %dx%d, style %d, pattern %x), stub!\n",
            dpr->ptPosition.x, dpr->ptPosition.y,
            dpr->ptSize.x, dpr->ptSize.y,
            dpr->wStyle, dpr->wPattern
      );
      return 1;
    }
    case BANDINFO:
    {
      BANDINFOSTRUCT    *ibi = (BANDINFOSTRUCT*)in_data;
      BANDINFOSTRUCT    *obi = (BANDINFOSTRUCT*)out_data;

      FIXME("BANDINFO(graphics %d, text %d, rect [%dx%d-%dx%d]), stub!\n",
            ibi->GraphicsFlag,
            ibi->TextFlag,
            ibi->GraphicsRect.top,
            ibi->GraphicsRect.bottom,
            ibi->GraphicsRect.left,
            ibi->GraphicsRect.right
      );
      *obi = *ibi;
      return 1;
    }
    case NEXTBAND:
    {
        RECT *r = out_data;
      if(!physDev->job.banding) {
          physDev->job.banding = TRUE;
            r->left   = 0;
            r->top    = 0;
            r->right  = physDev->horzRes;
            r->bottom = physDev->vertRes;
            TRACE("NEXTBAND returning %d,%d - %d,%d\n", r->left, r->top, r->right, r->bottom );
          return 1;
      }
        r->left   = 0;
        r->top    = 0;
        r->right  = 0;
        r->bottom = 0;
      TRACE("NEXTBAND rect to 0,0 - 0,0\n" );
      physDev->job.banding = FALSE;
        return EndPage( physDev->hdc );
    }

    case SETCOPYCOUNT:
        {
            const INT *NumCopies = in_data;
            INT *ActualCopies = out_data;
            if(cbInput != sizeof(INT)) {
                WARN("cbInput != sizeof(INT) (=%d) for SETCOPYCOUNT\n", cbInput);
            return 0;
          }
          TRACE("SETCOPYCOUNT %d\n", *NumCopies);
          *ActualCopies = 1;
          return 1;
      }

    case GETTECHNOLOGY:
        {
          LPSTR p = out_data;
          strcpy(p, "PostScript");
          *(p + strlen(p) + 1) = '\0'; /* 2 '\0's at end of string */
          return 1;
      }

    case SETLINECAP:
        {
            INT newCap = *(const INT *)in_data;
            if(cbInput != sizeof(INT)) {
                WARN("cbInput != sizeof(INT) (=%d) for SETLINECAP\n", cbInput);
            return 0;
            }
          TRACE("SETLINECAP %d\n", newCap);
          return 0;
      }

    case SETLINEJOIN:
        {
            INT newJoin = *(const INT *)in_data;
            if(cbInput != sizeof(INT)) {
                WARN("cbInput != sizeof(INT) (=%d) for SETLINEJOIN\n", cbInput);
            return 0;
            }
          TRACE("SETLINEJOIN %d\n", newJoin);
          return 0;
      }

    case SETMITERLIMIT:
        {
            INT newLimit = *(const INT *)in_data;
            if(cbInput != sizeof(INT)) {
                WARN("cbInput != sizeof(INT) (=%d) for SETMITERLIMIT\n", cbInput);
            return 0;
            }
          TRACE("SETMITERLIMIT %d\n", newLimit);
          return 0;
      }

    case SETCHARSET:
      /* Undocumented escape used by winword6.
       Switches between ANSI and a special charset.
       If *lpInData == 1 we require that
       0x91 is quoteleft
       0x92 is quoteright
       0x93 is quotedblleft
       0x94 is quotedblright
       0x95 is bullet
       0x96 is endash
       0x97 is emdash
       0xa0 is non break space - yeah right.

       If *lpInData == 0 we get ANSI.
       Since there's nothing else there, let's just make these the default
       anyway and see what happens...
      */
        return 1;

    case EXT_DEVICE_CAPS:
        {
            UINT cap = *(const UINT *)in_data;
            if(cbInput != sizeof(UINT)) {
                WARN("cbInput != sizeof(UINT) (=%d) for EXT_DEVICE_CAPS\n", cbInput);
            return 0;
            }
          TRACE("EXT_DEVICE_CAPS %d\n", cap);
          return 0;
      }

    case SET_BOUNDS:
        {
            const RECT *r = in_data;
            if(cbInput != sizeof(RECT)) {
                WARN("cbInput != sizeof(RECT) (=%d) for SET_BOUNDS\n", cbInput);
            return 0;
            }
          TRACE("SET_BOUNDS (%d,%d) - (%d,%d)\n", r->left, r->top,
              r->right, r->bottom);
          return 0;
      }

    case EPSPRINTING:
      {
            UINT epsprint = *(const UINT*)in_data;
          /* FIXME: In this mode we do not need to send page intros and page
           * ends according to the doc. But I just ignore that detail
           * for now.
           */
          TRACE("EPS Printing support %sable.\n",epsprint?"en":"dis");
          return 1;
        }

    case POSTSCRIPT_DATA:
    case PASSTHROUGH:
    case POSTSCRIPT_PASSTHROUGH:
        {
            /* Write directly to spool file, bypassing normal PS driver
             * processing that is done along with writing PostScript code
             * to the spool.
           * We have a WORD before the data counting the size, but
           * cbInput is just this +2.
             * However Photoshop 7 has a bug that sets cbInput to 2 less than the
             * length of the string, rather than 2 more.  So we'll use the WORD at
             * in_data[0] instead.
             */
            if(!physDev->job.in_passthrough) {
                WriteSpool16(physDev->job.hJob, (LPSTR)psbegindocument, sizeof(psbegindocument)-1);
                physDev->job.in_passthrough = TRUE;
            }
            return WriteSpool16(physDev->job.hJob,((char*)in_data)+2,*(const WORD*)in_data);
        }

    case POSTSCRIPT_IGNORE:
      {
      BOOL ret = physDev->job.quiet;
        TRACE("POSTSCRIPT_IGNORE %d\n", *(const short*)in_data);
      physDev->job.quiet = *(const short*)in_data;
      return ret;
      }

    case GETSETPRINTORIENT:
      {
          /* If lpInData is present, it is a 20 byte structure, first 32
           * bit LONG value is the orientation. if lpInData is NULL, it
           * returns the current orientation.
           */
          FIXME("GETSETPRINTORIENT not implemented (data %p)!\n",in_data);
          return 1;
      }
    case BEGIN_PATH:
        TRACE("BEGIN_PATH\n");
      if(physDev->pathdepth)
          FIXME("Nested paths not yet handled\n");
      return ++physDev->pathdepth;

    case END_PATH:
      {
      const struct PATH_INFO *info = (const struct PATH_INFO*)in_data;

      TRACE("END_PATH\n");
        if(!physDev->pathdepth) {
          ERR("END_PATH called without a BEIGN_PATH\n");
          return -1;
      }
      TRACE("RenderMode = %d, FillMode = %d, BkMode = %d\n",
            info->RenderMode, info->FillMode, info->BkMode);
      switch(info->RenderMode) {
      case RENDERMODE_NO_DISPLAY:
          PSDRV_WriteClosePath(physDev); /* not sure if this is necessary, but it can't hurt */
          break;
      case RENDERMODE_OPEN:
      case RENDERMODE_CLOSED:
      default:
          FIXME("END_PATH: RenderMode %d, not yet supported\n", info->RenderMode);
          break;
      }
      return --physDev->pathdepth;
      }

    case CLIP_TO_PATH:
      {
      WORD mode = *(const WORD*)in_data;

      switch(mode) {
      case CLIP_SAVE:
          TRACE("CLIP_TO_PATH: CLIP_SAVE\n");
          PSDRV_WriteGSave(physDev);
          return 1;
      case CLIP_RESTORE:
          TRACE("CLIP_TO_PATH: CLIP_RESTORE\n");
          PSDRV_WriteGRestore(physDev);
          return 1;
      case CLIP_INCLUSIVE:
          TRACE("CLIP_TO_PATH: CLIP_INCLUSIVE\n");
          /* FIXME to clip or eoclip ? (see PATH_INFO.FillMode) */
          PSDRV_WriteClip(physDev);
            PSDRV_WriteNewPath(physDev);
          return 1;
      case CLIP_EXCLUSIVE:
          FIXME("CLIP_EXCLUSIVE: not implemented\n");
          return 0;
      default:
          FIXME("Unknown CLIP_TO_PATH mode %d\n", mode);
          return 0;
      }
      }
    default:
        FIXME("Unimplemented code 0x%x\n", nEscape);
      return 0;
    }
}

/************************************************************************
 *           PSDRV_StartPage
 */
INT CDECL PSDRV_StartPage( PSDRV_PDEVICE *physDev )
{
    if(!physDev->job.OutOfPage) {
        FIXME("Already started a page?\n");
      return 1;
    }

    if(physDev->job.PageNo++ == 0) {
        if(!PSDRV_WriteHeader( physDev, physDev->job.DocName ))
            return 0;
    }

    if(!PSDRV_WriteNewPage( physDev ))
        return 0;
    physDev->job.OutOfPage = FALSE;
    return 1;
}


/************************************************************************
 *           PSDRV_EndPage
 */
INT CDECL PSDRV_EndPage( PSDRV_PDEVICE *physDev )
{
    if(physDev->job.OutOfPage) {
        FIXME("Already ended a page?\n");
      return 1;
    }
    if(!PSDRV_WriteEndPage( physDev ))
        return 0;
    PSDRV_EmptyDownloadList(physDev, FALSE);
    physDev->job.OutOfPage = TRUE;
    return 1;
}


/************************************************************************
 *           PSDRV_StartDocA
 */
static INT PSDRV_StartDocA( PSDRV_PDEVICE *physDev, const DOCINFOA *doc )
{
    LPCSTR output = "LPT1:";
    BYTE buf[300];
    HANDLE hprn = INVALID_HANDLE_VALUE;
    PRINTER_INFO_5A *pi5 = (PRINTER_INFO_5A*)buf;
    DWORD needed;

    if(physDev->job.hJob) {
        FIXME("hJob != 0. Now what?\n");
      return 0;
    }

    if(doc->lpszOutput)
        output = doc->lpszOutput;
    else if(physDev->job.output)
        output = physDev->job.output;
    else {
        if(OpenPrinterA(physDev->pi->FriendlyName, &hprn, NULL) &&
           GetPrinterA(hprn, 5, buf, sizeof(buf), &needed)) {
            output = pi5->pPortName;
        }
        if(hprn != INVALID_HANDLE_VALUE)
            ClosePrinter(hprn);
    }

    physDev->job.hJob = OpenJob16(output,  doc->lpszDocName, HDC_16(physDev->hdc) );
    if(!physDev->job.hJob) {
        WARN("OpenJob failed\n");
      return 0;
    }
    physDev->job.banding = FALSE;
    physDev->job.OutOfPage = TRUE;
    physDev->job.PageNo = 0;
    physDev->job.quiet = FALSE;
    physDev->job.in_passthrough = FALSE;
    physDev->job.had_passthrough_rect = FALSE;
    if(doc->lpszDocName) {
        physDev->job.DocName = HeapAlloc(GetProcessHeap(), 0, strlen(doc->lpszDocName)+1);
        strcpy(physDev->job.DocName, doc->lpszDocName);
    } else
        physDev->job.DocName = NULL;

    return physDev->job.hJob;
}

/************************************************************************
 *           PSDRV_StartDoc
 */
INT CDECL PSDRV_StartDoc( PSDRV_PDEVICE *physDev, const DOCINFOW *doc )
{
    DOCINFOA docA;
    INT ret, len;
    LPSTR docname = NULL, output = NULL, datatype = NULL;

    docA.cbSize = doc->cbSize;
    if (doc->lpszDocName)
    {
        len = WideCharToMultiByte( CP_ACP, 0, doc->lpszDocName, -1, NULL, 0, NULL, NULL );
        if ((docname = HeapAlloc( GetProcessHeap(), 0, len )))
            WideCharToMultiByte( CP_ACP, 0, doc->lpszDocName, -1, docname, len, NULL, NULL );
    }
    if (doc->lpszOutput)
    {
        len = WideCharToMultiByte( CP_ACP, 0, doc->lpszOutput, -1, NULL, 0, NULL, NULL );
        if ((output = HeapAlloc( GetProcessHeap(), 0, len )))
            WideCharToMultiByte( CP_ACP, 0, doc->lpszOutput, -1, output, len, NULL, NULL );
    }
    if (doc->lpszDatatype)
    {
        len = WideCharToMultiByte( CP_ACP, 0, doc->lpszDatatype, -1, NULL, 0, NULL, NULL );
        if ((datatype = HeapAlloc( GetProcessHeap(), 0, len )))
            WideCharToMultiByte( CP_ACP, 0, doc->lpszDatatype, -1, datatype, len, NULL, NULL );
    }
    docA.lpszDocName = docname;
    docA.lpszOutput = output;
    docA.lpszDatatype = datatype;
    docA.fwType = doc->fwType;

    ret = PSDRV_StartDocA(physDev, &docA);

    HeapFree( GetProcessHeap(), 0, docname );
    HeapFree( GetProcessHeap(), 0, output );
    HeapFree( GetProcessHeap(), 0, datatype );

    return ret;
}

/************************************************************************
 *           PSDRV_EndDoc
 */
INT CDECL PSDRV_EndDoc( PSDRV_PDEVICE *physDev )
{
    INT ret = 1;
    if(!physDev->job.hJob) {
        FIXME("hJob == 0. Now what?\n");
      return 0;
    }

    if(!physDev->job.OutOfPage) {
        WARN("Somebody forgot an EndPage\n");
      PSDRV_EndPage( physDev );
    }
    PSDRV_WriteFooter( physDev );

    if( CloseJob16( physDev->job.hJob ) == SP_ERROR ) {
        WARN("CloseJob error\n");
      ret = 0;
    }
    physDev->job.hJob = 0;
    HeapFree(GetProcessHeap(), 0, physDev->job.DocName);
    physDev->job.DocName = NULL;

    return ret;
}

Generated by  Doxygen 1.6.0   Back to index