os/graphics/graphicsdeviceinterface/gdi/sgdi/PRINTGDI.CPP
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     1 // Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies).
     2 // All rights reserved.
     3 // This component and the accompanying materials are made available
     4 // under the terms of "Eclipse Public License v1.0"
     5 // which accompanies this distribution, and is available
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
     7 //
     8 // Initial Contributors:
     9 // Nokia Corporation - initial contribution.
    10 //
    11 // Contributors:
    12 //
    13 // Description:
    14 //
    15 
    16 #include <gdi.h>
    17 #include <f32file.h>
    18 #include <s32file.h>
    19 #include <bautils.h>
    20 #include <barsc.h>
    21 #include <barsread.h>
    22 #include "GDIPANIC.h"
    23 
    24 _LIT(KPdrExtension,"*.PDR"); // must be capitalized
    25 _LIT(KPdlExtension,".PDL"); // must be capitalized
    26 _LIT(KUdlExtension,".UDL"); // must be capitalized
    27 _LIT(KRscExtension,".RSC");
    28 _LIT(KGdiPrintPanic,"GDI - PRINT");
    29 
    30 _LIT(KGDIPanicDesc1, "GDI Pdr internal Panic %S, in file %S @ line %i");
    31 _LIT(KGDIPanicDesc2, "Assert condition = \"%S\"");
    32 
    33 enum TPdrStorePanic
    34 	{
    35 	EPdrModelIndexOutOfRange,
    36 	EPdrModelUidNotFound,
    37 	EPdrDirectoryIndexOutOfRange,
    38 	EPdrFileIndexOutOfRange,
    39 	EPdrPrinterDeviceExists,
    40 	EPdrPrinterDeviceDoesNotExist,
    41 	};
    42 
    43 void Panic(TPdrStorePanic aPanic)
    44 	{
    45 	User::Panic(KGdiPrintPanic,aPanic);
    46 	}
    47 	
    48 void PanicWithCondAndInfo(TPdrStorePanic aError, const TDesC& aCondition, const TDesC& aFileName, const TDesC& aPanicName, TInt aLine)
    49 	{
    50 	TBuf<256> buf;
    51 	buf.Format(KGDIPanicDesc1, &aPanicName, &aFileName, aLine);
    52 	RDebug::Print(buf);
    53 
    54 	buf.Format(KGDIPanicDesc2, &aCondition);
    55 	RDebug::Print(buf);
    56 	Panic(aError);
    57 	}
    58 
    59 //
    60 // TPrinterModelEntry
    61 //
    62 
    63 
    64 EXPORT_C void TPrinterModelEntry::InternalizeL(RReadStream& aStream)
    65 
    66 /** Internalises a printer model entry from a read stream. 
    67 
    68 The presence of this function means that the standard templated stream operator>>(), 
    69 defined in s32strm.h, is available to internalise objects of this class.
    70 
    71 @param aStream The read stream. */
    72     {
    73 	aStream >> iModelName;
    74 	iRequiresPrinterPort=aStream.ReadUint8L();
    75 	aStream >> iUid;
    76 	}
    77 
    78 
    79 EXPORT_C void TPrinterModelEntry::ExternalizeL(RWriteStream& aStream) const
    80 /** Externalises the printer model entry to a write stream.
    81 
    82 The presence of this function means that the standard templated stream operator<<(), 
    83 defined in s32strm.h, is available to externalise objects of this class.
    84 
    85 @param aStream The write stream. */
    86 	{
    87 	aStream << iModelName;
    88 	aStream.WriteUint8L((TUint8) iRequiresPrinterPort);
    89 	aStream << iUid;
    90 	}
    91 
    92 //
    93 // TPrinterModelHeader
    94 //
    95 
    96 
    97 EXPORT_C void TPrinterModelHeader::InternalizeL(RReadStream& aStream)
    98 /** Internalises a printer model header from a read stream. 
    99 
   100 The presence of this function means that the standard templated stream operator>>(), 
   101 defined in s32strm.h, is available to internalise objects of this class.
   102 
   103 @param aStream The read stream. */
   104  	{
   105 	aStream >> iEntry;
   106 	aStream >> iModelDataStreamId;
   107 	}
   108 
   109 
   110 EXPORT_C void TPrinterModelHeader::ExternalizeL(RWriteStream& aStream) const
   111  
   112 /** Externalises the printer model header to a write stream.
   113 
   114 The presence of this function means that the standard templated stream operator<<(), 
   115 defined in s32strm.h, is available to externalise objects of this class.
   116 @param aStream The write stream. */
   117     {
   118 	aStream << iEntry;
   119 	aStream << iModelDataStreamId;
   120 	}
   121 
   122 //
   123 // CPrinterDevice
   124 //
   125 
   126 EXPORT_C CPrinterDevice::CPrinterDevice():
   127 	CGraphicsDevice(),
   128 	iCurrentPageSpecInTwips()
   129 /** Standard constructor. */
   130 	{}
   131 
   132 
   133 EXPORT_C CPrinterDevice::~CPrinterDevice()
   134 
   135 /** Destructor.
   136 It frees all resources owned by the object, prior to its destruction. */
   137 	{
   138 	delete iControl;
   139 	}
   140 
   141 
   142 EXPORT_C void CPrinterDevice::SelectPageSpecInTwips(const TPageSpec& aPageSpecInTwips)
   143 /** Sets the page specification in twips.
   144 @param  aPageSpec The page specification in twips. */	
   145     {
   146 	iCurrentPageSpecInTwips=aPageSpecInTwips;
   147 	}
   148 
   149 
   150 EXPORT_C TRect CPrinterDevice::PrintablePageInPixels() const
   151 /** Gets the dimensions of the area to which the printer device can print.
   152 
   153 These dimensions are normally less than those returned by TPageSpec::OrientedPageSize() 
   154 because a margin exists between the boundary of the printable page and the 
   155 absolute extent of the page.
   156 
   157 @return The dimensions of the printer device area in pixels, respecting the 
   158 page orientation */
   159 	{
   160 	return TRect(SizeInPixels());
   161 	}
   162 
   163 
   164 EXPORT_C void CPrinterDevice::DeleteControl()
   165  /** Deletes the printer control owned by this object.
   166 
   167 The function sets the iControl member to NULL. */
   168     {
   169 	delete iControl;
   170 	iControl=NULL;
   171 	}
   172 
   173 
   174 EXPORT_C void CPrinterDevice::RestorePropertiesL()
   175 /** Restores printer properties. */	
   176     {
   177 	_LIT(KSystemIniFileNameSpec,"Z:\\System\\System.ini");
   178 
   179 	RFs fs;
   180 	User::LeaveIfError(fs.Connect());
   181 	CleanupClosePushL(fs);
   182 	
   183 	TDriveUnit drive(static_cast<TUint>(RFs::GetSystemDrive()));
   184 	TParse systemIniFileName;
   185 	systemIniFileName.Set(drive.Name(), &KSystemIniFileNameSpec, NULL);
   186 	
   187 	TUint atts = 0;
   188 	TInt ret = fs.Att(systemIniFileName.FullName(), atts);
   189 	if (ret == KErrNone)
   190 		{
   191 		CDictionaryStore* dictionarystore = NULL;
   192 		TRAPD(err,dictionarystore = CDictionaryFileStore::SystemL(fs));
   193 		if (err == KErrNone)
   194 			{
   195 			CleanupStack::PushL(dictionarystore);
   196 			if (dictionarystore->IsPresentL(Model().iUid))
   197 				{
   198 				RDictionaryReadStream stream;
   199 				stream.OpenLC(*dictionarystore,Model().iUid);
   200 				InternalizePropertiesL(stream);
   201 				CleanupStack::PopAndDestroy(); // stream
   202 				}
   203 			CleanupStack::PopAndDestroy(); // dictionarystore
   204 			}
   205 		}
   206 	CleanupStack::PopAndDestroy(); // fs
   207 	}
   208 
   209 
   210 EXPORT_C void CPrinterDevice::StorePropertiesL() const
   211 /**  Stores the printer properties. */
   212     {
   213 	RFs fs;
   214 	User::LeaveIfError(fs.Connect());
   215 	CleanupClosePushL(fs);
   216 	CDictionaryStore* dictionarystore = CDictionaryFileStore::SystemLC(fs);
   217 	RDictionaryWriteStream stream;
   218 	stream.AssignLC(*dictionarystore,Model().iUid);
   219 	ExternalizePropertiesL(stream);
   220 	stream.CommitL();
   221 	CleanupStack::PopAndDestroy(); // stream
   222 	dictionarystore->CommitL();
   223 	CleanupStack::PopAndDestroy(2); // dictionarystore, fs
   224 	}
   225 
   226 //
   227 // CPrinterControl
   228 //
   229 
   230 
   231 EXPORT_C CPrinterControl::~CPrinterControl()
   232 /**  Destructor.
   233 
   234 It frees all resources owned by the object, prior to its destruction. */
   235  {
   236 	delete iPrinterPort;
   237 	}
   238 
   239 EXPORT_C CPrinterControl::CPrinterControl(CPrinterPort* aPrinterPort):
   240 	CBase(),
   241 	iState(ENotPrinting),
   242 	iPrinterPort(aPrinterPort)
   243 	{}
   244 
   245 //
   246 // TPageSpec
   247 //
   248 
   249 
   250 EXPORT_C TPageSpec::TPageSpec():
   251 	iPortraitPageSize(TSize(0,0)),
   252 	iOrientation(EPortrait)
   253 /** Default constructor. 
   254 
   255 Initialises the page orientation to portrait and the page height and width 
   256 to zero. */
   257 	{}
   258 
   259 
   260 EXPORT_C TPageSpec::TPageSpec(TPageOrientation anOrientation,const TSize& aSize):
   261 	iPortraitPageSize(aSize),
   262 	iOrientation(anOrientation)
   263 /** Constructor with page orientation and size. 
   264 
   265 @param aOrientation Specifies the page orientation. 
   266 @param aSize Specifies the page size. */
   267  	{}
   268 
   269 
   270 EXPORT_C void TPageSpec::InternalizeL(RReadStream& aStream)
   271 /** Internalises a page specification object from a read stream. 
   272 
   273 The presence of this function means that the standard templated stream operator>>(), 
   274 defined in s32strm.h, is available to internalise objects of this class.
   275 
   276 @param aStream The read stream. */
   277  	{
   278 	iPortraitPageSize.iWidth = aStream.ReadInt32L();
   279 	iPortraitPageSize.iHeight = aStream.ReadInt32L();
   280 	iOrientation=(TPageSpec::TPageOrientation)aStream.ReadInt8L();
   281 	}
   282 
   283 
   284 EXPORT_C void TPageSpec::ExternalizeL(RWriteStream& aStream) const
   285 /** Externalises the page specification object to a write stream.
   286 
   287 The presence of this function means that the standard templated stream operator<<(), 
   288 defined in s32strm.h, is available to externalise objects of this class.
   289 @param aStream The write stream. */
   290  	{
   291 	aStream.WriteInt32L(iPortraitPageSize.iWidth);
   292 	aStream.WriteInt32L(iPortraitPageSize.iHeight);
   293 	aStream.WriteInt8L(iOrientation);
   294 	}
   295 
   296 
   297 EXPORT_C TSize TPageSpec::OrientedPageSize()const
   298 /** Gets the oriented page size.
   299 
   300 The oriented page size is the absolute width and height of the page, respecting 
   301 the page orientation.
   302 @return The oriented page size (in pixels or twips). */
   303   	{
   304 	if(iOrientation==EPortrait)
   305 		return(iPortraitPageSize);
   306 	return(TSize(iPortraitPageSize.iHeight,iPortraitPageSize.iWidth));
   307 	}
   308 
   309 
   310 EXPORT_C TBool TPageSpec::operator==(const TPageSpec& aPageSpec) const
   311 /** Equality operator. 
   312 
   313 This operator compares page specifications for equality. Two page specifications 
   314 are equal if both their orientations and portrait page sizes are equal.
   315 
   316 @param aPageSpec Page specification to be compared.
   317 @return ETrue, if the page specifications are equal; EFalse, otherwise. */
   318    {
   319 	return(iPortraitPageSize==aPageSpec.iPortraitPageSize &&
   320 		iOrientation==aPageSpec.iOrientation);
   321 	}
   322 
   323  
   324 EXPORT_C TBool TPageSpec::operator!=(const TPageSpec& aPageSpec) const
   325 /** Inequality operator.
   326 
   327 This operator compares two page specifications for inequality. Two page specifications 
   328 are unequal if one or both of their orientations and portrait page sizes differ.
   329 
   330 @param aPageSpec Page specification to be compared.
   331 @return ETrue, if the page specifications differ; EFalse, otherwise. */
   332 	{
   333 	return(!(*this==aPageSpec));
   334 	}
   335 
   336 
   337 // TMargins
   338 
   339 EXPORT_C void TMargins::InternalizeL(RReadStream& aStream)
   340 /** Internalises a set of margins from a read stream.
   341 
   342 The presence of this function means that the standard templated stream operator>>() 
   343 is available to internalise objects of this class.
   344 
   345 @param aStream Stream from which the object is internalised. */
   346 	{
   347 	iLeft = aStream.ReadInt32L();
   348 	iRight = aStream.ReadInt32L();
   349 	iTop = aStream.ReadInt32L();
   350 	iBottom = aStream.ReadInt32L();
   351 	}
   352 
   353 EXPORT_C void TMargins::ExternalizeL(RWriteStream& aStream) const
   354 /** Externalises a set of margins to a write stream.
   355 
   356 The presence of this function means that the standard templated stream operator<<() 
   357 is available to externalise objects of this class.
   358 
   359 @param aStream Stream to which the object is externalised. */
   360 	{
   361 	aStream.WriteInt32L(iLeft);
   362 	aStream.WriteInt32L(iRight);
   363 	aStream.WriteInt32L(iTop);
   364 	aStream.WriteInt32L(iBottom);
   365 	}
   366 
   367 EXPORT_C TBool TMargins::operator==(const TMargins& aMargins) const
   368 /** Tests margins for equality.
   369 
   370 @param aMargins The margin to be compared with this margin. 
   371 @return ETrue, if the margins are equal; EFalse, otherwise. */
   372 	{
   373 	return(iLeft==aMargins.iLeft && iRight==aMargins.iRight &&
   374 		iTop==aMargins.iTop && iBottom==aMargins.iBottom);
   375 	}
   376 
   377 EXPORT_C TBool TMargins::operator!=(const TMargins& aMargins) const
   378 /** Tests margins for inequality.
   379 
   380 @param aMargins The margin to be compared with this margin. 
   381 @return ETrue, if the margins are unequal; EFalse, otherwise. */
   382 	{
   383 	return(!(*this==aMargins));
   384 	}
   385 
   386 //
   387 // CPrinterDriverUI
   388 //
   389 
   390 EXPORT_C CPrinterDriverUI::CPrinterDriverUI()
   391 	{
   392 	__DECLARE_NAME(_S("CPrinterDriverUI"));
   393 	}
   394 
   395 
   396 EXPORT_C TBool CPrinterDriverUI::BeforePrintL()
   397  /** Provides an opportunity for a dialog to be put up before printing begins.
   398 
   399 @return ETrue, if printing is to continue; EFalse, if printing is to be cancelled. 
   400 The default implementation returns ETrue. */
   401   	{
   402 	return ETrue;
   403 	}
   404 
   405 
   406 EXPORT_C void CPrinterDriverUI::AfterPrintL()
   407  /** Provides an opportunity for a dialog to be put up after printing is complete.
   408 The default implementation is empty. */
   409 	{
   410 	}
   411 
   412 
   413 EXPORT_C void CPrinterDriverUI::SetPropertiesL()
   414 /** Provides an opportunity for a dialog to be put up to capture or change printer 
   415 properties.
   416 The default implementation is empty. */
   417 	{
   418 	}
   419 
   420 
   421 EXPORT_C TBool CPrinterDriverUI::CanSetProperties()
   422 /** Tests whether printer properties can be set.
   423 
   424 @return ETrue, if printer properties can be set; EFalse, otherwise. The default 
   425 implementation returns EFalse. */
   426     {
   427 	return EFalse;
   428 	}
   429 
   430 //
   431 // CPrinterDriver
   432 //
   433 
   434 
   435 EXPORT_C CPrinterDriver* CPrinterDriver::NewL()
   436 /** Constructs, and returns a pointer to a new instance for accessing a printer 
   437 specification data store.
   438 
   439 @return Pointer to the object for accessing a printer specification data store. */
   440 	{
   441 	CPrinterDriver* printerdriver=new(ELeave) CPrinterDriver;
   442 	CleanupStack::PushL(printerdriver);
   443 	User::LeaveIfError(printerdriver->iFs.Connect());
   444 	CleanupStack::Pop();
   445 	return printerdriver;
   446 	}
   447 
   448 
   449 EXPORT_C CPrinterDriver::~CPrinterDriver()
   450 /** Destructor.
   451 
   452 It frees all resources owned by the object, prior to its destruction. In particular, 
   453 it closes the printer specification data store and any open session with the file server.  */	
   454     {
   455 	Close();
   456 	iFs.Close();
   457 	}
   458 
   459 
   460 EXPORT_C void CPrinterDriver::OpenPdrL(const TDesC &aName)
   461 /**  Opens the specified printer specification data store.
   462 
   463 @return  The name of the printer specification data store. This must be a 
   464 valid printer specification data store,otherwise the function leaves with
   465 KErrNotSupported. */	
   466     {
   467 	Close();
   468 	TRAPD(ret,DoOpenPdrL(aName));
   469 	if (ret!=KErrNone)
   470 		{
   471 		Close();
   472 		User::Leave(ret);
   473 		}
   474 	}
   475 
   476 EXPORT_C void CPrinterDriver::Close()
   477 /** Closes the printer specification data store and frees resources.
   478 
   479 An open session with the file server remains open. */
   480 	{
   481 	delete iPdrStore,
   482 	iPdrStore=NULL;
   483 	iNumModels=0;
   484 	delete[] iModelList;
   485 	iModelList=NULL;
   486 	DeletePrinterDevice();
   487 	}
   488 
   489 
   490 EXPORT_C TInt CPrinterDriver::NumModels() const
   491  /** Gets the number of printer models defined by the printer specification.
   492 
   493 @return The number of printer models. */
   494  	{
   495 	return iNumModels;
   496 	}
   497 
   498 
   499 EXPORT_C TPrinterModelEntry CPrinterDriver::Model(TInt aNum) const
   500 /** Gets the specified printer model.
   501 
   502 @param aNum An index into the list of printer models defined in the printer 
   503 specification data.
   504 @return Model specific information. */
   505  	{
   506 	GDI_ASSERT_DEBUG(aNum>=0,EPdrModelIndexOutOfRange);
   507 	GDI_ASSERT_DEBUG(aNum<iNumModels,EPdrModelIndexOutOfRange);
   508 	return iModelList[aNum].iEntry;
   509 	}
   510 
   511 
   512 EXPORT_C CPrinterDevice* CPrinterDriver::CreatePrinterDeviceL(TUid aModelUid)
   513 /** Creates the physical graphics device to be used for printing.
   514 
   515 @param aModelUid The UID of a specific model which is defined in the printer 
   516 specification data.
   517 @return The physical graphics device to be used for printing.  */	
   518     {
   519 	GDI_ASSERT_DEBUG(!iPrinterDevice,EPdrPrinterDeviceExists);
   520 	TRAPD(ret,DoCreatePrinterDeviceL(aModelUid));
   521 	if (ret!=KErrNone)
   522 		{
   523 		DeletePrinterDevice();
   524 		User::Leave(ret);
   525 		}
   526 	return iPrinterDevice;
   527 	}
   528 
   529 void CPrinterDriver::LoadLibraryL(RLibrary& aLibrary,const TDesC& aExt,TUid aUid2)
   530 	{
   531 	TFileName filename=iPdlName;
   532 	filename.Append(aExt);
   533 
   534 	User::LeaveIfError(aLibrary.Load(filename));
   535 	TUidType type=aLibrary.Type();
   536 	if (type[1]!=aUid2 && type[2]!=iPdlUid)
   537 		{
   538 		aLibrary.Close();
   539 		User::Leave(KErrNotSupported);
   540 		}
   541 	if (type[1]!=aUid2)
   542 		{
   543 		aLibrary.Close();
   544 		User::Leave(KErrNotFound);
   545 		}
   546 	}
   547 
   548 
   549 EXPORT_C CPrinterDriverUI* CPrinterDriver::CreatePrinterDriverUIL()
   550 /** Constructs a printer specific user interface.
   551 
   552 The user interface object is optional, but if it exists, it is implemented 
   553 as part of a UDL (i.e. a UI DLL).
   554 
   555 @return A pointer to the printer specific user interface, or NULL if there is 
   556 none. */
   557     {
   558 	GDI_ASSERT_DEBUG(iPrinterDevice,EPdrPrinterDeviceDoesNotExist);
   559 	if (iUdlLibrary.Handle()==0)
   560 		{
   561 		TRAPD(ret,LoadLibraryL(iUdlLibrary,KUdlExtension,TUid::Uid(KUdlUidVal)));
   562 		if (ret==KErrNotFound)
   563 			return NULL;
   564 		else
   565 			User::LeaveIfError(ret);
   566 		}
   567 	TLibraryFunction f = iUdlLibrary.Lookup(1);
   568 	CPrinterDriverUI* printerdriverui=(CPrinterDriverUI*)((*f)());
   569 	CleanupStack::PushL(printerdriverui);
   570 	User::LeaveIfError(printerdriverui->SetPrinterDevice(iPrinterDevice));
   571 	CleanupStack::Pop();
   572 	return printerdriverui;
   573 	}
   574 
   575 CPrinterDriver::CPrinterDriver()
   576 	{}
   577 
   578 void CPrinterDriver::DeletePrinterDevice()
   579 	{
   580 	iUdlLibrary.Close();
   581 	delete iPrinterDevice;
   582 	iPrinterDevice=NULL;
   583 	iPdlLibrary.Close();
   584 	}
   585 
   586 void CPrinterDriver::DoOpenPdrL(const TDesC &aName)
   587 	{
   588 	Close();
   589 	iPdrStore=CDirectFileStore::OpenL(iFs,aName,EFileStream|EFileRead|EFileShareReadersOnly);
   590 	if (iPdrStore->Type()[1]!=TUid::Uid(KPdrStoreFileUidVal))
   591 		User::Leave(KErrNotSupported);
   592 	TStreamId headerid = iPdrStore->Root();
   593 	RStoreReadStream stream;
   594 	stream.OpenLC(*iPdrStore,headerid);
   595 		stream >> iPdlName;
   596 	stream >> iPdlUid;
   597 	iNumModels = stream.ReadInt32L();
   598 	iModelList = new(ELeave) TPrinterModelHeader[iNumModels];
   599 	for (TInt i=0; i<iNumModels; i++)
   600 		iModelList[i].InternalizeL(stream);
   601 	CleanupStack::PopAndDestroy();
   602 	}
   603 
   604 void CPrinterDriver::DoCreatePrinterDeviceL(TUid aModelUid)
   605 	{
   606 	if (!iPdlName.Length())
   607 		User::Leave(KErrGeneral); // !! find a better error number
   608 	LoadLibraryL(iPdlLibrary,KPdlExtension,TUid::Uid(KPdlUidVal));
   609 	TLibraryFunction f = iPdlLibrary.Lookup(1);
   610 	iPrinterDevice=(CPrinterDevice*)((*f)());
   611 	TInt i;
   612 	for (i=0; (i<iNumModels) && (aModelUid!=iModelList[i].iEntry.iUid); i++)
   613 		{
   614 		}
   615 	GDI_ASSERT_DEBUG(i<iNumModels,EPdrModelUidNotFound);
   616 	User::LeaveIfError(iPrinterDevice->SetModel(iModelList[i],*iPdrStore));
   617 	iPrinterDevice->RestorePropertiesL();
   618 	}
   619 
   620 //
   621 // CPdrModelList
   622 //
   623 
   624 
   625 EXPORT_C CPdrModelList* CPdrModelList::NewL()
   626 /** Constructs, and returns a pointer to a new instance of the printer model 
   627 list interface.
   628 @return Pointer to the new printer model list interface object. */
   629     {
   630 	CPdrModelList* modellist=new(ELeave) CPdrModelList();
   631 	CleanupStack::PushL(modellist);
   632 	modellist->ConstructL();
   633 	CleanupStack::Pop();
   634 	return modellist;
   635 	}
   636 
   637 
   638 EXPORT_C CPdrModelList::~CPdrModelList()
   639 /** Virtual destructor.
   640 Frees resources owned by the object, prior to its destruction. */
   641 	{
   642 	delete iModelArray;
   643 	delete iFileArray;
   644 	if (iDirectoryArray)
   645 		{// delete all the HBufC's
   646 		for (TInt i=iDirectoryArray->Count()-1 ; i>=0 ; i--)
   647 			delete (*iDirectoryArray)[i];
   648 		delete iDirectoryArray;
   649 		}
   650 	iFileServer.Close();
   651 	}
   652 
   653 
   654 EXPORT_C TInt CPdrModelList::ModelCount() const
   655 /** Gets the number of printer models in the printer model list.
   656 @return The number of printer models. */
   657     {
   658 	return iModelArray->Count();
   659 	}
   660 
   661 
   662 EXPORT_C const TPrinterModelEntry CPdrModelList::operator [] (TInt anIndex)
   663 /** Gets printer model name.
   664 
   665 This is the name of the printer model at the specified index within the list 
   666 of printer models.
   667 
   668 @param anIndex The index of the printer model within the array of printer 
   669 models. Note that this number must be between zero and ModelCount(). 
   670 
   671 @return Name of printer model, up to 32 characters long */
   672  	{
   673 	GDI_ASSERT_DEBUG(anIndex>=0,EPdrModelIndexOutOfRange);
   674 	GDI_ASSERT_DEBUG(anIndex<iModelArray->Count(),EPdrModelIndexOutOfRange);
   675 
   676 	return (*iModelArray)[anIndex].iEntry;
   677 	}
   678 
   679 
   680 EXPORT_C TInt CPdrModelList::UidToNum(TUid aModelUid) const
   681 /** Gets a printer model's index within the model list from its UID.
   682 
   683 @param aModelUid The UID of the printer model.
   684 @return The index of the printer model within the array of printer models if 
   685 found; KErrNotFound, otherwise. */
   686     {
   687 	TInt i,count=iModelArray->Count();
   688 	for (i=0; (i<count) && (aModelUid!=(*iModelArray)[i].iEntry.iUid); i++)
   689 		{
   690 		}
   691 
   692 	if (i==count)
   693 		i=KErrNotFound;
   694 
   695 	return i;
   696 	}
   697 
   698 
   699 EXPORT_C void CPdrModelList::AddDirectoryL(const TDesC& aDir)
   700 /** Adds a directory to the list of directories to be scanned for printer models.
   701 
   702 @param aDir The directory to be added to the list. */
   703 	{
   704 	HBufC* buf = HBufC::NewL(aDir.Length());
   705 	CleanupStack::PushL(buf);
   706 	*buf = aDir;
   707 	iDirectoryArray->AppendL(buf);
   708 	CleanupStack::Pop(); //buf
   709 	}
   710 
   711 LOCAL_C void DereferenceAndDeleteHBufC8(TAny* aPointerToPointerToHBufC8)
   712 	{
   713 	delete *STATIC_CAST(HBufC8**, aPointerToPointerToHBufC8);
   714 	}
   715 
   716 
   717 EXPORT_C CPrinterModelList* CPdrModelList::ScanForModelsL()
   718 /** Scans through through the list of directories for all .pdr files and generates 
   719 a list of printer models.
   720 
   721 @return The list of model names. */
   722 	{
   723 	iModelArray->Reset();
   724 	iFileArray->Reset();
   725 	// check that there is at least one directory to parse?
   726 	// get a list of *.pdr files in all directories specified (using AddDirectory())
   727 	for (TInt index=iDirectoryArray->Count()-1 ; index>=0 ; index--)
   728 		ScanDirectoryL(index);
   729  	// then go through the files one at a time, adding all models to the list
   730 	TParse* parser = new(ELeave) TParse;
   731 	CleanupStack::PushL(parser);
   732 	TFileName* nameOfLoadedResourceFile=new(ELeave) TFileName;
   733 	CleanupStack::PushL(nameOfLoadedResourceFile);
   734 	TFileName* tempFileName=new(ELeave) TFileName;
   735 	CleanupStack::PushL(tempFileName);
   736 	RResourceFile resourceFile;
   737 	CleanupClosePushL(resourceFile);
   738 	HBufC8* resource=NULL;
   739 	CleanupStack::PushL(TCleanupItem(DereferenceAndDeleteHBufC8, &resource));
   740 	for (TInt fileNum=iFileArray->Count()-1 ; fileNum>=0 ; fileNum--)
   741 		ListModelsL(fileNum, *parser, *nameOfLoadedResourceFile, *tempFileName, resourceFile, resource);
   742 	CleanupStack::PopAndDestroy(5); // resource, resourceFile, tempFileName, nameOfLoadedResourceFile and parser
   743 	// return a handle to the array of model names
   744 	return this;
   745 	}
   746 
   747 
   748 EXPORT_C CPrinterDriver* CPdrModelList::CreatePrinterDriverL(TInt anIndex)
   749 /** Creates an object for accessing the specified store that contains printer specification 
   750 data.
   751 
   752 @param anIndex An index into a list of files containing printer specification 
   753 data. The files are the complete set of .pdr files found in the directories 
   754 known to this object.
   755 @return A pointer to the object representing the store containing the printer 
   756 specification data. */
   757  	{
   758 	GDI_ASSERT_DEBUG(anIndex>=0,EPdrModelIndexOutOfRange);
   759 	GDI_ASSERT_DEBUG(anIndex<iModelArray->Count(),EPdrModelIndexOutOfRange);
   760 
   761 	CPrinterDriver* driver = CPrinterDriver::NewL();
   762 	CleanupStack::PushL(driver);
   763 	HBufC* file = NewPathBufL(*((*iModelArray)[anIndex].iFile));
   764 	CleanupStack::PushL(file);
   765 	driver->OpenPdrL(*file);
   766 	driver->CreatePrinterDeviceL((*iModelArray)[anIndex].iEntry.iUid);
   767 	CleanupStack::PopAndDestroy();
   768 	CleanupStack::Pop();
   769 	return driver;
   770 	}
   771 
   772  
   773  CPdrModelList::CPdrModelList():
   774 	iModelArray(NULL),
   775 	iFileArray(NULL),
   776 	iDirectoryArray(NULL)
   777 	{
   778 	}
   779  
   780  void CPdrModelList::ConstructL()
   781 	{
   782 	__DECLARE_NAME(_S("CPdrModelList"));
   783 	iModelArray = new(ELeave) CArrayFixSeg<TModelEntry>(5);
   784 	iFileArray = new(ELeave) CArrayFixFlat<TFileEntry>(5);
   785 	iDirectoryArray = new(ELeave) CArrayFixFlat<HBufC*>(1);
   786 	User::LeaveIfError(iFileServer.Connect());
   787 	}
   788 
   789 void CPdrModelList::ScanDirectoryL(TInt aDirIndex)
   790 /** Scans the given directory, parsing all files found
   791  If a file is of the correct type it is appended to the file list*/
   792 	{
   793 	GDI_ASSERT_DEBUG(aDirIndex>=0,EPdrDirectoryIndexOutOfRange);
   794 	GDI_ASSERT_DEBUG(aDirIndex<iDirectoryArray->Count(),EPdrDirectoryIndexOutOfRange);
   795 
   796 	TDesC* dir = (*iDirectoryArray)[aDirIndex];
   797 	TParse path;
   798 	path.Set(KPdrExtension,dir,NULL);
   799 	CDir* fileList;
   800 	TInt ret = iFileServer.GetDir(path.FullName(),KEntryAttNormal,ESortByName,fileList);
   801 	if (ret == KErrNone)
   802 		{
   803 		CleanupStack::PushL(fileList);
   804 		for (TInt i=fileList->Count()-1 ; i>=0 ; i--) 
   805 			{
   806 			TFileEntry& entry = iFileArray->ExtendL();
   807 			entry.iFileName = (*fileList)[i].iName;
   808 			entry.iDirectory = dir;
   809 			}
   810 		CleanupStack::PopAndDestroy(); // fileList
   811 		}
   812 	else if (ret == KErrNoMemory) // Ignore errors other than KErrNoMemory
   813 		User::LeaveNoMemory();
   814 	}
   815 
   816 void CPdrModelList::ListModelsL(TInt aFileIndex, TParse& aParser, TFileName& aNameOfLoadedResourceFile, TFileName& aTempFileName, RResourceFile& aResourceFile, HBufC8*& aResource)
   817 /** given a pdr file list all the models it contains in the model array */
   818 	{
   819 	GDI_ASSERT_DEBUG(aFileIndex>=0,EPdrFileIndexOutOfRange);
   820 	GDI_ASSERT_DEBUG(aFileIndex<iFileArray->Count(),EPdrFileIndexOutOfRange);
   821 
   822 	CPrinterDriver* driver = CPrinterDriver::NewL() ;
   823 	CleanupStack::PushL(driver);
   824 	// open the file
   825 	HBufC* fullPath = NewPathBufL((*iFileArray)[aFileIndex]);
   826 	TRAPD(ret,driver->OpenPdrL(*fullPath));
   827 	delete fullPath;
   828 	if ((ret!=KErrNone) && (ret!=KErrNotSupported))
   829 		User::Leave(ret);
   830 	// get info on the models one by one and insert them into the array
   831 	if (ret==KErrNone)
   832 		{
   833 		TModelEntry modelentry;
   834 		modelentry.iFile = &(*iFileArray)[aFileIndex]; // set the file pointer for the entry
   835 		const TInt numberOfModels = driver->NumModels();
   836 		for (TInt i=0 ; i<numberOfModels ; i++)
   837 			{
   838 			modelentry.iEntry=driver->Model(i);
   839 			if (UidToNum(modelentry.iEntry.iUid)==KErrNotFound)
   840 				{
   841 				User::LeaveIfError(aParser.SetNoWild(KRscExtension, &modelentry.iFile->iFileName, modelentry.iFile->iDirectory));
   842 				aTempFileName=aParser.FullName();
   843 				BaflUtils::NearestLanguageFile(iFileServer, aTempFileName);
   844 				if (aNameOfLoadedResourceFile.CompareF(aTempFileName)!=0)
   845 					{
   846 					if (!BaflUtils::FileExists(iFileServer, aTempFileName))
   847 						{
   848 						iModelArray->AppendL(modelentry); // no resource file found, so reverting to old behaviour (i.e. where the model-name is set from the PDR file)
   849 						continue;
   850 						}
   851 					aNameOfLoadedResourceFile=KNullDesC;
   852 					aResourceFile.OpenL(iFileServer, aTempFileName);
   853 					HBufC8* resource=aResourceFile.AllocReadL(aResourceFile.Offset()+2); // read the first resource after the RSS_SIGNATURE resource
   854 					delete aResource;
   855 					aResource=resource;
   856 					aNameOfLoadedResourceFile=aTempFileName;
   857 					}
   858 				TResourceReader resourceReader;
   859 				resourceReader.SetBuffer(aResource);
   860 				for (TInt j=resourceReader.ReadUint16()-1; ; --j)
   861 					{
   862 					if (j<0)
   863 						{
   864 						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)
   865 						break;
   866 						}
   867 					TInt uid=resourceReader.ReadInt32();
   868 					TPtrC name=resourceReader.ReadTPtrC();
   869 					if (uid==modelentry.iEntry.iUid.iUid)
   870 						{
   871 						if (name.Length()>0)
   872 							{
   873 							modelentry.iEntry.iModelName=name;
   874 							iModelArray->AppendL(modelentry);
   875 							}
   876 						break;
   877 						}
   878 					}
   879 				}
   880 			}
   881 		}
   882 	CleanupStack::PopAndDestroy(); // driver
   883 	}
   884 
   885 
   886 HBufC* CPdrModelList::NewPathBufL(const TFileEntry& aFileEntry)  
   887 /** Create a buf of the right length and... 
   888  set its contents to the full filename of model aModel */
   889 	{
   890 	// Create a buf of the right length
   891 	HBufC* buf = HBufC::NewL(aFileEntry.iFileName.Length()+aFileEntry.iDirectory->Length());
   892 	// Insert the file path
   893 	TPtr filePtr = buf->Des();
   894 	filePtr.Append(*aFileEntry.iDirectory);
   895 	filePtr.Append(aFileEntry.iFileName);
   896 	return buf;
   897 	}
   898 
   899 // !!!!
   900 // Retained for binary compatibility only: remove if we make a binary incompatible release
   901 //
   902 
   903 IMPORT_C void GDI_Reserved();
   904 EXPORT_C void GDI_Reserved()
   905 	{}
   906