/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "nsCOMPtr.h" #include "nsQueryObject.h" #include "nsIServiceManager.h" #include "nsPrintOptionsX.h" #include "nsPrintSettingsX.h" // The constants for paper orientation were renamed in 10.9. __MAC_10_9 is // defined on OS X 10.9 and later. Although 10.8 and earlier are not supported // at this time, this allows for building on those older OS versions. The // values are consistent across OS versions so the rename does not affect // runtime, just compilation. #ifdef __MAC_10_9 #define NS_PAPER_ORIENTATION_PORTRAIT (NSPaperOrientationPortrait) #define NS_PAPER_ORIENTATION_LANDSCAPE (NSPaperOrientationLandscape) #else #define NS_PAPER_ORIENTATION_PORTRAIT (NSPortraitOrientation) #define NS_PAPER_ORIENTATION_LANDSCAPE (NSLandscapeOrientation) #endif using namespace mozilla::embedding; nsPrintOptionsX::nsPrintOptionsX() { } nsPrintOptionsX::~nsPrintOptionsX() { } NS_IMETHODIMP nsPrintOptionsX::SerializeToPrintData(nsIPrintSettings* aSettings, nsIWebBrowserPrint* aWBP, PrintData* data) { nsresult rv = nsPrintOptions::SerializeToPrintData(aSettings, aWBP, data); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } if (aWBP) { // When serializing an nsIWebBrowserPrint, we need to pass up the first // document name. We could pass up the entire collection of document // names, but the OS X printing prompt code only really cares about // the first one, so we just send the first to save IPC traffic. char16_t** docTitles; uint32_t titleCount; rv = aWBP->EnumerateDocumentNames(&titleCount, &docTitles); if (NS_SUCCEEDED(rv) && titleCount > 0) { data->printJobName().Assign(docTitles[0]); } for (int32_t i = titleCount - 1; i >= 0; i--) { free(docTitles[i]); } free(docTitles); docTitles = nullptr; } RefPtr<nsPrintSettingsX> settingsX(do_QueryObject(aSettings)); if (NS_WARN_IF(!settingsX)) { return NS_ERROR_FAILURE; } NSPrintInfo* printInfo = settingsX->GetCocoaPrintInfo(); if (NS_WARN_IF(!printInfo)) { return NS_ERROR_FAILURE; } double adjustedWidth, adjustedHeight; settingsX->GetAdjustedPaperSize(&adjustedWidth, &adjustedHeight); data->adjustedPaperWidth() = adjustedWidth; data->adjustedPaperHeight() = adjustedHeight; NSDictionary* dict = [printInfo dictionary]; if (NS_WARN_IF(!dict)) { return NS_ERROR_FAILURE; } NSString* printerName = [dict objectForKey: NSPrintPrinterName]; if (printerName) { nsCocoaUtils::GetStringForNSString(printerName, data->printerName()); } NSString* faxNumber = [dict objectForKey: NSPrintFaxNumber]; if (faxNumber) { nsCocoaUtils::GetStringForNSString(faxNumber, data->faxNumber()); } NSURL* printToFileURL = [dict objectForKey: NSPrintJobSavingURL]; if (printToFileURL) { nsCocoaUtils::GetStringForNSString([printToFileURL absoluteString], data->toFileName()); } NSDate* printTime = [dict objectForKey: NSPrintTime]; if (printTime) { NSTimeInterval timestamp = [printTime timeIntervalSinceReferenceDate]; data->printTime() = timestamp; } NSString* disposition = [dict objectForKey: NSPrintJobDisposition]; if (disposition) { nsCocoaUtils::GetStringForNSString(disposition, data->disposition()); } NSString* paperName = [dict objectForKey: NSPrintPaperName]; if (paperName) { nsCocoaUtils::GetStringForNSString(paperName, data->paperName()); } float scalingFactor = [[dict objectForKey: NSPrintScalingFactor] floatValue]; data->scalingFactor() = scalingFactor; int32_t orientation; if ([printInfo orientation] == NS_PAPER_ORIENTATION_PORTRAIT) { orientation = nsIPrintSettings::kPortraitOrientation; } else { orientation = nsIPrintSettings::kLandscapeOrientation; } data->orientation() = orientation; NSSize paperSize = [printInfo paperSize]; float widthScale, heightScale; settingsX->GetInchesScale(&widthScale, &heightScale); if (orientation == nsIPrintSettings::kLandscapeOrientation) { // switch widths and heights data->widthScale() = heightScale; data->heightScale() = widthScale; data->paperWidth() = paperSize.height / heightScale; data->paperHeight() = paperSize.width / widthScale; } else { data->widthScale() = widthScale; data->heightScale() = heightScale; data->paperWidth() = paperSize.width / widthScale; data->paperHeight() = paperSize.height / heightScale; } data->numCopies() = [[dict objectForKey: NSPrintCopies] intValue]; data->printAllPages() = [[dict objectForKey: NSPrintAllPages] boolValue]; data->startPageRange() = [[dict objectForKey: NSPrintFirstPage] intValue]; data->endPageRange() = [[dict objectForKey: NSPrintLastPage] intValue]; data->mustCollate() = [[dict objectForKey: NSPrintMustCollate] boolValue]; data->printReversed() = [[dict objectForKey: NSPrintReversePageOrder] boolValue]; data->pagesAcross() = [[dict objectForKey: NSPrintPagesAcross] unsignedShortValue]; data->pagesDown() = [[dict objectForKey: NSPrintPagesDown] unsignedShortValue]; data->detailedErrorReporting() = [[dict objectForKey: NSPrintDetailedErrorReporting] boolValue]; data->addHeaderAndFooter() = [[dict objectForKey: NSPrintHeaderAndFooter] boolValue]; data->fileNameExtensionHidden() = [[dict objectForKey: NSPrintJobSavingFileNameExtensionHidden] boolValue]; bool printSelectionOnly = [[dict objectForKey: NSPrintSelectionOnly] boolValue]; aSettings->SetPrintOptions(nsIPrintSettings::kEnableSelectionRB, printSelectionOnly); aSettings->GetPrintOptionsBits(&data->optionFlags()); return NS_OK; } NS_IMETHODIMP nsPrintOptionsX::DeserializeToPrintSettings(const PrintData& data, nsIPrintSettings* settings) { nsresult rv = nsPrintOptions::DeserializeToPrintSettings(data, settings); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } RefPtr<nsPrintSettingsX> settingsX(do_QueryObject(settings)); if (NS_WARN_IF(!settingsX)) { return NS_ERROR_FAILURE; } NSPrintInfo* sharedPrintInfo = [NSPrintInfo sharedPrintInfo]; if (NS_WARN_IF(!sharedPrintInfo)) { return NS_ERROR_FAILURE; } NSDictionary* sharedDict = [sharedPrintInfo dictionary]; if (NS_WARN_IF(!sharedDict)) { return NS_ERROR_FAILURE; } // We need to create a new NSMutableDictionary to pass to NSPrintInfo with // the values that we got from the other process. NSMutableDictionary* newPrintInfoDict = [NSMutableDictionary dictionaryWithDictionary:sharedDict]; if (NS_WARN_IF(!newPrintInfoDict)) { return NS_ERROR_OUT_OF_MEMORY; } NSString* printerName = nsCocoaUtils::ToNSString(data.printerName()); if (printerName) { NSPrinter* printer = [NSPrinter printerWithName: printerName]; if (printer) { [newPrintInfoDict setObject: printer forKey: NSPrintPrinter]; [newPrintInfoDict setObject: printerName forKey: NSPrintPrinterName]; } } [newPrintInfoDict setObject: [NSNumber numberWithInt: data.numCopies()] forKey: NSPrintCopies]; [newPrintInfoDict setObject: [NSNumber numberWithBool: data.printAllPages()] forKey: NSPrintAllPages]; [newPrintInfoDict setObject: [NSNumber numberWithInt: data.startPageRange()] forKey: NSPrintFirstPage]; [newPrintInfoDict setObject: [NSNumber numberWithInt: data.endPageRange()] forKey: NSPrintLastPage]; [newPrintInfoDict setObject: [NSNumber numberWithBool: data.mustCollate()] forKey: NSPrintMustCollate]; [newPrintInfoDict setObject: [NSNumber numberWithBool: data.printReversed()] forKey: NSPrintReversePageOrder]; [newPrintInfoDict setObject: nsCocoaUtils::ToNSString(data.disposition()) forKey: NSPrintJobDisposition]; [newPrintInfoDict setObject: nsCocoaUtils::ToNSString(data.paperName()) forKey: NSPrintPaperName]; [newPrintInfoDict setObject: [NSNumber numberWithFloat: data.scalingFactor()] forKey: NSPrintScalingFactor]; CGFloat width = data.paperWidth() * data.widthScale(); CGFloat height = data.paperHeight() * data.heightScale(); [newPrintInfoDict setObject: [NSValue valueWithSize:NSMakeSize(width,height)] forKey: NSPrintPaperSize]; int paperOrientation; if (data.orientation() == nsIPrintSettings::kPortraitOrientation) { paperOrientation = NS_PAPER_ORIENTATION_PORTRAIT; settings->SetOrientation(nsIPrintSettings::kPortraitOrientation); } else { paperOrientation = NS_PAPER_ORIENTATION_LANDSCAPE; settings->SetOrientation(nsIPrintSettings::kLandscapeOrientation); } [newPrintInfoDict setObject: [NSNumber numberWithInt:paperOrientation] forKey: NSPrintOrientation]; [newPrintInfoDict setObject: [NSNumber numberWithShort: data.pagesAcross()] forKey: NSPrintPagesAcross]; [newPrintInfoDict setObject: [NSNumber numberWithShort: data.pagesDown()] forKey: NSPrintPagesDown]; [newPrintInfoDict setObject: [NSNumber numberWithBool: data.detailedErrorReporting()] forKey: NSPrintDetailedErrorReporting]; [newPrintInfoDict setObject: nsCocoaUtils::ToNSString(data.faxNumber()) forKey: NSPrintFaxNumber]; [newPrintInfoDict setObject: [NSNumber numberWithBool: data.addHeaderAndFooter()] forKey: NSPrintHeaderAndFooter]; [newPrintInfoDict setObject: [NSNumber numberWithBool: data.fileNameExtensionHidden()] forKey: NSPrintJobSavingFileNameExtensionHidden]; // At this point, the base class should have properly deserialized the print // options bitfield for nsIPrintSettings, so that it holds the correct value // for kEnableSelectionRB, which we use to set NSPrintSelectionOnly. bool printSelectionOnly = false; rv = settings->GetPrintOptions(nsIPrintSettings::kEnableSelectionRB, &printSelectionOnly); if (NS_SUCCEEDED(rv)) { [newPrintInfoDict setObject: [NSNumber numberWithBool: printSelectionOnly] forKey: NSPrintSelectionOnly]; } else { [newPrintInfoDict setObject: [NSNumber numberWithBool: NO] forKey: NSPrintSelectionOnly]; } NSURL* jobSavingURL = [NSURL URLWithString: nsCocoaUtils::ToNSString(data.toFileName())]; if (jobSavingURL) { [newPrintInfoDict setObject: jobSavingURL forKey: NSPrintJobSavingURL]; } NSTimeInterval timestamp = data.printTime(); NSDate* printTime = [NSDate dateWithTimeIntervalSinceReferenceDate: timestamp]; if (printTime) { [newPrintInfoDict setObject: printTime forKey: NSPrintTime]; } // Next, we create a new NSPrintInfo with the values in our dictionary. NSPrintInfo* newPrintInfo = [[NSPrintInfo alloc] initWithDictionary: newPrintInfoDict]; if (NS_WARN_IF(!newPrintInfo)) { return NS_ERROR_OUT_OF_MEMORY; } // And now swap in the new NSPrintInfo we've just populated. settingsX->SetCocoaPrintInfo(newPrintInfo); [newPrintInfo release]; settingsX->SetAdjustedPaperSize(data.adjustedPaperWidth(), data.adjustedPaperHeight()); return NS_OK; } nsresult nsPrintOptionsX::ReadPrefs(nsIPrintSettings* aPS, const nsAString& aPrinterName, uint32_t aFlags) { nsresult rv; rv = nsPrintOptions::ReadPrefs(aPS, aPrinterName, aFlags); NS_ASSERTION(NS_SUCCEEDED(rv), "nsPrintOptions::ReadPrefs() failed"); RefPtr<nsPrintSettingsX> printSettingsX(do_QueryObject(aPS)); if (!printSettingsX) return NS_ERROR_NO_INTERFACE; rv = printSettingsX->ReadPageFormatFromPrefs(); return NS_OK; } nsresult nsPrintOptionsX::_CreatePrintSettings(nsIPrintSettings **_retval) { nsresult rv; *_retval = nullptr; nsPrintSettingsX* printSettings = new nsPrintSettingsX; // does not initially ref count NS_ENSURE_TRUE(printSettings, NS_ERROR_OUT_OF_MEMORY); NS_ADDREF(*_retval = printSettings); rv = printSettings->Init(); if (NS_FAILED(rv)) { NS_RELEASE(*_retval); return rv; } InitPrintSettingsFromPrefs(*_retval, false, nsIPrintSettings::kInitSaveAll); return rv; } nsresult nsPrintOptionsX::WritePrefs(nsIPrintSettings* aPS, const nsAString& aPrinterName, uint32_t aFlags) { nsresult rv; rv = nsPrintOptions::WritePrefs(aPS, aPrinterName, aFlags); NS_ASSERTION(NS_SUCCEEDED(rv), "nsPrintOptions::WritePrefs() failed"); RefPtr<nsPrintSettingsX> printSettingsX(do_QueryObject(aPS)); if (!printSettingsX) return NS_ERROR_NO_INTERFACE; rv = printSettingsX->WritePageFormatToPrefs(); NS_ASSERTION(NS_SUCCEEDED(rv), "nsPrintSettingsX::WritePageFormatToPrefs() failed"); return NS_OK; }