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