printing on linux bug 323928. r=vlad

This commit is contained in:
pavlov%pavlov.net 2006-11-29 23:40:16 +00:00
Родитель 30aa38725d
Коммит f0eb225e80
14 изменённых файлов: 968 добавлений и 3 удалений

Просмотреть файл

@ -557,6 +557,10 @@ nsThebesDeviceContext::GetDeviceContextFor(nsIDeviceContextSpec *aDevice,
NS_ADDREF(aDevice);
#ifdef MOZ_ENABLE_GTK2
newDevCon->mDeviceContextSpec = aDevice;
#endif
newDevCon->mPrinter = PR_TRUE;
aDevice->GetSurfaceForPrinter(getter_AddRefs(newDevCon->mPrintingSurface));
@ -605,6 +609,11 @@ nsThebesDeviceContext::EndDocument(void)
{
nsRefPtr<gfxContext> thebes = new gfxContext(mPrintingSurface);
thebes->EndPrinting();
cairo_surface_finish(mPrintingSurface->CairoSurface());
if (mDeviceContextSpec)
mDeviceContextSpec->EndDocument();
return NS_OK;
}

Просмотреть файл

@ -146,6 +146,7 @@ private:
nsRefPtrHashtable<nsISupportsHashKey, gfxASurface> mWidgetSurfaceCache;
nsRefPtr<gfxASurface> mPrintingSurface;
nsIDeviceContextSpec * mDeviceContextSpec;
};
#endif /* _NS_CAIRODEVICECONTEXT_H_ */

Просмотреть файл

