1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include "nsPrintSettingsService.h"
8 #include "mozilla/embedding/PPrinting.h"
9 #include "mozilla/layout/RemotePrintJobChild.h"
10 #include "mozilla/RefPtr.h"
12 #include "nsIPrinterList.h"
13 #include "nsPrintingProxy.h"
14 #include "nsReadableUtils.h"
15 #include "nsPrintSettingsImpl.h"
16 #include "nsIPrintSession.h"
17 #include "nsServiceManagerUtils.h"
23 #include "nsIStringEnumerator.h"
25 #include "mozilla/Preferences.h"
26 #include "nsPrintfCString.h"
28 using namespace mozilla
;
29 using namespace mozilla::embedding
;
31 typedef mozilla::layout::RemotePrintJobChild RemotePrintJobChild
;
33 NS_IMPL_ISUPPORTS(nsPrintSettingsService
, nsIPrintSettingsService
)
36 static const char kMarginTop
[] = "print_margin_top";
37 static const char kMarginLeft
[] = "print_margin_left";
38 static const char kMarginBottom
[] = "print_margin_bottom";
39 static const char kMarginRight
[] = "print_margin_right";
40 static const char kEdgeTop
[] = "print_edge_top";
41 static const char kEdgeLeft
[] = "print_edge_left";
42 static const char kEdgeBottom
[] = "print_edge_bottom";
43 static const char kEdgeRight
[] = "print_edge_right";
44 static const char kUnwriteableMarginTop
[] = "print_unwriteable_margin_top";
45 static const char kUnwriteableMarginLeft
[] = "print_unwriteable_margin_left";
46 static const char kUnwriteableMarginBottom
[] =
47 "print_unwriteable_margin_bottom";
48 static const char kUnwriteableMarginRight
[] = "print_unwriteable_margin_right";
50 // Prefs for Print Options
51 static const char kPrintHeaderStrLeft
[] = "print_headerleft";
52 static const char kPrintHeaderStrCenter
[] = "print_headercenter";
53 static const char kPrintHeaderStrRight
[] = "print_headerright";
54 static const char kPrintFooterStrLeft
[] = "print_footerleft";
55 static const char kPrintFooterStrCenter
[] = "print_footercenter";
56 static const char kPrintFooterStrRight
[] = "print_footerright";
59 static const char kPrintReversed
[] = "print_reversed";
60 static const char kPrintInColor
[] = "print_in_color";
61 static const char kPrintPaperId
[] = "print_paper_id";
62 static const char kPrintPaperSizeUnit
[] = "print_paper_size_unit";
63 static const char kPrintPaperWidth
[] = "print_paper_width";
64 static const char kPrintPaperHeight
[] = "print_paper_height";
65 static const char kPrintOrientation
[] = "print_orientation";
66 static const char kPrinterName
[] = "print_printer";
67 static const char kPrintToFile
[] = "print_to_file";
68 static const char kPrintToFileName
[] = "print_to_filename";
69 static const char kPrintPageDelay
[] = "print_page_delay";
70 static const char kPrintBGColors
[] = "print_bgcolor";
71 static const char kPrintBGImages
[] = "print_bgimages";
72 static const char kPrintShrinkToFit
[] = "print_shrink_to_fit";
73 static const char kPrintScaling
[] = "print_scaling";
74 static const char kPrintResolution
[] = "print_resolution";
75 static const char kPrintDuplex
[] = "print_duplex";
77 static const char kJustLeft
[] = "left";
78 static const char kJustCenter
[] = "center";
79 static const char kJustRight
[] = "right";
81 #define NS_PRINTER_LIST_CONTRACTID "@mozilla.org/gfx/printerlist;1"
83 nsresult
nsPrintSettingsService::Init() { return NS_OK
; }
86 nsPrintSettingsService::SerializeToPrintData(nsIPrintSettings
* aSettings
,
88 nsCOMPtr
<nsIPrintSession
> session
;
89 nsresult rv
= aSettings
->GetPrintSession(getter_AddRefs(session
));
90 if (NS_SUCCEEDED(rv
) && session
) {
91 data
->remotePrintJobChild() = session
->GetRemotePrintJob();
94 aSettings
->GetStartPageRange(&data
->startPageRange());
95 aSettings
->GetEndPageRange(&data
->endPageRange());
97 aSettings
->GetEdgeTop(&data
->edgeTop());
98 aSettings
->GetEdgeLeft(&data
->edgeLeft());
99 aSettings
->GetEdgeBottom(&data
->edgeBottom());
100 aSettings
->GetEdgeRight(&data
->edgeRight());
102 aSettings
->GetMarginTop(&data
->marginTop());
103 aSettings
->GetMarginLeft(&data
->marginLeft());
104 aSettings
->GetMarginBottom(&data
->marginBottom());
105 aSettings
->GetMarginRight(&data
->marginRight());
106 aSettings
->GetUnwriteableMarginTop(&data
->unwriteableMarginTop());
107 aSettings
->GetUnwriteableMarginLeft(&data
->unwriteableMarginLeft());
108 aSettings
->GetUnwriteableMarginBottom(&data
->unwriteableMarginBottom());
109 aSettings
->GetUnwriteableMarginRight(&data
->unwriteableMarginRight());
111 aSettings
->GetScaling(&data
->scaling());
113 data
->printBGColors() = aSettings
->GetPrintBGColors();
114 data
->printBGImages() = aSettings
->GetPrintBGImages();
116 data
->honorPageRuleMargins() = aSettings
->GetHonorPageRuleMargins();
117 data
->showMarginGuides() = aSettings
->GetShowMarginGuides();
118 data
->isPrintSelectionRBEnabled() = aSettings
->GetIsPrintSelectionRBEnabled();
119 data
->printSelectionOnly() = aSettings
->GetPrintSelectionOnly();
121 aSettings
->GetPrintRange(&data
->printRange());
123 aSettings
->GetTitle(data
->title());
124 aSettings
->GetDocURL(data
->docURL());
126 aSettings
->GetHeaderStrLeft(data
->headerStrLeft());
127 aSettings
->GetHeaderStrCenter(data
->headerStrCenter());
128 aSettings
->GetHeaderStrRight(data
->headerStrRight());
130 aSettings
->GetFooterStrLeft(data
->footerStrLeft());
131 aSettings
->GetFooterStrCenter(data
->footerStrCenter());
132 aSettings
->GetFooterStrRight(data
->footerStrRight());
134 aSettings
->GetIsCancelled(&data
->isCancelled());
135 aSettings
->GetPrintSilent(&data
->printSilent());
136 aSettings
->GetShrinkToFit(&data
->shrinkToFit());
137 aSettings
->GetShowPrintProgress(&data
->showPrintProgress());
139 aSettings
->GetPaperId(data
->paperId());
140 aSettings
->GetPaperWidth(&data
->paperWidth());
141 aSettings
->GetPaperHeight(&data
->paperHeight());
142 aSettings
->GetPaperSizeUnit(&data
->paperSizeUnit());
144 aSettings
->GetPrintReversed(&data
->printReversed());
145 aSettings
->GetPrintInColor(&data
->printInColor());
146 aSettings
->GetOrientation(&data
->orientation());
148 aSettings
->GetNumCopies(&data
->numCopies());
150 aSettings
->GetPrinterName(data
->printerName());
152 aSettings
->GetPrintToFile(&data
->printToFile());
154 aSettings
->GetToFileName(data
->toFileName());
156 aSettings
->GetOutputFormat(&data
->outputFormat());
157 aSettings
->GetPrintPageDelay(&data
->printPageDelay());
158 aSettings
->GetResolution(&data
->resolution());
159 aSettings
->GetDuplex(&data
->duplex());
160 aSettings
->GetIsInitializedFromPrinter(&data
->isInitializedFromPrinter());
161 aSettings
->GetIsInitializedFromPrefs(&data
->isInitializedFromPrefs());
163 // Initialize the platform-specific values that don't
164 // default-initialize, so that we don't send uninitialized data over
165 // IPC (which leads to valgrind warnings, and, for bools, fatal
167 // data->driverName() default-initializes
168 // data->deviceName() default-initializes
169 // data->GTKPrintSettings() default-initializes
170 // data->printJobName() default-initializes
171 data
->printAllPages() = true;
172 data
->mustCollate() = false;
173 // data->disposition() default-initializes
174 data
->pagesAcross() = 1;
175 data
->pagesDown() = 1;
176 data
->printTime() = 0;
177 data
->detailedErrorReporting() = true;
178 // data->faxNumber() default-initializes
179 data
->addHeaderAndFooter() = false;
180 data
->fileNameExtensionHidden() = false;
186 nsPrintSettingsService::DeserializeToPrintSettings(const PrintData
& data
,
187 nsIPrintSettings
* settings
) {
188 nsCOMPtr
<nsIPrintSession
> session
;
189 nsresult rv
= settings
->GetPrintSession(getter_AddRefs(session
));
190 if (NS_SUCCEEDED(rv
) && session
) {
191 session
->SetRemotePrintJob(
192 static_cast<RemotePrintJobChild
*>(data
.remotePrintJobChild()));
194 settings
->SetStartPageRange(data
.startPageRange());
195 settings
->SetEndPageRange(data
.endPageRange());
197 settings
->SetEdgeTop(data
.edgeTop());
198 settings
->SetEdgeLeft(data
.edgeLeft());
199 settings
->SetEdgeBottom(data
.edgeBottom());
200 settings
->SetEdgeRight(data
.edgeRight());
202 settings
->SetMarginTop(data
.marginTop());
203 settings
->SetMarginLeft(data
.marginLeft());
204 settings
->SetMarginBottom(data
.marginBottom());
205 settings
->SetMarginRight(data
.marginRight());
206 settings
->SetUnwriteableMarginTop(data
.unwriteableMarginTop());
207 settings
->SetUnwriteableMarginLeft(data
.unwriteableMarginLeft());
208 settings
->SetUnwriteableMarginBottom(data
.unwriteableMarginBottom());
209 settings
->SetUnwriteableMarginRight(data
.unwriteableMarginRight());
211 settings
->SetScaling(data
.scaling());
213 settings
->SetPrintBGColors(data
.printBGColors());
214 settings
->SetPrintBGImages(data
.printBGImages());
215 settings
->SetHonorPageRuleMargins(data
.honorPageRuleMargins());
216 settings
->SetShowMarginGuides(data
.showMarginGuides());
217 settings
->SetIsPrintSelectionRBEnabled(data
.isPrintSelectionRBEnabled());
218 settings
->SetPrintSelectionOnly(data
.printSelectionOnly());
219 settings
->SetPrintRange(data
.printRange());
221 settings
->SetTitle(data
.title());
222 settings
->SetDocURL(data
.docURL());
225 settings
->SetHeaderStrLeft(data
.headerStrLeft());
226 settings
->SetHeaderStrCenter(data
.headerStrCenter());
227 settings
->SetHeaderStrRight(data
.headerStrRight());
230 settings
->SetFooterStrLeft(data
.footerStrLeft());
231 settings
->SetFooterStrCenter(data
.footerStrCenter());
232 settings
->SetFooterStrRight(data
.footerStrRight());
234 settings
->SetIsCancelled(data
.isCancelled());
235 settings
->SetPrintSilent(data
.printSilent());
236 settings
->SetShrinkToFit(data
.shrinkToFit());
237 settings
->SetShowPrintProgress(data
.showPrintProgress());
239 settings
->SetPaperId(data
.paperId());
241 settings
->SetPaperWidth(data
.paperWidth());
242 settings
->SetPaperHeight(data
.paperHeight());
243 settings
->SetPaperSizeUnit(data
.paperSizeUnit());
245 settings
->SetPrintReversed(data
.printReversed());
246 settings
->SetPrintInColor(data
.printInColor());
247 settings
->SetOrientation(data
.orientation());
249 settings
->SetNumCopies(data
.numCopies());
251 settings
->SetPrinterName(data
.printerName());
253 settings
->SetPrintToFile(data
.printToFile());
255 settings
->SetToFileName(data
.toFileName());
257 settings
->SetOutputFormat(data
.outputFormat());
258 settings
->SetPrintPageDelay(data
.printPageDelay());
259 settings
->SetResolution(data
.resolution());
260 settings
->SetDuplex(data
.duplex());
261 settings
->SetIsInitializedFromPrinter(data
.isInitializedFromPrinter());
262 settings
->SetIsInitializedFromPrefs(data
.isInitializedFromPrefs());
267 /** ---------------------------------------------------
268 * Helper function - Creates the "prefix" for the pref
269 * It is either "print."
270 * or "print.printer_<print name>."
272 const char* nsPrintSettingsService::GetPrefName(const char* aPrefName
,
273 const nsAString
& aPrinterName
) {
274 if (!aPrefName
|| !*aPrefName
) {
275 NS_ERROR("Must have a valid pref name!");
279 mPrefName
.AssignLiteral("print.");
281 if (aPrinterName
.Length()) {
282 mPrefName
.AppendLiteral("printer_");
283 AppendUTF16toUTF8(aPrinterName
, mPrefName
);
284 mPrefName
.Append('.');
286 mPrefName
+= aPrefName
;
288 return mPrefName
.get();
292 * This will either read in the generic prefs (not specific to a printer)
293 * or read the prefs in using the printer name to qualify.
294 * It is either "print.attr_name" or "print.printer_HPLasr5.attr_name"
296 nsresult
nsPrintSettingsService::ReadPrefs(nsIPrintSettings
* aPS
,
297 const nsAString
& aPrinterName
,
299 NS_ENSURE_ARG_POINTER(aPS
);
306 #define GETBOOLPREF(_prefname, _retval) \
308 Preferences::GetBool(GetPrefName(_prefname, aPrinterName), _retval))
310 #define GETSTRPREF(_prefname, _retval) \
312 Preferences::GetString(GetPrefName(_prefname, aPrinterName), _retval))
314 #define GETINTPREF(_prefname, _retval) \
316 Preferences::GetInt(GetPrefName(_prefname, aPrinterName), _retval))
318 #define GETDBLPREF(_prefname, _retval) \
319 NS_SUCCEEDED(ReadPrefDouble(GetPrefName(_prefname, aPrinterName), _retval))
321 bool gotPaperSizeFromPrefs
= false;
322 int16_t paperSizeUnit
;
323 double paperWidth
, paperHeight
;
325 // Paper size prefs are read as a group
326 if (aFlags
& nsIPrintSettings::kInitSavePaperSize
) {
327 gotPaperSizeFromPrefs
= GETINTPREF(kPrintPaperSizeUnit
, &iVal
) &&
328 GETDBLPREF(kPrintPaperWidth
, paperWidth
) &&
329 GETDBLPREF(kPrintPaperHeight
, paperHeight
) &&
330 GETSTRPREF(kPrintPaperId
, str
);
331 paperSizeUnit
= (int16_t)iVal
;
333 if (gotPaperSizeFromPrefs
&&
334 paperSizeUnit
!= nsIPrintSettings::kPaperSizeInches
&&
335 paperSizeUnit
!= nsIPrintSettings::kPaperSizeMillimeters
) {
336 gotPaperSizeFromPrefs
= false;
339 if (gotPaperSizeFromPrefs
) {
340 // Bug 315687: Sanity check paper size to avoid paper size values in
341 // mm when the size unit flag is inches. The value 100 is arbitrary
342 // and can be changed.
343 gotPaperSizeFromPrefs
=
344 (paperSizeUnit
!= nsIPrintSettings::kPaperSizeInches
) ||
345 (paperWidth
< 100.0) || (paperHeight
< 100.0);
348 if (gotPaperSizeFromPrefs
) {
349 aPS
->SetPaperSizeUnit(paperSizeUnit
);
350 aPS
->SetPaperWidth(paperWidth
);
351 aPS
->SetPaperHeight(paperHeight
);
352 aPS
->SetPaperId(str
);
356 nsIntSize pageSizeInTwips
; // to sanity check margins
357 if (!gotPaperSizeFromPrefs
) {
358 aPS
->GetPaperSizeUnit(&paperSizeUnit
);
359 aPS
->GetPaperWidth(&paperWidth
);
360 aPS
->GetPaperHeight(&paperHeight
);
362 if (paperSizeUnit
== nsIPrintSettings::kPaperSizeMillimeters
) {
363 pageSizeInTwips
= nsIntSize((int)NS_MILLIMETERS_TO_TWIPS(paperWidth
),
364 (int)NS_MILLIMETERS_TO_TWIPS(paperHeight
));
366 pageSizeInTwips
= nsIntSize((int)NS_INCHES_TO_TWIPS(paperWidth
),
367 (int)NS_INCHES_TO_TWIPS(paperHeight
));
370 auto MarginIsOK
= [&pageSizeInTwips
](const nsIntMargin
& aMargin
) {
371 return aMargin
.top
>= 0 && aMargin
.right
>= 0 && aMargin
.bottom
>= 0 &&
372 aMargin
.left
>= 0 && aMargin
.LeftRight() < pageSizeInTwips
.width
&&
373 aMargin
.TopBottom() < pageSizeInTwips
.height
;
376 if (aFlags
& nsIPrintSettings::kInitSaveUnwriteableMargins
) {
378 ReadInchesIntToTwipsPref(GetPrefName(kUnwriteableMarginTop
, aPrinterName
),
379 margin
.top
, kUnwriteableMarginTop
);
380 ReadInchesIntToTwipsPref(GetPrefName(kUnwriteableMarginLeft
, aPrinterName
),
381 margin
.left
, kUnwriteableMarginLeft
);
382 ReadInchesIntToTwipsPref(
383 GetPrefName(kUnwriteableMarginBottom
, aPrinterName
), margin
.bottom
,
384 kUnwriteableMarginBottom
);
385 ReadInchesIntToTwipsPref(GetPrefName(kUnwriteableMarginRight
, aPrinterName
),
386 margin
.right
, kUnwriteableMarginRight
);
387 // SetUnwriteableMarginInTwips does its own validation and drops negative
388 // values individually. We still want to block overly large values though,
389 // so we do that part of MarginIsOK manually.
390 if (margin
.LeftRight() < pageSizeInTwips
.width
&&
391 margin
.TopBottom() < pageSizeInTwips
.height
) {
392 aPS
->SetUnwriteableMarginInTwips(margin
);
396 if (aFlags
& nsIPrintSettings::kInitSaveMargins
) {
397 int32_t halfInch
= NS_INCHES_TO_INT_TWIPS(0.5);
398 nsIntMargin
margin(halfInch
, halfInch
, halfInch
, halfInch
);
399 ReadInchesToTwipsPref(GetPrefName(kMarginTop
, aPrinterName
), margin
.top
,
401 ReadInchesToTwipsPref(GetPrefName(kMarginLeft
, aPrinterName
), margin
.left
,
403 ReadInchesToTwipsPref(GetPrefName(kMarginBottom
, aPrinterName
),
404 margin
.bottom
, kMarginBottom
);
405 ReadInchesToTwipsPref(GetPrefName(kMarginRight
, aPrinterName
), margin
.right
,
407 if (MarginIsOK(margin
)) {
408 aPS
->SetMarginInTwips(margin
);
412 if (aFlags
& nsIPrintSettings::kInitSaveEdges
) {
413 nsIntMargin
margin(0, 0, 0, 0);
414 ReadInchesIntToTwipsPref(GetPrefName(kEdgeTop
, aPrinterName
), margin
.top
,
416 ReadInchesIntToTwipsPref(GetPrefName(kEdgeLeft
, aPrinterName
), margin
.left
,
418 ReadInchesIntToTwipsPref(GetPrefName(kEdgeBottom
, aPrinterName
),
419 margin
.bottom
, kEdgeBottom
);
420 ReadInchesIntToTwipsPref(GetPrefName(kEdgeRight
, aPrinterName
),
421 margin
.right
, kEdgeRight
);
422 if (MarginIsOK(margin
)) {
423 aPS
->SetEdgeInTwips(margin
);
427 if (aFlags
& nsIPrintSettings::kInitSaveHeaderLeft
) {
428 if (GETSTRPREF(kPrintHeaderStrLeft
, str
)) {
429 aPS
->SetHeaderStrLeft(str
);
433 if (aFlags
& nsIPrintSettings::kInitSaveHeaderCenter
) {
434 if (GETSTRPREF(kPrintHeaderStrCenter
, str
)) {
435 aPS
->SetHeaderStrCenter(str
);
439 if (aFlags
& nsIPrintSettings::kInitSaveHeaderRight
) {
440 if (GETSTRPREF(kPrintHeaderStrRight
, str
)) {
441 aPS
->SetHeaderStrRight(str
);
445 if (aFlags
& nsIPrintSettings::kInitSaveFooterLeft
) {
446 if (GETSTRPREF(kPrintFooterStrLeft
, str
)) {
447 aPS
->SetFooterStrLeft(str
);
451 if (aFlags
& nsIPrintSettings::kInitSaveFooterCenter
) {
452 if (GETSTRPREF(kPrintFooterStrCenter
, str
)) {
453 aPS
->SetFooterStrCenter(str
);
457 if (aFlags
& nsIPrintSettings::kInitSaveFooterRight
) {
458 if (GETSTRPREF(kPrintFooterStrRight
, str
)) {
459 aPS
->SetFooterStrRight(str
);
463 if (aFlags
& nsIPrintSettings::kInitSaveBGColors
) {
464 if (GETBOOLPREF(kPrintBGColors
, &b
)) {
465 aPS
->SetPrintBGColors(b
);
469 if (aFlags
& nsIPrintSettings::kInitSaveBGImages
) {
470 if (GETBOOLPREF(kPrintBGImages
, &b
)) {
471 aPS
->SetPrintBGImages(b
);
475 if (aFlags
& nsIPrintSettings::kInitSaveReversed
) {
476 if (GETBOOLPREF(kPrintReversed
, &b
)) {
477 aPS
->SetPrintReversed(b
);
481 if (aFlags
& nsIPrintSettings::kInitSaveInColor
) {
482 if (GETBOOLPREF(kPrintInColor
, &b
)) {
483 aPS
->SetPrintInColor(b
);
487 if (aFlags
& nsIPrintSettings::kInitSaveOrientation
) {
488 if (GETINTPREF(kPrintOrientation
, &iVal
) &&
489 (iVal
== nsIPrintSettings::kPortraitOrientation
||
490 iVal
== nsIPrintSettings::kLandscapeOrientation
)) {
491 aPS
->SetOrientation(iVal
);
495 if (aFlags
& nsIPrintSettings::kInitSavePrintToFile
) {
496 if (GETBOOLPREF(kPrintToFile
, &b
)) {
497 aPS
->SetPrintToFile(b
);
501 if (aFlags
& nsIPrintSettings::kInitSaveToFileName
) {
502 if (GETSTRPREF(kPrintToFileName
, str
)) {
503 if (StringEndsWith(str
, u
".ps"_ns
)) {
504 // We only support PDF since bug 1425188 landed. Users may still have
505 // prefs with .ps filenames if they last saved a file as Postscript
506 // though, so we fix that up here. (The pref values will be
507 // overwritten the next time they save to file as a PDF.)
508 str
.Truncate(str
.Length() - 2);
509 str
.AppendLiteral("pdf");
511 aPS
->SetToFileName(str
);
515 if (aFlags
& nsIPrintSettings::kInitSavePageDelay
) {
517 if (GETINTPREF(kPrintPageDelay
, &iVal
) && iVal
>= 0 && iVal
<= 1000) {
518 aPS
->SetPrintPageDelay(iVal
);
522 if (aFlags
& nsIPrintSettings::kInitSaveShrinkToFit
) {
523 if (GETBOOLPREF(kPrintShrinkToFit
, &b
)) {
524 aPS
->SetShrinkToFit(b
);
528 if (aFlags
& nsIPrintSettings::kInitSaveScaling
) {
529 // The limits imposed here are fairly arbitrary and mainly intended to
530 // purge bad values which tend to be negative and/or very large. If we
531 // get complaints from users that settings outside these values "aren't
532 // saved" then we can consider increasing them.
533 if (GETDBLPREF(kPrintScaling
, dbl
) && dbl
>= 0.05 && dbl
<= 20) {
534 aPS
->SetScaling(dbl
);
538 if (aFlags
& nsIPrintSettings::kInitSaveResolution
) {
539 // DPI. Again, an arbitrary range mainly to purge bad values that have made
540 // their way into user prefs.
541 if (GETINTPREF(kPrintResolution
, &iVal
) && iVal
>= 50 && iVal
<= 12000) {
542 aPS
->SetResolution(iVal
);
546 if (aFlags
& nsIPrintSettings::kInitSaveDuplex
) {
547 if (GETINTPREF(kPrintDuplex
, &iVal
)) {
548 aPS
->SetDuplex(iVal
);
558 nsresult
nsPrintSettingsService::WritePrefs(nsIPrintSettings
* aPS
,
559 const nsAString
& aPrinterName
,
561 NS_ENSURE_ARG_POINTER(aPS
);
563 if (aFlags
& nsIPrintSettings::kInitSaveMargins
) {
564 nsIntMargin margin
= aPS
->GetMarginInTwips();
565 WriteInchesFromTwipsPref(GetPrefName(kMarginTop
, aPrinterName
), margin
.top
);
566 WriteInchesFromTwipsPref(GetPrefName(kMarginLeft
, aPrinterName
),
568 WriteInchesFromTwipsPref(GetPrefName(kMarginBottom
, aPrinterName
),
570 WriteInchesFromTwipsPref(GetPrefName(kMarginRight
, aPrinterName
),
574 if (aFlags
& nsIPrintSettings::kInitSaveEdges
) {
575 nsIntMargin edge
= aPS
->GetEdgeInTwips();
576 WriteInchesIntFromTwipsPref(GetPrefName(kEdgeTop
, aPrinterName
), edge
.top
);
577 WriteInchesIntFromTwipsPref(GetPrefName(kEdgeLeft
, aPrinterName
),
579 WriteInchesIntFromTwipsPref(GetPrefName(kEdgeBottom
, aPrinterName
),
581 WriteInchesIntFromTwipsPref(GetPrefName(kEdgeRight
, aPrinterName
),
585 if (aFlags
& nsIPrintSettings::kInitSaveUnwriteableMargins
) {
586 nsIntMargin unwriteableMargin
= aPS
->GetUnwriteableMarginInTwips();
587 WriteInchesIntFromTwipsPref(
588 GetPrefName(kUnwriteableMarginTop
, aPrinterName
),
589 unwriteableMargin
.top
);
590 WriteInchesIntFromTwipsPref(
591 GetPrefName(kUnwriteableMarginLeft
, aPrinterName
),
592 unwriteableMargin
.left
);
593 WriteInchesIntFromTwipsPref(
594 GetPrefName(kUnwriteableMarginBottom
, aPrinterName
),
595 unwriteableMargin
.bottom
);
596 WriteInchesIntFromTwipsPref(
597 GetPrefName(kUnwriteableMarginRight
, aPrinterName
),
598 unwriteableMargin
.right
);
601 // Paper size prefs are saved as a group
602 if (aFlags
& nsIPrintSettings::kInitSavePaperSize
) {
604 double width
, height
;
607 if (NS_SUCCEEDED(aPS
->GetPaperSizeUnit(&sizeUnit
)) &&
608 NS_SUCCEEDED(aPS
->GetPaperWidth(&width
)) &&
609 NS_SUCCEEDED(aPS
->GetPaperHeight(&height
)) &&
610 NS_SUCCEEDED(aPS
->GetPaperId(name
))) {
611 Preferences::SetInt(GetPrefName(kPrintPaperSizeUnit
, aPrinterName
),
613 WritePrefDouble(GetPrefName(kPrintPaperWidth
, aPrinterName
), width
);
614 WritePrefDouble(GetPrefName(kPrintPaperHeight
, aPrinterName
), height
);
615 Preferences::SetString(GetPrefName(kPrintPaperId
, aPrinterName
), name
);
624 if (aFlags
& nsIPrintSettings::kInitSaveHeaderLeft
) {
625 if (NS_SUCCEEDED(aPS
->GetHeaderStrLeft(uStr
))) {
626 Preferences::SetString(GetPrefName(kPrintHeaderStrLeft
, aPrinterName
),
631 if (aFlags
& nsIPrintSettings::kInitSaveHeaderCenter
) {
632 if (NS_SUCCEEDED(aPS
->GetHeaderStrCenter(uStr
))) {
633 Preferences::SetString(GetPrefName(kPrintHeaderStrCenter
, aPrinterName
),
638 if (aFlags
& nsIPrintSettings::kInitSaveHeaderRight
) {
639 if (NS_SUCCEEDED(aPS
->GetHeaderStrRight(uStr
))) {
640 Preferences::SetString(GetPrefName(kPrintHeaderStrRight
, aPrinterName
),
645 if (aFlags
& nsIPrintSettings::kInitSaveFooterLeft
) {
646 if (NS_SUCCEEDED(aPS
->GetFooterStrLeft(uStr
))) {
647 Preferences::SetString(GetPrefName(kPrintFooterStrLeft
, aPrinterName
),
652 if (aFlags
& nsIPrintSettings::kInitSaveFooterCenter
) {
653 if (NS_SUCCEEDED(aPS
->GetFooterStrCenter(uStr
))) {
654 Preferences::SetString(GetPrefName(kPrintFooterStrCenter
, aPrinterName
),
659 if (aFlags
& nsIPrintSettings::kInitSaveFooterRight
) {
660 if (NS_SUCCEEDED(aPS
->GetFooterStrRight(uStr
))) {
661 Preferences::SetString(GetPrefName(kPrintFooterStrRight
, aPrinterName
),
666 if (aFlags
& nsIPrintSettings::kInitSaveBGColors
) {
667 b
= aPS
->GetPrintBGColors();
668 Preferences::SetBool(GetPrefName(kPrintBGColors
, aPrinterName
), b
);
671 if (aFlags
& nsIPrintSettings::kInitSaveBGImages
) {
672 b
= aPS
->GetPrintBGImages();
673 Preferences::SetBool(GetPrefName(kPrintBGImages
, aPrinterName
), b
);
676 if (aFlags
& nsIPrintSettings::kInitSaveReversed
) {
677 if (NS_SUCCEEDED(aPS
->GetPrintReversed(&b
))) {
678 Preferences::SetBool(GetPrefName(kPrintReversed
, aPrinterName
), b
);
682 if (aFlags
& nsIPrintSettings::kInitSaveInColor
) {
683 if (NS_SUCCEEDED(aPS
->GetPrintInColor(&b
))) {
684 Preferences::SetBool(GetPrefName(kPrintInColor
, aPrinterName
), b
);
688 if (aFlags
& nsIPrintSettings::kInitSaveOrientation
) {
689 if (NS_SUCCEEDED(aPS
->GetOrientation(&iVal
))) {
690 Preferences::SetInt(GetPrefName(kPrintOrientation
, aPrinterName
), iVal
);
694 // Only the general version of this pref is saved
695 if ((aFlags
& nsIPrintSettings::kInitSavePrinterName
) &&
696 aPrinterName
.IsEmpty()) {
697 if (NS_SUCCEEDED(aPS
->GetPrinterName(uStr
))) {
698 Preferences::SetString(kPrinterName
, uStr
);
702 if (aFlags
& nsIPrintSettings::kInitSavePrintToFile
) {
703 if (NS_SUCCEEDED(aPS
->GetPrintToFile(&b
))) {
704 Preferences::SetBool(GetPrefName(kPrintToFile
, aPrinterName
), b
);
708 if (aFlags
& nsIPrintSettings::kInitSaveToFileName
) {
709 if (NS_SUCCEEDED(aPS
->GetToFileName(uStr
))) {
710 Preferences::SetString(GetPrefName(kPrintToFileName
, aPrinterName
), uStr
);
714 if (aFlags
& nsIPrintSettings::kInitSavePageDelay
) {
715 if (NS_SUCCEEDED(aPS
->GetPrintPageDelay(&iVal
))) {
716 Preferences::SetInt(GetPrefName(kPrintPageDelay
, aPrinterName
), iVal
);
720 if (aFlags
& nsIPrintSettings::kInitSaveShrinkToFit
) {
721 if (NS_SUCCEEDED(aPS
->GetShrinkToFit(&b
))) {
722 Preferences::SetBool(GetPrefName(kPrintShrinkToFit
, aPrinterName
), b
);
726 if (aFlags
& nsIPrintSettings::kInitSaveScaling
) {
727 if (NS_SUCCEEDED(aPS
->GetScaling(&dbl
))) {
728 WritePrefDouble(GetPrefName(kPrintScaling
, aPrinterName
), dbl
);
732 if (aFlags
& nsIPrintSettings::kInitSaveResolution
) {
733 if (NS_SUCCEEDED(aPS
->GetResolution(&iVal
))) {
734 Preferences::SetInt(GetPrefName(kPrintResolution
, aPrinterName
), iVal
);
738 if (aFlags
& nsIPrintSettings::kInitSaveDuplex
) {
739 if (NS_SUCCEEDED(aPS
->GetDuplex(&iVal
))) {
740 Preferences::SetInt(GetPrefName(kPrintDuplex
, aPrinterName
), iVal
);
751 nsPrintSettingsService::GetDefaultPrintSettingsForPrinting(
752 nsIPrintSettings
** aPrintSettings
) {
753 nsresult rv
= GetNewPrintSettings(aPrintSettings
);
754 NS_ENSURE_SUCCESS(rv
, rv
);
756 nsIPrintSettings
* settings
= *aPrintSettings
;
758 nsAutoString printerName
;
759 settings
->GetPrinterName(printerName
);
760 if (printerName
.IsEmpty()) {
761 GetLastUsedPrinterName(printerName
);
762 settings
->SetPrinterName(printerName
);
764 InitPrintSettingsFromPrinter(printerName
, settings
);
765 InitPrintSettingsFromPrefs(settings
, true, nsIPrintSettings::kInitSaveAll
);
770 nsPrintSettingsService::GetNewPrintSettings(
771 nsIPrintSettings
** aNewPrintSettings
) {
772 return _CreatePrintSettings(aNewPrintSettings
);
776 nsPrintSettingsService::GetLastUsedPrinterName(
777 nsAString
& aLastUsedPrinterName
) {
778 aLastUsedPrinterName
.Truncate();
779 Preferences::GetString(kPrinterName
, aLastUsedPrinterName
);
784 nsPrintSettingsService::InitPrintSettingsFromPrinter(
785 const nsAString
& aPrinterName
, nsIPrintSettings
* aPrintSettings
) {
786 // Don't get print settings from the printer in the child when printing via
787 // parent, these will be retrieved in the parent later in the print process.
788 if (XRE_IsContentProcess() &&
789 Preferences::GetBool("print.print_via_parent")) {
793 NS_ENSURE_ARG_POINTER(aPrintSettings
);
796 nsString printerName
;
797 aPrintSettings
->GetPrinterName(printerName
);
798 if (!printerName
.Equals(aPrinterName
)) {
799 NS_WARNING("Printer names should match!");
804 aPrintSettings
->GetIsInitializedFromPrinter(&isInitialized
);
805 if (isInitialized
) return NS_OK
;
808 nsCOMPtr
<nsIPrinterList
> printerList
=
809 do_GetService(NS_PRINTER_LIST_CONTRACTID
, &rv
);
810 NS_ENSURE_SUCCESS(rv
, rv
);
812 rv
= printerList
->InitPrintSettingsFromPrinter(aPrinterName
, aPrintSettings
);
813 NS_ENSURE_SUCCESS(rv
, rv
);
815 aPrintSettings
->SetIsInitializedFromPrinter(true);
819 /** ---------------------------------------------------
820 * Helper function - Returns either the name or sets the length to zero
822 static nsresult
GetAdjustedPrinterName(nsIPrintSettings
* aPS
, bool aUsePNP
,
823 nsAString
& aPrinterName
) {
824 NS_ENSURE_ARG_POINTER(aPS
);
826 aPrinterName
.Truncate();
827 if (!aUsePNP
) return NS_OK
;
829 // Get the Printer Name from the PrintSettings
830 // to use as a prefix for Pref Names
831 nsresult rv
= aPS
->GetPrinterName(aPrinterName
);
832 NS_ENSURE_SUCCESS(rv
, rv
);
834 // Convert any whitespaces, carriage returns or newlines to _
835 // The below algorithm is supposedly faster than using iterators
836 constexpr auto replSubstr
= u
"_"_ns
;
837 const char* replaceStr
= " \n\r";
840 for (x
= 0; x
< (int32_t)strlen(replaceStr
); x
++) {
841 char16_t uChar
= replaceStr
[x
];
844 while ((i
= aPrinterName
.FindChar(uChar
, i
)) != kNotFound
) {
845 aPrinterName
.Replace(i
, 1, replSubstr
);
853 nsPrintSettingsService::InitPrintSettingsFromPrefs(nsIPrintSettings
* aPS
,
856 NS_ENSURE_ARG_POINTER(aPS
);
859 aPS
->GetIsInitializedFromPrefs(&isInitialized
);
861 if (isInitialized
) return NS_OK
;
863 auto globalPrintSettings
= aFlags
;
864 #ifndef MOZ_WIDGET_ANDROID
865 globalPrintSettings
&= nsIPrintSettings::kInitSaveShrinkToFit
|
866 nsIPrintSettings::kInitSaveHeaderLeft
|
867 nsIPrintSettings::kInitSaveHeaderCenter
|
868 nsIPrintSettings::kInitSaveHeaderRight
|
869 nsIPrintSettings::kInitSaveFooterLeft
|
870 nsIPrintSettings::kInitSaveFooterCenter
|
871 nsIPrintSettings::kInitSaveFooterRight
|
872 nsIPrintSettings::kInitSaveEdges
|
873 nsIPrintSettings::kInitSaveReversed
|
874 nsIPrintSettings::kInitSaveInColor
;
877 nsAutoString prtName
;
878 // read any non printer specific prefs
879 // with empty printer name
880 nsresult rv
= ReadPrefs(aPS
, prtName
, globalPrintSettings
);
881 NS_ENSURE_SUCCESS(rv
, rv
);
883 // Get the Printer Name from the PrintSettings to use as a prefix for Pref
885 rv
= GetAdjustedPrinterName(aPS
, aUsePNP
, prtName
);
886 NS_ENSURE_SUCCESS(rv
, rv
);
888 if (prtName
.IsEmpty()) {
889 NS_WARNING("Caller should supply a printer name.");
893 // Now read any printer specific prefs
894 rv
= ReadPrefs(aPS
, prtName
, aFlags
);
895 if (NS_SUCCEEDED(rv
)) aPS
->SetIsInitializedFromPrefs(true);
901 * Save all of the printer settings; if we can find a printer name, save
902 * printer-specific preferences. Otherwise, save generic ones.
904 nsresult
nsPrintSettingsService::SavePrintSettingsToPrefs(
905 nsIPrintSettings
* aPS
, bool aUsePrinterNamePrefix
, uint32_t aFlags
) {
906 NS_ENSURE_ARG_POINTER(aPS
);
908 if (GeckoProcessType_Content
== XRE_GetProcessType()) {
909 // If we're in the content process, we can't directly write to the
910 // Preferences service - we have to proxy the save up to the
912 RefPtr
<nsPrintingProxy
> proxy
= nsPrintingProxy::GetInstance();
913 return proxy
->SavePrintSettings(aPS
, aUsePrinterNamePrefix
, aFlags
);
916 nsAutoString prtName
;
918 // Get the printer name from the PrinterSettings for an optional prefix.
919 nsresult rv
= GetAdjustedPrinterName(aPS
, aUsePrinterNamePrefix
, prtName
);
920 NS_ENSURE_SUCCESS(rv
, rv
);
922 // Write the prefs, with or without a printer name prefix.
923 return WritePrefs(aPS
, prtName
, aFlags
);
926 //-----------------------------------------------------
927 //-- Protected Methods --------------------------------
928 //-----------------------------------------------------
929 nsresult
nsPrintSettingsService::ReadPrefDouble(const char* aPrefId
,
931 NS_ENSURE_ARG_POINTER(aPrefId
);
934 nsresult rv
= Preferences::GetCString(aPrefId
, str
);
935 if (NS_FAILED(rv
) || str
.IsEmpty()) {
936 return NS_ERROR_NOT_AVAILABLE
;
939 double value
= str
.ToDouble(&rv
);
948 nsresult
nsPrintSettingsService::WritePrefDouble(const char* aPrefId
,
950 NS_ENSURE_ARG_POINTER(aPrefId
);
953 // We cast to a float so we only get up to 6 digits precision in the prefs.
954 str
.AppendFloat((float)aVal
);
955 return Preferences::SetCString(aPrefId
, str
);
958 void nsPrintSettingsService::ReadInchesToTwipsPref(const char* aPrefId
,
960 const char* aMarginPref
) {
962 nsresult rv
= Preferences::GetString(aPrefId
, str
);
963 if (NS_FAILED(rv
) || str
.IsEmpty()) {
964 rv
= Preferences::GetString(aMarginPref
, str
);
966 if (NS_SUCCEEDED(rv
) && !str
.IsEmpty()) {
968 float inches
= str
.ToFloat(&errCode
);
969 if (NS_SUCCEEDED(errCode
)) {
970 aTwips
= NS_INCHES_TO_INT_TWIPS(inches
);
977 void nsPrintSettingsService::WriteInchesFromTwipsPref(const char* aPrefId
,
979 double inches
= NS_TWIPS_TO_INCHES(aTwips
);
980 nsAutoCString inchesStr
;
981 inchesStr
.AppendFloat(inches
);
983 Preferences::SetCString(aPrefId
, inchesStr
);
986 void nsPrintSettingsService::ReadInchesIntToTwipsPref(const char* aPrefId
,
988 const char* aMarginPref
) {
990 nsresult rv
= Preferences::GetInt(aPrefId
, &value
);
992 rv
= Preferences::GetInt(aMarginPref
, &value
);
994 if (NS_SUCCEEDED(rv
)) {
995 aTwips
= NS_INCHES_TO_INT_TWIPS(float(value
) / 100.0f
);
1001 void nsPrintSettingsService::WriteInchesIntFromTwipsPref(const char* aPrefId
,
1003 Preferences::SetInt(aPrefId
,
1004 int32_t(NS_TWIPS_TO_INCHES(aTwips
) * 100.0f
+ 0.5f
));
1007 void nsPrintSettingsService::ReadJustification(const char* aPrefId
,
1009 int16_t aInitValue
) {
1011 nsAutoString justStr
;
1012 if (NS_SUCCEEDED(Preferences::GetString(aPrefId
, justStr
))) {
1013 if (justStr
.EqualsASCII(kJustRight
)) {
1014 aJust
= nsIPrintSettings::kJustRight
;
1015 } else if (justStr
.EqualsASCII(kJustCenter
)) {
1016 aJust
= nsIPrintSettings::kJustCenter
;
1018 aJust
= nsIPrintSettings::kJustLeft
;
1023 //---------------------------------------------------
1024 void nsPrintSettingsService::WriteJustification(const char* aPrefId
,
1027 case nsIPrintSettings::kJustLeft
:
1028 Preferences::SetCString(aPrefId
, kJustLeft
);
1031 case nsIPrintSettings::kJustCenter
:
1032 Preferences::SetCString(aPrefId
, kJustCenter
);
1035 case nsIPrintSettings::kJustRight
:
1036 Preferences::SetCString(aPrefId
, kJustRight
);