|
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 |