windowing/windowserver/nonnga/CLIENT/WSGRAPHIC.CPP
changeset 0 5d03bc08d59c
equal deleted inserted replaced
-1:000000000000 0:5d03bc08d59c
       
     1 // Copyright (c) 2005-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 // The client-side representation of a WsGraphic artwork
       
    15 // 
       
    16 //
       
    17 
       
    18 #include <w32std.h>
       
    19 #include "../SERVER/w32cmd.h"
       
    20 #include "w32comm.h"
       
    21 #include "CLIENT.H"
       
    22 #include <s32mem.h>
       
    23 #include <graphics/wsgraphicdrawerinterface.h>
       
    24 /** Panics the client. This will result in the client thread being destroyed. */
       
    25 GLREF_C void Panic(TW32Panic aPanic);
       
    26 
       
    27 NONSHARABLE_STRUCT(CWsGraphic::CPimpl): public CBase, public MWsClientClass
       
    28 /** @internalComponent @released */
       
    29 	{
       
    30 	friend class CWsGraphic;
       
    31 	enum
       
    32 		{
       
    33 		/** is registered in the graphic manager's array */
       
    34 		ERegistered = 0x01,
       
    35 		/** has a peer CWsGraphicDrawer on the server */
       
    36 		EHasPeer	= 0x02
       
    37 		};
       
    38 	CPimpl(CWsGraphic& aGraphic);
       
    39 	~CPimpl();
       
    40 	void ConstructL();		//LeaveScan: Member of macroised structure declaration.
       
    41 	CManager* iManager;
       
    42 	TInt WriteCreateGraphic(TWsClCmdCreateGraphic& aCreateGraphic,const TDesC8& aData,TInt aWsHandle) const;
       
    43 	CWsGraphic& iGraphic;
       
    44 	TWsGraphicId iId;
       
    45 	TUint iFlags;
       
    46 	MWsObjectProvider* iExt;
       
    47 	};
       
    48 
       
    49 LOCAL_C void MWsGraphicMessageAllocRelease(TAny* aAny)
       
    50 	{
       
    51 	MWsGraphicMessageAlloc::MBuffer* buf = static_cast<MWsGraphicMessageAlloc::MBuffer*>(aAny);
       
    52 	if(buf)
       
    53 		{
       
    54 		buf->Release();
       
    55 		}
       
    56 	}
       
    57 
       
    58 NONSHARABLE_CLASS(CWsGraphic::CManager): private CActive, public RWsSession
       
    59 /** Client-side manager singleton for marshalling messages for all CWsGraphics owned by a client
       
    60 
       
    61 @publishedAll
       
    62 @released
       
    63 */	{
       
    64 public:
       
    65 	static CManager* StaticL();			  //LeaveScan:  Member of macroised structure declaration.
       
    66 	// used by CWsGraphic
       
    67 	void AddL(CWsGraphic* aGraphic);	  //LeaveScan:  Member of macroised structure declaration.
       
    68 	void Replace(CWsGraphic* aGraphic);
       
    69 	void Remove(CWsGraphic* aGraphic);
       
    70 	CWsGraphic* Find(const TWsGraphicId& aId);
       
    71 	void Inc();
       
    72 	void Dec();
       
    73 	RWsBuffer* Buffer();
       
    74 	void ScheduleFlush();
       
    75 private:
       
    76 	CManager();
       
    77 	~CManager();
       
    78 	void ConstructL();					 //LeaveScan:  Member of macroised structure declaration.
       
    79 	void Queue();
       
    80 	void RunL();						 //LeaveScan:  Member of macroised structure declaration.
       
    81 	void DoCancel();
       
    82 	static TInt GraphicCompare(const CWsGraphic& aFirst,const CWsGraphic& aSecond);
       
    83 	static TInt FlushOnIdle(TAny* aArg);
       
    84 private:
       
    85 	TInt iRefCount;
       
    86 	RPointerArray<CWsGraphic> iArray;
       
    87 	CIdle* iFlusher;
       
    88 	TBool iFlushScheduled;
       
    89 	};
       
    90 
       
    91 // TWsGraphicId \\\\\\\\\\\\\\\\\\\\\\\\
       
    92 
       
    93 EXPORT_C TWsGraphicId::TWsGraphicId(TUid aUid):
       
    94 /** Construct a UID
       
    95     @param aUid UID of the graphic artwork.
       
    96     @publishedAll @released
       
    97 */	iFlags(EWsGraphicIdUid), iId(aUid.iUid)
       
    98 	{
       
    99 	}
       
   100 
       
   101 EXPORT_C TWsGraphicId::TWsGraphicId(TInt aId):
       
   102 /** Construct a transient Id
       
   103 	@publishedAll @released
       
   104 */	iFlags(EWsGraphicIdTransient), iId(aId)
       
   105 	{
       
   106 	}
       
   107 
       
   108 /** 
       
   109 Copy constructor.
       
   110 @param aCopy Graphic artwork Id.
       
   111 */
       
   112 EXPORT_C TWsGraphicId::TWsGraphicId(const TWsGraphicId& aCopy):
       
   113 	iFlags(aCopy.iFlags), iId(aCopy.iId)
       
   114 	{
       
   115 	}
       
   116 
       
   117 EXPORT_C TUid TWsGraphicId::Uid() const
       
   118 /** Returns UID.
       
   119     @return UID of graphic artwork. KNullUid if graphic artwork is transient.
       
   120     @publishedAll @released
       
   121 */	{
       
   122 	if(IsUid())
       
   123 		{
       
   124 		return TUid::Uid(iId);
       
   125 		}
       
   126 	return KNullUid;
       
   127 	}
       
   128 
       
   129 EXPORT_C TBool TWsGraphicId::IsUid() const
       
   130 /** Identifies whether graphic artwork is non-transient.
       
   131     @return ETrue if graphic artwork is non-transient.
       
   132     @publishedAll @released
       
   133 */	{
       
   134 	return (iFlags & EWsGraphicIdUid);
       
   135 	}
       
   136 
       
   137 EXPORT_C void TWsGraphicId::Set(TUid aUid)
       
   138 /** Set to be a UID
       
   139 	@publishedAll @released
       
   140 */	{
       
   141 	iId = aUid.iUid;
       
   142 	iFlags = EWsGraphicIdUid;
       
   143 	}
       
   144 
       
   145 EXPORT_C TInt TWsGraphicId::Id() const
       
   146 /** Returns the transient Id.
       
   147     @return Id of transient graphic artwork. Zero if graphic artwork is non-transient.
       
   148 	@publishedAll @released
       
   149 */	{
       
   150 	if(IsId())
       
   151 		{
       
   152 		return iId;
       
   153 		}
       
   154 	return 0;
       
   155 	}
       
   156 
       
   157 EXPORT_C TBool TWsGraphicId::IsId() const
       
   158 /** Identifies whether graphic artwork is transient.
       
   159     @return ETrue if graphic artwork is transient.
       
   160     @publishedAll @released
       
   161 */	{
       
   162 	return (iFlags & EWsGraphicIdTransient);
       
   163 	}
       
   164 
       
   165 EXPORT_C void TWsGraphicId::Set(TInt aId)
       
   166 /** Set to be a transient Id
       
   167 	@publishedAll @released
       
   168 */	{
       
   169 	iId = aId;
       
   170 	iFlags = EWsGraphicIdTransient;
       
   171 	}
       
   172 
       
   173 EXPORT_C TInt TWsGraphicId::Compare(const TWsGraphicId& aOther) const
       
   174 /** Compares another Id with this one.
       
   175 	@return 0 if the other Id is identical, else -1 if the other Id is to greater than or 1 if the other Id is less than
       
   176 	@publishedAll @released
       
   177 */	{
       
   178 	if(iId < aOther.iId)
       
   179 		{
       
   180 		return -1;
       
   181 		}
       
   182 	else if(iId > aOther.iId)
       
   183 		{
       
   184 		return 1;
       
   185 		}
       
   186 	// else we have to compare the iIsUid flag too; again, expect it to be a match 99.99% of these times
       
   187 	else if(IsUid() == aOther.IsUid())
       
   188 		{
       
   189 		return 0;
       
   190 		}
       
   191 	// collisions of id but not iIsUid are going to be really really rare
       
   192 	else if(IsUid())
       
   193 		{
       
   194 		return 1;
       
   195 		}
       
   196 	else
       
   197 		{
       
   198 		return -1;
       
   199 		}
       
   200 	}
       
   201 
       
   202 // CWsGraphicManager \\\\\\\\\\\\\\\\\\\\\\\\
       
   203 
       
   204 CWsGraphic::CManager* CWsGraphic::CManager::StaticL()
       
   205 	{
       
   206 	CManager* singleton = RWsBuffer::WsGraphicManager();
       
   207 	if(!singleton)
       
   208 		{
       
   209 		singleton = new(ELeave) CManager;
       
   210 		CleanupStack::PushL(singleton);
       
   211 		singleton->ConstructL();
       
   212 		CleanupStack::Pop(singleton);
       
   213 		__ASSERT_DEBUG(singleton == RWsBuffer::WsGraphicManager(),Panic(EW32PanicGraphicInternal));
       
   214 		}
       
   215 	return singleton;
       
   216 	}
       
   217 
       
   218 CWsGraphic::CManager::~CManager()
       
   219 	{
       
   220 	__ASSERT_DEBUG(!ResourceCount(),Panic(EW32PanicGraphicInternal));
       
   221 	__ASSERT_DEBUG(!iArray.Count(),Panic(EW32PanicGraphicOrphaned));
       
   222 	Close();
       
   223 	__ASSERT_DEBUG(!RWsBuffer::WsGraphicManager(),Panic(EW32PanicGraphicInternal));
       
   224 	iArray.Close();
       
   225 	delete iFlusher;
       
   226 	}
       
   227 
       
   228 CWsGraphic::CManager::CManager(): CActive(CActive::EPriorityStandard)
       
   229 	{
       
   230 	}
       
   231 
       
   232 void CWsGraphic::CManager::ConstructL()
       
   233 	{
       
   234 	User::LeaveIfError(Connect());
       
   235 	iBuffer->SetWsGraphicManager(this);
       
   236 	CActiveScheduler::Add(this);
       
   237 	iFlusher = CIdle::NewL(CActive::EPriorityIdle);
       
   238 	}
       
   239 
       
   240 void CWsGraphic::CManager::Inc()
       
   241 	{
       
   242 	iRefCount++;
       
   243 	}
       
   244 
       
   245 void CWsGraphic::CManager::Dec()
       
   246 	{
       
   247 	if(!--iRefCount)
       
   248 		{
       
   249 		delete this;
       
   250 		}
       
   251 	}
       
   252 
       
   253 RWsBuffer* CWsGraphic::CManager::Buffer()
       
   254 	{
       
   255 	return iBuffer;
       
   256 	}
       
   257 
       
   258 // used by CWsGraphic
       
   259 
       
   260 void CWsGraphic::CManager::AddL(CWsGraphic* aGraphic)
       
   261 /** Leaves if the graphic couldn't be added to the list
       
   262 	@internalComponent @released */
       
   263 	{
       
   264 	__ASSERT_ALWAYS(aGraphic && aGraphic->iPimpl,Panic(EW32PanicGraphicInternal));
       
   265 	__ASSERT_ALWAYS(aGraphic->Id().IsId() || aGraphic->Id().IsUid(),Panic(EW32PanicGraphicInternal));
       
   266 	__ASSERT_ALWAYS(!(aGraphic->iPimpl->iFlags & CWsGraphic::CPimpl::ERegistered),Panic(EW32PanicGraphicInternal));
       
   267 	iArray.InsertInOrderL(aGraphic,GraphicCompare);
       
   268 	__ASSERT_ALWAYS(0 <= iArray.FindInOrder(aGraphic,GraphicCompare),Panic(EW32PanicGraphicInternal));
       
   269 	aGraphic->iPimpl->iFlags |= CWsGraphic::CPimpl::ERegistered;
       
   270 	Queue();
       
   271 	}
       
   272 
       
   273 void CWsGraphic::CManager::Replace(CWsGraphic* aGraphic)
       
   274 /** @internalComponent @released */
       
   275 	{
       
   276 	__ASSERT_ALWAYS(aGraphic && aGraphic->iPimpl,Panic(EW32PanicGraphicInternal));
       
   277 	__ASSERT_ALWAYS(!(aGraphic->iPimpl->iFlags & CWsGraphic::CPimpl::ERegistered),Panic(EW32PanicGraphicInternal));
       
   278 	__ASSERT_ALWAYS(aGraphic->Id().IsId() || aGraphic->Id().IsUid(),Panic(EW32PanicGraphicInternal));
       
   279 	const TInt idx = iArray.FindInOrder(aGraphic,GraphicCompare);
       
   280 	__ASSERT_ALWAYS(0 <= idx,Panic(EW32PanicGraphicInternal));
       
   281 	__ASSERT_ALWAYS(iArray[idx]->iPimpl->iFlags & CWsGraphic::CPimpl::ERegistered,Panic(EW32PanicGraphicInternal));
       
   282 	iArray[idx]->iPimpl->iFlags &= ~CWsGraphic::CPimpl::ERegistered;
       
   283 	iArray[idx] = aGraphic;
       
   284 	iArray[idx]->iPimpl->iFlags |= CWsGraphic::CPimpl::ERegistered;
       
   285 	Queue();
       
   286 	}
       
   287 
       
   288 void CWsGraphic::CManager::Remove(CWsGraphic* aGraphic)
       
   289 /** @internalComponent @released */
       
   290 	{
       
   291 	__ASSERT_ALWAYS(aGraphic && aGraphic->iPimpl,Panic(EW32PanicGraphicInternal));
       
   292 	__ASSERT_ALWAYS(aGraphic->Id().IsId() || aGraphic->Id().IsUid(),Panic(EW32PanicGraphicInternal));
       
   293 	__ASSERT_ALWAYS(aGraphic->iPimpl->iFlags & CWsGraphic::CPimpl::ERegistered,Panic(EW32PanicGraphicInternal));
       
   294 	const TInt idx = iArray.FindInOrder(aGraphic,GraphicCompare);
       
   295 	__ASSERT_ALWAYS(0 <= idx,Panic(EW32PanicGraphicInternal));
       
   296 	iArray[idx]->iPimpl->iFlags &= ~CWsGraphic::CPimpl::ERegistered;
       
   297 	iArray.Remove(idx);
       
   298 	if(!iArray.Count())
       
   299 		{
       
   300 		Cancel();
       
   301 		}
       
   302 	}
       
   303 
       
   304 CWsGraphic* CWsGraphic::CManager::Find(const TWsGraphicId& aId)
       
   305 /** Find the active artwork identified by the Id
       
   306 	@return NULL if no active artwork has the Id
       
   307 	@publishedAll @released */
       
   308 	{
       
   309 	/*	RPointerArray can only FindInOrder other T*, which is a needless shame.  Therefore this search is
       
   310 		dumb sequential */
       
   311 	const TInt count = iArray.Count();
       
   312 	for(TInt i=0; i<count; i++)
       
   313 		{
       
   314 		CWsGraphic* graphic = iArray[i];
       
   315 		__ASSERT_ALWAYS(graphic && graphic->iPimpl && (graphic->iPimpl->iFlags & CWsGraphic::CPimpl::ERegistered),Panic(EW32PanicGraphicInternal));
       
   316 		const TWsGraphicId& candidate = graphic->Id();
       
   317 		if(0 == candidate.Compare(aId))
       
   318 			{
       
   319 			// found
       
   320 			__ASSERT_DEBUG(i == iArray.FindInOrder(graphic,GraphicCompare),Panic(EW32PanicGraphicInternal));
       
   321 			return graphic;
       
   322 			}
       
   323 		}
       
   324 	// not found
       
   325 	return NULL;
       
   326 	}
       
   327 
       
   328 void CWsGraphic::CManager::Queue()
       
   329 	{
       
   330 	if(!IsActive())
       
   331 		{
       
   332 		GraphicMessageReady(&iStatus);
       
   333 		SetActive();
       
   334 		}
       
   335 	}
       
   336 
       
   337 void CWsGraphic::CManager::RunL()
       
   338    	{
       
   339    	if(0 < iStatus.Int())
       
   340    		{
       
   341    		// a message to fetch!
       
   342    		const TInt msgLen = iStatus.Int();
       
   343  		TPtr8 buf(NULL,0);
       
   344  		MWsGraphicMessageAlloc* allocator = NULL;
       
   345  		MWsGraphicMessageAlloc::MBuffer* theirBuf = NULL;
       
   346  		HBufC8* ourBuf = HBufC8::New(msgLen);
       
   347  		if(ourBuf)
       
   348  			{
       
   349  			CleanupStack::PushL(ourBuf);
       
   350  			buf.Set(ourBuf->Des());
       
   351  			}
       
   352  		else // try to see if the destination CWsGraphic can allocate for us
       
   353  			{
       
   354 			const TInt handle = GraphicFetchHeaderMessage();
       
   355 			CWsGraphic* dest = reinterpret_cast<CWsGraphic*>(handle & ~0x03);
       
   356  			// check if it's valid
       
   357  			if(KErrNotFound != iArray.Find(dest) && dest->iPimpl && dest->iPimpl->iExt)
       
   358  				{
       
   359  				// check if the client is able to alloc memory for us
       
   360  				allocator = dest->iPimpl->iExt->ObjectInterface<MWsGraphicMessageAlloc>();
       
   361  				if(allocator)
       
   362  					{
       
   363  					// allocate memory
       
   364  					theirBuf = allocator->Alloc(msgLen);
       
   365  					if(theirBuf)
       
   366  						{
       
   367  						CleanupStack::PushL(TCleanupItem(MWsGraphicMessageAllocRelease,theirBuf));
       
   368  						buf.Set(theirBuf->Buffer());
       
   369  						}
       
   370  					}
       
   371  				}
       
   372  			}
       
   373  		if(!ourBuf && !theirBuf)
       
   374  			{
       
   375  			GraphicMessageCancel();
       
   376  			GraphicAbortMessage(KErrNoMemory);
       
   377  			}
       
   378  		else
       
   379  			{
       
   380  			GetGraphicMessage(buf);
       
   381  			// decode header and body
       
   382  			RDesReadStream in(buf);
       
   383  			in.PushL();
       
   384  			const TInt header = in.ReadInt32L();
       
   385  			__ASSERT_COMPILE(sizeof(header) == sizeof(TInt32));
       
   386  			const TInt clientHandle = (header & ~0x03);
       
   387  			const TInt msgType = (header & 0x03);
       
   388  			const TPtr8 body = buf.MidTPtr(sizeof(header));
       
   389  			// dispatch
       
   390  			CWsGraphic* dest = (CWsGraphic*)clientHandle;
       
   391  			if(KErrNotFound != iArray.Find(dest))
       
   392  				{
       
   393  				switch(msgType)
       
   394  					{
       
   395  					case EWsGraphMessageTypeUser:
       
   396  						dest->HandleMessage(body);
       
   397  						break;
       
   398  					default:
       
   399  						Panic(EW32PanicGraphicInternal);
       
   400  					}
       
   401  				}
       
   402  			// done
       
   403  			in.Pop();
       
   404  			}
       
   405  		if(ourBuf)
       
   406  			{
       
   407  			CleanupStack::PopAndDestroy(ourBuf);
       
   408  			}
       
   409  		else if(theirBuf)
       
   410  			{
       
   411  			CleanupStack::PopAndDestroy(theirBuf);
       
   412  			}
       
   413  		// done, wait for next message
       
   414  		Queue();
       
   415  		}
       
   416  	}
       
   417 
       
   418 void CWsGraphic::CManager::DoCancel()
       
   419 	{
       
   420 	GraphicMessageCancel();
       
   421 	}
       
   422 
       
   423 TInt CWsGraphic::CManager::GraphicCompare(const CWsGraphic& aFirst,const CWsGraphic& aSecond)
       
   424 /** Compares two graphics for id equality
       
   425 @internalComponent
       
   426 @released
       
   427 */	{
       
   428 	return aFirst.Id().Compare(aSecond.Id());
       
   429 	}
       
   430 
       
   431 void CWsGraphic::CManager::ScheduleFlush()
       
   432 /** Request to schedule flush when idle
       
   433 @internalComponent
       
   434 @released
       
   435 */
       
   436 	{
       
   437 	if (iFlushScheduled)
       
   438 		return;
       
   439 
       
   440 	iFlushScheduled = ETrue;
       
   441 	iFlusher->Start(TCallBack(CWsGraphic::CManager::FlushOnIdle,this));
       
   442 	}
       
   443 
       
   444 TInt CWsGraphic::CManager::FlushOnIdle(TAny* aArg)
       
   445 /** Flush buffer when idle and there is outstanding data in it
       
   446 @internalComponent
       
   447 @released
       
   448 */
       
   449 	{
       
   450 	CWsGraphic::CManager* mgr = reinterpret_cast<CWsGraphic::CManager*>(aArg);
       
   451 	if (mgr)
       
   452 		{
       
   453 		mgr->iFlushScheduled = EFalse;
       
   454 		if (mgr->iBuffer && !mgr->iBuffer->IsEmpty())
       
   455 			mgr->iBuffer->Flush();
       
   456 		}
       
   457 
       
   458 	return 0; // complete
       
   459 	}
       
   460 
       
   461 // CWsGraphic::CPimpl \\\\\\\\\\\\\\\\\\\\\\\\
       
   462 
       
   463 CWsGraphic::CPimpl::CPimpl(CWsGraphic& aGraphic):
       
   464 	iGraphic(aGraphic), iId(TWsGraphicId::EUninitialized)
       
   465 	{
       
   466 	}
       
   467 
       
   468 CWsGraphic::CPimpl::~CPimpl()
       
   469 	{
       
   470 	if(iManager)
       
   471 		{
       
   472 		iManager->Dec();
       
   473 		}
       
   474 	}
       
   475 
       
   476 void CWsGraphic::CPimpl::ConstructL()
       
   477 	{
       
   478 	iManager = CManager::StaticL();
       
   479 	iManager->Inc();
       
   480 	iBuffer = iManager->Buffer();
       
   481 	}
       
   482 
       
   483 TInt CWsGraphic::CPimpl::WriteCreateGraphic(TWsClCmdCreateGraphic& aCreateGraphic,const TDesC8& aData,TInt aWsHandle) const
       
   484 /** Writes the CreateGraphic message to the server.  If the data will not fit in the buffer, uses remote-read
       
   485 	@internalComponent @released */
       
   486 	{
       
   487 	aCreateGraphic.iDataLen = aData.Size();
       
   488 	aCreateGraphic.iRemoteReadData = ((aData.Size()+sizeof(aCreateGraphic))>(TInt)(iBuffer->BufferSize()-sizeof(TWsCmdHeader)));
       
   489 	if(aCreateGraphic.iRemoteReadData)
       
   490 		{
       
   491 		return iBuffer->WriteReplyByProvidingRemoteReadAccess(aWsHandle,EWsClOpCreateGraphic,&aCreateGraphic,sizeof(aCreateGraphic),&aData);
       
   492 		}
       
   493 	else if(aCreateGraphic.iDataLen)
       
   494 		{
       
   495 		return iBuffer->WriteReplyWs(&aCreateGraphic,sizeof(aCreateGraphic),aData.Ptr(),aData.Size(),EWsClOpCreateGraphic);
       
   496 		}
       
   497 	else
       
   498 		{
       
   499 		return iBuffer->WriteReplyWs(&aCreateGraphic,sizeof(aCreateGraphic),EWsClOpCreateGraphic);
       
   500 		}
       
   501 	}
       
   502 
       
   503 // CWsGraphic \\\\\\\\\\\\\\\\\\\\\\\\
       
   504 
       
   505 /** 
       
   506 Default Constructor.
       
   507 */
       
   508 EXPORT_C CWsGraphic::CWsGraphic()
       
   509 	{
       
   510 	}
       
   511 
       
   512 /**
       
   513 Destructor.
       
   514 */
       
   515 EXPORT_C CWsGraphic::~CWsGraphic()
       
   516 	{
       
   517 	Destroy();
       
   518 	delete iPimpl;
       
   519 	}
       
   520 	
       
   521 /**
       
   522 Completes construction of the baseclass. All the overloaded BaseConstructL() methods
       
   523 should invoke this method to complete the construction of the baseclass.
       
   524 */
       
   525 void CWsGraphic::BaseConstructL()
       
   526 	{
       
   527 	iPimpl = new(ELeave) CPimpl(*this);
       
   528 	iPimpl->ConstructL();
       
   529 	}
       
   530 
       
   531 EXPORT_C void CWsGraphic::BaseConstructL(TUid aUid,TUid aType,const TDesC8& aData)
       
   532 /** 
       
   533 Constructs a piece of non-transient graphic artwork.
       
   534 @capability ProtServ
       
   535 @param aUid	Graphic artwork UID.
       
   536 @param aType Graphic artwork type.
       
   537 @param aData User specific data.
       
   538 */	{
       
   539 	BaseConstructL();
       
   540 
       
   541 	TWsClCmdCreateGraphic createGraphic;
       
   542 	createGraphic.iFlags = EWsGraphicIdUid;
       
   543 	createGraphic.iId = aUid.iUid;
       
   544 	createGraphic.iType = aType;
       
   545 	createGraphic.iClientHandle = (TInt)this;
       
   546 
       
   547 	TInt ret = iPimpl->WriteCreateGraphic(createGraphic,aData,iPimpl->iManager->WsHandle());
       
   548 	User::LeaveIfError(ret);
       
   549 
       
   550 	iPimpl->iWsHandle=ret;
       
   551 	iPimpl->iId = aUid;
       
   552 	iPimpl->iFlags = CPimpl::EHasPeer;
       
   553 	iPimpl->iManager->AddL(this);
       
   554 	}
       
   555 
       
   556 EXPORT_C void CWsGraphic::BaseConstructL(TUid aType,const TDesC8& aData)
       
   557 /** 
       
   558 Constructs a piece of transient graphic artwork.
       
   559 @param aType Graphic artwork type.
       
   560 @param aData User specific data.
       
   561 */
       
   562 	{
       
   563 	BaseConstructL();
       
   564 
       
   565 	TWsClCmdCreateGraphic createGraphic;
       
   566 	createGraphic.iFlags = EWsGraphicIdTransient;
       
   567 	createGraphic.iId = 0;
       
   568 	createGraphic.iType = aType;
       
   569 	createGraphic.iClientHandle = (TInt)this;
       
   570 
       
   571 	TInt ret = iPimpl->WriteCreateGraphic(createGraphic,aData,iPimpl->iManager->WsHandle());
       
   572 	User::LeaveIfError(ret);
       
   573 
       
   574 	iPimpl->iWsHandle = ret;
       
   575 
       
   576 	// fetch id from server
       
   577 	TPckgBuf<TWsClCmdGdGetId> cmd;
       
   578 	User::LeaveIfError(iPimpl->WriteReplyP(TWriteDescriptorType(&cmd),EWsGdOpGetGraphicId));
       
   579 	if(cmd().iIsUid)
       
   580 		{
       
   581 		__DEBUG_ONLY(Panic(EW32PanicGraphicInternal));
       
   582 		User::Leave(KErrGeneral);
       
   583 		}
       
   584 	iPimpl->iId = cmd().iId;
       
   585 
       
   586 	iPimpl->iFlags = CPimpl::EHasPeer;
       
   587 	iPimpl->iManager->AddL(this);
       
   588 	}
       
   589 
       
   590 EXPORT_C void CWsGraphic::BaseConstructL(const TWsGraphicId& aReplace,TUid aType,const TDesC8& aData)
       
   591 /** 
       
   592 Atomically replace the artwork that already exists with this artwork.
       
   593 If failure to properly construct the replacement artwork occurs, the replacee artwork will remain
       
   594 @param aReplace Graphic artwork which will be replaced.
       
   595 @param aType New graphic artwork type.
       
   596 @param aData User specific data.
       
   597 */
       
   598 	{
       
   599 	BaseConstructL();
       
   600 
       
   601 	CWsGraphic* dup = iPimpl->iManager->Find(aReplace);
       
   602 	if(!dup || !dup->iPimpl)
       
   603 		{
       
   604 		Panic(EW32PanicGraphicInternal);
       
   605 		}
       
   606 
       
   607 	const TUint flags = aReplace.IsUid()?EWsGraphicIdUid:EWsGraphicIdTransient;
       
   608 
       
   609 	TWsClCmdCreateGraphic createGraphic;
       
   610 	createGraphic.iFlags = EWsGraphicReplace|flags;
       
   611 	createGraphic.iId = aReplace.IsUid()?aReplace.Uid().iUid:aReplace.Id();
       
   612 	createGraphic.iType = aType;
       
   613 	createGraphic.iClientHandle = (TInt)this;
       
   614 
       
   615 	TInt ret = iPimpl->WriteCreateGraphic(createGraphic,aData,iPimpl->iManager->WsHandle());
       
   616 	if(0 > ret)
       
   617 		{
       
   618 		User::Leave(ret);
       
   619 		}
       
   620 
       
   621 	iPimpl->iWsHandle = ret;
       
   622 	iPimpl->iId = aReplace;
       
   623 
       
   624 	iPimpl->iFlags = CPimpl::EHasPeer;
       
   625 	iPimpl->iManager->Replace(this);
       
   626 
       
   627 	// when WriteCreateGraphic succeeds, the replacee drawer has already been destroyed serverside
       
   628 	// so this cleanup is not quite the same as Destroy(), as it doesn't free server side
       
   629 	dup->iPimpl->iWsHandle = 0;
       
   630 	dup->OnReplace();
       
   631 	dup->iPimpl->iFlags &= ~CPimpl::EHasPeer;
       
   632 	}
       
   633 
       
   634 /**
       
   635 Shares the graphic artwork with all the client sessions.
       
   636 Sharing globally trumps explicit shares.
       
   637 @return KErrNone if the graphic is globally shared, else one of the system-wide error codes.
       
   638 */
       
   639 EXPORT_C TInt CWsGraphic::ShareGlobally()
       
   640 	{
       
   641 	if(!IsActive())
       
   642 		{
       
   643 		return KErrNotReady;
       
   644 		}
       
   645 	return iPimpl->WriteReply(EWsGdOpShareGlobally);
       
   646 	}
       
   647 
       
   648 /**
       
   649 Prevents this graphic artwork from being shared with all the client sessions.
       
   650 A graphic artwork that isn't shared explicitly is only available to clients it
       
   651 has been explicitly shared with using Share().
       
   652 @return KErrNone if the graphic is not globally shared, else one of the system-wide error codes.
       
   653 */
       
   654 EXPORT_C TInt CWsGraphic::UnShareGlobally()
       
   655 	{
       
   656 	if(!IsActive())
       
   657 		{
       
   658 		return KErrNotReady;
       
   659 		}
       
   660 	return iPimpl->WriteReply(EWsGdOpUnShareGlobally);
       
   661 	}
       
   662 	
       
   663 /** 
       
   664 Explicitly shares this graphic artwork with client sessions with the specified Secure ID.
       
   665 @param aClientId the Secure ID of the client sessions to share with.
       
   666 @return KErrNone If the graphic artwork was shared, else one of the system-wide error codes.
       
   667 */
       
   668 EXPORT_C TInt CWsGraphic::Share(TSecureId aClientId)
       
   669 	{
       
   670 	if(!IsActive())
       
   671 		{
       
   672 		return KErrNotReady;
       
   673 		}
       
   674 	return iPimpl->WriteReply(&aClientId,sizeof(TSecureId),EWsGdOpShare);
       
   675 	}
       
   676 
       
   677 /** 
       
   678 Stops this graphic artwork from being shared with all client sessions with the specific Secure ID.
       
   679 ShareGlobally() trumps explicit sharing.
       
   680 @param aClientId the Secure ID of the client sessions to not share with
       
   681 @return KErrNone if the graphic artwork is no longer shared, KErrNotFound if the graphic was not shared anyway, else one of the system-wide error codes
       
   682 */
       
   683 EXPORT_C TInt CWsGraphic::UnShare(TSecureId aClientId)
       
   684 	{
       
   685 	if(!IsActive())
       
   686 		{
       
   687 		return KErrNotReady;
       
   688 		}
       
   689 	return iPimpl->WriteReply(&aClientId,sizeof(TSecureId),EWsGdOpUnShare);
       
   690 	}
       
   691 
       
   692 /**
       
   693 Returns graphic artwork Id.
       
   694 @return Graphic artwork Id. KNullWsGraphicId if graphic artwork is not active.
       
   695 */
       
   696 EXPORT_C const TWsGraphicId& CWsGraphic::Id() const
       
   697 	{
       
   698 	if(IsActive())
       
   699 		{
       
   700 		return iPimpl->iId;
       
   701 		}
       
   702 	else
       
   703 		{
       
   704 		// fallback
       
   705 		static const TInt KNullWsGraphicId[4] = //binary compatible with TWsGraphicId
       
   706 			{
       
   707 			0, 0, 0, 0
       
   708 			};
       
   709 		__ASSERT_COMPILE(sizeof(KNullWsGraphicId) == sizeof(TWsGraphicId));
       
   710 		return reinterpret_cast<const TWsGraphicId&>(KNullWsGraphicId);
       
   711 		}
       
   712 	}
       
   713 	
       
   714 /** 
       
   715 Checks whether a peer of this graphic artwork has been fully constructed on the server.
       
   716 @return ETrue if this graphic artwork has a peer CWsGraphic on the server.
       
   717 */
       
   718 EXPORT_C TBool CWsGraphic::IsActive() const
       
   719 	{
       
   720 	return (iPimpl && iPimpl->iWsHandle && (iPimpl->iFlags & CPimpl::EHasPeer));
       
   721 	}
       
   722 	
       
   723 /**
       
   724 Derived class can override this method to provide custom operations when the client is closed.
       
   725 */
       
   726 EXPORT_C void CWsGraphic::OnClientClose()
       
   727 	{
       
   728 	}
       
   729 	
       
   730 /** 
       
   731 Sends message to this graphic artwork peer on the server.
       
   732 @param aData User specific data.
       
   733 */
       
   734 EXPORT_C void CWsGraphic::SendMessage(const TDesC8& aData) const
       
   735 	{
       
   736 	TWsClCmdGdSendMessage cmd;
       
   737 	cmd.iDataLen = aData.Size();
       
   738 	__ASSERT_DEBUG(cmd.iDataLen, Panic(EW32PanicGraphicNullData));
       
   739 	cmd.iRemoteReadData = ((aData.Size()+sizeof(cmd))>(TInt)(iPimpl->iBuffer->BufferSize()-sizeof(TWsCmdHeader)));
       
   740 	if(cmd.iRemoteReadData)
       
   741 		{
       
   742 		iPimpl->WriteReplyByProvidingRemoteReadAccess(&cmd,sizeof(cmd),&aData,EWsGdOpSendMsg);
       
   743 		//ignore return value!
       
   744 		}
       
   745 	else
       
   746 		{
       
   747 		iPimpl->Write(&cmd,sizeof(cmd),aData.Ptr(),aData.Size(),EWsGdOpSendMsg);
       
   748 		}
       
   749 	}
       
   750 
       
   751 EXPORT_C TInt CWsGraphic::SendSynchronMessage(const TDesC8& aData) const
       
   752 	 {
       
   753 	 TWsClCmdGdSendMessage cmd;
       
   754 	 cmd.iDataLen = aData.Size();
       
   755 	 __ASSERT_DEBUG(cmd.iDataLen, Panic(EW32PanicGraphicNullData));
       
   756 	 cmd.iRemoteReadData = ((aData.Size()+sizeof(cmd))>(TInt)(iPimpl->iBuffer->BufferSize()-sizeof(TWsCmdHeader)));
       
   757 	 if(cmd.iRemoteReadData)
       
   758 		{
       
   759 		return iPimpl->WriteReplyByProvidingRemoteReadAccess(&cmd,sizeof(cmd),&aData,EWsGdOpSendSynchronMsg);
       
   760 		}
       
   761 	 else
       
   762 		{
       
   763 		return iPimpl->WriteReply(&cmd,sizeof(cmd),aData.Ptr(),aData.Size(),EWsGdOpSendSynchronMsg);
       
   764 		}
       
   765 	 }
       
   766 
       
   767 /** 
       
   768 Flushes window server command buffer
       
   769 @return One of system-wide error codes.
       
   770 */
       
   771 EXPORT_C TInt CWsGraphic::Flush() const
       
   772 	{
       
   773 	return iPimpl->iBuffer->Flush();
       
   774 	}
       
   775 
       
   776 EXPORT_C void CWsGraphic::Destroy()
       
   777 /** Destroys the corresponding CWsGraphicDrawer instance on the server
       
   778 @released
       
   779 @publishedAll
       
   780 */	{
       
   781 	if(iPimpl && (iPimpl->iFlags & CPimpl::ERegistered))
       
   782 		{
       
   783 		iPimpl->iManager->Remove(this);
       
   784 		}
       
   785 	if(IsActive()) // if iPimpl==NULL, IsActive() returns false
       
   786 		{
       
   787 		iPimpl->Write(EWsGdOpFree);
       
   788 		iPimpl->iWsHandle = 0;
       
   789 		iPimpl->iFlags &= ~CPimpl::EHasPeer;
       
   790 		iPimpl->iManager->ScheduleFlush();
       
   791 		}
       
   792 	}
       
   793 
       
   794 EXPORT_C void CWsGraphic::SetGraphicExtension(MWsObjectProvider* aExt)
       
   795 	{
       
   796 	iPimpl->iExt = aExt;
       
   797 	}
       
   798 
       
   799 EXPORT_C RWsSession&  CWsGraphic::Session()
       
   800 	{
       
   801 	return *iPimpl->iManager;
       
   802 	}
       
   803 
       
   804 EXPORT_C TInt CWsGraphic::CWsGraphic_Reserved1()
       
   805 	{
       
   806 	return KErrNotSupported;
       
   807 	}
       
   808 
       
   809 EXPORT_C TInt CWsGraphic::CWsGraphic_Reserved2()
       
   810 	{
       
   811 	return KErrNotSupported;
       
   812 	}
       
   813 
       
   814 EXPORT_C TInt CWsGraphic::CWsGraphic_Reserved3()
       
   815 	{
       
   816 	return KErrNotSupported;
       
   817 	}
       
   818 
       
   819 // TWsGraphicMsgFixedBase \\\\\\\\\\\\\\\\\\\\\\\\
       
   820 
       
   821 EXPORT_C TWsGraphicMsgFixedBase::TWsGraphicMsgFixedBase(TUid aTypeId,TInt aSizeOfDerived):
       
   822 /** Protected constructor for subclasses to call
       
   823 @param aTypeId The UID representing this type of data
       
   824 @param aSizeOf The size of the derived class
       
   825 
       
   826 Example:
       
   827 @code
       
   828 TMyDerivedFixedMsg::TMyDerivedFixedMsg(): TWsGraphicMsgFixedBase(KUidMyDerivedType,sizeof(TMyDerivedFixedMsg)), ...
       
   829 @endcode
       
   830 */	iTypeId(aTypeId), iSize(aSizeOfDerived-sizeof(TWsGraphicMsgFixedBase))
       
   831 	{
       
   832 	__ASSERT_COMPILE(sizeof(*this) == (sizeof(TInt32)*2));
       
   833 	}
       
   834 
       
   835 EXPORT_C TPtrC8 TWsGraphicMsgFixedBase::Pckg() const
       
   836 /** @return this fixed message as a descriptor so that it can be passed as draw data in the CWindowGc::DrawWsGraphic command directly if only one such message is to be sent
       
   837 */	{
       
   838 	return TPtrC8(reinterpret_cast<const TUint8*>(this),sizeof(*this) + iSize);
       
   839 	}
       
   840 
       
   841 EXPORT_C TUid TWsGraphicMsgFixedBase::TypeId() const
       
   842 /** @return the UID identifying the type of the data that follows */
       
   843 	{
       
   844 	return iTypeId;
       
   845 	}
       
   846 
       
   847 EXPORT_C TInt TWsGraphicMsgFixedBase::Size() const
       
   848 /** @return the size of the derived class (not including this fixed base class size) */
       
   849 	{
       
   850 	return iSize;
       
   851 	}
       
   852 
       
   853 // RWsGraphicMsgBuf \\\\\\\\\\\\\\\\\\\\\\\\
       
   854 
       
   855 EXPORT_C RWsGraphicMsgBuf::RWsGraphicMsgBuf()
       
   856 /** Default Constructor */
       
   857 	{
       
   858 	}
       
   859 
       
   860 TInt RWsGraphicMsgBuf::IntAt(TInt aOfs) const
       
   861 /** @internalComponent @released */
       
   862 	{
       
   863 	if((aOfs < 0) || ((aOfs+sizeof(TInt)) > Length()))
       
   864 		{
       
   865 		Panic(EW32PanicGraphicBadBuffer);
       
   866 		}
       
   867 	TInt ret;
       
   868 	memcpy(&ret,Ptr()+aOfs,sizeof(TInt));
       
   869 	return ret;
       
   870 	}
       
   871 
       
   872 EXPORT_C TInt RWsGraphicMsgBuf::Append(TUid aTypeId,const TDesC8& aData)
       
   873 /** Append a descriptor as data
       
   874 	@param aTypeId the type of the message to append
       
   875 	@param aData arbitrary length data consisting of the whole message
       
   876 	@return KErrNone if successful, else a system-wide error code
       
   877 */	{
       
   878 	TInt err = ExpandForAppend(aData.Length());
       
   879 	if (err)
       
   880 		{
       
   881 		return err;
       
   882 		}
       
   883 	WriteHeader(aTypeId,aData.Length());
       
   884 	// append data
       
   885 	Insert(Length(),aData);
       
   886 	return KErrNone;
       
   887 	}
       
   888 
       
   889 EXPORT_C TInt RWsGraphicMsgBuf::Append(TUid aTypeId,const TDesC16& aData)
       
   890 /** Append a descriptor as data
       
   891 	@param aTypeId the type of the message to append
       
   892 	@param aData arbitrary length data consisting of the whole message
       
   893 	@return KErrNone if successful, else a system-wide error code
       
   894 */	{
       
   895 	TPtr8 data(NULL,0);
       
   896 	TInt err = Append(aTypeId,aData.Size(),data);
       
   897 	if (err)
       
   898 		{
       
   899 		return err;
       
   900 		}
       
   901 	// append data
       
   902 	data.Copy(reinterpret_cast<const TUint8*>(aData.Ptr()),aData.Size());
       
   903 	return KErrNone;
       
   904 	}
       
   905 
       
   906 TInt RWsGraphicMsgBuf::ExpandForAppend(TInt aDataLen)
       
   907 /** @internalComponent @released */
       
   908 	{
       
   909 	__ASSERT_COMPILE(sizeof(TInt) == sizeof(TInt32));
       
   910 	const TInt required = (sizeof(TUid) + sizeof(TInt) + aDataLen);
       
   911 	if(MaxLength() < (Length() + required))
       
   912 		{
       
   913 		TInt err = ReAlloc(Length()+required);
       
   914 		if(KErrNone != err)
       
   915 			{
       
   916 			return err;
       
   917 			}
       
   918 		}
       
   919 	return KErrNone;
       
   920 	}
       
   921 
       
   922 void RWsGraphicMsgBuf::WriteHeader(TUid aTypeId,TInt aLen)
       
   923 /** @internalComponent @released */
       
   924 	{
       
   925 	__ASSERT_COMPILE(sizeof(TInt) == sizeof(TInt32));
       
   926 	// append header
       
   927 	TPckgBuf<TInt32> i(aTypeId.iUid);
       
   928 	Insert(Length(),i);
       
   929 	i() = aLen;
       
   930 	Insert(Length(),i);
       
   931 	}
       
   932 
       
   933 EXPORT_C TInt RWsGraphicMsgBuf::Append(TUid aTypeId,TInt aLen,TPtr8& aPtr)
       
   934 /** Append a message of the specified length and type, and return a pointer to
       
   935 	allow client code to modify the message.
       
   936 	aPtr is only set if the append succeeds.
       
   937 	aPtr is only valid until the next message is appended to the buffer.
       
   938 	@param aTypeId the type of the message to append
       
   939 	@param aLen the length of the message to be reserved
       
   940 	@param aPtr a modifiable descriptor to be used by the client code to write into the message body
       
   941 	@return KErrNone if successful, else a system-wide error code
       
   942 */	{
       
   943 	TInt err = ExpandForAppend(aLen);
       
   944 	if (err)
       
   945 		{
       
   946 		return err;
       
   947 		}
       
   948 	WriteHeader(aTypeId,aLen);
       
   949 	// set aPtr
       
   950 	TInt usedLen = Length();
       
   951 	SetLength(usedLen+aLen);
       
   952 	aPtr.Set(MidTPtr(usedLen,aLen));
       
   953 	aPtr.Fill('_'); // prettier when debugging, but want consistant behaviour in release builds
       
   954 	aPtr.Zero();
       
   955 	return KErrNone;
       
   956 	}
       
   957 
       
   958 EXPORT_C void RWsGraphicMsgBuf::Remove(TInt aIndex)
       
   959 /** Remove a message from the buffer
       
   960 	@panic if the index is out of bounds
       
   961 	@param aIndex the ordinal position of message to be removed
       
   962 */	{
       
   963 	if((aIndex < 0) || (aIndex >= Count()))
       
   964 		{
       
   965 		Panic(EW32PanicGraphicBadBuffer);
       
   966 		}
       
   967 	TPtrC8 ptr = Data(aIndex);
       
   968 	const TInt ofs = (ptr.Ptr()-(sizeof(TInt)*2)-Ptr());
       
   969 	Delete(ofs,ptr.Length() + (sizeof(TInt)*2));
       
   970 	}
       
   971 
       
   972 EXPORT_C TInt RWsGraphicMsgBuf::Count() const
       
   973 /** Returns the number of messages in the buffer
       
   974 	@return the number of messages in the buffer
       
   975 */	{
       
   976 	const TInt length = Length();
       
   977 	TInt ofs = 0, count = 0;
       
   978 	while(ofs < length)
       
   979 		{
       
   980 		count++;
       
   981 		ofs += IntAt(ofs+sizeof(TInt)) + (sizeof(TInt)*2);
       
   982 		}
       
   983 	if(ofs != length)
       
   984 		{
       
   985 		Panic(EW32PanicGraphicBadBuffer);
       
   986 		}
       
   987 	return count;
       
   988 	}
       
   989 
       
   990 EXPORT_C TUid RWsGraphicMsgBuf::TypeId(TInt aIndex) const
       
   991 /** Returns the Type ID of a message in the buffer
       
   992 	@param aIndex the ordinal position of the message
       
   993 	@return the Type ID of the message
       
   994 	@panic if the index is out of bounds
       
   995 */	{
       
   996 	const TInt length = Length();
       
   997 	TInt ofs = 0, count = 0;
       
   998 	while(ofs < length)
       
   999 		{
       
  1000 		if(count == aIndex)
       
  1001 			{
       
  1002 			return TUid::Uid(IntAt(ofs));
       
  1003 			}
       
  1004 		count++;
       
  1005 		ofs += IntAt(ofs+sizeof(TInt)) + (sizeof(TInt)*2);
       
  1006 		}
       
  1007 	Panic(EW32PanicGraphicBadBuffer);
       
  1008 	return KNullUid; //dumb compiler
       
  1009 	}
       
  1010 
       
  1011 EXPORT_C TPtrC8 RWsGraphicMsgBuf::Data(TInt aIndex) const
       
  1012 /** Returns a non-modifiable descriptor of a message body in the buffer
       
  1013 	@param aIndex the ordinal position of the message
       
  1014 	@return the message body
       
  1015 	@panic if the index is out of bounds
       
  1016 */	{
       
  1017 	const TInt length = Length();
       
  1018 	TInt ofs = 0, count = 0;
       
  1019 	while(ofs < length)
       
  1020 		{
       
  1021 		if(count == aIndex)
       
  1022 			{
       
  1023 			return Mid(ofs+(sizeof(TInt)*2),IntAt(ofs+sizeof(TInt)));
       
  1024 			}
       
  1025 		count++;
       
  1026 		ofs += IntAt(ofs+sizeof(TInt)) + (sizeof(TInt)*2);
       
  1027 		}
       
  1028 	Panic(EW32PanicGraphicBadBuffer);
       
  1029 	return TPtrC8(KNullDesC8()); //dumb compiler
       
  1030 	}
       
  1031 
       
  1032 EXPORT_C TPtr8 RWsGraphicMsgBuf::Data(TInt aIndex)
       
  1033 /** Returns a modifiable descriptor of a message body in the buffer
       
  1034 	The returned TPtr8 is only valid until the next message is appended to the buffer.
       
  1035 	@param aIndex the ordinal position of the message
       
  1036 	@return the message body
       
  1037 	@panic if the index is out of bounds
       
  1038 */	{
       
  1039 	const TInt length = Length();
       
  1040 	TInt ofs = 0, count = 0;
       
  1041 	while(ofs < length)
       
  1042 		{
       
  1043 		if(count == aIndex)
       
  1044 			{
       
  1045 			return MidTPtr(ofs+(sizeof(TInt)*2),IntAt(ofs+sizeof(TInt)));
       
  1046 			}
       
  1047 		count++;
       
  1048 		ofs += IntAt(ofs+sizeof(TInt)) + (sizeof(TInt)*2);
       
  1049 		}
       
  1050 	Panic(EW32PanicGraphicBadBuffer);
       
  1051 	return TPtr8(NULL,0); //dumb compiler
       
  1052 	}
       
  1053 
       
  1054 EXPORT_C const TDesC8& RWsGraphicMsgBuf::Pckg() const
       
  1055 /** Returns the message buffer as a descriptor.  Example:
       
  1056 	@code
       
  1057 	RWsGraphicMsgBuf msgBuf;
       
  1058 	msgBuf.Append(...);
       
  1059 	...
       
  1060 	TWsGraphicId id(...);
       
  1061 	SystemGc().DrawWsGraphic(id,Rect(),msgBuf.Pckg());
       
  1062 	msgBuf.Close();
       
  1063 	@endcode
       
  1064 	@see CWindowGc::DrawWsGraphic
       
  1065 	@see CCoeControl::Draw
       
  1066 	@return the message buffer to be attached a command to draw a CWsGraphic
       
  1067 */	{
       
  1068 	return *this;
       
  1069 	}
       
  1070 
       
  1071 EXPORT_C TInt RWsGraphicMsgBuf::Append(const TWsGraphicMsgFixedBase& aMsg)
       
  1072 /** Append a fixed-size message
       
  1073 	@param aMsg the fixed-size message to append
       
  1074 	@return KErrNone if successful, else a system-wide error code
       
  1075 */	{
       
  1076 	__ASSERT_COMPILE(sizeof(TWsGraphicMsgFixedBase) == (sizeof(TInt)*2));
       
  1077 	TInt err = ExpandForAppend(aMsg.Size());
       
  1078 	if (err)
       
  1079 		{
       
  1080 		return err;
       
  1081 		}
       
  1082 	// append data
       
  1083 	RBuf8::Append(reinterpret_cast<const TUint8*>(&aMsg),sizeof(TWsGraphicMsgFixedBase) + aMsg.Size());
       
  1084 	Count();
       
  1085 	return KErrNone;
       
  1086 	}
       
  1087 
       
  1088 EXPORT_C void RWsGraphicMsgBuf::GetFixedMsg(TWsGraphicMsgFixedBase& aMsg,TInt aIndex) const
       
  1089 /** Returns a copy of a fixed-size message in the buffer
       
  1090 	@param a copy of the message
       
  1091 	@param aIndex the ordinal position of the message
       
  1092 	@panic if the index is out of bounds
       
  1093 	@panic the message specified is not of the correct type
       
  1094 */	{
       
  1095 	__ASSERT_COMPILE(sizeof(TWsGraphicMsgFixedBase) == (sizeof(TInt32)*2));
       
  1096 	const TInt KHeaderSize = sizeof(TWsGraphicMsgFixedBase);
       
  1097 	const TInt length = Length();
       
  1098 	TInt ofs = 0, count = 0;
       
  1099 	while(ofs < length)
       
  1100 		{
       
  1101 		if(count == aIndex)
       
  1102 			{
       
  1103 			if((TUid::Uid(IntAt(ofs)) != aMsg.TypeId()) ||
       
  1104 				(IntAt(ofs+sizeof(TInt)) != aMsg.Size()) ||
       
  1105 				((ofs + KHeaderSize + aMsg.Size()) > length))
       
  1106 				{
       
  1107 				Panic(EW32PanicGraphicBadBuffer);
       
  1108 				}
       
  1109 			memcpy(&aMsg,(Ptr()+ofs),KHeaderSize + aMsg.Size());
       
  1110 			return;
       
  1111 			}
       
  1112 		count++;
       
  1113 		ofs += IntAt(ofs+sizeof(TInt)) + (sizeof(TInt)*2);
       
  1114 		}
       
  1115 	Panic(EW32PanicGraphicBadBuffer);
       
  1116 	}
       
  1117