--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/graphicsdeviceinterface/gdi/sgdi/PRINTGDI.CPP Tue Feb 02 01:47:50 2010 +0200
@@ -0,0 +1,906 @@
+// Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+
+#include <gdi.h>
+#include <f32file.h>
+#include <s32file.h>
+#include <bautils.h>
+#include <barsc.h>
+#include <barsread.h>
+#include "GDIPANIC.h"
+
+_LIT(KPdrExtension,"*.PDR"); // must be capitalized
+_LIT(KPdlExtension,".PDL"); // must be capitalized
+_LIT(KUdlExtension,".UDL"); // must be capitalized
+_LIT(KRscExtension,".RSC");
+_LIT(KGdiPrintPanic,"GDI - PRINT");
+
+_LIT(KGDIPanicDesc1, "GDI Pdr internal Panic %S, in file %S @ line %i");
+_LIT(KGDIPanicDesc2, "Assert condition = \"%S\"");
+
+enum TPdrStorePanic
+ {
+ EPdrModelIndexOutOfRange,
+ EPdrModelUidNotFound,
+ EPdrDirectoryIndexOutOfRange,
+ EPdrFileIndexOutOfRange,
+ EPdrPrinterDeviceExists,
+ EPdrPrinterDeviceDoesNotExist,
+ };
+
+void Panic(TPdrStorePanic aPanic)
+ {
+ User::Panic(KGdiPrintPanic,aPanic);
+ }
+
+void PanicWithCondAndInfo(TPdrStorePanic aError, const TDesC& aCondition, const TDesC& aFileName, const TDesC& aPanicName, TInt aLine)
+ {
+ TBuf<256> buf;
+ buf.Format(KGDIPanicDesc1, &aPanicName, &aFileName, aLine);
+ RDebug::Print(buf);
+
+ buf.Format(KGDIPanicDesc2, &aCondition);
+ RDebug::Print(buf);
+ Panic(aError);
+ }
+
+//
+// TPrinterModelEntry
+//
+
+
+EXPORT_C void TPrinterModelEntry::InternalizeL(RReadStream& aStream)
+
+/** Internalises a printer model entry from a read stream.
+
+The presence of this function means that the standard templated stream operator>>(),
+defined in s32strm.h, is available to internalise objects of this class.
+
+@param aStream The read stream. */
+ {
+ aStream >> iModelName;
+ iRequiresPrinterPort=aStream.ReadUint8L();
+ aStream >> iUid;
+ }
+
+
+EXPORT_C void TPrinterModelEntry::ExternalizeL(RWriteStream& aStream) const
+/** Externalises the printer model entry to a write stream.
+
+The presence of this function means that the standard templated stream operator<<(),
+defined in s32strm.h, is available to externalise objects of this class.
+
+@param aStream The write stream. */
+ {
+ aStream << iModelName;
+ aStream.WriteUint8L((TUint8) iRequiresPrinterPort);
+ aStream << iUid;
+ }
+
+//
+// TPrinterModelHeader
+//
+
+
+EXPORT_C void TPrinterModelHeader::InternalizeL(RReadStream& aStream)
+/** Internalises a printer model header from a read stream.
+
+The presence of this function means that the standard templated stream operator>>(),
+defined in s32strm.h, is available to internalise objects of this class.
+
+@param aStream The read stream. */
+ {
+ aStream >> iEntry;
+ aStream >> iModelDataStreamId;
+ }
+
+
+EXPORT_C void TPrinterModelHeader::ExternalizeL(RWriteStream& aStream) const
+
+/** Externalises the printer model header to a write stream.
+
+The presence of this function means that the standard templated stream operator<<(),
+defined in s32strm.h, is available to externalise objects of this class.
+@param aStream The write stream. */
+ {
+ aStream << iEntry;
+ aStream << iModelDataStreamId;
+ }
+
+//
+// CPrinterDevice
+//
+
+EXPORT_C CPrinterDevice::CPrinterDevice():
+ CGraphicsDevice(),
+ iCurrentPageSpecInTwips()
+/** Standard constructor. */
+ {}
+
+
+EXPORT_C CPrinterDevice::~CPrinterDevice()
+
+/** Destructor.
+It frees all resources owned by the object, prior to its destruction. */
+ {
+ delete iControl;
+ }
+
+
+EXPORT_C void CPrinterDevice::SelectPageSpecInTwips(const TPageSpec& aPageSpecInTwips)
+/** Sets the page specification in twips.
+@param aPageSpec The page specification in twips. */
+ {
+ iCurrentPageSpecInTwips=aPageSpecInTwips;
+ }
+
+
+EXPORT_C TRect CPrinterDevice::PrintablePageInPixels() const
+/** Gets the dimensions of the area to which the printer device can print.
+
+These dimensions are normally less than those returned by TPageSpec::OrientedPageSize()
+because a margin exists between the boundary of the printable page and the
+absolute extent of the page.
+
+@return The dimensions of the printer device area in pixels, respecting the
+page orientation */
+ {
+ return TRect(SizeInPixels());
+ }
+
+
+EXPORT_C void CPrinterDevice::DeleteControl()
+ /** Deletes the printer control owned by this object.
+
+The function sets the iControl member to NULL. */
+ {
+ delete iControl;
+ iControl=NULL;
+ }
+
+
+EXPORT_C void CPrinterDevice::RestorePropertiesL()
+/** Restores printer properties. */
+ {
+ _LIT(KSystemIniFileNameSpec,"Z:\\System\\System.ini");
+
+ RFs fs;
+ User::LeaveIfError(fs.Connect());
+ CleanupClosePushL(fs);
+
+ TDriveUnit drive(static_cast<TUint>(RFs::GetSystemDrive()));
+ TParse systemIniFileName;
+ systemIniFileName.Set(drive.Name(), &KSystemIniFileNameSpec, NULL);
+
+ TUint atts = 0;
+ TInt ret = fs.Att(systemIniFileName.FullName(), atts);
+ if (ret == KErrNone)
+ {
+ CDictionaryStore* dictionarystore = NULL;
+ TRAPD(err,dictionarystore = CDictionaryFileStore::SystemL(fs));
+ if (err == KErrNone)
+ {
+ CleanupStack::PushL(dictionarystore);
+ if (dictionarystore->IsPresentL(Model().iUid))
+ {
+ RDictionaryReadStream stream;
+ stream.OpenLC(*dictionarystore,Model().iUid);
+ InternalizePropertiesL(stream);
+ CleanupStack::PopAndDestroy(); // stream
+ }
+ CleanupStack::PopAndDestroy(); // dictionarystore
+ }
+ }
+ CleanupStack::PopAndDestroy(); // fs
+ }
+
+
+EXPORT_C void CPrinterDevice::StorePropertiesL() const
+/** Stores the printer properties. */
+ {
+ RFs fs;
+ User::LeaveIfError(fs.Connect());
+ CleanupClosePushL(fs);
+ CDictionaryStore* dictionarystore = CDictionaryFileStore::SystemLC(fs);
+ RDictionaryWriteStream stream;
+ stream.AssignLC(*dictionarystore,Model().iUid);
+ ExternalizePropertiesL(stream);
+ stream.CommitL();
+ CleanupStack::PopAndDestroy(); // stream
+ dictionarystore->CommitL();
+ CleanupStack::PopAndDestroy(2); // dictionarystore, fs
+ }
+
+//
+// CPrinterControl
+//
+
+
+EXPORT_C CPrinterControl::~CPrinterControl()
+/** Destructor.
+
+It frees all resources owned by the object, prior to its destruction. */
+ {
+ delete iPrinterPort;
+ }
+
+EXPORT_C CPrinterControl::CPrinterControl(CPrinterPort* aPrinterPort):
+ CBase(),
+ iState(ENotPrinting),
+ iPrinterPort(aPrinterPort)
+ {}
+
+//
+// TPageSpec
+//
+
+
+EXPORT_C TPageSpec::TPageSpec():
+ iPortraitPageSize(TSize(0,0)),
+ iOrientation(EPortrait)
+/** Default constructor.
+
+Initialises the page orientation to portrait and the page height and width
+to zero. */
+ {}
+
+
+EXPORT_C TPageSpec::TPageSpec(TPageOrientation anOrientation,const TSize& aSize):
+ iPortraitPageSize(aSize),
+ iOrientation(anOrientation)
+/** Constructor with page orientation and size.
+
+@param aOrientation Specifies the page orientation.
+@param aSize Specifies the page size. */
+ {}
+
+
+EXPORT_C void TPageSpec::InternalizeL(RReadStream& aStream)
+/** Internalises a page specification object from a read stream.
+
+The presence of this function means that the standard templated stream operator>>(),
+defined in s32strm.h, is available to internalise objects of this class.
+
+@param aStream The read stream. */
+ {
+ iPortraitPageSize.iWidth = aStream.ReadInt32L();
+ iPortraitPageSize.iHeight = aStream.ReadInt32L();
+ iOrientation=(TPageSpec::TPageOrientation)aStream.ReadInt8L();
+ }
+
+
+EXPORT_C void TPageSpec::ExternalizeL(RWriteStream& aStream) const
+/** Externalises the page specification object to a write stream.
+
+The presence of this function means that the standard templated stream operator<<(),
+defined in s32strm.h, is available to externalise objects of this class.
+@param aStream The write stream. */
+ {
+ aStream.WriteInt32L(iPortraitPageSize.iWidth);
+ aStream.WriteInt32L(iPortraitPageSize.iHeight);
+ aStream.WriteInt8L(iOrientation);
+ }
+
+
+EXPORT_C TSize TPageSpec::OrientedPageSize()const
+/** Gets the oriented page size.
+
+The oriented page size is the absolute width and height of the page, respecting
+the page orientation.
+@return The oriented page size (in pixels or twips). */
+ {
+ if(iOrientation==EPortrait)
+ return(iPortraitPageSize);
+ return(TSize(iPortraitPageSize.iHeight,iPortraitPageSize.iWidth));
+ }
+
+
+EXPORT_C TBool TPageSpec::operator==(const TPageSpec& aPageSpec) const
+/** Equality operator.
+
+This operator compares page specifications for equality. Two page specifications
+are equal if both their orientations and portrait page sizes are equal.
+
+@param aPageSpec Page specification to be compared.
+@return ETrue, if the page specifications are equal; EFalse, otherwise. */
+ {
+ return(iPortraitPageSize==aPageSpec.iPortraitPageSize &&
+ iOrientation==aPageSpec.iOrientation);
+ }
+
+
+EXPORT_C TBool TPageSpec::operator!=(const TPageSpec& aPageSpec) const
+/** Inequality operator.
+
+This operator compares two page specifications for inequality. Two page specifications
+are unequal if one or both of their orientations and portrait page sizes differ.
+
+@param aPageSpec Page specification to be compared.
+@return ETrue, if the page specifications differ; EFalse, otherwise. */
+ {
+ return(!(*this==aPageSpec));
+ }
+
+
+// TMargins
+
+EXPORT_C void TMargins::InternalizeL(RReadStream& aStream)
+/** Internalises a set of margins from a read stream.
+
+The presence of this function means that the standard templated stream operator>>()
+is available to internalise objects of this class.
+
+@param aStream Stream from which the object is internalised. */
+ {
+ iLeft = aStream.ReadInt32L();
+ iRight = aStream.ReadInt32L();
+ iTop = aStream.ReadInt32L();
+ iBottom = aStream.ReadInt32L();
+ }
+
+EXPORT_C void TMargins::ExternalizeL(RWriteStream& aStream) const
+/** Externalises a set of margins to a write stream.
+
+The presence of this function means that the standard templated stream operator<<()
+is available to externalise objects of this class.
+
+@param aStream Stream to which the object is externalised. */
+ {
+ aStream.WriteInt32L(iLeft);
+ aStream.WriteInt32L(iRight);
+ aStream.WriteInt32L(iTop);
+ aStream.WriteInt32L(iBottom);
+ }
+
+EXPORT_C TBool TMargins::operator==(const TMargins& aMargins) const
+/** Tests margins for equality.
+
+@param aMargins The margin to be compared with this margin.
+@return ETrue, if the margins are equal; EFalse, otherwise. */
+ {
+ return(iLeft==aMargins.iLeft && iRight==aMargins.iRight &&
+ iTop==aMargins.iTop && iBottom==aMargins.iBottom);
+ }
+
+EXPORT_C TBool TMargins::operator!=(const TMargins& aMargins) const
+/** Tests margins for inequality.
+
+@param aMargins The margin to be compared with this margin.
+@return ETrue, if the margins are unequal; EFalse, otherwise. */
+ {
+ return(!(*this==aMargins));
+ }
+
+//
+// CPrinterDriverUI
+//
+
+EXPORT_C CPrinterDriverUI::CPrinterDriverUI()
+ {
+ __DECLARE_NAME(_S("CPrinterDriverUI"));
+ }
+
+
+EXPORT_C TBool CPrinterDriverUI::BeforePrintL()
+ /** Provides an opportunity for a dialog to be put up before printing begins.
+
+@return ETrue, if printing is to continue; EFalse, if printing is to be cancelled.
+The default implementation returns ETrue. */
+ {
+ return ETrue;
+ }
+
+
+EXPORT_C void CPrinterDriverUI::AfterPrintL()
+ /** Provides an opportunity for a dialog to be put up after printing is complete.
+The default implementation is empty. */
+ {
+ }
+
+
+EXPORT_C void CPrinterDriverUI::SetPropertiesL()
+/** Provides an opportunity for a dialog to be put up to capture or change printer
+properties.
+The default implementation is empty. */
+ {
+ }
+
+
+EXPORT_C TBool CPrinterDriverUI::CanSetProperties()
+/** Tests whether printer properties can be set.
+
+@return ETrue, if printer properties can be set; EFalse, otherwise. The default
+implementation returns EFalse. */
+ {
+ return EFalse;
+ }
+
+//
+// CPrinterDriver
+//
+
+
+EXPORT_C CPrinterDriver* CPrinterDriver::NewL()
+/** Constructs, and returns a pointer to a new instance for accessing a printer
+specification data store.
+
+@return Pointer to the object for accessing a printer specification data store. */
+ {
+ CPrinterDriver* printerdriver=new(ELeave) CPrinterDriver;
+ CleanupStack::PushL(printerdriver);
+ User::LeaveIfError(printerdriver->iFs.Connect());
+ CleanupStack::Pop();
+ return printerdriver;
+ }
+
+
+EXPORT_C CPrinterDriver::~CPrinterDriver()
+/** Destructor.
+
+It frees all resources owned by the object, prior to its destruction. In particular,
+it closes the printer specification data store and any open session with the file server. */
+ {
+ Close();
+ iFs.Close();
+ }
+
+
+EXPORT_C void CPrinterDriver::OpenPdrL(const TDesC &aName)
+/** Opens the specified printer specification data store.
+
+@return The name of the printer specification data store. This must be a
+valid printer specification data store,otherwise the function leaves with
+KErrNotSupported. */
+ {
+ Close();
+ TRAPD(ret,DoOpenPdrL(aName));
+ if (ret!=KErrNone)
+ {
+ Close();
+ User::Leave(ret);
+ }
+ }
+
+EXPORT_C void CPrinterDriver::Close()
+/** Closes the printer specification data store and frees resources.
+
+An open session with the file server remains open. */
+ {
+ delete iPdrStore,
+ iPdrStore=NULL;
+ iNumModels=0;
+ delete[] iModelList;
+ iModelList=NULL;
+ DeletePrinterDevice();
+ }
+
+
+EXPORT_C TInt CPrinterDriver::NumModels() const
+ /** Gets the number of printer models defined by the printer specification.
+
+@return The number of printer models. */
+ {
+ return iNumModels;
+ }
+
+
+EXPORT_C TPrinterModelEntry CPrinterDriver::Model(TInt aNum) const
+/** Gets the specified printer model.
+
+@param aNum An index into the list of printer models defined in the printer
+specification data.
+@return Model specific information. */
+ {
+ GDI_ASSERT_DEBUG(aNum>=0,EPdrModelIndexOutOfRange);
+ GDI_ASSERT_DEBUG(aNum<iNumModels,EPdrModelIndexOutOfRange);
+ return iModelList[aNum].iEntry;
+ }
+
+
+EXPORT_C CPrinterDevice* CPrinterDriver::CreatePrinterDeviceL(TUid aModelUid)
+/** Creates the physical graphics device to be used for printing.
+
+@param aModelUid The UID of a specific model which is defined in the printer
+specification data.
+@return The physical graphics device to be used for printing. */
+ {
+ GDI_ASSERT_DEBUG(!iPrinterDevice,EPdrPrinterDeviceExists);
+ TRAPD(ret,DoCreatePrinterDeviceL(aModelUid));
+ if (ret!=KErrNone)
+ {
+ DeletePrinterDevice();
+ User::Leave(ret);
+ }
+ return iPrinterDevice;
+ }
+
+void CPrinterDriver::LoadLibraryL(RLibrary& aLibrary,const TDesC& aExt,TUid aUid2)
+ {
+ TFileName filename=iPdlName;
+ filename.Append(aExt);
+
+ User::LeaveIfError(aLibrary.Load(filename));
+ TUidType type=aLibrary.Type();
+ if (type[1]!=aUid2 && type[2]!=iPdlUid)
+ {
+ aLibrary.Close();
+ User::Leave(KErrNotSupported);
+ }
+ if (type[1]!=aUid2)
+ {
+ aLibrary.Close();
+ User::Leave(KErrNotFound);
+ }
+ }
+
+
+EXPORT_C CPrinterDriverUI* CPrinterDriver::CreatePrinterDriverUIL()
+/** Constructs a printer specific user interface.
+
+The user interface object is optional, but if it exists, it is implemented
+as part of a UDL (i.e. a UI DLL).
+
+@return A pointer to the printer specific user interface, or NULL if there is
+none. */
+ {
+ GDI_ASSERT_DEBUG(iPrinterDevice,EPdrPrinterDeviceDoesNotExist);
+ if (iUdlLibrary.Handle()==0)
+ {
+ TRAPD(ret,LoadLibraryL(iUdlLibrary,KUdlExtension,TUid::Uid(KUdlUidVal)));
+ if (ret==KErrNotFound)
+ return NULL;
+ else
+ User::LeaveIfError(ret);
+ }
+ TLibraryFunction f = iUdlLibrary.Lookup(1);
+ CPrinterDriverUI* printerdriverui=(CPrinterDriverUI*)((*f)());
+ CleanupStack::PushL(printerdriverui);
+ User::LeaveIfError(printerdriverui->SetPrinterDevice(iPrinterDevice));
+ CleanupStack::Pop();
+ return printerdriverui;
+ }
+
+CPrinterDriver::CPrinterDriver()
+ {}
+
+void CPrinterDriver::DeletePrinterDevice()
+ {
+ iUdlLibrary.Close();
+ delete iPrinterDevice;
+ iPrinterDevice=NULL;
+ iPdlLibrary.Close();
+ }
+
+void CPrinterDriver::DoOpenPdrL(const TDesC &aName)
+ {
+ Close();
+ iPdrStore=CDirectFileStore::OpenL(iFs,aName,EFileStream|EFileRead|EFileShareReadersOnly);
+ if (iPdrStore->Type()[1]!=TUid::Uid(KPdrStoreFileUidVal))
+ User::Leave(KErrNotSupported);
+ TStreamId headerid = iPdrStore->Root();
+ RStoreReadStream stream;
+ stream.OpenLC(*iPdrStore,headerid);
+ stream >> iPdlName;
+ stream >> iPdlUid;
+ iNumModels = stream.ReadInt32L();
+ iModelList = new(ELeave) TPrinterModelHeader[iNumModels];
+ for (TInt i=0; i<iNumModels; i++)
+ iModelList[i].InternalizeL(stream);
+ CleanupStack::PopAndDestroy();
+ }
+
+void CPrinterDriver::DoCreatePrinterDeviceL(TUid aModelUid)
+ {
+ if (!iPdlName.Length())
+ User::Leave(KErrGeneral); // !! find a better error number
+ LoadLibraryL(iPdlLibrary,KPdlExtension,TUid::Uid(KPdlUidVal));
+ TLibraryFunction f = iPdlLibrary.Lookup(1);
+ iPrinterDevice=(CPrinterDevice*)((*f)());
+ TInt i;
+ for (i=0; (i<iNumModels) && (aModelUid!=iModelList[i].iEntry.iUid); i++)
+ {
+ }
+ GDI_ASSERT_DEBUG(i<iNumModels,EPdrModelUidNotFound);
+ User::LeaveIfError(iPrinterDevice->SetModel(iModelList[i],*iPdrStore));
+ iPrinterDevice->RestorePropertiesL();
+ }
+
+//
+// CPdrModelList
+//
+
+
+EXPORT_C CPdrModelList* CPdrModelList::NewL()
+/** Constructs, and returns a pointer to a new instance of the printer model
+list interface.
+@return Pointer to the new printer model list interface object. */
+ {
+ CPdrModelList* modellist=new(ELeave) CPdrModelList();
+ CleanupStack::PushL(modellist);
+ modellist->ConstructL();
+ CleanupStack::Pop();
+ return modellist;
+ }
+
+
+EXPORT_C CPdrModelList::~CPdrModelList()
+/** Virtual destructor.
+Frees resources owned by the object, prior to its destruction. */
+ {
+ delete iModelArray;
+ delete iFileArray;
+ if (iDirectoryArray)
+ {// delete all the HBufC's
+ for (TInt i=iDirectoryArray->Count()-1 ; i>=0 ; i--)
+ delete (*iDirectoryArray)[i];
+ delete iDirectoryArray;
+ }
+ iFileServer.Close();
+ }
+
+
+EXPORT_C TInt CPdrModelList::ModelCount() const
+/** Gets the number of printer models in the printer model list.
+@return The number of printer models. */
+ {
+ return iModelArray->Count();
+ }
+
+
+EXPORT_C const TPrinterModelEntry CPdrModelList::operator [] (TInt anIndex)
+/** Gets printer model name.
+
+This is the name of the printer model at the specified index within the list
+of printer models.
+
+@param anIndex The index of the printer model within the array of printer
+models. Note that this number must be between zero and ModelCount().
+
+@return Name of printer model, up to 32 characters long */
+ {
+ GDI_ASSERT_DEBUG(anIndex>=0,EPdrModelIndexOutOfRange);
+ GDI_ASSERT_DEBUG(anIndex<iModelArray->Count(),EPdrModelIndexOutOfRange);
+
+ return (*iModelArray)[anIndex].iEntry;
+ }
+
+
+EXPORT_C TInt CPdrModelList::UidToNum(TUid aModelUid) const
+/** Gets a printer model's index within the model list from its UID.
+
+@param aModelUid The UID of the printer model.
+@return The index of the printer model within the array of printer models if
+found; KErrNotFound, otherwise. */
+ {
+ TInt i,count=iModelArray->Count();
+ for (i=0; (i<count) && (aModelUid!=(*iModelArray)[i].iEntry.iUid); i++)
+ {
+ }
+
+ if (i==count)
+ i=KErrNotFound;
+
+ return i;
+ }
+
+
+EXPORT_C void CPdrModelList::AddDirectoryL(const TDesC& aDir)
+/** Adds a directory to the list of directories to be scanned for printer models.
+
+@param aDir The directory to be added to the list. */
+ {
+ HBufC* buf = HBufC::NewL(aDir.Length());
+ CleanupStack::PushL(buf);
+ *buf = aDir;
+ iDirectoryArray->AppendL(buf);
+ CleanupStack::Pop(); //buf
+ }
+
+LOCAL_C void DereferenceAndDeleteHBufC8(TAny* aPointerToPointerToHBufC8)
+ {
+ delete *STATIC_CAST(HBufC8**, aPointerToPointerToHBufC8);
+ }
+
+
+EXPORT_C CPrinterModelList* CPdrModelList::ScanForModelsL()
+/** Scans through through the list of directories for all .pdr files and generates
+a list of printer models.
+
+@return The list of model names. */
+ {
+ iModelArray->Reset();
+ iFileArray->Reset();
+ // check that there is at least one directory to parse?
+ // get a list of *.pdr files in all directories specified (using AddDirectory())
+ for (TInt index=iDirectoryArray->Count()-1 ; index>=0 ; index--)
+ ScanDirectoryL(index);
+ // then go through the files one at a time, adding all models to the list
+ TParse* parser = new(ELeave) TParse;
+ CleanupStack::PushL(parser);
+ TFileName* nameOfLoadedResourceFile=new(ELeave) TFileName;
+ CleanupStack::PushL(nameOfLoadedResourceFile);
+ TFileName* tempFileName=new(ELeave) TFileName;
+ CleanupStack::PushL(tempFileName);
+ RResourceFile resourceFile;
+ CleanupClosePushL(resourceFile);
+ HBufC8* resource=NULL;
+ CleanupStack::PushL(TCleanupItem(DereferenceAndDeleteHBufC8, &resource));
+ for (TInt fileNum=iFileArray->Count()-1 ; fileNum>=0 ; fileNum--)
+ ListModelsL(fileNum, *parser, *nameOfLoadedResourceFile, *tempFileName, resourceFile, resource);
+ CleanupStack::PopAndDestroy(5); // resource, resourceFile, tempFileName, nameOfLoadedResourceFile and parser
+ // return a handle to the array of model names
+ return this;
+ }
+
+
+EXPORT_C CPrinterDriver* CPdrModelList::CreatePrinterDriverL(TInt anIndex)
+/** Creates an object for accessing the specified store that contains printer specification
+data.
+
+@param anIndex An index into a list of files containing printer specification
+data. The files are the complete set of .pdr files found in the directories
+known to this object.
+@return A pointer to the object representing the store containing the printer
+specification data. */
+ {
+ GDI_ASSERT_DEBUG(anIndex>=0,EPdrModelIndexOutOfRange);
+ GDI_ASSERT_DEBUG(anIndex<iModelArray->Count(),EPdrModelIndexOutOfRange);
+
+ CPrinterDriver* driver = CPrinterDriver::NewL();
+ CleanupStack::PushL(driver);
+ HBufC* file = NewPathBufL(*((*iModelArray)[anIndex].iFile));
+ CleanupStack::PushL(file);
+ driver->OpenPdrL(*file);
+ driver->CreatePrinterDeviceL((*iModelArray)[anIndex].iEntry.iUid);
+ CleanupStack::PopAndDestroy();
+ CleanupStack::Pop();
+ return driver;
+ }
+
+
+ CPdrModelList::CPdrModelList():
+ iModelArray(NULL),
+ iFileArray(NULL),
+ iDirectoryArray(NULL)
+ {
+ }
+
+ void CPdrModelList::ConstructL()
+ {
+ __DECLARE_NAME(_S("CPdrModelList"));
+ iModelArray = new(ELeave) CArrayFixSeg<TModelEntry>(5);
+ iFileArray = new(ELeave) CArrayFixFlat<TFileEntry>(5);
+ iDirectoryArray = new(ELeave) CArrayFixFlat<HBufC*>(1);
+ User::LeaveIfError(iFileServer.Connect());
+ }
+
+void CPdrModelList::ScanDirectoryL(TInt aDirIndex)
+/** Scans the given directory, parsing all files found
+ If a file is of the correct type it is appended to the file list*/
+ {
+ GDI_ASSERT_DEBUG(aDirIndex>=0,EPdrDirectoryIndexOutOfRange);
+ GDI_ASSERT_DEBUG(aDirIndex<iDirectoryArray->Count(),EPdrDirectoryIndexOutOfRange);
+
+ TDesC* dir = (*iDirectoryArray)[aDirIndex];
+ TParse path;
+ path.Set(KPdrExtension,dir,NULL);
+ CDir* fileList;
+ TInt ret = iFileServer.GetDir(path.FullName(),KEntryAttNormal,ESortByName,fileList);
+ if (ret == KErrNone)
+ {
+ CleanupStack::PushL(fileList);
+ for (TInt i=fileList->Count()-1 ; i>=0 ; i--)
+ {
+ TFileEntry& entry = iFileArray->ExtendL();
+ entry.iFileName = (*fileList)[i].iName;
+ entry.iDirectory = dir;
+ }
+ CleanupStack::PopAndDestroy(); // fileList
+ }
+ else if (ret == KErrNoMemory) // Ignore errors other than KErrNoMemory
+ User::LeaveNoMemory();
+ }
+
+void CPdrModelList::ListModelsL(TInt aFileIndex, TParse& aParser, TFileName& aNameOfLoadedResourceFile, TFileName& aTempFileName, RResourceFile& aResourceFile, HBufC8*& aResource)
+/** given a pdr file list all the models it contains in the model array */
+ {
+ GDI_ASSERT_DEBUG(aFileIndex>=0,EPdrFileIndexOutOfRange);
+ GDI_ASSERT_DEBUG(aFileIndex<iFileArray->Count(),EPdrFileIndexOutOfRange);
+
+ CPrinterDriver* driver = CPrinterDriver::NewL() ;
+ CleanupStack::PushL(driver);
+ // open the file
+ HBufC* fullPath = NewPathBufL((*iFileArray)[aFileIndex]);
+ TRAPD(ret,driver->OpenPdrL(*fullPath));
+ delete fullPath;
+ if ((ret!=KErrNone) && (ret!=KErrNotSupported))
+ User::Leave(ret);
+ // get info on the models one by one and insert them into the array
+ if (ret==KErrNone)
+ {
+ TModelEntry modelentry;
+ modelentry.iFile = &(*iFileArray)[aFileIndex]; // set the file pointer for the entry
+ const TInt numberOfModels = driver->NumModels();
+ for (TInt i=0 ; i<numberOfModels ; i++)
+ {
+ modelentry.iEntry=driver->Model(i);
+ if (UidToNum(modelentry.iEntry.iUid)==KErrNotFound)
+ {
+ User::LeaveIfError(aParser.SetNoWild(KRscExtension, &modelentry.iFile->iFileName, modelentry.iFile->iDirectory));
+ aTempFileName=aParser.FullName();
+ BaflUtils::NearestLanguageFile(iFileServer, aTempFileName);
+ if (aNameOfLoadedResourceFile.CompareF(aTempFileName)!=0)
+ {
+ if (!BaflUtils::FileExists(iFileServer, aTempFileName))
+ {
+ iModelArray->AppendL(modelentry); // no resource file found, so reverting to old behaviour (i.e. where the model-name is set from the PDR file)
+ continue;
+ }
+ aNameOfLoadedResourceFile=KNullDesC;
+ aResourceFile.OpenL(iFileServer, aTempFileName);
+ HBufC8* resource=aResourceFile.AllocReadL(aResourceFile.Offset()+2); // read the first resource after the RSS_SIGNATURE resource
+ delete aResource;
+ aResource=resource;
+ aNameOfLoadedResourceFile=aTempFileName;
+ }
+ TResourceReader resourceReader;
+ resourceReader.SetBuffer(aResource);
+ for (TInt j=resourceReader.ReadUint16()-1; ; --j)
+ {
+ if (j<0)
+ {
+ iModelArray->AppendL(modelentry); // no matching uid found in the resource file, so reverting to old behaviour (i.e. where the model-name is set from the PDR file)
+ break;
+ }
+ TInt uid=resourceReader.ReadInt32();
+ TPtrC name=resourceReader.ReadTPtrC();
+ if (uid==modelentry.iEntry.iUid.iUid)
+ {
+ if (name.Length()>0)
+ {
+ modelentry.iEntry.iModelName=name;
+ iModelArray->AppendL(modelentry);
+ }
+ break;
+ }
+ }
+ }
+ }
+ }
+ CleanupStack::PopAndDestroy(); // driver
+ }
+
+
+HBufC* CPdrModelList::NewPathBufL(const TFileEntry& aFileEntry)
+/** Create a buf of the right length and...
+ set its contents to the full filename of model aModel */
+ {
+ // Create a buf of the right length
+ HBufC* buf = HBufC::NewL(aFileEntry.iFileName.Length()+aFileEntry.iDirectory->Length());
+ // Insert the file path
+ TPtr filePtr = buf->Des();
+ filePtr.Append(*aFileEntry.iDirectory);
+ filePtr.Append(aFileEntry.iFileName);
+ return buf;
+ }
+
+// !!!!
+// Retained for binary compatibility only: remove if we make a binary incompatible release
+//
+
+IMPORT_C void GDI_Reserved();
+EXPORT_C void GDI_Reserved()
+ {}
+