windowing/windowserver/nga/CLIENT/WSGRAPHIC.CPP
changeset 0 5d03bc08d59c
child 121 d72fc2aace31
child 163 bbf46f59e123
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 
       
    25 NONSHARABLE_STRUCT(CWsGraphic::CPimpl): public CBase, public MWsClientClass
       
    26 /** @internalComponent @released */
       
    27 	{
       
    28 	friend class CWsGraphic;
       
    29 	enum
       
    30 		{
       
    31 		/** is registered in the graphic manager's array */
       
    32 		ERegistered = 0x01,
       
    33 		/** has a peer CWsGraphicDrawer on the server */
       
    34 		EHasPeer	= 0x02
       
    35 		};
       
    36 	CPimpl(CWsGraphic& aGraphic);
       
    37 	~CPimpl();
       
    38 	void ConstructL();		//LeaveScan: Member of macroised structure declaration.
       
    39 	CManager* iManager;
       
    40 	TInt WriteCreateGraphic(TWsClCmdCreateGraphic& aCreateGraphic,const TDesC8& aData,TInt aWsHandle) const;
       
    41 	CWsGraphic& iGraphic;
       
    42 	TWsGraphicId iId;
       
    43 	TUint iFlags;
       
    44 	MWsObjectProvider* iExt;
       
    45 	};
       
    46 
       
    47 LOCAL_C void MWsGraphicMessageAllocRelease(TAny* aAny)
       
    48 	{
       
    49 	MWsGraphicMessageAlloc::MBuffer* buf = static_cast<MWsGraphicMessageAlloc::MBuffer*>(aAny);
       
    50 	if(buf)
       
    51 		{
       
    52 		buf->Release();
       
    53 		}
       
    54 	}
       
    55 
       
    56 NONSHARABLE_CLASS(CWsGraphic::CManager): private CActive, public RWsSession
       
    57 /** Client-side manager singleton for marshalling messages for all CWsGraphics owned by a client
       
    58 
       
    59 @publishedAll
       
    60 @released
       
    61 */	{
       
    62 public:
       
    63 	static CManager* StaticL();			  //LeaveScan:  Member of macroised structure declaration.
       
    64 	// used by CWsGraphic
       
    65 	void AddL(CWsGraphic* aGraphic);	  //LeaveScan:  Member of macroised structure declaration.
       
    66 	void Replace(CWsGraphic* aGraphic);
       
    67 	void Remove(CWsGraphic* aGraphic);
       
    68 	CWsGraphic* Find(const TWsGraphicId& aId);
       
    69 	void Inc();
       
    70 	void Dec();
       
    71 	RWsBuffer* Buffer();
       
    72 	void ScheduleFlush();
       
    73 private:
       
    74 	CManager();
       
    75 	~CManager();
       
    76 	void ConstructL();					 //LeaveScan:  Member of macroised structure declaration.
       
    77 	void Queue();
       
    78 	void RunL();						 //LeaveScan:  Member of macroised structure declaration.
       
    79 	void DoCancel();
       
    80 	static TInt GraphicCompare(const CWsGraphic& aFirst,const CWsGraphic& aSecond);
       
    81 	static TInt FlushOnIdle(TAny* aArg);
       
    82 private:
       
    83 	TInt iRefCount;
       
    84 	RPointerArray<CWsGraphic> iArray;
       
    85 	CIdle* iFlusher;
       
    86 	TBool iFlushScheduled;
       
    87 	};
       
    88 
       
    89 // TWsGraphicId \\\\\\\\\\\\\\\\\\\\\\\\
       
    90 
       
    91 EXPORT_C TWsGraphicId::TWsGraphicId(TUid aUid):
       
    92 /** Construct a UID
       
    93     @param aUid UID of the graphic artwork.
       
    94     @publishedAll @released
       
    95 */	iFlags(EWsGraphicIdUid), iId(aUid.iUid)
       
    96 	{
       
    97 	}
       
    98 
       
    99 EXPORT_C TWsGraphicId::TWsGraphicId(TInt aId):
       
   100 /** Construct a transient Id
       
   101 	@publishedAll @released
       
   102 */	iFlags(EWsGraphicIdTransient), iId(aId)
       
   103 	{
       
   104 	}
       
   105 
       
   106 /** 
       
   107 Copy constructor.
       
   108 @param aCopy Graphic artwork Id.
       
   109 */
       
   110 EXPORT_C TWsGraphicId::TWsGraphicId(const TWsGraphicId& aCopy):
       
   111 	iFlags(aCopy.iFlags), iId(aCopy.iId)
       
   112 	{
       
   113 	}
       
   114 
       
   115 EXPORT_C TUid TWsGraphicId::Uid() const
       
   116 /** Returns UID.
       
   117     @return UID of graphic artwork. KNullUid if graphic artwork is transient.
       
   118     @publishedAll @released
       
   119 */	{
       
   120 	if(IsUid())
       
   121 		{
       
   122 		return TUid::Uid(iId);
       
   123 		}
       
   124 	return KNullUid;
       
   125 	}
       
   126 
       
   127 EXPORT_C TBool TWsGraphicId::IsUid() const
       
   128 /** Identifies whether graphic artwork is non-transient.
       
   129     @return ETrue if graphic artwork is non-transient.
       
   130     @publishedAll @released
       
   131 */	{
       
   132 	return (iFlags & EWsGraphicIdUid);
       
   133 	}
       
   134 
       
   135 EXPORT_C void TWsGraphicId::Set(TUid aUid)
       
   136 /** Set to be a UID
       
   137 	@publishedAll @released
       
   138 */	{
       
   139 	iId = aUid.iUid;
       
   140 	iFlags = EWsGraphicIdUid;
       
   141 	}
       
   142 
       
   143 EXPORT_C TInt TWsGraphicId::Id() const
       
   144 /** Returns the transient Id.
       
   145     @return Id of transient graphic artwork. Zero if graphic artwork is non-transient.
       
   146 	@publishedAll @released
       
   147 */	{
       
   148 	if(IsId())
       
   149 		{
       
   150 		return iId;
       
   151 		}
       
   152 	return 0;
       
   153 	}
       
   154 
       
   155 EXPORT_C TBool TWsGraphicId::IsId() const
       
   156 /** Identifies whether graphic artwork is transient.
       
   157     @return ETrue if graphic artwork is transient.
       
   158     @publishedAll @released
       
   159 */	{
       
   160 	return (iFlags & EWsGraphicIdTransient);
       
   161 	}
       
   162 
       
   163 EXPORT_C void TWsGraphicId::Set(TInt aId)
       
   164 /** Set to be a transient Id
       
   165 	@publishedAll @released
       
   166 */	{
       
   167 	iId = aId;
       
   168 	iFlags = EWsGraphicIdTransient;
       
   169 	}
       
   170 
       
   171 EXPORT_C TInt TWsGraphicId::Compare(const TWsGraphicId& aOther) const
       
   172 /** Compares another Id with this one.
       
   173 	@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
       
   174 	@publishedAll @released
       
   175 */	{
       
   176 	if(iId < aOther.iId)
       
   177 		{
       
   178 		return -1;
       
   179 		}
       
   180 	else if(iId > aOther.iId)
       
   181 		{
       
   182 		return 1;
       
   183 		}
       
   184 	// else we have to compare the iIsUid flag too; again, expect it to be a match 99.99% of these times
       
   185 	else if(IsUid() == aOther.IsUid())
       
   186 		{
       
   187 		return 0;
       
   188 		}
       
   189 	// collisions of id but not iIsUid are going to be really really rare
       
   190 	else if(IsUid())
       
   191 		{
       
   192 		return 1;
       
   193 		}
       
   194 	else
       
   195 		{
       
   196 		return -1;
       
   197 		}
       
   198 	}
       
   199 
       
   200 // CWsGraphicManager \\\\\\\\\\\\\\\\\\\\\\\\
       
   201 
       
   202 CWsGraphic::CManager* CWsGraphic::CManager::StaticL()
       
   203 	{
       
   204 	CManager* singleton = RWsBuffer::WsGraphicManager();
       
   205 	if(!singleton)
       
   206 		{
       
   207 		singleton = new(ELeave) CManager;
       
   208 		CleanupStack::PushL(singleton);
       
   209 		singleton->ConstructL();
       
   210 		CleanupStack::Pop(singleton);
       
   211 		__ASSERT_DEBUG(singleton == RWsBuffer::WsGraphicManager(),Panic(EW32PanicGraphicInternal));
       
   212 		}
       
   213 	return singleton;
       
   214 	}
       
   215 
       
   216 CWsGraphic::CManager::~CManager()
       
   217 	{
       
   218 	__ASSERT_DEBUG(!ResourceCount(),Panic(EW32PanicGraphicInternal));
       
   219 	__ASSERT_DEBUG(!iArray.Count(),Panic(EW32PanicGraphicOrphaned));
       
   220 	Close();
       
   221 	__ASSERT_DEBUG(!RWsBuffer::WsGraphicManager(),Panic(EW32PanicGraphicInternal));
       
   222 	iArray.Close();
       
   223 	delete iFlusher;
       
   224 	}
       
   225 
       
   226 CWsGraphic::CManager::CManager(): CActive(CActive::EPriorityStandard)
       
   227 	{
       
   228 	}
       
   229 
       
   230 void CWsGraphic::CManager::ConstructL()
       
   231 	{
       
   232 	User::LeaveIfError(Connect());
       
   233 	iBuffer->SetWsGraphicManager(this);
       
   234 	CActiveScheduler::Add(this);
       
   235 	iFlusher = CIdle::NewL(CActive::EPriorityIdle);
       
   236 	}
       
   237 
       
   238 void CWsGraphic::CManager::Inc()
       
   239 	{
       
   240 	iRefCount++;
       
   241 	}
       
   242 
       
   243 void CWsGraphic::CManager::Dec()
       
   244 	{
       
   245 	if(!--iRefCount)
       
   246 		{
       
   247 		delete this;
       
   248 		}
       
   249 	}
       
   250 
       
   251 RWsBuffer* CWsGraphic::CManager::Buffer()
       
   252 	{
       
   253 	return iBuffer;
       
   254 	}
       
   255 
       
   256 // used by CWsGraphic
       
   257 
       
   258 void CWsGraphic::CManager::AddL(CWsGraphic* aGraphic)
       
   259 /** Leaves if the graphic couldn't be added to the list
       
   260 	@internalComponent @released */
       
   261 	{
       
   262 	__ASSERT_ALWAYS(aGraphic && aGraphic->iPimpl,Panic(EW32PanicGraphicInternal));
       
   263 	__ASSERT_ALWAYS(aGraphic->Id().IsId() || aGraphic->Id().IsUid(),Panic(EW32PanicGraphicInternal));
       
   264 	__ASSERT_ALWAYS(!(aGraphic->iPimpl->iFlags & CWsGraphic::CPimpl::ERegistered),Panic(EW32PanicGraphicInternal));
       
   265 	iArray.InsertInOrderL(aGraphic,GraphicCompare);
       
   266 	__ASSERT_ALWAYS(0 <= iArray.FindInOrder(aGraphic,GraphicCompare),Panic(EW32PanicGraphicInternal));
       
   267 	aGraphic->iPimpl->iFlags |= CWsGraphic::CPimpl::ERegistered;
       
   268 	Queue();
       
   269 	}
       
   270 
       
   271 void CWsGraphic::CManager::Replace(CWsGraphic* aGraphic)
       
   272 /** @internalComponent @released */
       
   273 	{
       
   274 	__ASSERT_ALWAYS(aGraphic && aGraphic->iPimpl,Panic(EW32PanicGraphicInternal));
       
   275 	__ASSERT_ALWAYS(!(aGraphic->iPimpl->iFlags & CWsGraphic::CPimpl::ERegistered),Panic(EW32PanicGraphicInternal));
       
   276 	__ASSERT_ALWAYS(aGraphic->Id().IsId() || aGraphic->Id().IsUid(),Panic(EW32PanicGraphicInternal));
       
   277 	const TInt idx = iArray.FindInOrder(aGraphic,GraphicCompare);
       
   278 	__ASSERT_ALWAYS(0 <= idx,Panic(EW32PanicGraphicInternal));
       
   279 	__ASSERT_ALWAYS(iArray[idx]->iPimpl->iFlags & CWsGraphic::CPimpl::ERegistered,Panic(EW32PanicGraphicInternal));
       
   280 	iArray[idx]->iPimpl->iFlags &= ~CWsGraphic::CPimpl::ERegistered;
       
   281 	iArray[idx] = aGraphic;
       
   282 	iArray[idx]->iPimpl->iFlags |= CWsGraphic::CPimpl::ERegistered;
       
   283 	Queue();
       
   284 	}
       
   285 
       
   286 void CWsGraphic::CManager::Remove(CWsGraphic* aGraphic)
       
   287 /** @internalComponent @released */
       
   288 	{
       
   289 	__ASSERT_ALWAYS(aGraphic && aGraphic->iPimpl,Panic(EW32PanicGraphicInternal));
       
   290 	__ASSERT_ALWAYS(aGraphic->Id().IsId() || aGraphic->Id().IsUid(),Panic(EW32PanicGraphicInternal));
       
   291 	__ASSERT_ALWAYS(aGraphic->iPimpl->iFlags & CWsGraphic::CPimpl::ERegistered,Panic(EW32PanicGraphicInternal));
       
   292 	const TInt idx = iArray.FindInOrder(aGraphic,GraphicCompare);
       
   293 	__ASSERT_ALWAYS(0 <= idx,Panic(EW32PanicGraphicInternal));
       
   294 	iArray[idx]->iPimpl->iFlags &= ~CWsGraphic::CPimpl::ERegistered;
       
   295 	iArray.Remove(idx);
       
   296 	if(!iArray.Count())
       
   297 		{
       
   298 		Cancel();
       
   299 		}
       
   300 	}
       
   301 
       
   302 CWsGraphic* CWsGraphic::CManager::Find(const TWsGraphicId& aId)
       
   303 /** Find the active artwork identified by the Id
       
   304 	@return NULL if no active artwork has the Id
       
   305 	@publishedAll @released */
       
   306 	{
       
   307 	/*	RPointerArray can only FindInOrder other T*, which is a needless shame.  Therefore this search is
       
   308 		dumb sequential */
       
   309 	const TInt count = iArray.Count();
       
   310 	for(TInt i=0; i<count; i++)
       
   311 		{
       
   312 		CWsGraphic* graphic = iArray[i];
       
   313 		__ASSERT_ALWAYS(graphic && graphic->iPimpl && (graphic->iPimpl->iFlags & CWsGraphic::CPimpl::ERegistered),Panic(EW32PanicGraphicInternal));
       
   314 		const TWsGraphicId& candidate = graphic->Id();
       
   315 		if(0 == candidate.Compare(aId))
       
   316 			{
       
   317 			// found
       
   318 			__ASSERT_DEBUG(i == iArray.FindInOrder(graphic,GraphicCompare),Panic(EW32PanicGraphicInternal));
       
   319 			return graphic;
       
   320 			}
       
   321 		}
       
   322 	// not found
       
   323 	return NULL;
       
   324 	}
       
   325 
       
   326 void CWsGraphic::CManager::Queue()
       
   327 	{
       
   328 	if(!IsActive())
       
   329 		{
       
   330 		GraphicMessageReady(&iStatus);
       
   331 		SetActive();
       
   332 		}
       
   333 	}
       
   334 
       
   335 void CWsGraphic::CManager::RunL()
       
   336    	{
       
   337    	if(0 < iStatus.Int())
       
   338    		{
       
   339    		// a message to fetch!
       
   340    		const TInt msgLen = iStatus.Int();
       
   341  		TPtr8 buf(NULL,0);
       
   342  		MWsGraphicMessageAlloc* allocator = NULL;
       
   343  		MWsGraphicMessageAlloc::MBuffer* theirBuf = NULL;
       
   344  		HBufC8* ourBuf = HBufC8::New(msgLen);
       
   345  		if(ourBuf)
       
   346  			{
       
   347  			CleanupStack::PushL(ourBuf);
       
   348  			buf.Set(ourBuf->Des());
       
   349  			}
       
   350  		else // try to see if the destination CWsGraphic can allocate for us
       
   351  			{
       
   352 			const TInt handle = GraphicFetchHeaderMessage();
       
   353 			CWsGraphic* dest = reinterpret_cast<CWsGraphic*>(handle & ~0x03);
       
   354  			// check if it's valid
       
   355  			if(KErrNotFound != iArray.Find(dest) && dest->iPimpl && dest->iPimpl->iExt)
       
   356  				{
       
   357  				// check if the client is able to alloc memory for us
       
   358  				allocator = dest->iPimpl->iExt->ObjectInterface<MWsGraphicMessageAlloc>();
       
   359  				if(allocator)
       
   360  					{
       
   361  					// allocate memory
       
   362  					theirBuf = allocator->Alloc(msgLen);
       
   363  					if(theirBuf)
       
   364  						{
       
   365  						CleanupStack::PushL(TCleanupItem(MWsGraphicMessageAllocRelease,theirBuf));
       
   366  						buf.Set(theirBuf->Buffer());
       
   367  						}
       
   368  					}
       
   369  				}
       
   370  			}
       
   371  		if(!ourBuf && !theirBuf)
       
   372  			{
       
   373  			GraphicMessageCancel();
       
   374  			GraphicAbortMessage(KErrNoMemory);
       
   375  			}
       
   376  		else
       
   377  			{
       
   378  			GetGraphicMessage(buf);
       
   379  			// decode header and body
       
   380  			RDesReadStream in(buf);
       
   381  			in.PushL();
       
   382  			const TInt header = in.ReadInt32L();
       
   383  			__ASSERT_COMPILE(sizeof(header) == sizeof(TInt32));
       
   384  			const TInt clientHandle = (header & ~0x03);
       
   385  			const TInt msgType = (header & 0x03);
       
   386  			const TPtr8 body = buf.MidTPtr(sizeof(header));
       
   387  			// dispatch
       
   388  			CWsGraphic* dest = (CWsGraphic*)clientHandle;
       
   389  			if(KErrNotFound != iArray.Find(dest))
       
   390  				{
       
   391  				switch(msgType)
       
   392  					{
       
   393  					case EWsGraphMessageTypeUser:
       
   394  						dest->HandleMessage(body);
       
   395  						break;
       
   396  					default:
       
   397  						Panic(EW32PanicGraphicInternal);
       
   398  					}
       
   399  				}
       
   400  			// done
       
   401  			in.Pop();
       
   402  			}
       
   403  		if(ourBuf)
       
   404  			{
       
   405  			CleanupStack::PopAndDestroy(ourBuf);
       
   406  			}
       
   407  		else if(theirBuf)
       
   408  			{
       
   409  			CleanupStack::PopAndDestroy(theirBuf);
       
   410  			}
       
   411  		// done, wait for next message
       
   412  		Queue();
       
   413  		}
       
   414  	}
       
   415 
       
   416 void CWsGraphic::CManager::DoCancel()
       
   417 	{
       
   418 	GraphicMessageCancel();
       
   419 	}
       
   420 
       
   421 TInt CWsGraphic::CManager::GraphicCompare(const CWsGraphic& aFirst,const CWsGraphic& aSecond)
       
   422 /** Compares two graphics for id equality
       
   423 @internalComponent
       
   424 @released
       
   425 */	{
       
   426 	return aFirst.Id().Compare(aSecond.Id());
       
   427 	}
       
   428 
       
   429 void CWsGraphic::CManager::ScheduleFlush()
       
   430 /** Request to schedule flush when idle
       
   431 @internalComponent
       
   432 @released
       
   433 */
       
   434 	{
       
   435 	if (iFlushScheduled)
       
   436 		return;
       
   437 
       
   438 	iFlushScheduled = ETrue;
       
   439 	iFlusher->Start(TCallBack(CWsGraphic::CManager::FlushOnIdle,this));
       
   440 	}
       
   441 
       
   442 TInt CWsGraphic::CManager::FlushOnIdle(TAny* aArg)
       
   443 /** Flush buffer when idle and there is outstanding data in it
       
   444 @internalComponent
       
   445 @released
       
   446 */
       
   447 	{
       
   448 	CWsGraphic::CManager* mgr = reinterpret_cast<CWsGraphic::CManager*>(aArg);
       
   449 	if (mgr)
       
   450 		{
       
   451 		mgr->iFlushScheduled = EFalse;
       
   452 		if (mgr->iBuffer && !mgr->iBuffer->IsEmpty())
       
   453 			mgr->iBuffer->Flush();
       
   454 		}
       
   455 
       
   456 	return 0; // complete
       
   457 	}
       
   458 
       
   459 // CWsGraphic::CPimpl \\\\\\\\\\\\\\\\\\\\\\\\
       
   460 
       
   461 CWsGraphic::CPimpl::CPimpl(CWsGraphic& aGraphic):
       
   462 	iGraphic(aGraphic), iId(TWsGraphicId::EUninitialized)
       
   463 	{
       
   464 	}
       
   465 
       
   466 CWsGraphic::CPimpl::~CPimpl()
       
   467 	{
       
   468 	if(iManager)
       
   469 		{
       
   470 		iManager->Dec();
       
   471 		}
       
   472 	}
       
   473 
       
   474 void CWsGraphic::CPimpl::ConstructL()
       
   475 	{
       
   476 	iManager = CManager::StaticL();
       
   477 	iManager->Inc();
       
   478 	iBuffer = iManager->Buffer();
       
   479 	}
       
   480 
       
   481 TInt CWsGraphic::CPimpl::WriteCreateGraphic(TWsClCmdCreateGraphic& aCreateGraphic,const TDesC8& aData,TInt aWsHandle) const
       
   482 /** Writes the CreateGraphic message to the server.  If the data will not fit in the buffer, uses remote-read
       
   483 	@internalComponent @released */
       
   484 	{
       
   485 	aCreateGraphic.iDataLen = aData.Size();
       
   486 	aCreateGraphic.iRemoteReadData = ((aData.Size()+sizeof(aCreateGraphic))>(TInt)(iBuffer->BufferSize()-sizeof(TWsCmdHeader)));
       
   487 	if(aCreateGraphic.iRemoteReadData)
       
   488 		{
       
   489 		return iBuffer->WriteReplyByProvidingRemoteReadAccess(aWsHandle,EWsClOpCreateGraphic,&aCreateGraphic,sizeof(aCreateGraphic),&aData);
       
   490 		}
       
   491 	else if(aCreateGraphic.iDataLen)
       
   492 		{
       
   493 		return iBuffer->WriteReplyWs(&aCreateGraphic,sizeof(aCreateGraphic),aData.Ptr(),aData.Size(),EWsClOpCreateGraphic);
       
   494 		}
       
   495 	else
       
   496 		{
       
   497 		return iBuffer->WriteReplyWs(&aCreateGraphic,sizeof(aCreateGraphic),EWsClOpCreateGraphic);
       
   498 		}
       
   499 	}
       
   500 
       
   501 // CWsGraphic \\\\\\\\\\\\\\\\\\\\\\\\
       
   502 
       
   503 /** 
       
   504 Default Constructor.
       
   505 */
       
   506 EXPORT_C CWsGraphic::CWsGraphic()
       
   507 	{
       
   508 	}
       
   509 
       
   510 /**
       
   511 Destructor.
       
   512 */
       
   513 EXPORT_C CWsGraphic::~CWsGraphic()
       
   514 	{
       
   515 	Destroy();
       
   516 	delete iPimpl;
       
   517 	}
       
   518 	
       
   519 /**
       
   520 Completes construction of the baseclass. All the overloaded BaseConstructL() methods
       
   521 should invoke this method to complete the construction of the baseclass.
       
   522 */
       
   523 void CWsGraphic::BaseConstructL()
       
   524 	{
       
   525 	iPimpl = new(ELeave) CPimpl(*this);
       
   526 	iPimpl->ConstructL();
       
   527 	}
       
   528 
       
   529 EXPORT_C void CWsGraphic::BaseConstructL(TUid aUid,TUid aType,const TDesC8& aData)
       
   530 /** 
       
   531 Constructs a piece of non-transient graphic artwork.
       
   532 @capability ProtServ
       
   533 @param aUid	Graphic artwork UID.
       
   534 @param aType Graphic artwork type.
       
   535 @param aData User specific data.
       
   536 */	{
       
   537 	BaseConstructL();
       
   538 
       
   539 	TWsClCmdCreateGraphic createGraphic;
       
   540 	createGraphic.iFlags = EWsGraphicIdUid;
       
   541 	createGraphic.iId = aUid.iUid;
       
   542 	createGraphic.iType = aType;
       
   543 	createGraphic.iClientHandle = (TInt)this;
       
   544 
       
   545 	TInt ret = iPimpl->WriteCreateGraphic(createGraphic,aData,iPimpl->iManager->WsHandle());
       
   546 	User::LeaveIfError(ret);
       
   547 
       
   548 	iPimpl->iWsHandle=ret;
       
   549 	iPimpl->iId = aUid;
       
   550 	iPimpl->iFlags = CPimpl::EHasPeer;
       
   551 	iPimpl->iManager->AddL(this);
       
   552 	}
       
   553 
       
   554 EXPORT_C void CWsGraphic::BaseConstructL(TUid aType,const TDesC8& aData)
       
   555 /** 
       
   556 Constructs a piece of transient graphic artwork.
       
   557 @param aType Graphic artwork type.
       
   558 @param aData User specific data.
       
   559 */
       
   560 	{
       
   561 	BaseConstructL();
       
   562 
       
   563 	TWsClCmdCreateGraphic createGraphic;
       
   564 	createGraphic.iFlags = EWsGraphicIdTransient;
       
   565 	createGraphic.iId = 0;
       
   566 	createGraphic.iType = aType;
       
   567 	createGraphic.iClientHandle = (TInt)this;
       
   568 
       
   569 	TInt ret = iPimpl->WriteCreateGraphic(createGraphic,aData,iPimpl->iManager->WsHandle());
       
   570 	User::LeaveIfError(ret);
       
   571 
       
   572 	iPimpl->iWsHandle = ret;
       
   573 
       
   574 	// fetch id from server
       
   575 	TPckgBuf<TWsClCmdGdGetId> cmd;
       
   576 	User::LeaveIfError(iPimpl->WriteReplyP(TWriteDescriptorType(&cmd),EWsGdOpGetGraphicId));
       
   577 	if(cmd().iIsUid)
       
   578 		{
       
   579 		__DEBUG_ONLY(Panic(EW32PanicGraphicInternal));
       
   580 		User::Leave(KErrGeneral);
       
   581 		}
       
   582 	iPimpl->iId = cmd().iId;
       
   583 
       
   584 	iPimpl->iFlags = CPimpl::EHasPeer;
       
   585 	iPimpl->iManager->AddL(this);
       
   586 	}
       
   587 
       
   588 EXPORT_C void CWsGraphic::BaseConstructL(const TWsGraphicId& aReplace,TUid aType,const TDesC8& aData)
       
   589 /** 
       
   590 Atomically replace the artwork that already exists with this artwork.
       
   591 If failure to properly construct the replacement artwork occurs, the replacee artwork will remain
       
   592 @param aReplace Graphic artwork which will be replaced.
       
   593 @param aType New graphic artwork type.
       
   594 @param aData User specific data.
       
   595 */
       
   596 	{
       
   597 	BaseConstructL();
       
   598 
       
   599 	CWsGraphic* dup = iPimpl->iManager->Find(aReplace);
       
   600 	if(!dup || !dup->iPimpl)
       
   601 		{
       
   602 		Panic(EW32PanicGraphicInternal);
       
   603 		}
       
   604 
       
   605 	const TUint flags = aReplace.IsUid()?EWsGraphicIdUid:EWsGraphicIdTransient;
       
   606 
       
   607 	TWsClCmdCreateGraphic createGraphic;
       
   608 	createGraphic.iFlags = EWsGraphicReplace|flags;
       
   609 	createGraphic.iId = aReplace.IsUid()?aReplace.Uid().iUid:aReplace.Id();
       
   610 	createGraphic.iType = aType;
       
   611 	createGraphic.iClientHandle = (TInt)this;
       
   612 
       
   613 	TInt ret = iPimpl->WriteCreateGraphic(createGraphic,aData,iPimpl->iManager->WsHandle());
       
   614 	if(0 > ret)
       
   615 		{
       
   616 		User::Leave(ret);
       
   617 		}
       
   618 
       
   619 	iPimpl->iWsHandle = ret;
       
   620 	iPimpl->iId = aReplace;
       
   621 
       
   622 	iPimpl->iFlags = CPimpl::EHasPeer;
       
   623 	iPimpl->iManager->Replace(this);
       
   624 
       
   625 	// when WriteCreateGraphic succeeds, the replacee drawer has already been destroyed serverside
       
   626 	// so this cleanup is not quite the same as Destroy(), as it doesn't free server side
       
   627 	// coverity[var_deref_op]
       
   628 	dup->iPimpl->iWsHandle = 0;
       
   629 	dup->OnReplace();
       
   630 	dup->iPimpl->iFlags &= ~CPimpl::EHasPeer;
       
   631 	}
       
   632 
       
   633 /**
       
   634 Shares the graphic artwork with all the client sessions.
       
   635 Sharing globally trumps explicit shares.
       
   636 @return KErrNone if the graphic is globally shared, else one of the system-wide error codes.
       
   637 */
       
   638 EXPORT_C TInt CWsGraphic::ShareGlobally()
       
   639 	{
       
   640 	if(!IsActive())
       
   641 		{
       
   642 		return KErrNotReady;
       
   643 		}
       
   644 	return iPimpl->WriteReply(EWsGdOpShareGlobally);
       
   645 	}
       
   646 
       
   647 /**
       
   648 Prevents this graphic artwork from being shared with all the client sessions.
       
   649 A graphic artwork that isn't shared explicitly is only available to clients it
       
   650 has been explicitly shared with using Share().
       
   651 @return KErrNone if the graphic is not globally shared, else one of the system-wide error codes.
       
   652 */
       
   653 EXPORT_C TInt CWsGraphic::UnShareGlobally()
       
   654 	{
       
   655 	if(!IsActive())
       
   656 		{
       
   657 		return KErrNotReady;
       
   658 		}
       
   659 	return iPimpl->WriteReply(EWsGdOpUnShareGlobally);
       
   660 	}
       
   661 	
       
   662 /** 
       
   663 Explicitly shares this graphic artwork with client sessions with the specified Secure ID.
       
   664 @param aClientId the Secure ID of the client sessions to share with.
       
   665 @return KErrNone If the graphic artwork was shared, else one of the system-wide error codes.
       
   666 */
       
   667 EXPORT_C TInt CWsGraphic::Share(TSecureId aClientId)
       
   668 	{
       
   669 	if(!IsActive())
       
   670 		{
       
   671 		return KErrNotReady;
       
   672 		}
       
   673 	return iPimpl->WriteReply(&aClientId,sizeof(TSecureId),EWsGdOpShare);
       
   674 	}
       
   675 
       
   676 /** 
       
   677 Stops this graphic artwork from being shared with all client sessions with the specific Secure ID.
       
   678 ShareGlobally() trumps explicit sharing.
       
   679 @param aClientId the Secure ID of the client sessions to not share with
       
   680 @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
       
   681 */
       
   682 EXPORT_C TInt CWsGraphic::UnShare(TSecureId aClientId)
       
   683 	{
       
   684 	if(!IsActive())
       
   685 		{
       
   686 		return KErrNotReady;
       
   687 		}
       
   688 	return iPimpl->WriteReply(&aClientId,sizeof(TSecureId),EWsGdOpUnShare);
       
   689 	}
       
   690 
       
   691 /**
       
   692 Returns graphic artwork Id.
       
   693 @return Graphic artwork Id. KNullWsGraphicId if graphic artwork is not active.
       
   694 */
       
   695 EXPORT_C const TWsGraphicId& CWsGraphic::Id() const
       
   696 	{
       
   697 	if(IsActive())
       
   698 		{
       
   699 		return iPimpl->iId;
       
   700 		}
       
   701 	else
       
   702 		{
       
   703 		// fallback
       
   704 		static const TInt KNullWsGraphicId[4] = //binary compatible with TWsGraphicId
       
   705 			{
       
   706 			0, 0, 0, 0
       
   707 			};
       
   708 		__ASSERT_COMPILE(sizeof(KNullWsGraphicId) == sizeof(TWsGraphicId));
       
   709 		return reinterpret_cast<const TWsGraphicId&>(KNullWsGraphicId);
       
   710 		}
       
   711 	}
       
   712 	
       
   713 /** 
       
   714 Checks whether a peer of this graphic artwork has been fully constructed on the server.
       
   715 @return ETrue if this graphic artwork has a peer CWsGraphic on the server.
       
   716 */
       
   717 EXPORT_C TBool CWsGraphic::IsActive() const
       
   718 	{
       
   719 	return (iPimpl && iPimpl->iWsHandle && (iPimpl->iFlags & CPimpl::EHasPeer));
       
   720 	}
       
   721 	
       
   722 /**
       
   723 Derived class can override this method to provide custom operations when the client is closed.
       
   724 */
       
   725 EXPORT_C void CWsGraphic::OnClientClose()
       
   726 	{
       
   727 	}
       
   728 	
       
   729 /** 
       
   730 Sends message to this graphic artwork peer on the server.
       
   731 @param aData User specific data.
       
   732 */
       
   733 EXPORT_C void CWsGraphic::SendMessage(const TDesC8& aData) const
       
   734 	{
       
   735 	TWsClCmdGdSendMessage cmd;
       
   736 	cmd.iDataLen = aData.Size();
       
   737 	__ASSERT_DEBUG(cmd.iDataLen, Panic(EW32PanicGraphicNullData));
       
   738 	cmd.iRemoteReadData = ((aData.Size()+sizeof(cmd))>(TInt)(iPimpl->iBuffer->BufferSize()-sizeof(TWsCmdHeader)));
       
   739 	if(cmd.iRemoteReadData)
       
   740 		{
       
   741 		iPimpl->WriteReplyByProvidingRemoteReadAccess(&cmd,sizeof(cmd),&aData,EWsGdOpSendMsg);
       
   742 		//ignore return value!
       
   743 		}
       
   744 	else
       
   745 		{
       
   746 		iPimpl->Write(&cmd,sizeof(cmd),aData.Ptr(),aData.Size(),EWsGdOpSendMsg);
       
   747 		}
       
   748 	}
       
   749 
       
   750 EXPORT_C TInt CWsGraphic::SendSynchronMessage(const TDesC8& aData) const
       
   751 	 {
       
   752 	 TWsClCmdGdSendMessage cmd;
       
   753 	 cmd.iDataLen = aData.Size();
       
   754 	 __ASSERT_DEBUG(cmd.iDataLen, Panic(EW32PanicGraphicNullData));
       
   755 	 cmd.iRemoteReadData = ((aData.Size()+sizeof(cmd))>(TInt)(iPimpl->iBuffer->BufferSize()-sizeof(TWsCmdHeader)));
       
   756 	 if(cmd.iRemoteReadData)
       
   757 		{
       
   758 		return iPimpl->WriteReplyByProvidingRemoteReadAccess(&cmd,sizeof(cmd),&aData,EWsGdOpSendSynchronMsg);
       
   759 		}
       
   760 	 else
       
   761 		{
       
   762 		return iPimpl->WriteReply(&cmd,sizeof(cmd),aData.Ptr(),aData.Size(),EWsGdOpSendSynchronMsg);
       
   763 		}
       
   764 	 }
       
   765 
       
   766 /** 
       
   767 Flushes window server command buffer
       
   768 @return One of system-wide error codes.
       
   769 */
       
   770 EXPORT_C TInt CWsGraphic::Flush() const
       
   771 	{
       
   772 	return iPimpl->iBuffer->Flush();
       
   773 	}
       
   774 
       
   775 EXPORT_C void CWsGraphic::Destroy()
       
   776 /** Destroys the corresponding CWsGraphicDrawer instance on the server
       
   777 @released
       
   778 @publishedAll
       
   779 */	{
       
   780 	if(iPimpl && (iPimpl->iFlags & CPimpl::ERegistered))
       
   781 		{
       
   782 		iPimpl->iManager->Remove(this);
       
   783 		}
       
   784 	if(IsActive()) // if iPimpl==NULL, IsActive() returns false
       
   785 		{
       
   786 		__ASSERT_DEBUG(iPimpl != NULL, Panic(EW32PanicGraphicInternal));
       
   787 
       
   788 		iPimpl->Write(EWsGdOpFree);
       
   789 		iPimpl->iWsHandle = 0;
       
   790 		iPimpl->iFlags &= ~CPimpl::EHasPeer;
       
   791 		iPimpl->iManager->ScheduleFlush();
       
   792 		}
       
   793 	}
       
   794 
       
   795 EXPORT_C void CWsGraphic::SetGraphicExtension(MWsObjectProvider* aExt)
       
   796 	{
       
   797 	iPimpl->iExt = aExt;
       
   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