зеркало из https://github.com/mozilla/pjs.git
Bug 382169 - Print Preview overwrites printed file. r=pavlov, sr=cbiesinger.
This commit is contained in:
Родитель
09656ac081
Коммит
c98a3c0e17
|
@ -110,7 +110,6 @@ CPPSRCS = \
|
|||
nsAccessibilityHelper.cpp \
|
||||
nsPrintJobFactoryGTK.cpp \
|
||||
nsPrintJobGTK.cpp \
|
||||
nsTempfilePS.cpp \
|
||||
nsIdleServiceGTK.cpp \
|
||||
$(NULL)
|
||||
|
||||
|
|
|
@ -67,6 +67,7 @@
|
|||
#endif /* USE_POSTSCRIPT */
|
||||
|
||||
#include "nsPrintJobFactoryGTK.h"
|
||||
#include "nsIPrintJobGTK.h"
|
||||
|
||||
#include "nsIFileStreams.h"
|
||||
#include "nsILocalFile.h"
|
||||
|
@ -411,8 +412,12 @@ NS_IMETHODIMP nsDeviceContextSpecGTK::GetSurfaceForPrinter(gfxASurface **aSurfac
|
|||
|
||||
printf("\"%s\", %d, %d\n", path, width, height);
|
||||
|
||||
nsCOMPtr<nsILocalFile> file = do_CreateInstance("@mozilla.org/file/local;1");
|
||||
nsresult rv = file->InitWithPath(NS_ConvertUTF8toUTF16(path));
|
||||
nsresult rv = nsPrintJobFactoryGTK::CreatePrintJob(this, mPrintJob);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
nsCOMPtr<nsILocalFile> file;
|
||||
rv = mPrintJob->GetSpoolFile(getter_AddRefs(file));
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
|
@ -421,7 +426,6 @@ NS_IMETHODIMP nsDeviceContextSpecGTK::GetSurfaceForPrinter(gfxASurface **aSurfac
|
|||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
nsPrintJobFactoryGTK::CreatePrintJob((this), mPrintJob);
|
||||
#ifdef USE_PDF
|
||||
gfxPDFSurface *surface = new gfxPDFSurface(stream, gfxSize(w, h));
|
||||
#else
|
||||
|
@ -439,17 +443,6 @@ NS_IMETHODIMP nsDeviceContextSpecGTK::GetSurfaceForPrinter(gfxASurface **aSurfac
|
|||
* Initialize the nsDeviceContextSpecGTK
|
||||
* @update dc 2/15/98
|
||||
* @update syd 3/2/99
|
||||
*
|
||||
* gisburn: Please note that this function exists as 1:1 copy in other
|
||||
* toolkits including:
|
||||
* - GTK+-toolkit:
|
||||
* file: mozilla/gfx/src/gtk/nsDeviceContextSpecG.cpp
|
||||
* function: NS_IMETHODIMP nsDeviceContextSpecGTK::Init()
|
||||
* - Xlib-toolkit:
|
||||
* file: mozilla/gfx/src/xlib/nsDeviceContextSpecXlib.cpp
|
||||
* function: NS_IMETHODIMP nsDeviceContextSpecXlib::Init()
|
||||
*
|
||||
* ** Please update the other toolkits when changing this function.
|
||||
*/
|
||||
NS_IMETHODIMP nsDeviceContextSpecGTK::Init(nsIWidget *aWidget,
|
||||
nsIPrintSettings* aPS,
|
||||
|
@ -700,24 +693,10 @@ NS_IMETHODIMP nsDeviceContextSpecGTK::BeginDocument(PRUnichar * aTitle, PRUnicha
|
|||
{
|
||||
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;
|
||||
return mPrintJob->Submit();
|
||||
}
|
||||
|
||||
/* Get prefs for printer
|
||||
|
|
|
@ -42,12 +42,11 @@
|
|||
#include "nsIDeviceContextSpec.h"
|
||||
#include "nsIPrintSettings.h"
|
||||
#include "nsIPrintOptions.h"
|
||||
#include "nsVoidArray.h"
|
||||
#include "nsCOMPtr.h"
|
||||
|
||||
#include "nsCRT.h" /* should be <limits.h>? */
|
||||
|
||||
#include "nsIPrintJobGTK.h"
|
||||
class nsIPrintJobGTK;
|
||||
|
||||
#define NS_PORTRAIT 0
|
||||
#define NS_LANDSCAPE 1
|
||||
|
|
|
@ -39,16 +39,17 @@
|
|||
#ifndef nsIPrintJobGTK_h__
|
||||
#define nsIPrintJobGTK_h__
|
||||
|
||||
#include <stdio.h>
|
||||
#include "nsCOMPtr.h"
|
||||
|
||||
class nsDeviceContextSpecGTK;
|
||||
class nsILocalFile;
|
||||
|
||||
/*
|
||||
* This is an interface for a class that accepts and submits print jobs.
|
||||
*
|
||||
* Instances should be obtained through nsPrintJobFactoryGTK::CreatePrintJob().
|
||||
* After obtaining a print job object, the caller can retrieve the PostScript
|
||||
* object associated with the print job and use that to generate the content.
|
||||
* After obtaining a print job object, the caller can retrieve the spool file
|
||||
* object associated with the print job and write the print job to that.
|
||||
* Once that is done, the caller may call Submit() to finalize and print
|
||||
* the job, or Cancel() to abort the job.
|
||||
*/
|
||||
|
@ -56,9 +57,6 @@ class nsDeviceContextSpecGTK;
|
|||
class nsIPrintJobGTK
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Obligatory virtual destructor for polymorphic objects.
|
||||
*/
|
||||
virtual ~nsIPrintJobGTK();
|
||||
|
||||
/* Allow the print job factory to create instances */
|
||||
|
@ -77,7 +75,8 @@ public:
|
|||
* @return NS_OK The print job class will request the specified
|
||||
* number of copies when printing the job.
|
||||
*/
|
||||
virtual nsresult SetNumCopies(int aNumCopies) = 0;
|
||||
virtual nsresult SetNumCopies(int aNumCopies)
|
||||
{ return NS_ERROR_NOT_IMPLEMENTED; }
|
||||
|
||||
/**
|
||||
* Set the print job title. Some printing systems accept a job title
|
||||
|
@ -92,43 +91,51 @@ public:
|
|||
virtual void SetJobTitle(const PRUnichar *aTitle) { }
|
||||
|
||||
/**
|
||||
* Begin submitting a print job.
|
||||
* @param aHandle If the return value is NS_OK, this will be filled
|
||||
* in with a file handle which the caller should use
|
||||
* to write the text of the print job. The file
|
||||
* handle may not support seeking. The caller must
|
||||
* not close the file handle.
|
||||
* @return NS_ERROR_GFX_PRINTING_NOT_IMPLEMENTED if the print
|
||||
* job object doesn't actually support printing (e.g.
|
||||
* for print preview)
|
||||
* NS_OK for success
|
||||
* Another value for initialization/startup failures.
|
||||
* Get the temporary file that the print job should be written to. The
|
||||
* caller may open this file for writing and write the text of the print
|
||||
* job to it.
|
||||
*
|
||||
* The spool file is owned by the print job object, and will be removed
|
||||
* by the print job dtor. Each print job object has one spool file.
|
||||
*
|
||||
* @return NS_ERROR_NOT_INITIALIZED if the object hasn't been initialized.
|
||||
* NS_OK otherwise.
|
||||
*
|
||||
* This is currently non-virtual for efficiency.
|
||||
*/
|
||||
virtual nsresult StartSubmission(FILE **aHandle) = 0;
|
||||
nsresult GetSpoolFile(nsILocalFile **aFile);
|
||||
|
||||
/**
|
||||
* Finish submitting a print job. The caller must call this after
|
||||
* calling StartSubmission() and writing the text of the print job
|
||||
* to the file handle. The return value indicates the overall success
|
||||
* or failure of the print operation.
|
||||
* Submit a finished print job. The caller may call this after
|
||||
* calling GetSpoolFile(), writing the text of the print job to the
|
||||
* spool file, and closing the spool file. The return value indicates
|
||||
* the overall success or failure of the print operation.
|
||||
*
|
||||
* The caller must not try to access the spool file in any way after
|
||||
* calling this function.
|
||||
*
|
||||
* @return NS_ERROR_GFX_PRINTING_NOT_IMPLEMENTED if the print
|
||||
* job object doesn't actually support printing (e.g.
|
||||
* for print preview)
|
||||
* NS_OK for success
|
||||
* Another value for initialization/startup failures.
|
||||
* Other values indicate failure of the print operation.
|
||||
*/
|
||||
virtual nsresult FinishSubmission() = 0;
|
||||
virtual nsresult Submit() = 0;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Initialize an object from a device context spec. This must be
|
||||
* called before any of the public methods.
|
||||
* called before any of the public methods. Implementations must
|
||||
* initialize mSpoolFile declared below.
|
||||
*
|
||||
* @param aContext The device context spec describing the
|
||||
* desired print job.
|
||||
* @return NS_OK or a suitable error value.
|
||||
*/
|
||||
virtual nsresult Init(nsDeviceContextSpecGTK *aContext) = 0;
|
||||
|
||||
/* The spool file */
|
||||
nsCOMPtr<nsILocalFile> mSpoolFile;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -39,9 +39,8 @@
|
|||
#ifndef nsPrintJobFactoryGTK_h__
|
||||
#define nsPrintJobFactoryGTK_h__
|
||||
|
||||
#include "nscore.h"
|
||||
#include "nsIPrintJobGTK.h"
|
||||
#include "nsDeviceContextSpecG.h"
|
||||
class nsIPrintJobGTK;
|
||||
class nsDeviceContextSpecGTK;
|
||||
|
||||
/* Factory class for the print job subsystem. This class determines
|
||||
* which print job class should handle a print job, and constructs
|
||||
|
|
|
@ -45,6 +45,8 @@
|
|||
#include "nsPrintJobGTK.h"
|
||||
#include "nsPSPrinters.h"
|
||||
#include "nsReadableUtils.h"
|
||||
#include "nsDirectoryServiceDefs.h"
|
||||
#include "nsIFileStreams.h"
|
||||
|
||||
#include "prenv.h"
|
||||
#include "prinit.h"
|
||||
|
@ -64,30 +66,65 @@ 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)
|
||||
/* Interface class. It implements a spoolfile getter and destructor
|
||||
* so that none of the subclasses have to.
|
||||
*/
|
||||
nsIPrintJobGTK::~nsIPrintJobGTK()
|
||||
{
|
||||
if (mSpoolFile)
|
||||
mSpoolFile->Remove(PR_FALSE);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsIPrintJobGTK::GetSpoolFile(nsILocalFile **aFile)
|
||||
{
|
||||
if (!mSpoolFile)
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
*aFile = mSpoolFile;
|
||||
NS_ADDREF(*aFile);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/**** nsPrintJobPreviewGTK - Stub class for print preview ****/
|
||||
|
||||
/* nsDeviceContextSpecGTK needs a spool file even for print preview, so this
|
||||
* class includes code to create one. Some of the other print job classes
|
||||
* inherit from this one to reuse the spoolfile initializer.
|
||||
*/
|
||||
|
||||
nsresult
|
||||
nsPrintJobPreviewGTK::InitSpoolFile(PRUint32 aPermissions)
|
||||
{
|
||||
nsCOMPtr<nsIFile> spoolFile;
|
||||
nsresult rv = NS_GetSpecialDirectory(NS_OS_TEMP_DIR,
|
||||
getter_AddRefs(spoolFile));
|
||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_GFX_PRINTER_COULD_NOT_OPEN_FILE);
|
||||
|
||||
spoolFile->AppendNative(NS_LITERAL_CSTRING("tmp.prn"));
|
||||
|
||||
rv = spoolFile->CreateUnique(nsIFile::NORMAL_FILE_TYPE, aPermissions);
|
||||
if (NS_FAILED(rv))
|
||||
return NS_ERROR_GFX_PRINTER_COULD_NOT_OPEN_FILE;
|
||||
mSpoolFile = do_QueryInterface(spoolFile, &rv);
|
||||
if (NS_FAILED(rv))
|
||||
spoolFile->Remove(PR_FALSE);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsPrintJobPreviewGTK::Init(nsDeviceContextSpecGTK *aSpec)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
PRBool isPreview;
|
||||
aSpec->GetIsPrintPreview(isPreview);
|
||||
NS_PRECONDITION(isPreview, "This print job is to a printer");
|
||||
#endif
|
||||
return InitSpoolFile(0600);
|
||||
}
|
||||
|
||||
/**** 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.
|
||||
|
@ -101,175 +138,40 @@ nsPrintJobFileGTK::Init(nsDeviceContextSpecGTK *aSpec)
|
|||
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+");
|
||||
// The final output file will inherit the permissions of the temporary.
|
||||
nsresult rv = InitSpoolFile(0666);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
SetDestHandle(printHandle);
|
||||
*aHandle = printHandle;
|
||||
const char *path;
|
||||
aSpec->GetPath(&path);
|
||||
rv = NS_NewNativeLocalFile(nsDependentCString(path), PR_FALSE,
|
||||
getter_AddRefs(mDestFile));
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsPrintJobVMSCmdGTK::FinishSubmission()
|
||||
nsPrintJobFileGTK::Submit()
|
||||
{
|
||||
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);
|
||||
// Move the spool file to the destination
|
||||
nsAutoString destLeafName;
|
||||
nsresult rv = mDestFile->GetLeafName(destLeafName);
|
||||
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;
|
||||
nsCOMPtr<nsIFile> mDestDir;
|
||||
rv = mDestFile->GetParent(getter_AddRefs(mDestDir));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = mSpoolFile->MoveTo(mDestDir, destLeafName);
|
||||
}
|
||||
}
|
||||
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.
|
||||
|
@ -284,10 +186,15 @@ nsPrintJobPipeGTK::Init(nsDeviceContextSpecGTK *aSpec)
|
|||
NS_PRECONDITION(toPrinter, "Wrong class for this print job");
|
||||
#endif
|
||||
|
||||
/* Print command. This is stored as the destination string. */
|
||||
/* Spool file */
|
||||
nsresult rv = InitSpoolFile(0600);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
/* Print command */
|
||||
const char *command;
|
||||
aSpec->GetCommand(&command);
|
||||
SetDestination(command);
|
||||
mCommand = command;
|
||||
|
||||
/* Printer name */
|
||||
const char *printerName;
|
||||
|
@ -303,47 +210,84 @@ nsPrintJobPipeGTK::Init(nsDeviceContextSpecGTK *aSpec)
|
|||
}
|
||||
|
||||
|
||||
/* Helper for nsPrintJobPipeGTK::Submit(). Start the print command. */
|
||||
static nsresult
|
||||
popenPrintCommand(FILE **aPipe, nsCString &aPrinter, nsCString &aCommand)
|
||||
{
|
||||
// Set up the environment for the print command
|
||||
if (PR_SUCCESS != EnvLock())
|
||||
return NS_ERROR_OUT_OF_MEMORY; // Couldn't allocate the object?
|
||||
|
||||
if (!aPrinter.IsEmpty())
|
||||
EnvSetPrinter(aPrinter);
|
||||
|
||||
// Start the print command
|
||||
*aPipe = popen(aCommand.get(), "w");
|
||||
EnvClear();
|
||||
return (*aPipe) ? NS_OK : NS_ERROR_GFX_PRINTER_CMD_FAILURE;
|
||||
}
|
||||
|
||||
/* Helper for nsPrintJobPipeGTK::Submit(). Copy data from a temporary file
|
||||
* to the command pipe.
|
||||
*/
|
||||
static nsresult
|
||||
CopySpoolToCommand(nsIFileInputStream *aSource, FILE *aDest)
|
||||
{
|
||||
nsresult rv;
|
||||
PRUint32 count;
|
||||
do {
|
||||
char buf[256];
|
||||
count = 0;
|
||||
rv = aSource->Read(buf, sizeof buf, &count);
|
||||
fwrite(buf, 1, count, aDest);
|
||||
} while (NS_SUCCEEDED(rv) && count);
|
||||
return rv;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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()
|
||||
nsPrintJobPipeGTK::Submit()
|
||||
{
|
||||
NS_PRECONDITION(GetDestHandle(), "No destination file handle");
|
||||
NS_PRECONDITION(!GetDestination().IsEmpty(), "No destination");
|
||||
NS_PRECONDITION(mSpoolFile, "No spool file");
|
||||
|
||||
int presult = pclose(GetDestHandle());
|
||||
SetDestHandle(nsnull);
|
||||
if (!WIFEXITED(presult) || (EXIT_SUCCESS != WEXITSTATUS(presult)))
|
||||
return NS_ERROR_GFX_PRINTER_CMD_FAILURE;
|
||||
return NS_OK;
|
||||
// Open the spool file
|
||||
nsCOMPtr<nsIFileInputStream> spoolStream =
|
||||
do_CreateInstance("@mozilla.org/network/file-input-stream;1");
|
||||
if (!spoolStream)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
nsresult rv = spoolStream->Init(mSpoolFile, -1, -1,
|
||||
nsIFileInputStream::DELETE_ON_CLOSE|nsIFileInputStream::CLOSE_ON_EOF);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Start the print command
|
||||
FILE *destPipe;
|
||||
rv = popenPrintCommand(&destPipe, mPrinterName, mCommand);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = CopySpoolToCommand(spoolStream, destPipe);
|
||||
int presult = pclose(destPipe);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
if (!WIFEXITED(presult) || (EXIT_SUCCESS != WEXITSTATUS(presult)))
|
||||
rv = NS_ERROR_GFX_PRINTER_CMD_FAILURE;
|
||||
}
|
||||
}
|
||||
spoolStream->Close();
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
/**** Print via CUPS ****/
|
||||
|
||||
/* nsPrintJobCUPS doesn't inherit its spoolfile code from the preview
|
||||
* class. CupsPrintFile() needs the filename as an 8-bit string, but an
|
||||
* nsILocalFile doesn't portably expose the filename in this format.
|
||||
* So it's necessary to construct the spoolfile name outside of the
|
||||
* nsILocalFile object, and retain it as a string for use when calling
|
||||
* CupsPrintFile().
|
||||
*/
|
||||
|
||||
/**
|
||||
* Initialize a print-to-CUPS object.
|
||||
* See nsIPrintJobGTK.h and nsPrintJobGTK.h for details.
|
||||
|
@ -368,6 +312,24 @@ nsPrintJobCUPS::Init(nsDeviceContextSpecGTK *aSpec)
|
|||
const char *slash = strchr(printerName, '/');
|
||||
mPrinterName = slash ? slash + 1 : printerName;
|
||||
mJobTitle.SetIsVoid(PR_TRUE);
|
||||
|
||||
/* Spool file */
|
||||
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);
|
||||
close(fd);
|
||||
|
||||
nsresult rv = NS_NewNativeLocalFile(nsDependentCString(buf), PR_FALSE,
|
||||
getter_AddRefs(mSpoolFile));
|
||||
if (NS_FAILED(rv)) {
|
||||
unlink(buf);
|
||||
return NS_ERROR_GFX_PRINTER_COULD_NOT_OPEN_FILE;
|
||||
}
|
||||
mSpoolName = buf;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -393,40 +355,11 @@ nsPrintJobCUPS::SetJobTitle(const PRUnichar *aTitle)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
nsPrintJobCUPS::StartSubmission(FILE **aHandle)
|
||||
nsPrintJobCUPS::Submit()
|
||||
{
|
||||
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);
|
||||
NS_PRECONDITION(!mSpoolName.IsEmpty(), "No spool file");
|
||||
|
||||
nsCStringArray printer(3);
|
||||
printer.ParseString(mPrinterName.get(),"/");
|
||||
|
@ -452,11 +385,10 @@ nsPrintJobCUPS::FinishSubmission()
|
|||
const char *title = mJobTitle.IsVoid() ?
|
||||
"Untitled Document" : mJobTitle.get();
|
||||
result = (mCups.mCupsPrintFile)(printer.CStringAt(0)->get(),
|
||||
GetDestination().get(), title,
|
||||
mSpoolName.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
|
||||
|
@ -467,10 +399,6 @@ nsPrintJobCUPS::FinishSubmission()
|
|||
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.
|
||||
*/
|
||||
|
|
|
@ -45,7 +45,6 @@
|
|||
#include "nsILocalFile.h"
|
||||
#include "nsIPrintJobGTK.h"
|
||||
#include "nsString.h"
|
||||
#include "nsTempfilePS.h"
|
||||
#include "nsDeviceContextSpecG.h"
|
||||
|
||||
/* Print job class for print preview operations. */
|
||||
|
@ -55,108 +54,55 @@ class nsPrintJobPreviewGTK : public nsIPrintJobGTK {
|
|||
/* see nsIPrintJobGTK.h. Print preview doesn't actually
|
||||
* implement printing.
|
||||
*/
|
||||
nsresult StartSubmission(FILE **aHandle)
|
||||
virtual nsresult Submit()
|
||||
{ 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 *);
|
||||
virtual nsresult Init(nsDeviceContextSpecGTK *);
|
||||
nsresult InitSpoolFile(PRUint32 aPermissions);
|
||||
};
|
||||
|
||||
|
||||
/* Print job class for print-to-file. */
|
||||
class nsPrintJobFileGTK : public nsIPrintJobGTK {
|
||||
class nsPrintJobFileGTK : public nsPrintJobPreviewGTK {
|
||||
public:
|
||||
nsPrintJobFileGTK();
|
||||
~nsPrintJobFileGTK();
|
||||
|
||||
/* see nsIPrintJobGTK.h */
|
||||
nsresult StartSubmission(FILE **aHandle);
|
||||
nsresult FinishSubmission();
|
||||
|
||||
nsresult SetNumCopies(int aNumCopies)
|
||||
{ return NS_ERROR_NOT_IMPLEMENTED; }
|
||||
virtual nsresult Submit();
|
||||
|
||||
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;
|
||||
virtual nsresult Init(nsDeviceContextSpecGTK *);
|
||||
nsCOMPtr<nsILocalFile> mDestFile;
|
||||
};
|
||||
|
||||
/* 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 {
|
||||
/* This is the class for printing to a pipe. */
|
||||
class nsPrintJobPipeGTK : public nsPrintJobPreviewGTK {
|
||||
public:
|
||||
/* see nsIPrintJobGTK.h */
|
||||
~nsPrintJobPipeGTK();
|
||||
nsresult StartSubmission(FILE **aHandle);
|
||||
nsresult FinishSubmission();
|
||||
virtual nsresult Submit();
|
||||
|
||||
protected:
|
||||
nsresult Init(nsDeviceContextSpecGTK *);
|
||||
virtual nsresult Init(nsDeviceContextSpecGTK *);
|
||||
|
||||
private:
|
||||
nsCString mCommand;
|
||||
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 {
|
||||
/* This class submits print jobs through CUPS. */
|
||||
class nsPrintJobCUPS : public nsIPrintJobGTK {
|
||||
public:
|
||||
nsresult StartSubmission(FILE **aHandle);
|
||||
nsresult FinishSubmission();
|
||||
nsresult SetNumCopies(int aNumCopies);
|
||||
void SetJobTitle(const PRUnichar *aTitle);
|
||||
virtual nsresult Submit();
|
||||
virtual nsresult SetNumCopies(int aNumCopies);
|
||||
virtual void SetJobTitle(const PRUnichar *aTitle);
|
||||
|
||||
protected:
|
||||
nsresult Init(nsDeviceContextSpecGTK *);
|
||||
virtual nsresult Init(nsDeviceContextSpecGTK *);
|
||||
|
||||
private:
|
||||
nsCUPSShim mCups;
|
||||
nsCString mPrinterName;
|
||||
nsCString mNumCopies;
|
||||
nsCString mJobTitle; // IsVoid() if no title
|
||||
nsCString mSpoolName;
|
||||
};
|
||||
|
||||
#endif /* nsPrintJobPS_h__ */
|
||||
|
|
Загрузка…
Ссылка в новой задаче