diff --git a/config/system-headers b/config/system-headers index ff1938614258..ecc27a66d59b 100644 --- a/config/system-headers +++ b/config/system-headers @@ -250,6 +250,9 @@ gtk/gtkinvisible.h gtk/gtkmain.h gtk/gtkmessagedialog.h gtk/gtkobject.h +gtk/gtkprinter.h +gtk/gtkprintjob.h +gtk/gtkprintunixdialog.h gtk/gtkprivate.h gtk/gtkselection.h gtk/gtksignal.h diff --git a/configure.in b/configure.in index b012687ac8f2..46089cf7d0c7 100644 --- a/configure.in +++ b/configure.in @@ -4599,7 +4599,7 @@ fi if test "$COMPILE_ENVIRONMENT"; then if test "$MOZ_ENABLE_GTK2" then - PKG_CHECK_MODULES(MOZ_GTK2, gtk+-2.0 >= $GTK2_VERSION gdk-x11-2.0 glib-2.0 gobject-2.0) + PKG_CHECK_MODULES(MOZ_GTK2, gtk+-2.0 >= $GTK2_VERSION gtk+-unix-print-2.0 gdk-x11-2.0 glib-2.0 gobject-2.0) fi fi # COMPILE_ENVIRONMENT diff --git a/embedding/components/printingui/src/unixshared/nsPrintingPromptService.cpp b/embedding/components/printingui/src/unixshared/nsPrintingPromptService.cpp index a897df008ca7..6df7bc59fc10 100644 --- a/embedding/components/printingui/src/unixshared/nsPrintingPromptService.cpp +++ b/embedding/components/printingui/src/unixshared/nsPrintingPromptService.cpp @@ -44,6 +44,7 @@ #include "nsISupportsUtils.h" #include "nsISupportsArray.h" #include "nsString.h" +#include "nsIPrintDialogService.h" // Printing Progress Includes #include "nsPrintProgress.h" @@ -109,6 +110,13 @@ nsPrintingPromptService::ShowPrintDialog(nsIDOMWindow *parent, nsIWebBrowserPrin NS_ENSURE_ARG(webBrowserPrint); NS_ENSURE_ARG(printSettings); + // Try to access a component dialog + nsCOMPtr dlgPrint(do_GetService( + NS_PRINTDIALOGSERVICE_CONTRACTID)); + if (dlgPrint) + return dlgPrint->Show(printSettings); + + // Show the built-in dialog instead ParamBlock block; nsresult rv = block.Init(); if (NS_FAILED(rv)) @@ -177,6 +185,12 @@ nsPrintingPromptService::ShowPageSetup(nsIDOMWindow *parent, nsIPrintSettings *p { NS_ENSURE_ARG(printSettings); + // Try to access a component dialog + nsCOMPtr dlgPrint(do_GetService( + NS_PRINTDIALOGSERVICE_CONTRACTID)); + if (dlgPrint) + return dlgPrint->ShowPageSetup(printSettings); + ParamBlock block; nsresult rv = block.Init(); if (NS_FAILED(rv)) diff --git a/layout/base/nsDocumentViewer.cpp b/layout/base/nsDocumentViewer.cpp index 68469fe9a652..d11174354a5f 100644 --- a/layout/base/nsDocumentViewer.cpp +++ b/layout/base/nsDocumentViewer.cpp @@ -3431,6 +3431,11 @@ DocumentViewerImpl::Print(nsIPrintSettings* aPrintSettings, } #endif + if (!mContainer) { + PR_PL(("Container was destroyed yet we are still trying to use it!")); + return NS_ERROR_FAILURE; + } + nsCOMPtr docShell(do_QueryReferent(mContainer)); NS_ASSERTION(docShell, "This has to be a docshell"); @@ -3525,6 +3530,11 @@ DocumentViewerImpl::PrintPreview(nsIPrintSettings* aPrintSettings, } #endif + if (!mContainer) { + PR_PL(("Container was destroyed yet we are still trying to use it!")); + return NS_ERROR_FAILURE; + } + nsCOMPtr docShell(do_QueryReferent(mContainer)); NS_ASSERTION(docShell, "This has to be a docshell"); nsCOMPtr presShell; diff --git a/layout/printing/nsPrintEngine.cpp b/layout/printing/nsPrintEngine.cpp index 81faeb8c91a4..f1bd3dc3d8f6 100644 --- a/layout/printing/nsPrintEngine.cpp +++ b/layout/printing/nsPrintEngine.cpp @@ -597,9 +597,14 @@ nsPrintEngine::DoCommonPrint(PRBool aIsPrintPreview, // are telling GFX we want to print silent printSilently = PR_TRUE; } + // The user might have changed shrink-to-fit in the print dialog, so update our copy of its state + mPrt->mPrintSettings->GetShrinkToFit(&mPrt->mShrinkToFit); } else { rv = NS_ERROR_GFX_NO_PRINTROMPTSERVICE; } + } else { + // Call any code that requires a run of the event loop. + rv = mPrt->mPrintSettings->SetupSilentPrinting(); } // Check explicitly for abort because it's expected if (rv == NS_ERROR_ABORT) diff --git a/toolkit/locales/en-US/chrome/global/gnomeprintdialog.properties b/toolkit/locales/en-US/chrome/global/gnomeprintdialog.properties new file mode 100644 index 000000000000..96a8c55e290f --- /dev/null +++ b/toolkit/locales/en-US/chrome/global/gnomeprintdialog.properties @@ -0,0 +1,28 @@ +printTitle=Print +optionsTabLabel=Options +printFramesTitle=Print Frames + +# TRANSLATOR NOTE: For radio button labels and check button labels, an underscore _ +# before a character will turn that character into an accesskey. +# e.g. "_As laid out" will make A the accesskey. + +asLaidOut=_As Laid Out on the Screen +selectedFrame=The _Selected Frame +separateFrames=Each Frame on Separate _Pages +shrinkToFit=Ignore Scaling and S_hrink To Fit Page Width +selectionOnly=Print Selection _Only +printBGOptions=Print Backgrounds +printBGColors=Print Background _Colors +printBGImages=Print Background I_mages +headerFooter=Header and Footer +left=Left +center=Center +right=Right +headerFooterBlank=--blank-- +headerFooterTitle=Title +headerFooterURL=URL +headerFooterDate=Date/Time +headerFooterPage=Page # +headerFooterPageTotal=Page # of # +headerFooterCustom=Custom... +customHeaderFooterPrompt=Please enter your custom header/footer text diff --git a/toolkit/locales/jar.mn b/toolkit/locales/jar.mn index 1b2477c57b04..ef85fbeffdb2 100644 --- a/toolkit/locales/jar.mn +++ b/toolkit/locales/jar.mn @@ -40,6 +40,7 @@ + locale/@AB_CD@/global/printPageSetup.dtd (%chrome/global/printPageSetup.dtd) + locale/@AB_CD@/global/printPreview.dtd (%chrome/global/printPreview.dtd) + locale/@AB_CD@/global/printPreviewProgress.dtd (%chrome/global/printPreviewProgress.dtd) + locale/@AB_CD@/global/gnomeprintdialog.properties (%chrome/global/gnomeprintdialog.properties) + locale/@AB_CD@/global/printProgress.dtd (%chrome/global/printProgress.dtd) + locale/@AB_CD@/global/regionNames.properties (%chrome/global/regionNames.properties) + locale/@AB_CD@/global/dialog.properties (%chrome/global/dialog.properties) diff --git a/widget/public/Makefile.in b/widget/public/Makefile.in index 349ab33527f3..141f4e081b12 100644 --- a/widget/public/Makefile.in +++ b/widget/public/Makefile.in @@ -79,7 +79,10 @@ EXPORTS += nsIDragSessionBeOS.h endif ifneq (,$(filter gtk2,$(MOZ_WIDGET_TOOLKIT))) -EXPORTS += nsIDragSessionGTK.h +EXPORTS += \ + nsIDragSessionGTK.h \ + nsIPrintDialogService.h \ + $(NULL) endif XPIDLSRCS = \ diff --git a/widget/public/nsIPrintDialogService.h b/widget/public/nsIPrintDialogService.h new file mode 100644 index 000000000000..1b8d5c5db4ff --- /dev/null +++ b/widget/public/nsIPrintDialogService.h @@ -0,0 +1,97 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** 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 + * Portions created by the Initial Developer are Copyright (C) 2007 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either of 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 nsIPrintDialogService_h__ +#define nsIPrintDialogService_h__ + +#include "nsISupports.h" + +class nsIPrintSettings; + +/* + * Interface to a print dialog accessed through the widget library. + */ + +#define NS_IPRINTDIALOGSERVICE_IID \ +{ 0x3715eb1a, 0xb314, 0x447c, \ +{ 0x95, 0x33, 0xd0, 0x6a, 0x6d, 0xa6, 0xa6, 0xf0 } } + + +/** + * + */ +class nsIPrintDialogService : public nsISupports +{ +public: + NS_DECLARE_STATIC_IID_ACCESSOR(NS_IPRINTDIALOGSERVICE_IID) + + /** + * Initialize the service. + * @return NS_OK or a suitable error. + */ + NS_IMETHOD Init() = 0; + + /** + * Show the print dialog. + * @param aSettings On entry, this contains initial settings for the + * print dialog. On return, if the print operation should + * proceed then this contains settings for the print + * operation. + * @return NS_OK if the print operation should proceed + * @return NS_ERROR_ABORT if the user indicated not to proceed + * @return a suitable error for failures to show the print dialog. + */ + NS_IMETHOD Show(nsIPrintSettings *aSettings) = 0; + + /** + * Show the page setup dialog. Note that there is no way to tell whether the user clicked OK or Cancel on the + * dialog. + * @param aSettings On entry, this contains initial settings for the + * page setup dialog. On return, this contains new default page setup options. + * @return NS_OK if everything is OK. + * @return a suitable error for failures to show the page setup dialog. + */ + NS_IMETHOD ShowPageSetup(nsIPrintSettings *aSettings) = 0; + +}; + +NS_DEFINE_STATIC_IID_ACCESSOR(nsIPrintDialogService, NS_IPRINTDIALOGSERVICE_IID) + +#define NS_PRINTDIALOGSERVICE_CONTRACTID ("@mozilla.org/widget/printdialog-service;1") + +#endif // nsIPrintDialogService_h__ + diff --git a/widget/public/nsIPrintSettings.idl b/widget/public/nsIPrintSettings.idl index 52dac49b36c4..bd87d364d36b 100644 --- a/widget/public/nsIPrintSettings.idl +++ b/widget/public/nsIPrintSettings.idl @@ -58,7 +58,7 @@ interface nsIPrintSession; * * @status UNDER_REVIEW */ -[scriptable, uuid(81b8dfee-25cc-479c-ad2c-a5e3875650cb)] +[scriptable, uuid(3e097aba-c1d6-425d-9c52-b371d5da964a)] interface nsIPrintSettings : nsISupports { @@ -301,4 +301,14 @@ interface nsIPrintSettings : nsISupports /* Purposely made this an "in" arg */ [noscript] void GetMarginInTwips(in nsNativeMarginRef aMargin); [noscript] void GetEdgeInTwips(in nsNativeMarginRef aEdge); + + /** + * We call this function so that anything that requires a run of the event loop + * can do so safely. The print dialog runs the event loop but in silent printing + * that doesn't happen. + * + * Either this or ShowPrintDialog (but not both) MUST be called by the print engine + * before printing, otherwise printing can fail on some platforms. + */ + [noscript] void SetupSilentPrinting(); }; diff --git a/widget/public/nsWidgetsCID.h b/widget/public/nsWidgetsCID.h index b4b462aaf4cd..c9157d165cad 100644 --- a/widget/public/nsWidgetsCID.h +++ b/widget/public/nsWidgetsCID.h @@ -167,3 +167,6 @@ { 0x2f977d53, 0x5485, 0x11d4, \ { 0x87, 0xe2, 0x00, 0x10, 0xa4, 0xe7, 0x5e, 0xf2 } } +#define NS_PRINTDIALOGSERVICE_CID \ +{ 0x06beec76, 0xa183, 0x4d9f, \ +{ 0x85, 0xdd, 0x08, 0x5f, 0x26, 0xda, 0x56, 0x5a } } diff --git a/widget/src/gtk2/Makefile.in b/widget/src/gtk2/Makefile.in index 1d3cdf472efe..2d0620675674 100644 --- a/widget/src/gtk2/Makefile.in +++ b/widget/src/gtk2/Makefile.in @@ -108,9 +108,9 @@ CPPSRCS = \ nsPrintOptionsGTK.cpp \ nsImageToPixbuf.cpp \ nsAccessibilityHelper.cpp \ - nsPrintJobFactoryGTK.cpp \ - nsPrintJobGTK.cpp \ nsIdleServiceGTK.cpp \ + nsPrintDialogGTK.cpp \ + nsPrintSettingsGTK.cpp \ $(NULL) # build our subdirs, too diff --git a/widget/src/gtk2/nsDeviceContextSpecG.cpp b/widget/src/gtk2/nsDeviceContextSpecG.cpp index 70e91b1d0428..8702338e7a06 100644 --- a/widget/src/gtk2/nsDeviceContextSpecG.cpp +++ b/widget/src/gtk2/nsDeviceContextSpecG.cpp @@ -23,6 +23,7 @@ * Roland Mainz * Ken Herron * Julien Lafon + * Michael Ventnor * * Alternatively, the contents of this file may be used under the terms of * either of the GNU General Public License Version 2 or later (the "GPL"), @@ -66,12 +67,15 @@ #include "nsPaperPS.h" /* Paper size list */ #endif /* USE_POSTSCRIPT */ -#include "nsPrintJobFactoryGTK.h" -#include "nsIPrintJobGTK.h" +#include "nsPrintSettingsGTK.h" #include "nsIFileStreams.h" #include "nsILocalFile.h" +#include +#include +#include + /* Ensure that the result is always equal to either PR_TRUE or PR_FALSE */ #define MAKE_PR_BOOL(val) ((val)?(PR_TRUE):(PR_FALSE)) @@ -382,13 +386,11 @@ 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; } NS_IMPL_ISUPPORTS1(nsDeviceContextSpecGTK, @@ -410,18 +412,30 @@ NS_IMETHODIMP nsDeviceContextSpecGTK::GetSurfaceForPrinter(gfxASurface **aSurfac height /= 20; DO_PR_DEBUG_LOG(("\"%s\", %f, %f\n", path, width, height)); + nsresult rv; - nsresult rv = nsPrintJobFactoryGTK::CreatePrintJob(this, mPrintJob); - if (NS_FAILED(rv)) - return rv; + // Spool file. Use Glib's temporary file function since we're + // already dependent on the gtk software stack. + gchar *buf; + gint fd = g_file_open_tmp("XXXXXX.tmp", &buf, nsnull); + if (-1 == fd) + return NS_ERROR_GFX_PRINTER_COULD_NOT_OPEN_FILE; + close(fd); - nsCOMPtr file; - rv = mPrintJob->GetSpoolFile(getter_AddRefs(file)); - if (NS_FAILED(rv)) - return rv; + 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; + g_free(buf); + + mSpoolFile->SetPermissions(0600); nsCOMPtr stream = do_CreateInstance("@mozilla.org/network/file-output-stream;1"); - rv = stream->Init(file, -1, -1, 0); + rv = stream->Init(mSpoolFile, -1, -1, 0); if (NS_FAILED(rv)) return rv; @@ -429,10 +443,31 @@ NS_IMETHODIMP nsDeviceContextSpecGTK::GetSurfaceForPrinter(gfxASurface **aSurfac mPrintSettings->GetOutputFormat(&format); nsRefPtr surface; - if (nsIPrintSettings::kOutputFormatPDF == format) { - surface = new gfxPDFSurface(stream, gfxSize(width, height)); + gfxSize surfaceSize(width, height); + + // Determine the real format with some GTK magic + if (format == nsIPrintSettings::kOutputFormatNative) { + if (mIsPPreview) { + // There is nothing to detect on Print Preview, use PS. + format = nsIPrintSettings::kOutputFormatPS; + } else { + const gchar* fmtGTK = gtk_print_settings_get(mGtkPrintSettings, GTK_PRINT_SETTINGS_OUTPUT_FILE_FORMAT); + if (!fmtGTK && GTK_IS_PRINTER(mGtkPrinter)) { + // Likely not print-to-file, check printer's capabilities + format = (gtk_printer_accepts_pdf(mGtkPrinter)) ? nsIPrintSettings::kOutputFormatPDF + : nsIPrintSettings::kOutputFormatPS; + } else if (nsDependentCString(fmtGTK).EqualsIgnoreCase("pdf")) { + format = nsIPrintSettings::kOutputFormatPDF; + } else { + format = nsIPrintSettings::kOutputFormatPS; + } + } + } + + if (format == nsIPrintSettings::kOutputFormatPDF) { + surface = new gfxPDFSurface(stream, surfaceSize); } else { - surface = new gfxPSSurface(stream, gfxSize(width, height)); + surface = new gfxPSSurface(stream, surfaceSize); } if (!surface) @@ -453,104 +488,29 @@ NS_IMETHODIMP nsDeviceContextSpecGTK::Init(nsIWidget *aWidget, PRBool aIsPrintPreview) { DO_PR_DEBUG_LOG(("nsDeviceContextSpecGTK::Init(aPS=%p)\n", aPS)); - nsresult rv = NS_ERROR_FAILURE; + + if (gtk_major_version < 2 || + (gtk_major_version == 2 && gtk_minor_version < 10)) + return NS_ERROR_NOT_AVAILABLE; // I'm so sorry bz mPrintSettings = aPS; + mIsPPreview = aIsPrintPreview; - // if there is a current selection then enable the "Selection" radio button - rv = GlobalPrinters::GetInstance()->InitializeGlobalPrinters(); - if (NS_FAILED(rv)) { - return rv; - } + // This is only set by embedders + PRBool toFile; + aPS->GetPrintToFile(&toFile); - GlobalPrinters::GetInstance()->FreeGlobalPrinters(); + mToPrinter = !toFile && !aIsPrintPreview; - if (aPS) { - PRBool reversed = PR_FALSE; - PRBool color = PR_FALSE; - PRBool tofile = PR_FALSE; - PRInt16 printRange = nsIPrintSettings::kRangeAllPages; - PRInt32 orientation = NS_PORTRAIT; - PRInt32 fromPage = 1; - PRInt32 toPage = 1; - PRUnichar *command = nsnull; - PRInt32 copies = 1; - PRUnichar *printer = nsnull; - PRUnichar *papername = nsnull; - PRUnichar *plexname = nsnull; - PRUnichar *resolutionname = nsnull; - PRUnichar *colorspace = nsnull; - PRBool downloadfonts = PR_TRUE; - PRUnichar *printfile = nsnull; - double dleft = 0.5; - double dright = 0.5; - double dtop = 0.5; - double dbottom = 0.5; + nsCOMPtr printSettingsGTK(do_QueryInterface(aPS)); + if (!printSettingsGTK) + return NS_ERROR_NO_INTERFACE; - aPS->GetPrinterName(&printer); - aPS->GetPrintReversed(&reversed); - aPS->GetPrintInColor(&color); - aPS->GetPaperName(&papername); - aPS->GetResolutionName(&resolutionname); - aPS->GetColorspace(&colorspace); - aPS->GetDownloadFonts(&downloadfonts); - aPS->GetPlexName(&plexname); - aPS->GetOrientation(&orientation); - aPS->GetPrintCommand(&command); - aPS->GetPrintRange(&printRange); - aPS->GetToFileName(&printfile); - aPS->GetPrintToFile(&tofile); - aPS->GetStartPageRange(&fromPage); - aPS->GetEndPageRange(&toPage); - aPS->GetNumCopies(&copies); - aPS->GetMarginTop(&dtop); - aPS->GetMarginLeft(&dleft); - aPS->GetMarginBottom(&dbottom); - aPS->GetMarginRight(&dright); + mGtkPrinter = printSettingsGTK->GetGtkPrinter(); + mGtkPrintSettings = printSettingsGTK->GetGtkPrintSettings(); + mGtkPageSetup = printSettingsGTK->GetGtkPageSetup(); - if (printfile) - PL_strncpyz(mPath, NS_ConvertUTF16toUTF8(printfile).get(), sizeof(mPath)); - if (command) - PL_strncpyz(mCommand, NS_ConvertUTF16toUTF8(command).get(), sizeof(mCommand)); - if (printer) - PL_strncpyz(mPrinter, NS_ConvertUTF16toUTF8(printer).get(), sizeof(mPrinter)); - if (papername) - PL_strncpyz(mPaperName, NS_ConvertUTF16toUTF8(papername).get(), sizeof(mPaperName)); - if (plexname) - PL_strncpyz(mPlexName, NS_ConvertUTF16toUTF8(plexname).get(), sizeof(mPlexName)); - if (resolutionname) - PL_strncpyz(mResolutionName, NS_ConvertUTF16toUTF8(resolutionname).get(), sizeof(mResolutionName)); - if (colorspace) - PL_strncpyz(mColorspace, NS_ConvertUTF16toUTF8(colorspace).get(), sizeof(mColorspace)); - - DO_PR_DEBUG_LOG(("margins: %5.2f,%5.2f,%5.2f,%5.2f\n", dtop, dleft, dbottom, dright)); - DO_PR_DEBUG_LOG(("printRange %d\n", printRange)); - DO_PR_DEBUG_LOG(("fromPage %d\n", fromPage)); - DO_PR_DEBUG_LOG(("toPage %d\n", toPage)); - DO_PR_DEBUG_LOG(("tofile %d\n", tofile)); - DO_PR_DEBUG_LOG(("printfile '%s'\n", printfile? NS_ConvertUTF16toUTF8(printfile).get():"")); - DO_PR_DEBUG_LOG(("command '%s'\n", command? NS_ConvertUTF16toUTF8(command).get():"")); - DO_PR_DEBUG_LOG(("printer '%s'\n", printer? NS_ConvertUTF16toUTF8(printer).get():"")); - DO_PR_DEBUG_LOG(("papername '%s'\n", papername? NS_ConvertUTF16toUTF8(papername).get():"")); - DO_PR_DEBUG_LOG(("plexname '%s'\n", plexname? NS_ConvertUTF16toUTF8(plexname).get():"")); - DO_PR_DEBUG_LOG(("resolution '%s'\n", resolutionname? NS_ConvertUTF16toUTF8(resolutionname).get():"")); - DO_PR_DEBUG_LOG(("colorspace '%s'\n", colorspace? NS_ConvertUTF16toUTF8(colorspace).get():"")); - - mTop = dtop; - mBottom = dbottom; - mLeft = dleft; - mRight = dright; - mFpf = !reversed; - mDownloadFonts = downloadfonts; - mGrayscale = !color; - mOrientation = orientation; - mToPrinter = !tofile; - mCopies = copies; - mIsPPreview = aIsPrintPreview; - mCancel = PR_FALSE; - } - - return rv; + return NS_OK; } NS_IMETHODIMP nsDeviceContextSpecGTK::GetToPrinter(PRBool &aToPrinter) @@ -688,14 +648,69 @@ NS_IMETHODIMP nsDeviceContextSpecGTK::ClosePrintManager() return NS_OK; } -NS_IMETHODIMP nsDeviceContextSpecGTK::BeginDocument(PRUnichar * aTitle, PRUnichar * aPrintToFileName, PRInt32 aStartPage, PRInt32 aEndPage) +static void +print_callback(GtkPrintJob *aJob, gpointer aData, GError *aError) { + g_object_unref(aJob); + ((nsILocalFile*) aData)->Remove(PR_FALSE); +} + +static void +ns_release_macro(gpointer aData) { + nsILocalFile* spoolFile = (nsILocalFile*) aData; + NS_RELEASE(spoolFile); +} + +NS_IMETHODIMP nsDeviceContextSpecGTK::BeginDocument(PRUnichar * aTitle, PRUnichar * aPrintToFileName, + PRInt32 aStartPage, PRInt32 aEndPage) { + if (mToPrinter) { + if (!GTK_IS_PRINTER(mGtkPrinter)) + return NS_ERROR_FAILURE; + + mPrintJob = gtk_print_job_new(NS_ConvertUTF16toUTF8(aTitle).get(), mGtkPrinter, + mGtkPrintSettings, mGtkPageSetup); + } + return NS_OK; } NS_IMETHODIMP nsDeviceContextSpecGTK::EndDocument() { - return mPrintJob->Submit(); + if (mToPrinter) { + if (!gtk_print_job_set_source_file(mPrintJob, mSpoolName.get(), NULL)) + return NS_ERROR_GFX_PRINTER_COULD_NOT_OPEN_FILE; + + NS_ADDREF(mSpoolFile.get()); + gtk_print_job_send(mPrintJob, print_callback, mSpoolFile, ns_release_macro); + } else { + // Handle print-to-file ourselves for the benefit of embedders + nsXPIDLString targetPath; + nsCOMPtr destFile; + mPrintSettings->GetToFileName(getter_Copies(targetPath)); + + nsresult rv = NS_NewNativeLocalFile(NS_ConvertUTF16toUTF8(targetPath), + PR_FALSE, getter_AddRefs(destFile)); + NS_ENSURE_SUCCESS(rv, rv); + + nsAutoString destLeafName; + rv = destFile->GetLeafName(destLeafName); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr destDir; + rv = destFile->GetParent(getter_AddRefs(destDir)); + NS_ENSURE_SUCCESS(rv, rv); + + rv = mSpoolFile->MoveTo(destDir, destLeafName); + NS_ENSURE_SUCCESS(rv, rv); + + // This is the standard way to get the UNIX umask. Ugh. + mode_t mask = umask(0); + umask(mask); + // If you're not familiar with umasks, they contain the bits of what NOT to set in the permissions + // (thats because files and directories have different numbers of bits for their permissions) + destFile->SetPermissions(0666 & ~(mask)); + } + return NS_OK; } /* Get prefs for printer diff --git a/widget/src/gtk2/nsDeviceContextSpecG.h b/widget/src/gtk2/nsDeviceContextSpecG.h index e453f92945b4..2105d403c92e 100644 --- a/widget/src/gtk2/nsDeviceContextSpecG.h +++ b/widget/src/gtk2/nsDeviceContextSpecG.h @@ -43,10 +43,13 @@ #include "nsIPrintSettings.h" #include "nsIPrintOptions.h" #include "nsCOMPtr.h" +#include "nsString.h" #include "nsCRT.h" /* should be ? */ -class nsIPrintJobGTK; +#include +#include +#include #define NS_PORTRAIT 0 #define NS_LANDSCAPE 1 @@ -117,7 +120,15 @@ protected: float mRight; /* right margin */ float mTop; /* top margin */ float mBottom; /* bottom margin */ - nsIPrintJobGTK * mPrintJob; + + GtkPrintJob* mPrintJob; + GtkPrinter* mGtkPrinter; + GtkPrintSettings* mGtkPrintSettings; + GtkPageSetup* mGtkPageSetup; + + nsCString mSpoolName; + nsCOMPtr mSpoolFile; + }; //------------------------------------------------------------------------- diff --git a/widget/src/gtk2/nsIPrintJobGTK.h b/widget/src/gtk2/nsIPrintJobGTK.h deleted file mode 100644 index 99c21116e2ba..000000000000 --- a/widget/src/gtk2/nsIPrintJobGTK.h +++ /dev/null @@ -1,142 +0,0 @@ -/* -*- 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 . - * 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 nsIPrintJobGTK_h__ -#define nsIPrintJobGTK_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 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. - */ - -class nsIPrintJobGTK -{ -public: - virtual ~nsIPrintJobGTK(); - - /* Allow the print job factory to create instances */ - friend class nsPrintJobFactoryGTK; - - /** - * Set the number of copies for this print job. Some printing systems - * allow setting this out of band, instead of embedding it into the - * postscript. - * @param aNumCopies Number of copies requested. Values <= 1 are - * interpreted as "do not specify a copy count to the - * printing system" when possible, or else as - * one copy. - * @return NS_ERROR_NOT_IMPLEMENTED if this print job class doesn't - * support the specific copy count requested. - * @return NS_OK The print job class will request the specified - * number of copies when printing the job. - */ - virtual nsresult SetNumCopies(int aNumCopies) - { return NS_ERROR_NOT_IMPLEMENTED; } - - /** - * Set the print job title. Some printing systems accept a job title - * which is displayed on a banner page, in a print queue listing, etc. - * - * This must be called after Init() and before StartSubmission(). - * nsIPrintJobGTK provides a stub implementation because most classes - * do not make use of this information. - * - * @param aTitle The job title. - */ - virtual void SetJobTitle(const PRUnichar *aTitle) { } - - /** - * 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. - */ - nsresult GetSpoolFile(nsILocalFile **aFile); - - /** - * 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 - * Other values indicate failure of the print operation. - */ - virtual nsresult Submit() = 0; - -protected: - /** - * Initialize an object from a device context spec. This must be - * 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 mSpoolFile; -}; - - -#endif /* nsIPrintJobGTK_h__ */ diff --git a/widget/src/gtk2/nsPrintDialogGTK.cpp b/widget/src/gtk2/nsPrintDialogGTK.cpp new file mode 100644 index 000000000000..fb5ff790a28a --- /dev/null +++ b/widget/src/gtk2/nsPrintDialogGTK.cpp @@ -0,0 +1,561 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** 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 the Mozilla GTK2 print dialog interface. + * + * The Initial Developer of the Original Code is + * Kenneth Herron + * Portions created by the Initial Developer are Copyright (C) 2007 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Michael Ventnor + * + * 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 +#include +#include + +#include "mozcontainer.h" +#include "nsAccessibilityHelper.h" +#include "nsIPrintSettings.h" +#include "nsIWidget.h" +#include "nsPrintDialogGTK.h" +#include "nsPrintSettingsGTK.h" +#include "nsString.h" +#include "nsReadableUtils.h" +#include "nsILocalFile.h" +#include "nsNetUtil.h" +#include "nsIStringBundle.h" +#include "nsIPrintSettingsService.h" + +static const char header_footer_tags[][4] = {"", "&T", "&U", "&D", "&P", "&PT"}; + +#define CUSTOM_VALUE_INDEX NS_ARRAY_LENGTH(header_footer_tags) + +static void +ShowCustomDialog(GtkComboBox *changed_box, gpointer user_data) +{ + if (gtk_combo_box_get_active(changed_box) != CUSTOM_VALUE_INDEX) + return; + + nsCOMPtr bundleSvc = + do_GetService(NS_STRINGBUNDLE_CONTRACTID); + + nsCOMPtr printBundle; + bundleSvc->CreateBundle("chrome://global/locale/gnomeprintdialog.properties", getter_AddRefs(printBundle)); + nsXPIDLString intlString; + + printBundle->GetStringFromName(NS_LITERAL_STRING("headerFooterCustom").get(), getter_Copies(intlString)); + GtkWidget* prompt_dialog = gtk_dialog_new_with_buttons(NS_ConvertUTF16toUTF8(intlString).get(), NULL, + GTK_DIALOG_MODAL, + GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, + GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT, + NULL); + + printBundle->GetStringFromName(NS_LITERAL_STRING("customHeaderFooterPrompt").get(), getter_Copies(intlString)); + GtkWidget* custom_label = gtk_label_new(NS_ConvertUTF16toUTF8(intlString).get()); + GtkWidget* custom_entry = gtk_entry_new(); + GtkWidget* question_icon = gtk_image_new_from_stock(GTK_STOCK_DIALOG_QUESTION, GTK_ICON_SIZE_DIALOG); + + // To be convenient, prefill the textbox with the existing value, if any, and select it all so they can easily + // both edit it and type in a new one. + const char* current_text = (const char*) g_object_get_data(G_OBJECT(changed_box), "custom-text"); + if (current_text) { + gtk_entry_set_text(GTK_ENTRY(custom_entry), current_text); + gtk_editable_select_region(GTK_EDITABLE(custom_entry), 0, -1); + } + + GtkWidget* custom_vbox = gtk_vbox_new(TRUE, 2); + gtk_box_pack_start(GTK_BOX(custom_vbox), custom_label, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(custom_vbox), custom_entry, FALSE, FALSE, 5); // Make entry 5px underneath label + GtkWidget* custom_hbox = gtk_hbox_new(FALSE, 2); + gtk_box_pack_start(GTK_BOX(custom_hbox), question_icon, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(custom_hbox), custom_vbox, FALSE, FALSE, 10); // Make question icon 10px away from content + gtk_container_set_border_width(GTK_CONTAINER(custom_hbox), 2); + gtk_widget_show_all(custom_hbox); + + gtk_box_pack_start(GTK_BOX(GTK_DIALOG(prompt_dialog)->vbox), custom_hbox, FALSE, FALSE, 0); + gint diag_response = gtk_dialog_run(GTK_DIALOG(prompt_dialog)); + + if (diag_response == GTK_RESPONSE_ACCEPT) { + const gchar* response_text = gtk_entry_get_text(GTK_ENTRY(custom_entry)); + g_object_set_data_full(G_OBJECT(changed_box), "custom-text", strdup(response_text), (GDestroyNotify) free); + } else { + // XXX I wish there was a way to be smarter than this... but at least we were smarter than before + // where the dropdown stayed on Custom... even after clicking Cancel. + gtk_combo_box_set_active(changed_box, 0); + } + + gtk_widget_destroy(prompt_dialog); +} + +class nsPrintDialogWidgetGTK { + public: + nsPrintDialogWidgetGTK(nsIPrintSettings *aPrintSettings); + ~nsPrintDialogWidgetGTK() { gtk_widget_destroy(dialog); } + NS_ConvertUTF16toUTF8 GetUTF8FromBundle(const char* aKey); + const gint Run(); + + nsresult ImportSettings(nsIPrintSettings *aNSSettings); + nsresult ExportSettings(nsIPrintSettings *aNSSettings); + + private: + GtkWidget* dialog; + GtkWidget* radio_as_laid_out; + GtkWidget* radio_selected_frame; + GtkWidget* radio_separate_frames; + GtkWidget* shrink_to_fit_toggle; + GtkWidget* print_bg_colors_toggle; + GtkWidget* print_bg_images_toggle; + GtkWidget* selection_only_toggle; + GtkWidget* header_dropdown[3]; // {left, center, right} + GtkWidget* footer_dropdown[3]; + + nsCOMPtr printBundle; + + GtkWidget* ConstructHeaderFooterDropdown(const PRUnichar *currentString); + const char* OptionWidgetToString(GtkWidget *dropdown); + + /* Code to copy between GTK and NS print settings structures. + * In the following, + * "Import" means to copy from NS to GTK + * "Export" means to copy from GTK to NS + */ + void ExportFramePrinting(nsIPrintSettings *aNS, GtkPrintSettings *aSettings); + void ExportHeaderFooter(nsIPrintSettings *aNS); +}; + +nsPrintDialogWidgetGTK::nsPrintDialogWidgetGTK(nsIPrintSettings *aSettings) +{ + nsCOMPtr bundleSvc = do_GetService(NS_STRINGBUNDLE_CONTRACTID); + bundleSvc->CreateBundle("chrome://global/locale/gnomeprintdialog.properties", getter_AddRefs(printBundle)); + + dialog = gtk_print_unix_dialog_new(GetUTF8FromBundle("printTitle").get(), NULL); + + gtk_print_unix_dialog_set_manual_capabilities(GTK_PRINT_UNIX_DIALOG(dialog), + GtkPrintCapabilities( + GTK_PRINT_CAPABILITY_PAGE_SET + | GTK_PRINT_CAPABILITY_COPIES + | GTK_PRINT_CAPABILITY_COLLATE + | GTK_PRINT_CAPABILITY_REVERSE + | GTK_PRINT_CAPABILITY_SCALE + ) + ); + + // The vast majority of magic numbers in this widget construction are padding. e.g. for + // the set_border_width below, 12px matches that of just about every other window. + GtkWidget* custom_options_tab = gtk_vbox_new(FALSE, 0); + gtk_container_set_border_width(GTK_CONTAINER(custom_options_tab), 12); + GtkWidget* tab_label = gtk_label_new(GetUTF8FromBundle("optionsTabLabel").get()); + + PRInt16 frameUIFlag; + aSettings->GetHowToEnableFrameUI(&frameUIFlag); + radio_as_laid_out = gtk_radio_button_new_with_mnemonic(NULL, GetUTF8FromBundle("asLaidOut").get()); + if (frameUIFlag == nsIPrintSettings::kFrameEnableNone) + gtk_widget_set_sensitive(radio_as_laid_out, FALSE); + + radio_selected_frame = gtk_radio_button_new_with_mnemonic_from_widget(GTK_RADIO_BUTTON(radio_as_laid_out), + GetUTF8FromBundle("selectedFrame").get()); + if (frameUIFlag == nsIPrintSettings::kFrameEnableNone || + frameUIFlag == nsIPrintSettings::kFrameEnableAsIsAndEach) + gtk_widget_set_sensitive(radio_selected_frame, FALSE); + + radio_separate_frames = gtk_radio_button_new_with_mnemonic_from_widget(GTK_RADIO_BUTTON(radio_as_laid_out), + GetUTF8FromBundle("separateFrames").get()); + if (frameUIFlag == nsIPrintSettings::kFrameEnableNone) + gtk_widget_set_sensitive(radio_separate_frames, FALSE); + + // "Print Frames" options label, bold and center-aligned + GtkWidget* print_frames_label = gtk_label_new(NULL); + char* pangoMarkup = g_markup_printf_escaped("%s", GetUTF8FromBundle("printFramesTitle").get()); + gtk_label_set_markup(GTK_LABEL(print_frames_label), pangoMarkup); + g_free(pangoMarkup); + gtk_misc_set_alignment(GTK_MISC(print_frames_label), 0, 0); + + // Align the radio buttons slightly so they appear to fall under the aforementioned label as per the GNOME HIG + GtkWidget* frames_radio_container = gtk_alignment_new(0, 0, 0, 0); + gtk_alignment_set_padding(GTK_ALIGNMENT(frames_radio_container), 8, 0, 12, 0); + + // Radio buttons for the print frames options + GtkWidget* frames_radio_list = gtk_vbox_new(TRUE, 2); + gtk_box_pack_start(GTK_BOX(frames_radio_list), radio_as_laid_out, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(frames_radio_list), radio_selected_frame, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(frames_radio_list), radio_separate_frames, FALSE, FALSE, 0); + gtk_container_add(GTK_CONTAINER(frames_radio_container), frames_radio_list); + + // Check buttons for shrink-to-fit and print selection + GtkWidget* check_buttons_container = gtk_vbox_new(TRUE, 2); + shrink_to_fit_toggle = gtk_check_button_new_with_mnemonic(GetUTF8FromBundle("shrinkToFit").get()); + selection_only_toggle = gtk_check_button_new_with_mnemonic(GetUTF8FromBundle("selectionOnly").get()); + PRBool canSelectText; + aSettings->GetPrintOptions(nsIPrintSettings::kEnableSelectionRB, &canSelectText); + if (!canSelectText) + gtk_widget_set_sensitive(selection_only_toggle, FALSE); + + gtk_box_pack_start(GTK_BOX(check_buttons_container), shrink_to_fit_toggle, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(check_buttons_container), selection_only_toggle, FALSE, FALSE, 0); + + // Check buttons for printing background + GtkWidget* appearance_buttons_container = gtk_vbox_new(TRUE, 2); + print_bg_colors_toggle = gtk_check_button_new_with_mnemonic(GetUTF8FromBundle("printBGColors").get()); + print_bg_images_toggle = gtk_check_button_new_with_mnemonic(GetUTF8FromBundle("printBGImages").get()); + gtk_box_pack_start(GTK_BOX(appearance_buttons_container), print_bg_colors_toggle, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(appearance_buttons_container), print_bg_images_toggle, FALSE, FALSE, 0); + + // "Appearance" options label, bold and center-aligned + GtkWidget* appearance_label = gtk_label_new(NULL); + pangoMarkup = g_markup_printf_escaped("%s", GetUTF8FromBundle("printBGOptions").get()); + gtk_label_set_markup(GTK_LABEL(appearance_label), pangoMarkup); + g_free(pangoMarkup); + gtk_misc_set_alignment(GTK_MISC(appearance_label), 0, 0); + + GtkWidget* appearance_container = gtk_alignment_new(0, 0, 0, 0); + gtk_alignment_set_padding(GTK_ALIGNMENT(appearance_container), 8, 0, 12, 0); + gtk_container_add(GTK_CONTAINER(appearance_container), appearance_buttons_container); + + GtkWidget* appearance_vertical_squasher = gtk_vbox_new(FALSE, 0); + gtk_box_pack_start(GTK_BOX(appearance_vertical_squasher), appearance_label, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(appearance_vertical_squasher), appearance_container, FALSE, FALSE, 0); + + // "Header & Footer" options label, bold and center-aligned + GtkWidget* header_footer_label = gtk_label_new(NULL); + pangoMarkup = g_markup_printf_escaped("%s", GetUTF8FromBundle("headerFooter").get()); + gtk_label_set_markup(GTK_LABEL(header_footer_label), pangoMarkup); + g_free(pangoMarkup); + gtk_misc_set_alignment(GTK_MISC(header_footer_label), 0, 0); + + GtkWidget* header_footer_container = gtk_alignment_new(0, 0, 0, 0); + gtk_alignment_set_padding(GTK_ALIGNMENT(header_footer_container), 8, 0, 12, 0); + + + // --- Table for making the header and footer options --- + GtkWidget* header_footer_table = gtk_table_new(3, 3, FALSE); // 3x3 table + nsXPIDLString header_footer_str[3]; + + aSettings->GetHeaderStrLeft(getter_Copies(header_footer_str[0])); + aSettings->GetHeaderStrCenter(getter_Copies(header_footer_str[1])); + aSettings->GetHeaderStrRight(getter_Copies(header_footer_str[2])); + + for (unsigned int i = 0; i < NS_ARRAY_LENGTH(header_dropdown); i++) { + header_dropdown[i] = ConstructHeaderFooterDropdown(header_footer_str[i].get()); + // Those 4 magic numbers in the middle provide the position in the table. + // The last two numbers mean 2 px padding on every side. + gtk_table_attach(GTK_TABLE(header_footer_table), header_dropdown[i], i, (i + 1), + 0, 1, (GtkAttachOptions) 0, (GtkAttachOptions) 0, 2, 2); + } + + const char labelKeys[][7] = {"left", "center", "right"}; + for (unsigned int i = 0; i < NS_ARRAY_LENGTH(labelKeys); i++) { + gtk_table_attach(GTK_TABLE(header_footer_table), + gtk_label_new(GetUTF8FromBundle(labelKeys[i]).get()), + i, (i + 1), 1, 2, (GtkAttachOptions) 0, (GtkAttachOptions) 0, 2, 2); + } + + aSettings->GetFooterStrLeft(getter_Copies(header_footer_str[0])); + aSettings->GetFooterStrCenter(getter_Copies(header_footer_str[1])); + aSettings->GetFooterStrRight(getter_Copies(header_footer_str[2])); + + for (unsigned int i = 0; i < NS_ARRAY_LENGTH(footer_dropdown); i++) { + footer_dropdown[i] = ConstructHeaderFooterDropdown(header_footer_str[i].get()); + gtk_table_attach(GTK_TABLE(header_footer_table), footer_dropdown[i], i, (i + 1), + 2, 3, (GtkAttachOptions) 0, (GtkAttachOptions) 0, 2, 2); + } + // --- + + gtk_container_add(GTK_CONTAINER(header_footer_container), header_footer_table); + + GtkWidget* header_footer_vertical_squasher = gtk_vbox_new(FALSE, 0); + gtk_box_pack_start(GTK_BOX(header_footer_vertical_squasher), header_footer_label, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(header_footer_vertical_squasher), header_footer_container, FALSE, FALSE, 0); + + // Construction of everything + gtk_box_pack_start(GTK_BOX(custom_options_tab), print_frames_label, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(custom_options_tab), frames_radio_container, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(custom_options_tab), check_buttons_container, FALSE, FALSE, 10); // 10px padding + gtk_box_pack_start(GTK_BOX(custom_options_tab), appearance_vertical_squasher, FALSE, FALSE, 10); + gtk_box_pack_start(GTK_BOX(custom_options_tab), header_footer_vertical_squasher, FALSE, FALSE, 0); + + gtk_print_unix_dialog_add_custom_tab(GTK_PRINT_UNIX_DIALOG(dialog), custom_options_tab, tab_label); + gtk_widget_show_all(custom_options_tab); +} + +NS_ConvertUTF16toUTF8 +nsPrintDialogWidgetGTK::GetUTF8FromBundle(const char *aKey) +{ + nsXPIDLString intlString; + printBundle->GetStringFromName(NS_ConvertUTF8toUTF16(aKey).get(), getter_Copies(intlString)); + return NS_ConvertUTF16toUTF8(intlString); // Return the actual object so we don't lose reference +} + +const char* +nsPrintDialogWidgetGTK::OptionWidgetToString(GtkWidget *dropdown) +{ + gint index = gtk_combo_box_get_active(GTK_COMBO_BOX(dropdown)); + + NS_ASSERTION(index <= CUSTOM_VALUE_INDEX, "Index of dropdown is higher than expected!"); + + if (index == CUSTOM_VALUE_INDEX) + return (const char*) g_object_get_data(G_OBJECT(dropdown), "custom-text"); + else + return header_footer_tags[index]; +} + +const gint +nsPrintDialogWidgetGTK::Run() +{ + const gint response = RunDialog(GTK_DIALOG(dialog)); + gtk_widget_hide(dialog); + return response; +} + +void +nsPrintDialogWidgetGTK::ExportFramePrinting(nsIPrintSettings *aNS, GtkPrintSettings *aSettings) +{ + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(radio_as_laid_out))) + aNS->SetPrintFrameType(nsIPrintSettings::kFramesAsIs); + else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(radio_selected_frame))) + aNS->SetPrintFrameType(nsIPrintSettings::kSelectedFrame); + else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(radio_separate_frames))) + aNS->SetPrintFrameType(nsIPrintSettings::kEachFrameSep); + else + aNS->SetPrintFrameType(nsIPrintSettings::kNoFrames); +} + +void +nsPrintDialogWidgetGTK::ExportHeaderFooter(nsIPrintSettings *aNS) +{ + const char* header_footer_str; + header_footer_str = OptionWidgetToString(header_dropdown[0]); + aNS->SetHeaderStrLeft(NS_ConvertUTF8toUTF16(header_footer_str).get()); + + header_footer_str = OptionWidgetToString(header_dropdown[1]); + aNS->SetHeaderStrCenter(NS_ConvertUTF8toUTF16(header_footer_str).get()); + + header_footer_str = OptionWidgetToString(header_dropdown[2]); + aNS->SetHeaderStrRight(NS_ConvertUTF8toUTF16(header_footer_str).get()); + + header_footer_str = OptionWidgetToString(footer_dropdown[0]); + aNS->SetFooterStrLeft(NS_ConvertUTF8toUTF16(header_footer_str).get()); + + header_footer_str = OptionWidgetToString(footer_dropdown[1]); + aNS->SetFooterStrCenter(NS_ConvertUTF8toUTF16(header_footer_str).get()); + + header_footer_str = OptionWidgetToString(footer_dropdown[2]); + aNS->SetFooterStrRight(NS_ConvertUTF8toUTF16(header_footer_str).get()); +} + +nsresult +nsPrintDialogWidgetGTK::ImportSettings(nsIPrintSettings *aNSSettings) +{ + NS_PRECONDITION(aNSSettings, "aSettings must not be null"); + NS_ENSURE_TRUE(aNSSettings, NS_ERROR_FAILURE); + + nsCOMPtr aNSSettingsGTK(do_QueryInterface(aNSSettings)); + if (!aNSSettingsGTK) + return NS_ERROR_FAILURE; + + GtkPrintSettings* settings = aNSSettingsGTK->GetGtkPrintSettings(); + GtkPageSetup* setup = aNSSettingsGTK->GetGtkPageSetup(); + + PRBool geckoBool; + aNSSettings->GetShrinkToFit(&geckoBool); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(shrink_to_fit_toggle), geckoBool); + + aNSSettings->GetPrintBGColors(&geckoBool); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(print_bg_colors_toggle), geckoBool); + + aNSSettings->GetPrintBGImages(&geckoBool); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(print_bg_images_toggle), geckoBool); + + gtk_print_unix_dialog_set_settings(GTK_PRINT_UNIX_DIALOG(dialog), settings); + gtk_print_unix_dialog_set_page_setup(GTK_PRINT_UNIX_DIALOG(dialog), setup); + + return NS_OK; +} + +nsresult +nsPrintDialogWidgetGTK::ExportSettings(nsIPrintSettings *aNSSettings) +{ + NS_PRECONDITION(aNSSettings, "aSettings must not be null"); + NS_ENSURE_TRUE(aNSSettings, NS_ERROR_FAILURE); + + GtkPrintSettings* settings = gtk_print_unix_dialog_get_settings(GTK_PRINT_UNIX_DIALOG(dialog)); + GtkPageSetup* setup = gtk_print_unix_dialog_get_page_setup(GTK_PRINT_UNIX_DIALOG(dialog)); + GtkPrinter* printer = gtk_print_unix_dialog_get_selected_printer(GTK_PRINT_UNIX_DIALOG(dialog)); + if (settings && setup && printer) { + ExportFramePrinting(aNSSettings, settings); + ExportHeaderFooter(aNSSettings); + + aNSSettings->SetOutputFormat(nsIPrintSettings::kOutputFormatNative); + + // Print-to-file is true by default. This must be turned off or else printing won't occur! + // (We manually copy the spool file when this flag is set, because we love our embedders) + // Even if it is print-to-file in GTK's case, GTK does The Right Thing when we send the job. + aNSSettings->SetPrintToFile(PR_FALSE); + + aNSSettings->SetShrinkToFit(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(shrink_to_fit_toggle))); + + aNSSettings->SetPrintBGColors(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(print_bg_colors_toggle))); + aNSSettings->SetPrintBGImages(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(print_bg_images_toggle))); + + // Try to save native settings in the session object + nsCOMPtr aNSSettingsGTK(do_QueryInterface(aNSSettings)); + if (aNSSettingsGTK) { + aNSSettingsGTK->SetGtkPrintSettings(settings); + aNSSettingsGTK->SetGtkPageSetup(setup); + aNSSettingsGTK->SetGtkPrinter(printer); + aNSSettingsGTK->SetForcePrintSelectionOnly(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(selection_only_toggle))); + } + } + + if (settings) + g_object_unref(settings); + return NS_OK; +} + +GtkWidget* +nsPrintDialogWidgetGTK::ConstructHeaderFooterDropdown(const PRUnichar *currentString) +{ + GtkWidget* dropdown = gtk_combo_box_new_text(); + const char hf_options[][22] = {"headerFooterBlank", "headerFooterTitle", + "headerFooterURL", "headerFooterDate", + "headerFooterPage", "headerFooterPageTotal", + "headerFooterCustom"}; + + for (unsigned int i = 0; i < NS_ARRAY_LENGTH(hf_options); i++) { + gtk_combo_box_append_text(GTK_COMBO_BOX(dropdown), GetUTF8FromBundle(hf_options[i]).get()); + } + + PRPackedBool shouldBeCustom = PR_TRUE; + NS_ConvertUTF16toUTF8 currentStringUTF8(currentString); + + for (unsigned int i = 0; i < NS_ARRAY_LENGTH(header_footer_tags); i++) { + if (!strcmp(currentStringUTF8.get(), header_footer_tags[i])) { + gtk_combo_box_set_active(GTK_COMBO_BOX(dropdown), i); + shouldBeCustom = PR_FALSE; + break; + } + } + + if (shouldBeCustom) { + gtk_combo_box_set_active(GTK_COMBO_BOX(dropdown), CUSTOM_VALUE_INDEX); + char* custom_string = strdup(currentStringUTF8.get()); + g_object_set_data_full(G_OBJECT(dropdown), "custom-text", custom_string, (GDestroyNotify) free); + } + + g_signal_connect(dropdown, "changed", (GCallback) ShowCustomDialog, NULL); + return dropdown; +} + +NS_IMPL_ISUPPORTS1(nsPrintDialogServiceGTK, nsIPrintDialogService) + +nsPrintDialogServiceGTK::nsPrintDialogServiceGTK() +{ +} + +nsPrintDialogServiceGTK::~nsPrintDialogServiceGTK() +{ +} + +NS_IMETHODIMP +nsPrintDialogServiceGTK::Init() +{ + return NS_OK; +} + +NS_IMETHODIMP +nsPrintDialogServiceGTK::Show(nsIPrintSettings *aSettings) +{ + NS_PRECONDITION(aSettings, "aSettings must not be null"); + + nsPrintDialogWidgetGTK printDialog(aSettings); + nsresult rv = printDialog.ImportSettings(aSettings); + + NS_ENSURE_SUCCESS(rv, rv); + + const gint response = printDialog.Run(); + + // Handle the result + switch (response) { + case GTK_RESPONSE_OK: // Proceed + rv = printDialog.ExportSettings(aSettings); + break; + + case GTK_RESPONSE_CANCEL: + case GTK_RESPONSE_CLOSE: + case GTK_RESPONSE_DELETE_EVENT: + case GTK_RESPONSE_NONE: + rv = NS_ERROR_ABORT; + break; + + case GTK_RESPONSE_APPLY: // Print preview + default: + NS_WARNING("Unexpected response"); + rv = NS_ERROR_ABORT; + } + return rv; +} + +NS_IMETHODIMP +nsPrintDialogServiceGTK::ShowPageSetup(nsIPrintSettings *aNSSettings) +{ + NS_PRECONDITION(aNSSettings, "aSettings must not be null"); + NS_ENSURE_TRUE(aNSSettings, NS_ERROR_FAILURE); + + nsCOMPtr aNSSettingsGTK(do_QueryInterface(aNSSettings)); + if (!aNSSettingsGTK) + return NS_ERROR_FAILURE; + + // We need to init the prefs here because aNSSettings in its current form is a dummy in both uses of the word + nsCOMPtr psService = do_GetService("@mozilla.org/gfx/printsettings-service;1"); + if (psService) { + nsXPIDLString printName; + aNSSettings->GetPrinterName(getter_Copies(printName)); + if (!printName) { + psService->GetDefaultPrinterName(getter_Copies(printName)); + aNSSettings->SetPrinterName(printName.get()); + } + psService->InitPrintSettingsFromPrefs(aNSSettings, PR_TRUE, nsIPrintSettings::kInitSaveAll); + } + + GtkPrintSettings* gtkSettings = aNSSettingsGTK->GetGtkPrintSettings(); + GtkPageSetup* oldPageSetup = aNSSettingsGTK->GetGtkPageSetup(); + + GtkPageSetup* newPageSetup = gtk_print_run_page_setup_dialog(NULL, oldPageSetup, gtkSettings); + + aNSSettingsGTK->SetGtkPageSetup(newPageSetup); + + // Now newPageSetup has a refcount of 2 (SetGtkPageSetup will addref), put it to 1 so if + // this gets replaced we don't leak. + g_object_unref(newPageSetup); + + if (psService) + psService->SavePrintSettingsToPrefs(aNSSettings, PR_TRUE, nsIPrintSettings::kInitSaveAll); + + return NS_OK; +} diff --git a/widget/src/gtk2/nsPrintJobFactoryGTK.h b/widget/src/gtk2/nsPrintDialogGTK.h similarity index 57% rename from widget/src/gtk2/nsPrintJobFactoryGTK.h rename to widget/src/gtk2/nsPrintDialogGTK.h index 237c5acd35ec..1c2ec22a00b0 100644 --- a/widget/src/gtk2/nsPrintJobFactoryGTK.h +++ b/widget/src/gtk2/nsPrintDialogGTK.h @@ -1,5 +1,4 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* ex: set tabstop=8 softtabstop=4 shiftwidth=4 expandtab: */ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * @@ -13,11 +12,11 @@ * for the specific language governing rights and limitations under the * License. * - * The Original Code is mozilla.org code. + * The Original Code is the Mozilla GTK2 print dialog interface. * * The Initial Developer of the Original Code is - * Kenneth Herron . - * Portions created by the Initial Developer are Copyright (C) 2004 + * Kenneth Herron + * Portions created by the Initial Developer are Copyright (C) 2007 * the Initial Developer. All Rights Reserved. * * Contributor(s): @@ -36,35 +35,24 @@ * * ***** END LICENSE BLOCK ***** */ -#ifndef nsPrintJobFactoryGTK_h__ -#define nsPrintJobFactoryGTK_h__ +#ifndef nsPrintDialog_h__ +#define nsPrintDialog_h__ -class nsIPrintJobGTK; -class nsDeviceContextSpecGTK; +#include "nsIPrintDialogService.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 nsIPrintSettings; - -class nsPrintJobFactoryGTK +class nsPrintDialogServiceGTK : public nsIPrintDialogService { 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); + nsPrintDialogServiceGTK(); + virtual ~nsPrintDialogServiceGTK(); + + NS_DECL_ISUPPORTS + + NS_IMETHODIMP Init(); + NS_IMETHODIMP Show(nsIPrintSettings *aSettings); + NS_IMETHODIMP ShowPageSetup(nsIPrintSettings *aSettings); }; - -#endif /* nsPrintJobFactoryGTK_h__ */ +#endif diff --git a/widget/src/gtk2/nsPrintJobFactoryGTK.cpp b/widget/src/gtk2/nsPrintJobFactoryGTK.cpp deleted file mode 100644 index 5f6053927d88..000000000000 --- a/widget/src/gtk2/nsPrintJobFactoryGTK.cpp +++ /dev/null @@ -1,93 +0,0 @@ -/* -*- 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 . - * 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; -} diff --git a/widget/src/gtk2/nsPrintJobGTK.cpp b/widget/src/gtk2/nsPrintJobGTK.cpp deleted file mode 100644 index 9cacc39ed36a..000000000000 --- a/widget/src/gtk2/nsPrintJobGTK.cpp +++ /dev/null @@ -1,481 +0,0 @@ -/* -*- 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 . - * 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 "nsIDeviceContextSpec.h" -#include "nsDeviceContextSpecG.h" - -#include "nsPrintJobGTK.h" -#include "nsPSPrinters.h" -#include "nsReadableUtils.h" -#include "nsDirectoryServiceDefs.h" -#include "nsIFileStreams.h" - -#include "prenv.h" -#include "prinit.h" -#include "prlock.h" -#include "prprf.h" - -#include -#include -#include - - -/* Routines to set environment variables. These are defined toward - * the end of this file. - */ -static PRStatus EnvLock(); -static PRStatus EnvSetPrinter(nsCString&); -static void EnvClear(); - - -/* 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 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 ****/ - -/** - * 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 - - // The final output file will inherit the permissions of the temporary. - nsresult rv = InitSpoolFile(0666); - if (NS_SUCCEEDED(rv)) { - const char *path; - aSpec->GetPath(&path); - rv = NS_NewNativeLocalFile(nsDependentCString(path), PR_FALSE, - getter_AddRefs(mDestFile)); - } - return rv; -} - -nsresult -nsPrintJobFileGTK::Submit() -{ - // Move the spool file to the destination - nsAutoString destLeafName; - nsresult rv = mDestFile->GetLeafName(destLeafName); - if (NS_SUCCEEDED(rv)) { - nsCOMPtr mDestDir; - rv = mDestFile->GetParent(getter_AddRefs(mDestDir)); - if (NS_SUCCEEDED(rv)) { - rv = mSpoolFile->MoveTo(mDestDir, destLeafName); - } - } - return rv; -} - -/**** Print-to-Pipe for unix and unix-like systems ****/ - -/* This launches a command using popen(); the print job is then written - * to the pipe. - */ - -/** - * 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 - - /* Spool file */ - nsresult rv = InitSpoolFile(0600); - if (NS_FAILED(rv)) - return rv; - - /* Print command */ - const char *command; - aSpec->GetCommand(&command); - mCommand = 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; -} - - -/* 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::Submit() -{ - NS_PRECONDITION(mSpoolFile, "No spool file"); - - // Open the spool file - nsCOMPtr 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 = NULL; - 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. - */ -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); - - /* 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; -} - -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 - * . - */ -void -nsPrintJobCUPS::SetJobTitle(const PRUnichar *aTitle) -{ - if (aTitle) { - LossyCopyUTF16toASCII(aTitle, mJobTitle); - } -} - -nsresult -nsPrintJobCUPS::Submit() -{ - NS_ENSURE_TRUE(mCups.IsInitialized(), NS_ERROR_NOT_INITIALIZED); - NS_PRECONDITION(!mSpoolName.IsEmpty(), "No spool file"); - - 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(), - mSpoolName.get(), title, - dest->num_options, dest->options); - } - (mCups.mCupsFreeDests)(num_dests, dests); - - // 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; -} - -/* 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); -} diff --git a/widget/src/gtk2/nsPrintJobGTK.h b/widget/src/gtk2/nsPrintJobGTK.h deleted file mode 100644 index 741658217668..000000000000 --- a/widget/src/gtk2/nsPrintJobGTK.h +++ /dev/null @@ -1,108 +0,0 @@ -/* -*- 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 . - * 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 "nsDeviceContextSpecG.h" - -/* Print job class for print preview operations. */ - -class nsPrintJobPreviewGTK : public nsIPrintJobGTK { - public: - /* see nsIPrintJobGTK.h. Print preview doesn't actually - * implement printing. - */ - virtual nsresult Submit() - { return NS_ERROR_GFX_PRINTING_NOT_IMPLEMENTED; } - - protected: - virtual nsresult Init(nsDeviceContextSpecGTK *); - nsresult InitSpoolFile(PRUint32 aPermissions); -}; - - -/* Print job class for print-to-file. */ -class nsPrintJobFileGTK : public nsPrintJobPreviewGTK { - public: - virtual nsresult Submit(); - - protected: - virtual nsresult Init(nsDeviceContextSpecGTK *); - nsCOMPtr mDestFile; -}; - -/* This is the class for printing to a pipe. */ -class nsPrintJobPipeGTK : public nsPrintJobPreviewGTK { - public: - virtual nsresult Submit(); - - protected: - virtual nsresult Init(nsDeviceContextSpecGTK *); - - private: - nsCString mCommand; - nsCString mPrinterName; -}; - - -/* This class submits print jobs through CUPS. */ -class nsPrintJobCUPS : public nsIPrintJobGTK { - public: - virtual nsresult Submit(); - virtual nsresult SetNumCopies(int aNumCopies); - virtual void SetJobTitle(const PRUnichar *aTitle); - - protected: - virtual nsresult Init(nsDeviceContextSpecGTK *); - - private: - nsCUPSShim mCups; - nsCString mPrinterName; - nsCString mNumCopies; - nsCString mJobTitle; // IsVoid() if no title - nsCString mSpoolName; -}; - -#endif /* nsPrintJobPS_h__ */ diff --git a/widget/src/gtk2/nsPrintOptionsGTK.cpp b/widget/src/gtk2/nsPrintOptionsGTK.cpp index 7ddf4877a037..63aa7407d488 100644 --- a/widget/src/gtk2/nsPrintOptionsGTK.cpp +++ b/widget/src/gtk2/nsPrintOptionsGTK.cpp @@ -35,7 +35,7 @@ * * ***** END LICENSE BLOCK ***** */ #include "nsPrintOptionsGTK.h" - +#include "nsPrintSettingsGTK.h" /** --------------------------------------------------- @@ -55,3 +55,16 @@ nsPrintOptionsGTK::~nsPrintOptionsGTK() { } +/* nsIPrintSettings CreatePrintSettings (); */ +nsresult nsPrintOptionsGTK::_CreatePrintSettings(nsIPrintSettings **_retval) +{ + *_retval = nsnull; + nsPrintSettingsGTK* printSettings = new nsPrintSettingsGTK(); // does not initially ref count + NS_ENSURE_TRUE(printSettings, NS_ERROR_OUT_OF_MEMORY); + + NS_ADDREF(*_retval = printSettings); // ref count + + return NS_OK; +} + + diff --git a/widget/src/gtk2/nsPrintOptionsGTK.h b/widget/src/gtk2/nsPrintOptionsGTK.h index 84b9a6ad6935..f357aab923eb 100644 --- a/widget/src/gtk2/nsPrintOptionsGTK.h +++ b/widget/src/gtk2/nsPrintOptionsGTK.h @@ -52,6 +52,7 @@ public: nsPrintOptionsGTK(); virtual ~nsPrintOptionsGTK(); + virtual nsresult _CreatePrintSettings(nsIPrintSettings **_retval); }; diff --git a/widget/src/gtk2/nsPrintSettingsGTK.cpp b/widget/src/gtk2/nsPrintSettingsGTK.cpp new file mode 100644 index 000000000000..9e456491be11 --- /dev/null +++ b/widget/src/gtk2/nsPrintSettingsGTK.cpp @@ -0,0 +1,732 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** 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 Mozilla Corporation. + * Portions created by the Initial Developer are Copyright (C) 2008 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Michael Ventnor + * + * Alternatively, the contents of this file may be used under the terms of + * either of 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 "nsPrintSettingsGTK.h" +#include "nsILocalFile.h" +#include "nsNetUtil.h" +#include + +static +gboolean ref_printer(GtkPrinter *aPrinter, gpointer aData) +{ + ((nsPrintSettingsGTK*) aData)->SetGtkPrinter(aPrinter); + return TRUE; +} + +static +gboolean printer_enumerator(GtkPrinter *aPrinter, gpointer aData) +{ + if (gtk_printer_is_default(aPrinter)) + return ref_printer(aPrinter, aData); + + return FALSE; // Keep 'em coming... +} + +static +GtkPaperSize* moz_gtk_paper_size_copy_to_new_custom(GtkPaperSize* oldPaperSize) +{ + // We make a "custom-ified" copy of the paper size so it can be changed later. + return gtk_paper_size_new_custom(gtk_paper_size_get_name(oldPaperSize), + gtk_paper_size_get_display_name(oldPaperSize), + gtk_paper_size_get_width(oldPaperSize, GTK_UNIT_INCH), + gtk_paper_size_get_height(oldPaperSize, GTK_UNIT_INCH), + GTK_UNIT_INCH); +} + +NS_IMPL_ISUPPORTS_INHERITED1(nsPrintSettingsGTK, + nsPrintSettings, + nsPrintSettingsGTK) + +/** --------------------------------------------------- + */ +nsPrintSettingsGTK::nsPrintSettingsGTK() : + mPageSetup(NULL), + mPrintSettings(NULL), + mGTKPrinter(NULL) +{ + // The aim here is to set up the objects enough that silent printing works well. + // These will be replaced anyway if the print dialog is used. + mPrintSettings = gtk_print_settings_new(); + mPageSetup = gtk_page_setup_new(); + + SetOutputFormat(nsIPrintSettings::kOutputFormatNative); + + GtkPaperSize* defaultPaperSize = gtk_paper_size_new(NULL); + mPaperSize = moz_gtk_paper_size_copy_to_new_custom(defaultPaperSize); + gtk_paper_size_free(defaultPaperSize); + SaveNewPageSize(); +} + +/** --------------------------------------------------- + */ +nsPrintSettingsGTK::~nsPrintSettingsGTK() +{ + if (mPageSetup) { + g_object_unref(mPageSetup); + mPageSetup = NULL; + } + if (mPrintSettings) { + g_object_unref(mPrintSettings); + mPrintSettings = NULL; + } + if (mGTKPrinter) { + g_object_unref(mGTKPrinter); + mGTKPrinter = NULL; + } + gtk_paper_size_free(mPaperSize); +} + +/** --------------------------------------------------- + */ +nsPrintSettingsGTK::nsPrintSettingsGTK(const nsPrintSettingsGTK& aPS) : + mPageSetup(NULL), + mPrintSettings(NULL), + mGTKPrinter(NULL), + mPrintSelectionOnly(PR_FALSE) +{ + *this = aPS; +} + +/** --------------------------------------------------- + */ +nsPrintSettingsGTK& nsPrintSettingsGTK::operator=(const nsPrintSettingsGTK& rhs) +{ + if (this == &rhs) { + return *this; + } + + nsPrintSettings::operator=(rhs); + + if (mPageSetup) + g_object_unref(mPageSetup); + mPageSetup = gtk_page_setup_copy(rhs.mPageSetup); + + if (mPrintSettings) + g_object_unref(mPrintSettings); + mPrintSettings = gtk_print_settings_copy(rhs.mPrintSettings); + + if (mGTKPrinter) + g_object_unref(mGTKPrinter); + mGTKPrinter = (GtkPrinter*) g_object_ref(rhs.mGTKPrinter); + + mPrintSelectionOnly = rhs.mPrintSelectionOnly; + + return *this; +} + +/** ------------------------------------------- + */ +nsresult nsPrintSettingsGTK::_Clone(nsIPrintSettings **_retval) +{ + NS_ENSURE_ARG_POINTER(_retval); + *_retval = nsnull; + + nsPrintSettingsGTK *newSettings = new nsPrintSettingsGTK(*this); + if (!newSettings) + return NS_ERROR_FAILURE; + *_retval = newSettings; + NS_ADDREF(*_retval); + return NS_OK; +} + + +/** ------------------------------------------- + */ +NS_IMETHODIMP +nsPrintSettingsGTK::_Assign(nsIPrintSettings *aPS) +{ + nsPrintSettingsGTK *printSettingsGTK = static_cast(aPS); + if (!printSettingsGTK) + return NS_ERROR_UNEXPECTED; + *this = *printSettingsGTK; + return NS_OK; +} + +/** --------------------------------------------------- + */ +void +nsPrintSettingsGTK::SetGtkPageSetup(GtkPageSetup *aPageSetup) +{ + if (mPageSetup) + g_object_unref(mPageSetup); + + mPageSetup = (GtkPageSetup*) g_object_ref(aPageSetup); + + // We make a custom copy of the GtkPaperSize so it can be mutable. If a + // GtkPaperSize wasn't made as custom, its properties are immutable. + GtkPaperSize* newPaperSize = gtk_page_setup_get_paper_size(aPageSetup); + if (newPaperSize) { // Yes, this can be null + gtk_paper_size_free(mPaperSize); + mPaperSize = moz_gtk_paper_size_copy_to_new_custom(newPaperSize); + } + // If newPaperSize was not null, we must update our twin too (GtkPrintSettings). + // If newPaperSize was null, we must set this object to use mPaperSize. + SaveNewPageSize(); +} + +/** --------------------------------------------------- + */ +void +nsPrintSettingsGTK::SetGtkPrintSettings(GtkPrintSettings *aPrintSettings) +{ + if (mPrintSettings) + g_object_unref(mPrintSettings); + + mPrintSettings = (GtkPrintSettings*) g_object_ref(aPrintSettings); + + GtkPaperSize* newPaperSize = gtk_print_settings_get_paper_size(aPrintSettings); + if (newPaperSize) { + gtk_paper_size_free(mPaperSize); + mPaperSize = moz_gtk_paper_size_copy_to_new_custom(newPaperSize); + } + SaveNewPageSize(); +} + +/** --------------------------------------------------- + */ +void +nsPrintSettingsGTK::SetGtkPrinter(GtkPrinter *aPrinter) +{ + if (mGTKPrinter) + g_object_unref(mGTKPrinter); + + mGTKPrinter = (GtkPrinter*) g_object_ref(aPrinter); +} + +/** + * Reimplementation of nsPrintSettings functions so that we get the values + * from the GTK objects rather than our own variables. + */ + +/* attribute long printRange; */ +NS_IMETHODIMP nsPrintSettingsGTK::GetPrintRange(PRInt16 *aPrintRange) +{ + NS_ENSURE_ARG_POINTER(aPrintRange); + if (mPrintSelectionOnly) { + *aPrintRange = kRangeSelection; + return NS_OK; + } + + GtkPrintPages gtkRange = gtk_print_settings_get_print_pages(mPrintSettings); + if (gtkRange == GTK_PRINT_PAGES_RANGES) + *aPrintRange = kRangeSpecifiedPageRange; + else + *aPrintRange = kRangeAllPages; + + return NS_OK; +} +NS_IMETHODIMP nsPrintSettingsGTK::SetPrintRange(PRInt16 aPrintRange) +{ + if (aPrintRange == kRangeSelection) { + mPrintSelectionOnly = PR_TRUE; + return NS_OK; + } + + mPrintSelectionOnly = PR_FALSE; + if (aPrintRange == kRangeSpecifiedPageRange) + gtk_print_settings_set_print_pages(mPrintSettings, GTK_PRINT_PAGES_RANGES); + else + gtk_print_settings_set_print_pages(mPrintSettings, GTK_PRINT_PAGES_ALL); + return NS_OK; +} + +/* attribute long startPageRange; */ +NS_IMETHODIMP +nsPrintSettingsGTK::GetStartPageRange(PRInt32 *aStartPageRange) +{ + gint ctRanges; + GtkPageRange* lstRanges = gtk_print_settings_get_page_ranges(mPrintSettings, &ctRanges); + + // Make sure we got a range. + if (ctRanges < 1) { + *aStartPageRange = 1; + } else { + // GTK supports multiple page ranges; gecko only supports 1. So find + // the lowest start page. + PRInt32 start(lstRanges[0].start); + for (gint ii = 1; ii < ctRanges; ii++) { + start = PR_MIN(lstRanges[ii].start, start); + } + *aStartPageRange = start + 1; + } + + g_free(lstRanges); + return NS_OK; +} +NS_IMETHODIMP +nsPrintSettingsGTK::SetStartPageRange(PRInt32 aStartPageRange) +{ + PRInt32 endRange; + GetEndPageRange(&endRange); + + GtkPageRange gtkRange; + gtkRange.start = aStartPageRange - 1; + gtkRange.end = endRange - 1; + + gtk_print_settings_set_page_ranges(mPrintSettings, >kRange, 1); + + return NS_OK; +} + +/* attribute long endPageRange; */ +NS_IMETHODIMP +nsPrintSettingsGTK::GetEndPageRange(PRInt32 *aEndPageRange) +{ + gint ctRanges; + GtkPageRange* lstRanges = gtk_print_settings_get_page_ranges(mPrintSettings, &ctRanges); + + if (ctRanges < 1) { + *aEndPageRange = 1; + } else { + PRInt32 end(lstRanges[0].end); + for (gint ii = 1; ii < ctRanges; ii++) { + end = PR_MAX(lstRanges[ii].end, end); + } + *aEndPageRange = end + 1; + } + + g_free(lstRanges); + return NS_OK; +} +NS_IMETHODIMP +nsPrintSettingsGTK::SetEndPageRange(PRInt32 aEndPageRange) +{ + PRInt32 startRange; + GetStartPageRange(&startRange); + + GtkPageRange gtkRange; + gtkRange.start = startRange - 1; + gtkRange.end = aEndPageRange - 1; + + gtk_print_settings_set_page_ranges(mPrintSettings, >kRange, 1); + + return NS_OK; +} + +/* attribute boolean printReversed; */ +NS_IMETHODIMP +nsPrintSettingsGTK::GetPrintReversed(PRBool *aPrintReversed) +{ + *aPrintReversed = gtk_print_settings_get_reverse(mPrintSettings); + return NS_OK; +} +NS_IMETHODIMP +nsPrintSettingsGTK::SetPrintReversed(PRBool aPrintReversed) +{ + gtk_print_settings_set_reverse(mPrintSettings, aPrintReversed); + return NS_OK; +} + +/* attribute boolean printInColor; */ +NS_IMETHODIMP +nsPrintSettingsGTK::GetPrintInColor(PRBool *aPrintInColor) +{ + *aPrintInColor = gtk_print_settings_get_use_color(mPrintSettings); + return NS_OK; +} +NS_IMETHODIMP +nsPrintSettingsGTK::SetPrintInColor(PRBool aPrintInColor) +{ + gtk_print_settings_set_use_color(mPrintSettings, aPrintInColor); + return NS_OK; +} + +/* attribute short orientation; */ +NS_IMETHODIMP +nsPrintSettingsGTK::GetOrientation(PRInt32 *aOrientation) +{ + NS_ENSURE_ARG_POINTER(aOrientation); + + GtkPageOrientation gtkOrient = gtk_page_setup_get_orientation(mPageSetup); + switch (gtkOrient) { + case GTK_PAGE_ORIENTATION_LANDSCAPE: + case GTK_PAGE_ORIENTATION_REVERSE_LANDSCAPE: + *aOrientation = kLandscapeOrientation; + break; + + case GTK_PAGE_ORIENTATION_PORTRAIT: + case GTK_PAGE_ORIENTATION_REVERSE_PORTRAIT: + default: + *aOrientation = kPortraitOrientation; + } + return NS_OK; +} +NS_IMETHODIMP +nsPrintSettingsGTK::SetOrientation(PRInt32 aOrientation) +{ + GtkPageOrientation gtkOrient; + if (aOrientation == kLandscapeOrientation) + gtkOrient = GTK_PAGE_ORIENTATION_LANDSCAPE; + else + gtkOrient = GTK_PAGE_ORIENTATION_PORTRAIT; + + gtk_print_settings_set_orientation(mPrintSettings, gtkOrient); + gtk_page_setup_set_orientation(mPageSetup, gtkOrient); + return NS_OK; +} + +/* attribute wstring toFileName; */ +NS_IMETHODIMP +nsPrintSettingsGTK::GetToFileName(PRUnichar * *aToFileName) +{ + // Get the gtk output filename + const char* gtk_output_uri = gtk_print_settings_get(mPrintSettings, GTK_PRINT_SETTINGS_OUTPUT_URI); + if (!gtk_output_uri) { + *aToFileName = ToNewUnicode(mToFileName); + return NS_OK; + } + + // Convert to an nsIFile + nsCOMPtr file; + NS_GetFileFromURLSpec(nsDependentCString(gtk_output_uri), getter_AddRefs(file)); + + // Extract the path + nsAutoString path; + file->GetPath(path); + + *aToFileName = ToNewUnicode(path); + return NS_OK; +} +NS_IMETHODIMP +nsPrintSettingsGTK::SetToFileName(const PRUnichar * aToFileName) +{ + if (aToFileName[0] == 0) { + mToFileName.SetLength(0); + gtk_print_settings_set(mPrintSettings, GTK_PRINT_SETTINGS_OUTPUT_URI, NULL); + return NS_OK; + } + + nsCOMPtr file; + NS_NewLocalFile(nsDependentString(aToFileName), PR_TRUE, getter_AddRefs(file)); + + // Convert the nsIFile to a URL + nsCAutoString url; + NS_GetURLSpecFromFile(file, url); + + gtk_print_settings_set(mPrintSettings, GTK_PRINT_SETTINGS_OUTPUT_URI, url.get()); + mToFileName = aToFileName; + + return NS_OK; +} + +NS_IMETHODIMP +nsPrintSettingsGTK::GetPrinterName(PRUnichar * *aPrinter) +{ + const char* gtkPrintName = gtk_print_settings_get_printer(mPrintSettings); + if (!gtkPrintName) { + if (GTK_IS_PRINTER(mGTKPrinter)) { + gtkPrintName = gtk_printer_get_name(mGTKPrinter); + } else { + *aPrinter = nsnull; + return NS_OK; + } + } + *aPrinter = ToNewUnicode(nsDependentCString(gtkPrintName)); + return NS_OK; +} + +NS_IMETHODIMP +nsPrintSettingsGTK::SetPrinterName(const PRUnichar * aPrinter) +{ + NS_ConvertUTF16toUTF8 gtkPrinter(aPrinter); + + if (StringBeginsWith(gtkPrinter, NS_LITERAL_CSTRING("PostScript/"))) { + // Don't bother importing this name + gtkPrinter.AssignLiteral(""); + } + + if (StringBeginsWith(gtkPrinter, NS_LITERAL_CSTRING("CUPS/"))) { + // Strip off "CUPS/"; GTK might recognize the rest + gtkPrinter.Cut(0, strlen("CUPS/")); + } + + if (!gtkPrinter.Equals(gtk_print_settings_get_printer(mPrintSettings))) { + mIsInitedFromPrinter = PR_FALSE; + mIsInitedFromPrefs = PR_FALSE; + gtk_print_settings_set_printer(mPrintSettings, gtkPrinter.get()); + } + + return NS_OK; +} + +/* attribute long numCopies; */ +NS_IMETHODIMP +nsPrintSettingsGTK::GetNumCopies(PRInt32 *aNumCopies) +{ + NS_ENSURE_ARG_POINTER(aNumCopies); + *aNumCopies = gtk_print_settings_get_n_copies(mPrintSettings); + return NS_OK; +} +NS_IMETHODIMP +nsPrintSettingsGTK::SetNumCopies(PRInt32 aNumCopies) +{ + gtk_print_settings_set_n_copies(mPrintSettings, aNumCopies); + return NS_OK; +} + +/* attribute double edgeTop; */ +NS_IMETHODIMP +nsPrintSettingsGTK::GetEdgeTop(double *aEdgeTop) +{ + NS_ENSURE_ARG_POINTER(aEdgeTop); + *aEdgeTop = gtk_page_setup_get_top_margin(mPageSetup, GTK_UNIT_INCH); + return NS_OK; +} +NS_IMETHODIMP +nsPrintSettingsGTK::SetEdgeTop(double aEdgeTop) +{ + gtk_page_setup_set_top_margin(mPageSetup, aEdgeTop, GTK_UNIT_INCH); + return NS_OK; +} + +/* attribute double edgeLeft; */ +NS_IMETHODIMP +nsPrintSettingsGTK::GetEdgeLeft(double *aEdgeLeft) +{ + NS_ENSURE_ARG_POINTER(aEdgeLeft); + *aEdgeLeft = gtk_page_setup_get_left_margin(mPageSetup, GTK_UNIT_INCH); + return NS_OK; +} +NS_IMETHODIMP +nsPrintSettingsGTK::SetEdgeLeft(double aEdgeLeft) +{ + gtk_page_setup_set_left_margin(mPageSetup, aEdgeLeft, GTK_UNIT_INCH); + return NS_OK; +} + +/* attribute double edgeBottom; */ +NS_IMETHODIMP +nsPrintSettingsGTK::GetEdgeBottom(double *aEdgeBottom) +{ + NS_ENSURE_ARG_POINTER(aEdgeBottom); + *aEdgeBottom = gtk_page_setup_get_bottom_margin(mPageSetup, GTK_UNIT_INCH); + return NS_OK; +} +NS_IMETHODIMP +nsPrintSettingsGTK::SetEdgeBottom(double aEdgeBottom) +{ + gtk_page_setup_set_bottom_margin(mPageSetup, aEdgeBottom, GTK_UNIT_INCH); + return NS_OK; +} + +/* attribute double edgeRight; */ +NS_IMETHODIMP +nsPrintSettingsGTK::GetEdgeRight(double *aEdgeRight) +{ + NS_ENSURE_ARG_POINTER(aEdgeRight); + *aEdgeRight = gtk_page_setup_get_right_margin(mPageSetup, GTK_UNIT_INCH); + return NS_OK; +} +NS_IMETHODIMP +nsPrintSettingsGTK::SetEdgeRight(double aEdgeRight) +{ + gtk_page_setup_set_right_margin(mPageSetup, aEdgeRight, GTK_UNIT_INCH); + return NS_OK; +} + +/* attribute double scaling; */ +NS_IMETHODIMP +nsPrintSettingsGTK::GetScaling(double *aScaling) +{ + *aScaling = gtk_print_settings_get_scale(mPrintSettings) / 100.0; + return NS_OK; +} + +NS_IMETHODIMP +nsPrintSettingsGTK::SetScaling(double aScaling) +{ + gtk_print_settings_set_scale(mPrintSettings, aScaling * 100.0); + return NS_OK; +} + +/* attribute wstring paperName; */ +NS_IMETHODIMP +nsPrintSettingsGTK::GetPaperName(PRUnichar * *aPaperName) +{ + NS_ENSURE_ARG_POINTER(aPaperName); + *aPaperName = ToNewUnicode(NS_ConvertUTF8toUTF16(gtk_paper_size_get_name(mPaperSize))); + return NS_OK; +} +NS_IMETHODIMP +nsPrintSettingsGTK::SetPaperName(const PRUnichar * aPaperName) +{ + NS_ConvertUTF16toUTF8 gtkPaperName(aPaperName); + + // Convert these Gecko names to GTK names + if (gtkPaperName.EqualsIgnoreCase("letter")) + gtkPaperName.AssignLiteral(GTK_PAPER_NAME_LETTER); + else if (gtkPaperName.EqualsIgnoreCase("legal")) + gtkPaperName.AssignLiteral(GTK_PAPER_NAME_LEGAL); + + // Try to get the display name from the name so our paper size fits in the Page Setup dialog. + GtkPaperSize* paperSize = gtk_paper_size_new(gtkPaperName.get()); + char* displayName = strdup(gtk_paper_size_get_display_name(paperSize)); + gtk_paper_size_free(paperSize); + + paperSize = gtk_paper_size_new_custom(gtkPaperName.get(), displayName, + gtk_paper_size_get_width(mPaperSize, GTK_UNIT_INCH), + gtk_paper_size_get_height(mPaperSize, GTK_UNIT_INCH), + GTK_UNIT_INCH); + + free(displayName); + gtk_paper_size_free(mPaperSize); + mPaperSize = paperSize; + SaveNewPageSize(); + return NS_OK; +} + +GtkUnit +nsPrintSettingsGTK::GetGTKUnit(PRInt16 aGeckoUnit) +{ + if (aGeckoUnit == kPaperSizeMillimeters) + return GTK_UNIT_MM; + else + return GTK_UNIT_INCH; +} + +void +nsPrintSettingsGTK::SaveNewPageSize() +{ + gtk_print_settings_set_paper_size(mPrintSettings, mPaperSize); + gtk_page_setup_set_paper_size(mPageSetup, mPaperSize); +} + +/* attribute double paperWidth; */ +NS_IMETHODIMP +nsPrintSettingsGTK::GetPaperWidth(double *aPaperWidth) +{ + NS_ENSURE_ARG_POINTER(aPaperWidth); + *aPaperWidth = gtk_paper_size_get_width(mPaperSize, GetGTKUnit(mPaperSizeUnit)); + return NS_OK; +} +NS_IMETHODIMP +nsPrintSettingsGTK::SetPaperWidth(double aPaperWidth) +{ + gtk_paper_size_set_size(mPaperSize, + aPaperWidth, + gtk_paper_size_get_height(mPaperSize, GetGTKUnit(mPaperSizeUnit)), + GetGTKUnit(mPaperSizeUnit)); + SaveNewPageSize(); + return NS_OK; +} + +/* attribute double paperHeight; */ +NS_IMETHODIMP +nsPrintSettingsGTK::GetPaperHeight(double *aPaperHeight) +{ + NS_ENSURE_ARG_POINTER(aPaperHeight); + *aPaperHeight = gtk_paper_size_get_height(mPaperSize, GetGTKUnit(mPaperSizeUnit)); + return NS_OK; +} +NS_IMETHODIMP +nsPrintSettingsGTK::SetPaperHeight(double aPaperHeight) +{ + gtk_paper_size_set_size(mPaperSize, + gtk_paper_size_get_width(mPaperSize, GetGTKUnit(mPaperSizeUnit)), + aPaperHeight, + GetGTKUnit(mPaperSizeUnit)); + SaveNewPageSize(); + return NS_OK; +} + +NS_IMETHODIMP +nsPrintSettingsGTK::SetPaperSizeUnit(PRInt16 aPaperSizeUnit) +{ + // Convert units internally. e.g. they might have set the values while we're still in mm but + // they change to inch just afterwards, expecting that their sizes are in inches. + gtk_paper_size_set_size(mPaperSize, + gtk_paper_size_get_width(mPaperSize, GetGTKUnit(mPaperSizeUnit)), + gtk_paper_size_get_height(mPaperSize, GetGTKUnit(mPaperSizeUnit)), + GetGTKUnit(aPaperSizeUnit)); + SaveNewPageSize(); + + mPaperSizeUnit = aPaperSizeUnit; + return NS_OK; +} + +// Get/Set our margins as an nsMargin +NS_IMETHODIMP +nsPrintSettingsGTK::SetEdgeInTwips(nsMargin& aEdge) +{ + gtk_page_setup_set_top_margin(mPageSetup, NS_TWIPS_TO_INCHES(aEdge.top), GTK_UNIT_INCH); + gtk_page_setup_set_left_margin(mPageSetup, NS_TWIPS_TO_INCHES(aEdge.left), GTK_UNIT_INCH); + gtk_page_setup_set_bottom_margin(mPageSetup, NS_TWIPS_TO_INCHES(aEdge.bottom), GTK_UNIT_INCH); + gtk_page_setup_set_right_margin(mPageSetup, NS_TWIPS_TO_INCHES(aEdge.right), GTK_UNIT_INCH); + return NS_OK; +} + +NS_IMETHODIMP +nsPrintSettingsGTK::GetEdgeInTwips(nsMargin& aEdge) +{ + aEdge.SizeTo(NS_INCHES_TO_TWIPS(gtk_page_setup_get_left_margin(mPageSetup, GTK_UNIT_INCH)), + NS_INCHES_TO_TWIPS(gtk_page_setup_get_top_margin(mPageSetup, GTK_UNIT_INCH)), + NS_INCHES_TO_TWIPS(gtk_page_setup_get_right_margin(mPageSetup, GTK_UNIT_INCH)), + NS_INCHES_TO_TWIPS(gtk_page_setup_get_bottom_margin(mPageSetup, GTK_UNIT_INCH))); + return NS_OK; +} + +NS_IMETHODIMP +nsPrintSettingsGTK::GetEffectivePageSize(double *aWidth, double *aHeight) +{ + *aWidth = NS_INCHES_TO_TWIPS(gtk_paper_size_get_width(mPaperSize, GTK_UNIT_INCH)); + *aHeight = NS_INCHES_TO_TWIPS(gtk_paper_size_get_height(mPaperSize, GTK_UNIT_INCH)); + + GtkPageOrientation gtkOrient = gtk_page_setup_get_orientation(mPageSetup); + + if (gtkOrient == GTK_PAGE_ORIENTATION_LANDSCAPE || + gtkOrient == GTK_PAGE_ORIENTATION_REVERSE_LANDSCAPE) { + double temp = *aWidth; + *aWidth = *aHeight; + *aHeight = temp; + } + return NS_OK; +} + +NS_IMETHODIMP +nsPrintSettingsGTK::SetupSilentPrinting() +{ + // We have to get a printer here, rather than when the print settings are constructed. + // This is because when we request sync, GTK makes us wait in the *event loop* while waiting + // for the enumeration to finish. We must do this when event loop runs are expected. + gtk_enumerate_printers(printer_enumerator, this, NULL, TRUE); + + // XXX If no default printer set, get the first one. + if (!GTK_IS_PRINTER(mGTKPrinter)) + gtk_enumerate_printers(ref_printer, this, NULL, TRUE); + + return NS_OK; +} diff --git a/widget/src/gtk2/nsPrintSettingsGTK.h b/widget/src/gtk2/nsPrintSettingsGTK.h new file mode 100644 index 000000000000..7b89365e568b --- /dev/null +++ b/widget/src/gtk2/nsPrintSettingsGTK.h @@ -0,0 +1,177 @@ +/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * ***** 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 the Mozilla browser. + * + * The Initial Developer of the Original Code is Mozilla Corporation. + * Portions created by the Initial Developer are Copyright (C) 2008 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Michael Ventnor + * + * Alternatively, the contents of this file may be used under the terms of + * either of 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 nsPrintSettingsGTK_h_ +#define nsPrintSettingsGTK_h_ + +#include "nsPrintSettingsImpl.h" + +extern "C" { +#include +#include +#include +} + +#define NS_PRINTSETTINGSGTK_IID \ +{ 0x758df520, 0xc7c3, 0x11dc, { 0x95, 0xff, 0x08, 0x00, 0x20, 0x0c, 0x9a, 0x66 } } + + +//***************************************************************************** +//*** nsPrintSettingsGTK +//***************************************************************************** + +class nsPrintSettingsGTK : public nsPrintSettings +{ +public: + NS_DECL_ISUPPORTS_INHERITED + NS_DECLARE_STATIC_IID_ACCESSOR(NS_PRINTSETTINGSGTK_IID) + + nsPrintSettingsGTK(); + virtual ~nsPrintSettingsGTK(); + + // We're overriding these methods because we want to read/write with GTK objects, + // not local variables. This allows a simpler settings implementation between + // Gecko and GTK. + + GtkPageSetup* GetGtkPageSetup() { return mPageSetup; }; + void SetGtkPageSetup(GtkPageSetup *aPageSetup); + + GtkPrintSettings* GetGtkPrintSettings() { return mPrintSettings; }; + void SetGtkPrintSettings(GtkPrintSettings *aPrintSettings); + + GtkPrinter* GetGtkPrinter() { return mGTKPrinter; }; + void SetGtkPrinter(GtkPrinter *aPrinter); + + PRBool GetForcePrintSelectionOnly() { return mPrintSelectionOnly; }; + void SetForcePrintSelectionOnly(PRBool aPrintSelectionOnly) { mPrintSelectionOnly = aPrintSelectionOnly; }; + + // If not printing the selection, this is stored in the GtkPrintSettings. Printing the + // selection is stored as a protected boolean (mPrintSelectionOnly). + NS_IMETHOD GetPrintRange(PRInt16 *aPrintRange); + NS_IMETHOD SetPrintRange(PRInt16 aPrintRange); + + // The page range is stored as as single range in the GtkPrintSettings object. + NS_IMETHOD GetStartPageRange(PRInt32 *aStartPageRange); + NS_IMETHOD SetStartPageRange(PRInt32 aStartPageRange); + NS_IMETHOD GetEndPageRange(PRInt32 *aEndPageRange); + NS_IMETHOD SetEndPageRange(PRInt32 aEndPageRange); + + // Reversed, color, orientation and file name are all stored in the GtkPrintSettings. + // Orientation is also stored in the GtkPageSetup and its setting takes priority when getting the orientation. + NS_IMETHOD GetPrintReversed(PRBool *aPrintReversed); + NS_IMETHOD SetPrintReversed(PRBool aPrintReversed); + + NS_IMETHOD GetPrintInColor(PRBool *aPrintInColor); + NS_IMETHOD SetPrintInColor(PRBool aPrintInColor); + + NS_IMETHOD GetOrientation(PRInt32 *aOrientation); + NS_IMETHOD SetOrientation(PRInt32 aOrientation); + + NS_IMETHOD GetToFileName(PRUnichar * *aToFileName); + NS_IMETHOD SetToFileName(const PRUnichar * aToFileName); + + // Gets/Sets the printer name in the GtkPrintSettings. If no printer name is specified there, + // you will get back the name of the current internal GtkPrinter. + NS_IMETHOD GetPrinterName(PRUnichar * *aPrinter); + NS_IMETHOD SetPrinterName(const PRUnichar * aPrinter); + + // Number of copies is stored/gotten from the GtkPrintSettings. + NS_IMETHOD GetNumCopies(PRInt32 *aNumCopies); + NS_IMETHOD SetNumCopies(PRInt32 aNumCopies); + + NS_IMETHOD GetEdgeTop(double *aEdgeTop); + NS_IMETHOD SetEdgeTop(double aEdgeTop); + + NS_IMETHOD GetEdgeLeft(double *aEdgeLeft); + NS_IMETHOD SetEdgeLeft(double aEdgeLeft); + + NS_IMETHOD GetEdgeBottom(double *aEdgeBottom); + NS_IMETHOD SetEdgeBottom(double aEdgeBottom); + + NS_IMETHOD GetEdgeRight(double *aEdgeRight); + NS_IMETHOD SetEdgeRight(double aEdgeRight); + + NS_IMETHOD GetScaling(double *aScaling); + NS_IMETHOD SetScaling(double aScaling); + + // A name recognised by GTK is strongly advised here, as this is used to create a GtkPaperSize. + NS_IMETHOD GetPaperName(PRUnichar * *aPaperName); + NS_IMETHOD SetPaperName(const PRUnichar * aPaperName); + + NS_IMETHOD GetPaperWidth(double *aPaperWidth); + NS_IMETHOD SetPaperWidth(double aPaperWidth); + + NS_IMETHOD GetPaperHeight(double *aPaperHeight); + NS_IMETHOD SetPaperHeight(double aPaperHeight); + + NS_IMETHOD SetPaperSizeUnit(PRInt16 aPaperSizeUnit); + + NS_IMETHOD SetEdgeInTwips(nsMargin& aEdge); + NS_IMETHOD GetEdgeInTwips(nsMargin& aEdge); + + NS_IMETHOD GetEffectivePageSize(double *aWidth, double *aHeight); + + NS_IMETHOD SetupSilentPrinting(); + +protected: + nsPrintSettingsGTK(const nsPrintSettingsGTK& src); + nsPrintSettingsGTK& operator=(const nsPrintSettingsGTK& rhs); + + virtual nsresult _Clone(nsIPrintSettings **_retval); + virtual nsresult _Assign(nsIPrintSettings *aPS); + + GtkUnit GetGTKUnit(PRInt16 aGeckoUnit); + void SaveNewPageSize(); + + /** + * On construction: + * - mPrintSettings, mPageSetup and mPaperSize are just new objects with defaults determined by GTK. + * - mGTKPrinter is NULL!!! Remember to be careful when accessing this property. + */ + GtkPageSetup* mPageSetup; + GtkPrintSettings* mPrintSettings; + GtkPrinter* mGTKPrinter; + GtkPaperSize* mPaperSize; + + PRBool mPrintSelectionOnly; +}; + +NS_DEFINE_STATIC_IID_ACCESSOR(nsPrintSettingsGTK, NS_PRINTSETTINGSGTK_IID) + + +#endif // nsPrintSettingsGTK_h_ diff --git a/widget/src/gtk2/nsWidgetFactory.cpp b/widget/src/gtk2/nsWidgetFactory.cpp index 9514066d597a..71240da8898c 100644 --- a/widget/src/gtk2/nsWidgetFactory.cpp +++ b/widget/src/gtk2/nsWidgetFactory.cpp @@ -60,6 +60,7 @@ #include "nsIPrefBranch.h" #include "nsImageToPixbuf.h" #include "nsIdleServiceGTK.h" +#include "nsPrintDialogGTK.h" #ifdef NATIVE_THEME_SUPPORT #include "nsNativeThemeGTK.h" @@ -97,6 +98,7 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsPrinterEnumeratorGTK) NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsPrintSession, Init) NS_GENERIC_FACTORY_CONSTRUCTOR(nsImageToPixbuf) NS_GENERIC_FACTORY_CONSTRUCTOR(nsIdleServiceGTK) +NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsPrintDialogServiceGTK, Init) static NS_IMETHODIMP nsFilePickerConstructor(nsISupports *aOuter, REFNSIID aIID, @@ -274,6 +276,10 @@ static const nsModuleComponentInfo components[] = NS_IDLE_SERVICE_CID, "@mozilla.org/widget/idleservice;1", nsIdleServiceGTKConstructor }, + { "Native Print Dialog", + NS_PRINTDIALOGSERVICE_CID, + NS_PRINTDIALOGSERVICE_CONTRACTID, + nsPrintDialogServiceGTKConstructor }, }; PR_STATIC_CALLBACK(void) diff --git a/widget/src/xpwidgets/nsPrintSettingsImpl.cpp b/widget/src/xpwidgets/nsPrintSettingsImpl.cpp index 9159e023f870..0e813936d9b8 100644 --- a/widget/src/xpwidgets/nsPrintSettingsImpl.cpp +++ b/widget/src/xpwidgets/nsPrintSettingsImpl.cpp @@ -971,6 +971,15 @@ nsPrintSettings::GetEdgeInTwips(nsMargin& aEdge) return NS_OK; } +/** --------------------------------------------------- + * Stub - platform-specific implementations can use this function. + */ +NS_IMETHODIMP +nsPrintSettings::SetupSilentPrinting() +{ + return NS_OK; +} + /** --------------------------------------------------- * See documentation in nsPrintOptionsImpl.h */