@ -38,10 +38,14 @@
#ifndef GFX_PSSURFACE_H
#define GFX_PSSURFACE_H
#include <stdio.h>
#include "gfxASurface.h"
class THEBES_API gfxPSSurface : public gfxASurface {
public:
#ifdef UNTESTED_CODE
gfxPSSurface(FILE *file, gfxSize aSizeInPonits); /* does not close the file */
#endif
gfxPSSurface(const char *filename, gfxSize aSizeInPonits);
virtual ~gfxPSSurface();

Просмотреть файл

@ -39,12 +39,30 @@
#include <cairo-ps.h>
#ifdef UNTESTED_CODE
static cairo_status_t
write_func(void *closure,
const unsigned char *data,
unsigned int length)
{
fwrite(data, 1, length, (FILE*)closure);
}
#endif
gfxPSSurface::gfxPSSurface(const char *filename, gfxSize aSizeInPoints)
: mXDPI(-1), mYDPI(-1), mSize(aSizeInPoints)
{
Init(cairo_ps_surface_create(filename, mSize.width, mSize.height));
}
#ifdef UNTESTED_CODE
gfxPSSurface::gfxPSSurface(FILE *file, gfxSize aSizeInPoints)
: mXDPI(-1), mYDPI(-1), mSize(aSizeInPoints)
{
Init(cairo_ps_surface_create_for_stream(write_func, file, mSize.width, mSize.height));
}
#endif
gfxPSSurface::~gfxPSSurface()
{
Destroy();

Просмотреть файл

@ -55,6 +55,13 @@ public:
#ifdef MOZ_CAIRO_GFX
NS_IMETHOD GetSurfaceForPrinter(gfxASurface **nativeSurface) = 0;
NS_IMETHOD BeginDocument(PRUnichar* aTitle,
PRUnichar* aPrintToFileName,
PRInt32 aStartPage,
PRInt32 aEndPage) = 0;
NS_IMETHOD EndDocument() = 0;
#endif
};

Просмотреть файл

@ -111,6 +111,8 @@ CPPSRCS = \
nsPrintOptionsGTK.cpp \
nsImageToPixbuf.cpp \
nsAccessibilityHelper.cpp \
nsPrintJobFactoryGTK.cpp \
nsPrintJobGTK.cpp \
$(NULL)
# build our subdirs, too

Просмотреть файл

@ -69,6 +69,8 @@
#include "nsPaperPS.h" /* Paper size list */
#endif /* USE_POSTSCRIPT */
#include "nsPrintJobFactoryGTK.h"
/* Ensure that the result is always equal to either PR_TRUE or PR_FALSE */
#define MAKE_PR_BOOL(val) ((val)?(PR_TRUE):(PR_FALSE))
@ -379,11 +381,13 @@ nsStringArray* GlobalPrinters::mGlobalPrinterList = nsnull;
nsDeviceContextSpecGTK::nsDeviceContextSpecGTK()
{
DO_PR_DEBUG_LOG(("nsDeviceContextSpecGTK::nsDeviceContextSpecGTK()\n"));
mPrintJob = nsnull;
}
nsDeviceContextSpecGTK::~nsDeviceContextSpecGTK()
{
DO_PR_DEBUG_LOG(("nsDeviceContextSpecGTK::~nsDeviceContextSpecGTK()\n"));
delete mPrintJob;
}
/* Use both PostScript and Xprint module */
@ -417,7 +421,7 @@ NS_IMPL_ISUPPORTS1(nsDeviceContextSpecGTK,
#include "nsUnitConversion.h"
NS_IMETHODIMP nsDeviceContextSpecGTK::GetSurfaceForPrinter(gfxASurface **aSurface)
{
const char *path = nsnull;
const char *path;
GetPath(&path);
PRInt32 width, height;
@ -427,14 +431,15 @@ NS_IMETHODIMP nsDeviceContextSpecGTK::GetSurfaceForPrinter(gfxASurface **aSurfac
w = width/20;
h = height/20;
printf("%s, %d, %d\n", path, width, height);
printf("\"%s\", %d, %d\n", path, width, height);
nsPrintJobFactoryGTK::CreatePrintJob((this), mPrintJob);
#ifdef USE_PDF
gfxPDFSurface *surface = new gfxPDFSurface(path, gfxSize(w, h));
#else
gfxPSSurface *surface = new gfxPSSurface(path, gfxSize(w, h));
#endif
surface->SetDPI(600, 600);
// surface->SetDPI(600, 600);
*aSurface = surface;
NS_ADDREF(*aSurface);
@ -713,6 +718,30 @@ NS_IMETHODIMP nsDeviceContextSpecGTK::ClosePrintManager()
return NS_OK;
}
NS_IMETHODIMP nsDeviceContextSpecGTK::BeginDocument(PRUnichar * aTitle, PRUnichar * aPrintToFileName, PRInt32 aStartPage, PRInt32 aEndPage)
{
return NS_OK;
}
#include <errno.h>
NS_IMETHODIMP nsDeviceContextSpecGTK::EndDocument()
{
if (mToPrinter) {
const char *path;
GetPath(&path);
FILE *src = fopen(path, "r");
FILE *dst;
mPrintJob->StartSubmission(&dst);
while(!feof(src)) {
char data[255] = {0};
size_t s = fread(data, 1, sizeof(data), src);
fwrite(data, 1, s, dst);
}
fclose(src);
mPrintJob->FinishSubmission();
}
return NS_OK;
}
/* Get prefs for printer
* Search order:
* - Get prefs per printer name and module name

Просмотреть файл

@ -52,6 +52,8 @@
#endif /* USE_XPRINT */
#include "nsCRT.h" /* should be <limits.h>? */
#include "nsIPrintJobGTK.h"
#define NS_PORTRAIT 0
#define NS_LANDSCAPE 1
@ -81,6 +83,8 @@ public:
NS_IMETHOD Init(nsIPrintSettings* aPS, PRBool aIsPrintPreview);
NS_IMETHOD ClosePrintManager();
NS_IMETHOD BeginDocument(PRUnichar * aTitle, PRUnichar * aPrintToFileName, PRInt32 aStartPage, PRInt32 aEndPage);
NS_IMETHOD EndDocument();
NS_IMETHOD GetToPrinter(PRBool &aToPrinter);
NS_IMETHOD GetIsPrintPreview(PRBool &aIsPPreview);
@ -127,6 +131,7 @@ protected:
float mRight; /* right margin */
float mTop; /* top margin */
float mBottom; /* bottom margin */
nsIPrintJobGTK * mPrintJob;
};
//-------------------------------------------------------------------------

Просмотреть файл

@ -0,0 +1,93 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ex: set tabstop=8 softtabstop=4 shiftwidth=4 expandtab: */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Kenneth Herron <kherron@fastmail.us>.
* Portions created by the Initial Developer are Copyright (C) 2004
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsDebug.h"
#include "nsPrintJobFactoryGTK.h"
#include "nsIDeviceContextSpec.h"
#include "nsDeviceContextSpecG.h"
#include "nsPrintJobGTK.h"
#include "nsPSPrinters.h"
/**
* Construct a print job object for the given device context spec.
*
* @param aSpec An nsDeviceContextSpecGTK object for the print
* job in question.
* @param aPrintJob A pointer to a print job object which will
* handle the print job.
* @return NS_OK if all is well, or a suitable error value.
*/
nsresult
nsPrintJobFactoryGTK::CreatePrintJob(nsDeviceContextSpecGTK *aSpec,
nsIPrintJobGTK* &aPrintJob)
{
NS_PRECONDITION(nsnull != aSpec, "aSpec is NULL");
nsIPrintJobGTK *newPJ;
PRBool setting;
aSpec->GetIsPrintPreview(setting);
if (setting)
newPJ = new nsPrintJobPreviewGTK();
else {
aSpec->GetToPrinter(setting);
if (!setting)
newPJ = new nsPrintJobFileGTK();
else
{
const char *printerName;
aSpec->GetPrinterName(&printerName);
if (nsPSPrinterList::kTypeCUPS == nsPSPrinterList::GetPrinterType(
nsDependentCString(printerName)))
newPJ = new nsPrintJobCUPS();
else
newPJ = new nsPrintJobPipeGTK();
}
}
if (!newPJ)
return NS_ERROR_OUT_OF_MEMORY;
nsresult rv = newPJ->Init(aSpec);
if (NS_FAILED(rv))
delete newPJ;
else
aPrintJob = newPJ;
return rv;
}

Просмотреть файл

@ -0,0 +1,71 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ex: set tabstop=8 softtabstop=4 shiftwidth=4 expandtab: */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Kenneth Herron <kherron@fastmail.us>.
* Portions created by the Initial Developer are Copyright (C) 2004
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef nsPrintJobFactoryGTK_h__
#define nsPrintJobFactoryGTK_h__
#include "nscore.h"
#include "nsIPrintJobGTK.h"
#include "nsDeviceContextSpecG.h"
/* Factory class for the print job subsystem. This class determines
* which print job class should handle a print job, and constructs
* an object of the appropriate class.
*/
class nsPrintJobFactoryGTK
{
public:
/**
* Construct a print job object for the given device context spec.
* On success, the print job object is owned by the caller and should
* be destroyed when no longer needed.
*
* @param aSpec An nsIDeviceContextSpecGTK object for the print
* job in question.
* @param aPrintJob If NS_OK is returned, this will be filled in with
* a pointer to a print job object.
* @return NS_OK or a suitable error value.
*/
static nsresult CreatePrintJob(nsDeviceContextSpecGTK *aSpec,
nsIPrintJobGTK* &aPrintJob);
};
#endif /* nsPrintJobFactoryGTK_h__ */

Просмотреть файл

@ -0,0 +1,554 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ex: set tabstop=8 softtabstop=4 shiftwidth=4 expandtab: */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Ken Herron <kherron@fastmail.us>.
* Portions created by the Initial Developer are Copyright (C) 2004
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nscore.h"
#include "nsIDeviceContext.h" // NS_ERROR_GFX_*
#include "nsIDeviceContextPS.h" // NS_POSTSCRIPT_DRIVER_NAME_LEN
#include "nsIDeviceContextSpec.h"
#include "nsDeviceContextSpecG.h"
#include "nsPrintJobGTK.h"
#include "nsPSPrinters.h"
#include "nsReadableUtils.h"
#include "prenv.h"
#include "prinit.h"
#include "prlock.h"
#include "prprf.h"
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
/* Routines to set environment variables. These are defined toward
* the end of this file.
*/
static PRStatus EnvLock();
static PRStatus EnvSetPrinter(nsCString&);
static void EnvClear();
/* ~nsIPrintJobGTK() is virtual, so must implement a destructor. */
nsIPrintJobGTK::~nsIPrintJobGTK() {}
//#ifdef OLD_GFX_PRINTING
/**** nsPrintJobPreviewGTK - Stub class for print preview ****/
nsresult
nsPrintJobPreviewGTK::Init(nsDeviceContextSpecGTK *aSpec)
{
return NS_OK;
}
/**** nsPrintJobFileGTK - Print-to-file support ****/
/* Print-to-file constructor */
nsPrintJobFileGTK::nsPrintJobFileGTK() : mDestHandle(nsnull) { }
/* Print-to-file destructor */
nsPrintJobFileGTK::~nsPrintJobFileGTK()
{
if (mDestHandle)
fclose(mDestHandle);
}
/**
* Initialize the print-to-file object from the printing spec.
* See nsPrintJobGTK.h for details.
*/
nsresult
nsPrintJobFileGTK::Init(nsDeviceContextSpecGTK *aSpec)
{
NS_PRECONDITION(aSpec, "aSpec must not be NULL");
#ifdef DEBUG
PRBool toPrinter;
aSpec->GetToPrinter(toPrinter);
NS_PRECONDITION(!toPrinter, "This print job is to a printer");
#endif
const char *path;
aSpec->GetPath(&path);
mDestination = path;
return NS_OK;
}
/**
* Create the final output file and copy the temporary files there.
* See nsIPrintJobGTK.h and nsPrintJobGTK.h for details.
*/
nsresult
nsPrintJobFileGTK::StartSubmission(FILE **aHandle)
{
NS_PRECONDITION(aHandle, "aHandle is NULL");
NS_PRECONDITION(!mDestination.IsEmpty(), "No destination");
NS_PRECONDITION(!mDestHandle, "Already have a destination handle");
nsCOMPtr<nsILocalFile> destFile;
nsresult rv = NS_NewNativeLocalFile(GetDestination(),
PR_FALSE, getter_AddRefs(destFile));
if (NS_SUCCEEDED(rv))
rv = destFile->OpenANSIFileDesc("w", &mDestHandle);
NS_ENSURE_SUCCESS(rv, NS_ERROR_GFX_PRINTER_COULD_NOT_OPEN_FILE);
NS_POSTCONDITION(mDestHandle,
"OpenANSIFileDesc succeeded but no file handle");
*aHandle = mDestHandle;
return rv;
}
/**
* Finish a print job. See nsIPrintJobGTK.h and nsPrintJobGTK.h for details.
*/
nsresult
nsPrintJobFileGTK::FinishSubmission()
{
NS_PRECONDITION(mDestHandle, "No destination file handle");
fclose(mDestHandle);
mDestHandle = nsnull;
return NS_OK;
}
//#endif /* OLD_GFX_PRINTING */
#ifdef VMS
/**** Print-to-command on VMS. ****/
/* This implementation writes the print job to a temporary file, then runs
* the print command with the name of that file appended.
*/
/**
* Initialize a VMS print-to-command object from the printing spec.
* See nsIPrintJobGTK.h and nsPrintJobGTK.h.
*/
nsresult
nsPrintJobVMSCmdGTK::Init(nsIDeviceContextSpec *aSpec)
{
NS_PRECONDITION(aSpec, "argument must not be NULL");
#ifdef DEBUG
PRBool toPrinter;
aSpec->GetToPrinter(toPrinter);
NS_PRECONDITION(toPrinter, "This print job is not to a printer");
#endif
/* Print command. This is stored as the destination string. */
const char *command;
aSpec->GetCommand(&command);
SetDestination(command);
/* Printer name */
const char *printerName;
aSpec->GetPrinterName(&printerName);
if (printerName) {
const char *slash = strchr(printerName, '/');
if (slash)
printerName = slash + 1;
if (0 != strcmp(printerName, "default"))
mPrinterName = printerName;
}
return NS_OK;
}
/**
* Create the temporary file for the print job and return a file handle
* to the caller.
* See nsIPrintJobGTK.h and nsPrintJobGTK.h for details.
*/
nsresult
nsPrintJobVMSCmdGTK::StartSubmission(FILE **aHandle)
{
NS_PRECONDITION(aHandle, "aHandle is NULL");
NS_PRECONDITION(!GetDestination().IsEmpty(), "No destination");
NS_PRECONDITION(!GetDestHandle(), "Already have a destination handle");
/* Create the final output file */
FILE *printHandle = nsnull;
nsresult rv = mTempFactory.CreateTempFile(
getter_AddRefs(mTempFile), &printHandle, "w+");
if (NS_SUCCEEDED(rv)) {
SetDestHandle(printHandle);
*aHandle = printHandle;
}
return rv;
}
nsresult
nsPrintJobVMSCmdGTK::FinishSubmission()
{
NS_PRECONDITION(GetDestHandle(), "No destination file handle");
NS_PRECONDITION(!GetDestination().IsEmpty(), "No destination");
/* Close the temporary file handle */
fclose(GetDestHandle());
SetDestHandle(nsnull);
/* construct the print command */
nsCAutoString printFileName;
nsresult rv = mTempFile->GetNativePath(printFileName);
if (NS_SUCCEEDED(rv)) {
nsCAutoString cmd(GetDestination());
cmd += " "; cmd += printFileName; cmd += ".";
/* Set up the environment. */
if (PR_SUCCESS != EnvLock())
return NS_ERROR_OUT_OF_MEMORY;
if (!mPrinterName.IsEmpty())
EnvSetPrinter(mPrinterName);
/* Run the print command */
int presult = system(cmd.get());
/* Clean up */
EnvClear();
mTempFile->Remove(PR_FALSE);
rv = (!WIFEXITED(presult) || (EXIT_SUCCESS != WEXITSTATUS(presult)))
? NS_ERROR_GFX_PRINTER_CMD_FAILURE : NS_OK;
}
return rv;
}
#else /* NOT VMS */
/**** Print-to-Pipe for unix and unix-like systems ****/
/* This launches a command using popen(); the print job is then written
* to the pipe.
*/
/* Destructor. We must override the print-to-file destructor in order
* to pclose() any open file handle.
*/
nsPrintJobPipeGTK::~nsPrintJobPipeGTK()
{
if (GetDestHandle()) {
pclose(GetDestHandle());
SetDestHandle(nsnull);
}
}
/**
* Initialize a print-to-pipe object.
* See nsIPrintJobGTK.h and nsPrintJobGTK.h for details.
*/
nsresult
nsPrintJobPipeGTK::Init(nsDeviceContextSpecGTK *aSpec)
{
NS_PRECONDITION(aSpec, "argument must not be NULL");
#ifdef DEBUG
PRBool toPrinter;
aSpec->GetToPrinter(toPrinter);
NS_PRECONDITION(toPrinter, "Wrong class for this print job");
#endif
/* Print command. This is stored as the destination string. */
const char *command;
aSpec->GetCommand(&command);
SetDestination(command);
/* Printer name */
const char *printerName;
aSpec->GetPrinterName(&printerName);
if (printerName) {
const char *slash = strchr(printerName, '/');
if (slash)
printerName = slash + 1;
if (0 != strcmp(printerName, "default"))
mPrinterName = printerName;
}
return NS_OK;
}
/**
* Launch the print command using popen(), then copy the print job data
* to the pipe. See nsIPrintJobGTK.h and nsPrintJobGTK.h for details.
*/
nsresult
nsPrintJobPipeGTK::StartSubmission(FILE **aHandle)
{
NS_PRECONDITION(aHandle, "aHandle is NULL");
NS_PRECONDITION(!GetDestination().IsEmpty(), "No destination");
NS_PRECONDITION(!GetDestHandle(), "Already have a destination handle");
if (PR_SUCCESS != EnvLock())
return NS_ERROR_OUT_OF_MEMORY; // Couldn't allocate the object?
if (!mPrinterName.IsEmpty())
EnvSetPrinter(mPrinterName);
FILE *destPipe = popen(GetDestination().get(), "w");
EnvClear();
if (!destPipe)
return NS_ERROR_GFX_PRINTER_CMD_FAILURE;
SetDestHandle(destPipe);
*aHandle = destPipe;
return NS_OK;
}
nsresult
nsPrintJobPipeGTK::FinishSubmission()
{
NS_PRECONDITION(GetDestHandle(), "No destination file handle");
NS_PRECONDITION(!GetDestination().IsEmpty(), "No destination");
int presult = pclose(GetDestHandle());
SetDestHandle(nsnull);
if (!WIFEXITED(presult) || (EXIT_SUCCESS != WEXITSTATUS(presult)))
return NS_ERROR_GFX_PRINTER_CMD_FAILURE;
return NS_OK;
}
/**** Print via CUPS ****/
/**
* Initialize a print-to-CUPS object.
* See nsIPrintJobGTK.h and nsPrintJobGTK.h for details.
*/
nsresult
nsPrintJobCUPS::Init(nsDeviceContextSpecGTK *aSpec)
{
NS_PRECONDITION(aSpec, "argument must not be NULL");
#ifdef DEBUG
PRBool toPrinter;
aSpec->GetToPrinter(toPrinter);
NS_PRECONDITION(toPrinter, "Wrong class for this print job");
#endif
NS_ENSURE_TRUE(mCups.Init(), NS_ERROR_NOT_INITIALIZED);
/* Printer name */
const char *printerName = nsnull;
aSpec->GetPrinterName(&printerName);
NS_ENSURE_TRUE(printerName, NS_ERROR_GFX_PRINTER_NAME_NOT_FOUND);
const char *slash = strchr(printerName, '/');
mPrinterName = slash ? slash + 1 : printerName;
mJobTitle.SetIsVoid(PR_TRUE);
return NS_OK;
}
nsresult
nsPrintJobCUPS::SetNumCopies(int aNumCopies)
{
mNumCopies.Truncate();
if (aNumCopies > 1)
mNumCopies.AppendInt(aNumCopies);
return NS_OK;
}
/* According to the cups.development forum, only plain ASCII may be
* reliably used for CUPS print job titles. See
* <http://www.cups.org/newsgroups.php?s523+gcups.development+v530+T0>.
*/
void
nsPrintJobCUPS::SetJobTitle(const PRUnichar *aTitle)
{
if (aTitle) {
LossyCopyUTF16toASCII(aTitle, mJobTitle);
}
}
nsresult
nsPrintJobCUPS::StartSubmission(FILE **aHandle)
{
NS_ENSURE_TRUE(mCups.IsInitialized(), NS_ERROR_NOT_INITIALIZED);
int fd;
char buf[FILENAME_MAX];
fd = (mCups.mCupsTempFd)(buf, sizeof buf);
// The CUPS manual doesn't describe what cupsTempFd() returns to
// indicate failure. -1 is a likely value.
NS_ENSURE_TRUE(fd > 0, NS_ERROR_GFX_PRINTER_COULD_NOT_OPEN_FILE);
SetDestHandle(fdopen(fd, "r+"));
if (!GetDestHandle()) {
close(fd);
return NS_ERROR_GFX_PRINTER_COULD_NOT_OPEN_FILE;
}
SetDestination(buf);
*aHandle = GetDestHandle();
return NS_OK;
}
nsresult
nsPrintJobCUPS::FinishSubmission()
{
NS_ENSURE_TRUE(mCups.IsInitialized(), NS_ERROR_NOT_INITIALIZED);
NS_PRECONDITION(GetDestHandle(), "No destination file handle");
NS_PRECONDITION(!GetDestination().IsEmpty(), "No destination");
fclose(GetDestHandle());
SetDestHandle(nsnull);
nsCStringArray printer(3);
printer.ParseString(mPrinterName.get(),"/");
cups_dest_t *dests, *dest;
int num_dests = (mCups.mCupsGetDests)(&dests);
if (printer.Count() == 1) {
dest = (mCups.mCupsGetDest)(printer.CStringAt(0)->get(), NULL, num_dests, dests);
} else {
dest = (mCups.mCupsGetDest)(printer.CStringAt(0)->get(),
printer.CStringAt(1)->get(), num_dests, dests);
}
// Setting result just to get rid of compilation warning
int result=0;
if (dest != NULL) {
if (!mNumCopies.IsEmpty())
dest->num_options = (mCups.mCupsAddOption)("copies",
mNumCopies.get(),
dest->num_options,
&dest->options);
const char *title = mJobTitle.IsVoid() ?
"Untitled Document" : mJobTitle.get();
result = (mCups.mCupsPrintFile)(printer.CStringAt(0)->get(),
GetDestination().get(), title,
dest->num_options, dest->options);
}
(mCups.mCupsFreeDests)(num_dests, dests);
unlink(GetDestination().get());
// cupsPrintFile() result codes below 0x0300 indicate success.
// Individual success codes are defined in the cups headers, but
// we're not including those.
if (dest == NULL)
return NS_ERROR_GFX_PRINTER_NAME_NOT_FOUND;
else
return (result < 0x0300) ? NS_OK : NS_ERROR_GFX_PRINTER_CMD_FAILURE;
}
#endif /* VMS */
/* Routines to set the MOZ_PRINTER_NAME environment variable and to
* single-thread print jobs while the variable is set.
*/
static PRLock *EnvLockObj;
static PRCallOnceType EnvLockOnce;
/* EnvLock callback function */
static PRStatus
EnvLockInit()
{
EnvLockObj = PR_NewLock();
return EnvLockObj ? PR_SUCCESS : PR_FAILURE;
}
/**
* Get the lock for setting printing-related environment variables and
* running print commands.
* @return PR_SUCCESS on success
* PR_FAILURE if the lock object could not be initialized.
*
*/
static PRStatus
EnvLock()
{
if (PR_FAILURE == PR_CallOnce(&EnvLockOnce, EnvLockInit))
return PR_FAILURE;
PR_Lock(EnvLockObj);
return PR_SUCCESS;
}
static char *EnvPrinterString;
static const char EnvPrinterName[] = { "MOZ_PRINTER_NAME" };
/**
* Set MOZ_PRINTER_NAME to the specified string.
* @param aPrinter The value for MOZ_PRINTER_NAME. May be an empty string.
* @return PR_SUCCESS on success.
* PR_FAILURE if memory could not be allocated.
*/
static PRStatus
EnvSetPrinter(nsCString& aPrinter)
{
/* Construct the new environment string */
char *newVar = PR_smprintf("%s=%s", EnvPrinterName, aPrinter.get());
if (!newVar)
return PR_FAILURE;
/* Add it to the environment and dispose of any old string */
PR_SetEnv(newVar);
if (EnvPrinterString)
PR_smprintf_free(EnvPrinterString);
EnvPrinterString = newVar;
return PR_SUCCESS;
}
/**
* Clear the printer environment variable and release the environment lock.
*/
static void
EnvClear()
{
if (EnvPrinterString) {
/* On some systems, setenv("FOO") will remove FOO
* from the environment.
*/
PR_SetEnv(EnvPrinterName);
if (!PR_GetEnv(EnvPrinterName)) {
/* It must have worked */
PR_smprintf_free(EnvPrinterString);
EnvPrinterString = nsnull;
}
}
PR_Unlock(EnvLockObj);
}

Просмотреть файл

@ -0,0 +1,162 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ex: set tabstop=8 softtabstop=4 shiftwidth=4 expandtab: */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Ken Herron <kherron@fastmail.us>.
* Portions created by the Initial Developer are Copyright (C) 2004
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef nsPrintJobGTK_h__
#define nsPrintJobGTK_h__
#include "nsCUPSShim.h"
#include "nsDebug.h"
#include "nsIDeviceContext.h" // for NS_ERROR_GFX_PRINTING_NOT_IMPLEMENTED
#include "nsILocalFile.h"
#include "nsIPrintJobGTK.h"
#include "nsString.h"
#include "nsTempfilePS.h"
#include "nsDeviceContextSpecG.h"
/* Print job class for print preview operations. */
class nsPrintJobPreviewGTK : public nsIPrintJobGTK {
public:
/* see nsIPrintJobGTK.h. Print preview doesn't actually
* implement printing.
*/
nsresult StartSubmission(FILE **aHandle)
{ return NS_ERROR_GFX_PRINTING_NOT_IMPLEMENTED; }
nsresult FinishSubmission()
{ return NS_ERROR_GFX_PRINTING_NOT_IMPLEMENTED; }
nsresult SetNumCopies(int aNumCopies)
{ return NS_ERROR_NOT_IMPLEMENTED; }
protected:
/* See nsIPrintJobGTK.h. */
nsresult Init(nsDeviceContextSpecGTK *);
};
/* Print job class for print-to-file. */
class nsPrintJobFileGTK : public nsIPrintJobGTK {
public:
nsPrintJobFileGTK();
~nsPrintJobFileGTK();
/* see nsIPrintJobGTK.h */
nsresult StartSubmission(FILE **aHandle);
nsresult FinishSubmission();
nsresult SetNumCopies(int aNumCopies)
{ return NS_ERROR_NOT_IMPLEMENTED; }
protected:
/* see nsIPrintJobGTK.h */
nsresult Init(nsDeviceContextSpecGTK *);
/**
* Set the destination file handle.
* @param aHandle New value for the handle.
*/
void SetDestHandle(FILE *aHandle) { mDestHandle = aHandle; }
/**
* Get the current value for the destination file handle.
* @return the current value for the destination file handle.
*/
FILE *GetDestHandle() { return mDestHandle; }
/**
* Set a string representing the destination. For print-to-file
* this is the name of the destination file. Subclasses could
* store something else here.
* @param aDest Destination filename.
*/
void SetDestination(const char *aDest) { mDestination = aDest; }
/**
* Get the string representing the destination.
* @return The current value of the destination string.
*/
nsCString& GetDestination() { return mDestination; }
private:
FILE *mDestHandle; // Destination file handle
nsCString mDestination;
};
/* This is the class for printing to a pipe. The destination for
* GetDestination() and SetDestination() is a command to be executed,
* rather than a filename.
*/
class nsPrintJobPipeGTK : public nsPrintJobFileGTK {
public:
/* see nsIPrintJobGTK.h */
~nsPrintJobPipeGTK();
nsresult StartSubmission(FILE **aHandle);
nsresult FinishSubmission();
protected:
nsresult Init(nsDeviceContextSpecGTK *);
private:
nsCString mPrinterName;
};
/* This class submits print jobs through CUPS. mDestHandle and
* mDestination point to a temporary file used to assemble the
* final print job.
*/
class nsPrintJobCUPS : public nsPrintJobFileGTK {
public:
nsresult StartSubmission(FILE **aHandle);
nsresult FinishSubmission();
nsresult SetNumCopies(int aNumCopies);
void SetJobTitle(const PRUnichar *aTitle);
protected:
nsresult Init(nsDeviceContextSpecGTK *);
private:
nsCUPSShim mCups;
nsCString mPrinterName;
nsCString mNumCopies;
nsCString mJobTitle; // IsVoid() if no title
};
#endif /* nsPrintJobPS_h__ */

Просмотреть файл

@ -57,6 +57,11 @@ public:
NS_DECL_ISUPPORTS
#ifdef MOZ_CAIRO_GFX
NS_IMETHOD GetSurfaceForPrinter(gfxASurface **surface);
NS_IMETHOD BeginDocument(PRUnichar* aTitle,
PRUnichar* aPrintToFileName,
PRInt32 aStartPage,
PRInt32 aEndPage) { return NS_ERROR_NOT_IMPLEMENTED; }
NS_IMETHOD EndDocument() { return NS_ERROR_NOT_IMPLEMENTED; }
#endif
/**

Просмотреть файл

@ -58,6 +58,11 @@ public:
#ifdef MOZ_CAIRO_GFX
NS_IMETHOD GetSurfaceForPrinter(gfxASurface **surface);
NS_IMETHOD BeginDocument(PRUnichar* aTitle,
PRUnichar* aPrintToFileName,
PRInt32 aStartPage,
PRInt32 aEndPage) { return NS_ERROR_NOT_IMPLEMENTED; }
NS_IMETHOD EndDocument() { return NS_ERROR_NOT_IMPLEMENTED; }
#else
// kill these when we move to CAIRO_GFX
NS_IMETHOD GetType(PRUint16 *aType) { *aType = nsISupportsPrimitive::TYPE_VOID; return NS_OK; }