Back to index

lightning-sunbird  0.9+nobinonly
nsPrintSettingsX.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *   Conrad Carlen <ccarlen@netscape.com>
00024  *
00025  * Alternatively, the contents of this file may be used under the terms of
00026  * either of the GNU General Public License Version 2 or later (the "GPL"),
00027  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00028  * in which case the provisions of the GPL or the LGPL are applicable instead
00029  * of those above. If you wish to allow use of your version of this file only
00030  * under the terms of either the GPL or the LGPL, and not to allow others to
00031  * use your version of this file under the terms of the MPL, indicate your
00032  * decision by deleting the provisions above and replace them with the notice
00033  * and other provisions required by the GPL or the LGPL. If you do not delete
00034  * the provisions above, a recipient may use your version of this file under
00035  * the terms of any one of the MPL, the GPL or the LGPL.
00036  *
00037  * ***** END LICENSE BLOCK ***** */
00038 
00039 #include "nsPrintSettingsX.h"
00040 #include "nsIPrintSessionX.h"
00041 
00042 #include "nsIPrefService.h"
00043 #include "nsIPrefBranch.h"
00044 #include "nsServiceManagerUtils.h"
00045 
00046 #include "plbase64.h"
00047 #include "prmem.h"
00048 #include "prnetdb.h"
00049 #include "nsGfxUtils.h"
00050 
00051 // This struct should be represented identically on all architectures, and
00052 // there shouldn't be any padding before the data field.
00053 struct FrozenHandle {
00054   PRUint32 size;
00055   char     data[0];
00056 };
00057 
00058 // Constants
00059 #define PRINTING_PREF_BRANCH            "print."
00060 #define MAC_OS_X_PAGE_SETUP_PREFNAME    "macosx.pagesetup-2"
00061 
00062 
00063 NS_IMPL_ISUPPORTS_INHERITED1(nsPrintSettingsX, 
00064                              nsPrintSettings, 
00065                              nsIPrintSettingsX)
00066 
00067 
00069 nsPrintSettingsX::nsPrintSettingsX() :
00070   mPageFormat(kPMNoPageFormat),
00071   mPrintSettings(kPMNoPrintSettings)
00072 {
00073 }
00074 
00077 nsPrintSettingsX::nsPrintSettingsX(const nsPrintSettingsX& src) :
00078   mPageFormat(kPMNoPageFormat),
00079   mPrintSettings(kPMNoPrintSettings)
00080 {
00081   *this = src;
00082 }
00083 
00086 nsPrintSettingsX::~nsPrintSettingsX()
00087 {
00088   if (mPageFormat != kPMNoPageFormat) {
00089     ::PMRelease(mPageFormat);
00090     mPageFormat = kPMNoPageFormat;
00091   }
00092   if (mPrintSettings != kPMNoPrintSettings) {
00093     ::PMRelease(mPrintSettings);
00094     mPrintSettings = kPMNoPrintSettings;
00095   }
00096 }
00097 
00100 nsPrintSettingsX& nsPrintSettingsX::operator=(const nsPrintSettingsX& rhs)
00101 {
00102   if (this == &rhs) {
00103     return *this;
00104   }
00105   
00106   nsPrintSettings::operator=(rhs);
00107 
00108   OSStatus status;
00109    
00110   if (mPageFormat != kPMNoPageFormat) {
00111     ::PMRelease(mPageFormat);
00112     mPageFormat = kPMNoPageFormat;
00113   }
00114   if (rhs.mPageFormat != kPMNoPageFormat) {
00115     PMPageFormat pageFormat;
00116     status = ::PMCreatePageFormat(&pageFormat);
00117     if (status == noErr) {
00118       status = ::PMCopyPageFormat(rhs.mPageFormat, pageFormat);
00119       if (status == noErr)
00120         mPageFormat = pageFormat;
00121       else
00122         ::PMRelease(pageFormat);
00123     }
00124   }
00125   
00126   if (mPrintSettings != kPMNoPrintSettings) {
00127     ::PMRelease(mPrintSettings);
00128     mPrintSettings = kPMNoPrintSettings;
00129   }
00130   if (rhs.mPrintSettings != kPMNoPrintSettings) {
00131     PMPrintSettings    printSettings;
00132     status = ::PMCreatePrintSettings(&printSettings);
00133     if (status == noErr) {
00134       status = ::PMCopyPrintSettings(rhs.mPrintSettings, printSettings);
00135       if (status == noErr)
00136         mPrintSettings = printSettings;
00137       else
00138         ::PMRelease(printSettings);
00139     }
00140   }
00141 
00142   return *this;
00143 }
00144 
00147 nsresult nsPrintSettingsX::Init()
00148 {
00149   OSStatus status;
00150 
00151   PMPrintSession printSession = NULL;
00152   status = ::PMCreateSession(&printSession);
00153   
00154   if (status == noErr) {
00155     // First, create a default page format
00156     status = CreateDefaultPageFormat(printSession, mPageFormat);
00157 
00158     // Then, if no error, create the default print settings
00159     if (status == noErr) {
00160       status = CreateDefaultPrintSettings(printSession, mPrintSettings);
00161     }
00162     OSStatus tempStatus = ::PMRelease(printSession);
00163     if (status == noErr)
00164       status = tempStatus;
00165   }
00166   return (status == noErr) ? NS_OK : NS_ERROR_FAILURE;
00167 }
00168 
00171 NS_IMETHODIMP nsPrintSettingsX::GetNativePrintSession(PMPrintSession *aNativePrintSession)
00172 {
00173    NS_ENSURE_ARG_POINTER(aNativePrintSession);
00174    *aNativePrintSession = nsnull;
00175    
00176    nsCOMPtr<nsIPrintSession> printSession;
00177    GetPrintSession(getter_AddRefs(printSession));
00178    if (!printSession)
00179     return NS_ERROR_FAILURE;
00180    nsCOMPtr<nsIPrintSessionX> printSessionX(do_QueryInterface(printSession));
00181    if (!printSession)
00182     return NS_ERROR_FAILURE;
00183 
00184    return printSessionX->GetNativeSession(aNativePrintSession);
00185 }
00186 
00189 NS_IMETHODIMP nsPrintSettingsX::GetPMPageFormat(PMPageFormat *aPMPageFormat)
00190 {
00191   NS_ENSURE_ARG_POINTER(aPMPageFormat);
00192   *aPMPageFormat = kPMNoPageFormat;
00193   NS_ENSURE_STATE(mPageFormat != kPMNoPageFormat);
00194   
00195   *aPMPageFormat = mPageFormat;
00196   OSStatus status = noErr;
00197   
00198   return (status == noErr) ? NS_OK : NS_ERROR_FAILURE;
00199 }
00200 
00203 NS_IMETHODIMP nsPrintSettingsX::SetPMPageFormat(PMPageFormat aPMPageFormat)
00204 {
00205   NS_ENSURE_ARG(aPMPageFormat);
00206   
00207   OSStatus status = ::PMRetain(aPMPageFormat);
00208   if (status == noErr) {
00209     if (mPageFormat)
00210       status = ::PMRelease(mPageFormat);
00211     mPageFormat = aPMPageFormat;
00212   }        
00213   return (status == noErr) ? NS_OK : NS_ERROR_FAILURE;
00214 }
00215 
00218 NS_IMETHODIMP nsPrintSettingsX::GetPMPrintSettings(PMPrintSettings *aPMPrintSettings)
00219 {
00220   NS_ENSURE_ARG_POINTER(aPMPrintSettings);
00221   *aPMPrintSettings = kPMNoPrintSettings;
00222   NS_ENSURE_STATE(mPrintSettings != kPMNoPrintSettings);
00223   
00224   *aPMPrintSettings = mPrintSettings;
00225   OSStatus status = noErr;
00226   
00227   return (status == noErr) ? NS_OK : NS_ERROR_FAILURE;
00228 }
00229 
00232 NS_IMETHODIMP nsPrintSettingsX::SetPMPrintSettings(PMPrintSettings aPMPrintSettings)
00233 {
00234   NS_ENSURE_ARG(aPMPrintSettings);
00235   
00236   OSStatus status = ::PMRetain(aPMPrintSettings);
00237   if (status == noErr) {
00238     if (mPrintSettings)
00239       status = ::PMRelease(mPrintSettings);
00240     mPrintSettings = aPMPrintSettings;
00241   }        
00242   return (status == noErr) ? NS_OK : NS_ERROR_FAILURE;
00243 }
00244 
00247 NS_IMETHODIMP nsPrintSettingsX::ReadPageFormatFromPrefs()
00248 {
00249   nsresult rv;
00250   nsCOMPtr<nsIPrefService> prefService(do_GetService(NS_PREFSERVICE_CONTRACTID, &rv));
00251   if (NS_FAILED(rv))
00252     return rv;
00253   nsCOMPtr<nsIPrefBranch> prefBranch;
00254   rv = prefService->GetBranch(PRINTING_PREF_BRANCH, getter_AddRefs(prefBranch));
00255   if (NS_FAILED(rv))
00256     return rv;
00257       
00258   nsXPIDLCString  encodedData;
00259   rv = prefBranch->GetCharPref(MAC_OS_X_PAGE_SETUP_PREFNAME, getter_Copies(encodedData));
00260   if (NS_FAILED(rv))
00261     return rv;
00262 
00263   // decode the base64
00264   PRInt32 encodedDataLen = encodedData.Length();
00265   FrozenHandle* frozenHandle =
00266    (FrozenHandle*)::PL_Base64Decode(encodedData.get(), encodedDataLen, nsnull);
00267   if (!frozenHandle)
00268     return NS_ERROR_FAILURE;
00269 
00270   PRUint32 handleSize = PR_ntohl(frozenHandle->size);
00271 
00272   // Ensure that the length reported in the frozen handle agrees with the
00273   // amount of decoded data.  At most 3 bytes of data map to 4 bytes when
00274   // base64-encoded.
00275   PRUint32 maximumDataSize = (encodedDataLen * 3) / 4 - sizeof(FrozenHandle);
00276   PRUint32 minimumDataSize = maximumDataSize - 2;
00277   if (handleSize > maximumDataSize || handleSize < minimumDataSize) {
00278     PR_Free(frozenHandle);
00279     return NS_ERROR_FAILURE;
00280   }
00281 
00282   Handle    decodedDataHandle = nsnull;
00283   OSErr err = ::PtrToHand(frozenHandle->data, &decodedDataHandle, handleSize);
00284   PR_Free(frozenHandle);
00285   if (err != noErr)
00286     return NS_ERROR_OUT_OF_MEMORY;
00287 
00288   StHandleOwner   handleOwner(decodedDataHandle);  
00289 
00290   OSStatus      status;
00291   PMPageFormat  newPageFormat = kPMNoPageFormat;
00292   
00293   status = ::PMCreatePageFormat(&newPageFormat);
00294   if (status == noErr) { 
00295     status = ::PMUnflattenPageFormat(decodedDataHandle, &newPageFormat);
00296     if (status == noErr) {
00297       if (mPageFormat)
00298         status = ::PMRelease(mPageFormat);
00299       mPageFormat = newPageFormat; // PMCreatePageFormat returned it with a refcnt of 1
00300     }
00301   }
00302   return (status == noErr) ? NS_OK : NS_ERROR_FAILURE;
00303 }
00304 
00307 NS_IMETHODIMP nsPrintSettingsX::WritePageFormatToPrefs()
00308 {
00309   if (mPageFormat == kPMNoPageFormat)
00310     return NS_ERROR_NOT_INITIALIZED;
00311     
00312   nsresult rv;
00313   nsCOMPtr<nsIPrefService> prefService(do_GetService(NS_PREFSERVICE_CONTRACTID, &rv));
00314   if (NS_FAILED(rv))
00315     return rv;
00316   nsCOMPtr<nsIPrefBranch> prefBranch;
00317   rv = prefService->GetBranch(PRINTING_PREF_BRANCH, getter_AddRefs(prefBranch));
00318   if (NS_FAILED(rv))
00319     return rv;
00320 
00321   Handle    pageFormatHandle = nsnull;
00322   OSStatus  err = ::PMFlattenPageFormat(mPageFormat, &pageFormatHandle);
00323   if (err != noErr)
00324     return NS_ERROR_FAILURE;
00325     
00326   StHandleOwner   handleOwner(pageFormatHandle);
00327   StHandleLocker  handleLocker(pageFormatHandle);
00328 
00329   // Save the handle in a struct that identifies the data length and
00330   // the data itself, and wrap it all up in base64.  The length must be
00331   // included because PL_DecodeBase64 doesn't return the size of the
00332   // decoded data, and the handle will need to be reconstructed later with
00333   // the correct size.
00334   PRUint32 dataSize = ::GetHandleSize(pageFormatHandle);
00335   PRUint32 frozenDataSize = sizeof(FrozenHandle) + dataSize;
00336   FrozenHandle* frozenHandle = (FrozenHandle*)PR_Malloc(frozenDataSize);
00337   if (!frozenHandle)
00338     return NS_ERROR_OUT_OF_MEMORY;
00339 
00340   frozenHandle->size = PR_htonl(dataSize);
00341   memcpy(&frozenHandle->data, *pageFormatHandle, dataSize);
00342 
00343   nsXPIDLCString  encodedData;
00344   encodedData.Adopt(::PL_Base64Encode((char*)frozenHandle, frozenDataSize,
00345                     nsnull));
00346   PR_Free(frozenHandle);
00347   if (!encodedData.get())
00348     return NS_ERROR_OUT_OF_MEMORY;
00349 
00350   return prefBranch->SetCharPref(MAC_OS_X_PAGE_SETUP_PREFNAME, encodedData);
00351 }
00352 
00353 //-------------------------------------------
00354 nsresult nsPrintSettingsX::_Clone(nsIPrintSettings **_retval)
00355 {
00356   NS_ENSURE_ARG_POINTER(_retval);
00357   *_retval = nsnull;
00358   
00359   nsPrintSettingsX *newSettings = new nsPrintSettingsX(*this);
00360   if (!newSettings)
00361     return NS_ERROR_FAILURE;
00362   *_retval = newSettings;
00363   NS_ADDREF(*_retval);
00364   return NS_OK;
00365 }
00366 
00367 
00368 //-------------------------------------------
00369 NS_IMETHODIMP nsPrintSettingsX::_Assign(nsIPrintSettings *aPS)
00370 {
00371   nsPrintSettingsX *printSettingsX = NS_STATIC_CAST(nsPrintSettingsX*, aPS);
00372   if (!printSettingsX)
00373     return NS_ERROR_UNEXPECTED;
00374   *this = *printSettingsX;
00375   return NS_OK;
00376 }
00377 
00378 //-------------------------------------------
00379 OSStatus nsPrintSettingsX::CreateDefaultPageFormat(PMPrintSession aSession, PMPageFormat& outFormat)
00380 {
00381   OSStatus status;
00382   PMPageFormat pageFormat;
00383   
00384   outFormat = kPMNoPageFormat;
00385   status = ::PMCreatePageFormat(&pageFormat);
00386     if (status == noErr && pageFormat != kPMNoPageFormat) {
00387       status = ::PMSessionDefaultPageFormat(aSession, pageFormat);
00388     if (status == noErr) {
00389       outFormat = pageFormat;
00390       return NS_OK;
00391     }
00392   }
00393   return status;
00394 }
00395   
00396 //-------------------------------------------
00397 
00398 OSStatus nsPrintSettingsX::CreateDefaultPrintSettings(PMPrintSession aSession, PMPrintSettings& outSettings)
00399 {
00400   OSStatus status;
00401   PMPrintSettings printSettings;
00402   
00403   outSettings = kPMNoPrintSettings;
00404   status = ::PMCreatePrintSettings(&printSettings);
00405   if (status == noErr && printSettings != kPMNoPrintSettings) {
00406     status = ::PMSessionDefaultPrintSettings(aSession, printSettings);
00407     if (status == noErr) {
00408       outSettings = printSettings;
00409       return noErr;
00410     }
00411   }
00412   return status;  
00413 }
00414