1 /*
2     SDL_Main.cpp
3     Symbian OS services for SDL
4 
5     Markus Mertama
6 */
7 
8 
9 #include "epoc_sdl.h"
10 
11 #include"sdlepocapi.h"
12 #include <e32base.h>
13 #include <estlib.h>
14 #include <stdio.h>
15 #include <badesca.h>
16 
17 #include "vectorbuffer.h"
18 #include <w32std.h>
19 #include <aknappui.h>
20 #include <aknapp.h>
21 #include "SDL_epocevents_c.h"
22 #include "SDL_keysym.h"
23 #include "dsa.h"
24 
25 
26 #ifdef SYMBIANC
27 #include <reent.h>
28 #endif
29 
30 //Markus Mertama
31 
32 
33 extern SDLKey* KeyMap();
34 extern void ResetKeyMap();
35 
36 class CCurrentAppUi;
37 
38 //const TUid KSDLUid =  { 0xF01F3D69 };
39 
NONSHARABLE_CLASS(EnvUtils)40 NONSHARABLE_CLASS(EnvUtils)
41 	{
42 	public:
43 	static void DisableKeyBlocking();
44 	static TBool Rendezvous(RThread& aThread, TRequestStatus& aStatus);
45 	};
46 
47 TInt Panic(TInt aErr, TInt aLine)
48 	{
49 	TBuf<64> b;
50 	b.Format(_L("Main at %d"), aLine);
51 	User::Panic(b, aErr);
52 	return 0;
53 	}
54 
55 
56 NONSHARABLE_CLASS(CCurrentAppUi) : public CAknAppUi
57 	{
58 	public:
59 	static CCurrentAppUi* Cast(CEikAppUi* aUi);
60 	void DisableKeyBlocking();
61 	};
62 
63 
64 CCurrentAppUi* CCurrentAppUi::Cast(CEikAppUi* aUi)
65 	{
66 	return static_cast<CCurrentAppUi*>(aUi);
67 	}
68 
69 void CCurrentAppUi::DisableKeyBlocking()
70 	{
71 	SetKeyBlockMode(ENoKeyBlock);
72 	}
73 
74 
75 class CEventQueue : public CBase, public MEventQueue
76     {
77     public:
78         static CEventQueue* NewL();
79         ~CEventQueue();
80     public:
81         TInt Append(const TWsEvent& aEvent);
82        	const TWsEvent& Shift();
83        	void Lock();
84        	void Unlock();
85         TBool HasData();
86     private:
87         TVector<TWsEvent, 64> iVector;
88         RCriticalSection iCS;
89     };
90 
91  CEventQueue* CEventQueue::NewL()
92     {
93     CEventQueue* q = new (ELeave) CEventQueue();
94     CleanupStack::PushL(q);
95     User::LeaveIfError(q->iCS.CreateLocal());
96     CleanupStack::Pop();
97     return q;
98     }
99 
100 CEventQueue::~CEventQueue()
101     {
102     iCS.Close();
103     }
104 
105 TInt CEventQueue::Append(const TWsEvent& aEvent)
106     {
107     iCS.Wait();
108    	const TInt err = iVector.Append(aEvent);
109     iCS.Signal();
110     return err;
111     }
112 
113 
114 TBool CEventQueue::HasData()
115     {
116     return iVector.Size() > 0;
117     }
118 
119 
120 void CEventQueue::Lock()
121 	{
122     iCS.Wait();
123 	}
124 
125 void CEventQueue::Unlock()
126 	{
127 	iCS.Signal();
128 	}
129 
130 const TWsEvent& CEventQueue::Shift()
131     {
132     const TWsEvent& event =  iVector.Shift();
133     return event;
134     }
135 
136 
137 TSdlCleanupItem::TSdlCleanupItem(TSdlCleanupOperation aOperation, TAny* aItem) :
138 iOperation(aOperation), iItem(aItem), iThread(RThread().Id())
139     {
140     }
141 
142 class CEikonEnv;
143 class CSdlAppServ;
144 
145 
146 NONSHARABLE_CLASS(EpocSdlEnvData)
147     {
148     public:
149     void Free();
150     CEventQueue*            iEventQueue;
151     TMainFunc				iMain;
152     TInt            		iEpocEnvFlags;
153     int                     iArgc;
154     char**                  iArgv;
155     CDsa*                   iDsa;
156     CSdlAppServ*            iAppSrv;
157     TThreadId               iId;
158     CArrayFix<TSdlCleanupItem>* iCleanupItems;
159     CEikAppUi*				iAppUi;
160     CSDL*					iSdl;
161     };
162 
163 
164 EpocSdlEnvData* gEpocEnv;
165 
166 #define MAINFUNC(x) EXPORT_C TMainFunc::TMainFunc(mainfunc##x aFunc){Mem::FillZ(iMainFunc, sizeof(iMainFunc)); iMainFunc[x - 1] = (void*) aFunc;}
167 
168 MAINFUNC(1)
169 MAINFUNC(2)
170 MAINFUNC(3)
171 MAINFUNC(4)
172 MAINFUNC(5)
173 MAINFUNC(6)
174 
175 EXPORT_C TMainFunc::TMainFunc()
176 	{
177 	Mem::FillZ(iMainFunc, sizeof(iMainFunc));
178 	}
179 
180 
181 const void* TMainFunc::operator[](TInt aIndex) const
182 	{
183 	return iMainFunc[aIndex];
184 	}
185 
186 
187 NONSHARABLE_CLASS(CSdlAppServ) : public CActive
188     {
189     public:
190         enum
191             {
192             EAppSrvNoop = CDsa::ELastDsaRequest,
193             EAppSrvWindowWidth,
194             EAppSrvWindowHeight,
195             EAppSrvWindowDisplayMode,
196             EAppSrvWindowPointerCursorMode,
197             EAppSrvDsaStatus,
198             EAppSrvStopThread,
199             EAppSrvWaitDsa
200             };
201         CSdlAppServ();
202         void ConstructL();
203         ~CSdlAppServ();
204         TInt Request(TInt aService);
205         TInt RequestValue(TInt aService);
206         void Init();
207         void PanicMain(TInt aReason);
208         void PanicMain(const TDesC& aInfo, TInt aReason);
209         void SetObserver(MSDLObserver* aObserver);
210         TInt ObserverEvent(TInt aEvent, TInt aParam);
211         void SetParam(TInt aParam);
212         void HandleObserverValue(TInt aService, TInt aReturnValue, TBool aMainThread);
213         MSDLObserver* Observer();
214     private:
215         void RunL();
216         void DoCancel();
217     private:
218         const TThreadId iMainId;
219         RThread iAppThread;
220         TInt iService;
221         TInt iReturnValue;
222         RSemaphore iSema;
223         MSDLObserver* iObserver;
224         TRequestStatus* iStatusPtr;
225     };
226 
227 CSdlAppServ::CSdlAppServ() : CActive(CActive::EPriorityHigh), iMainId(RThread().Id())
228     {
229     }
230 
231 
232 
233 MSDLObserver* CSdlAppServ::Observer()
234 	{
235 	return iObserver;
236 	}
237 
238 
239 void CSdlAppServ::SetObserver(MSDLObserver* aObserver)
240 	{
241 	iObserver = aObserver;
242 	}
243 
244 TInt CSdlAppServ::ObserverEvent(TInt aEvent, TInt aParam)
245 	{
246 	if(iObserver != NULL)
247 		{
248 		if(RThread().Id() == gEpocEnv->iId)
249 			{
250 			return iObserver->SdlThreadEvent(aEvent, aParam);
251 			}
252 		else if(RThread().Id() == iMainId)
253 			{
254 			return iObserver->SdlEvent(aEvent, aParam);
255 			}
256 		PANIC(KErrNotSupported);
257 		}
258 	return 0;
259 	}
260 
261 void CSdlAppServ::PanicMain(TInt aReason)
262     {
263     iAppThread.Panic(RThread().Name(), aReason);
264     }
265 
266 void CSdlAppServ::PanicMain(const TDesC& aInfo, TInt aReason)
267     {
268     iAppThread.Panic(aInfo, aReason);
269     }
270 
271 void CSdlAppServ::ConstructL()
272     {
273     CActiveScheduler::Add(this);
274     User::LeaveIfError(iSema.CreateLocal(1));
275     iStatus = KRequestPending;
276     iStatusPtr = &iStatus;
277     SetActive();
278     }
279 
280  CSdlAppServ::~CSdlAppServ()
281     {
282     Cancel();
283     if(iSema.Handle() != NULL)
284         iSema.Signal();
285     iSema.Close();
286     iAppThread.Close();
287     }
288 
289 TInt CSdlAppServ::Request(TInt aService)
290     {
291     if(RThread().Id() != iAppThread.Id())
292     	{
293     	iSema.Wait();
294     	iService = aService;
295     	iAppThread.RequestComplete(iStatusPtr, KErrNone);
296     	return KErrNone;
297     	}
298     return KErrBadHandle;
299     }
300 
301 TInt CSdlAppServ::RequestValue(TInt aService)
302     {
303     Request(aService);
304     Request(EAppSrvNoop);
305     return iReturnValue;
306     }
307 
308 void CSdlAppServ::Init()
309     {
310     PANIC_IF_ERROR(iAppThread.Open(iMainId));
311     }
312 
313 void CSdlAppServ::SetParam(TInt aParam)
314 	{
315 	iReturnValue = aParam;
316 	}
317 
318 void CSdlAppServ::HandleObserverValue(TInt aService, TInt aReturnValue, TBool aMainThread)
319 	{
320 	if(iObserver != NULL && aMainThread)
321 		{
322 		switch(aService)
323 			{
324 			case MSDLObserver::EEventScreenSizeChanged:
325 			if(aReturnValue == MSDLObserver::EScreenSizeChangedDefaultPalette)
326 				EpocSdlEnv::LockPalette(EFalse);
327 			break;
328 			}
329 		}
330 	if(!aMainThread && aService == MSDLObserver::EEventSuspend)
331 		{
332 		if(iObserver == NULL ||
333 		(gEpocEnv->iDsa->Stopped() && aReturnValue != MSDLObserver::ESuspendNoSuspend))
334 			{
335 			EpocSdlEnv::Suspend();
336 			}
337 		}
338 	}
339 
340 void CSdlAppServ::RunL()
341     {
342     if(iStatus == KErrNone)
343         {
344         switch(iService)
345             {
346             case CSdlAppServ::EAppSrvWaitDsa:
347             	EpocSdlEnv::SetWaitDsa();
348             	iReturnValue = EpocSdlEnv::IsDsaAvailable();
349             //		}
350             //	gEpocEnv->iDsa->Stop();
351             //	gEpocEnv->iDsa->RestartL();
352             	break;
353            	 case CSdlAppServ::EAppSrvStopThread:
354             	gEpocEnv->iDsa->SetSuspend();
355             	break;
356             case EpocSdlEnv::EDisableKeyBlocking:
357                 EnvUtils::DisableKeyBlocking();
358                 break;
359 
360             case EAppSrvWindowPointerCursorMode:
361                 iReturnValue = gEpocEnv->iDsa != NULL ?
362                  gEpocEnv->iDsa->Session().PointerCursorMode() : KErrNotReady;
363                 break;
364             case EAppSrvDsaStatus:
365             	gEpocEnv->iDsa->Stop();
366                 iReturnValue = KErrNone;
367                 break;
368             case CDsa::ERequestUpdate:
369             	gEpocEnv->iDsa->UnlockHWSurfaceRequestComplete();
370             	break;
371             case EAppSrvNoop:
372                 break;
373             case MSDLObserver::EEventResume:
374             case MSDLObserver::EEventSuspend:
375             case MSDLObserver::EEventScreenSizeChanged:
376             case MSDLObserver::EEventWindowReserved:
377             case MSDLObserver::EEventKeyMapInit:
378             case MSDLObserver::EEventWindowNotAvailable:
379             case MSDLObserver::EEventMainExit:
380             	iReturnValue = ObserverEvent(iService, iReturnValue);
381             	HandleObserverValue(iService, iReturnValue, ETrue);
382             	break;
383             default:
384                 PANIC(KErrNotSupported);
385             }
386         iStatus = KRequestPending;
387         iStatusPtr = &iStatus;
388         SetActive();
389         }
390     iSema.Signal();
391     }
392 
393 void CSdlAppServ::DoCancel()
394     {
395     iSema.Wait();
396     TRequestStatus* s = &iStatus;
397     iAppThread.RequestComplete(s, KErrCancel);
398     }
399 
400 
401 
402 MEventQueue& EpocSdlEnv::EventQueue()
403     {
404     __ASSERT_DEBUG(gEpocEnv != NULL, PANIC(KErrNotReady));
405     return *gEpocEnv->iEventQueue;
406     }
407 
408 
409 TBool EpocSdlEnv::Flags(TInt aFlag)
410     {
411 	const TInt flag = gEpocEnv->iEpocEnvFlags & aFlag;
412 	return flag == aFlag;
413     }
414 
415 TInt EpocSdlEnv::Argc()
416     {
417     __ASSERT_DEBUG(gEpocEnv != NULL, PANIC(KErrNotReady));
418     return gEpocEnv->iArgc;
419     }
420 
421 
422 char** EpocSdlEnv::Argv()
423     {
424     __ASSERT_DEBUG(gEpocEnv != NULL, PANIC(KErrNotReady));
425     return gEpocEnv->iArgv;
426     }
427 
428 
429 TBool EpocSdlEnv::IsDsaAvailable()
430     {
431     __ASSERT_DEBUG(gEpocEnv != NULL, PANIC(KErrNotReady));
432     return gEpocEnv->iDsa != NULL && gEpocEnv->iDsa->IsDsaAvailable();
433     }
434 
435 
436 void EpocSdlEnv::WaitDsaAvailable()
437 	{
438 	EpocSdlEnv::ObserverEvent(MSDLObserver::EEventWindowNotAvailable, 0);
439 	gEpocEnv->iAppSrv->Request(CSdlAppServ::EAppSrvStopThread);
440 	if(EpocSdlEnv::Flags(CSDL::EEnableFocusStop))
441 		{
442 		EpocSdlEnv::ObserverEvent(MSDLObserver::EEventSuspend, 0);
443 		}
444 	}
445 
446 void EpocSdlEnv::Suspend()
447 	{
448 	if(gEpocEnv->iDsa->Stopped() || EpocSdlEnv::Flags(CSDL::EEnableFocusStop))
449 		{
450 	//	gEpocEnv->iDsa->ReleaseStop();
451 		gEpocEnv->iDsa->SetSuspend();
452 		RThread().Suspend();
453 		EpocSdlEnv::ObserverEvent(MSDLObserver::EEventResume, 0);
454 		}
455 	}
456 
457 void EpocSdlEnv::SetWaitDsa()
458 	{
459 	if(!IsDsaAvailable())
460 		{
461 		RThread th;
462 		th.Open(gEpocEnv->iId);
463 		th.Suspend();
464 		th.Close();
465 		gEpocEnv->iDsa->SetSuspend();
466 		}
467 	}
468 
469 void EpocSdlEnv::Resume()
470 	{
471 	gEpocEnv->iDsa->Resume();
472 	RThread th;
473 	th.Open(gEpocEnv->iId);
474 	th.Resume();
475 	th.Close();
476 
477 	const TInt value = gEpocEnv->iAppSrv->ObserverEvent(MSDLObserver::EEventResume, 0);
478 	gEpocEnv->iAppSrv->HandleObserverValue(MSDLObserver::EEventResume, value, ETrue);
479 	}
480 
481 
482 TInt EpocSdlEnv::AllocSwSurface(const TSize& aSize, TDisplayMode aMode)
483 	{
484 	return gEpocEnv->iDsa->AllocSurface(EFalse, aSize, aMode);
485 	}
486 
487 TInt EpocSdlEnv::AllocHwSurface(const TSize& aSize, TDisplayMode aMode)
488 	{
489 	return gEpocEnv->iDsa->AllocSurface(ETrue, aSize, aMode);
490 	}
491 
492 
493 void EpocSdlEnv::UnlockHwSurface()
494 	{
495 	gEpocEnv->iDsa->UnlockHwSurface();
496 	}
497 
498 TUint8* EpocSdlEnv::LockHwSurface()
499 	{
500 	return gEpocEnv->iDsa->LockHwSurface();
501 	}
502 
503 
504 void EpocSdlEnv::UpdateSwSurface()
505 	{
506 	gEpocEnv->iDsa->UpdateSwSurface();
507 	}
508 
509 TBool EpocSdlEnv::AddUpdateRect(TUint8* aAddress, const TRect& aUpdateRect, const TRect& aRect)
510 	{
511 	return gEpocEnv->iDsa->AddUpdateRect(aAddress, aUpdateRect, aRect);
512 	}
513 
514 void EpocSdlEnv::Request(TInt aService)
515     {
516     __ASSERT_DEBUG(gEpocEnv != NULL, PANIC(KErrNotReady));
517     gEpocEnv->iAppSrv->Request(aService);
518     }
519 
520 
521 TSize EpocSdlEnv::WindowSize(const TSize& aRequestedSize)
522     {
523     __ASSERT_DEBUG(gEpocEnv != NULL, PANIC(KErrNotReady));
524     if(EpocSdlEnv::Flags(CSDL::EAllowImageResize) && gEpocEnv->iDsa->WindowSize() != aRequestedSize)
525     	{
526     	TRAP_IGNORE(gEpocEnv->iDsa->CreateZoomerL(aRequestedSize));
527     	}
528     return gEpocEnv->iDsa->WindowSize();
529     }
530 
531  TSize EpocSdlEnv::WindowSize()
532     {
533     __ASSERT_DEBUG(gEpocEnv != NULL, PANIC(KErrNotReady));
534     return gEpocEnv->iDsa->WindowSize();
535     }
536 
537 TDisplayMode EpocSdlEnv::DisplayMode()
538     {
539     return gEpocEnv->iDsa->DisplayMode();
540     }
541 
542 TPointerCursorMode EpocSdlEnv::PointerMode()
543     {
544     return static_cast<TPointerCursorMode>
545     (gEpocEnv->iAppSrv->RequestValue(CSdlAppServ::EAppSrvWindowPointerCursorMode));
546     }
547 
548 TInt EpocSdlEnv::SetPalette(TInt aFirstcolor, TInt aColorCount, TUint32* aPalette)
549 	{
550 	return 	gEpocEnv->iDsa->SetPalette(aFirstcolor, aColorCount, aPalette);
551 	}
552 
553 void EpocSdlEnv::PanicMain(TInt aErr)
554     {
555     gEpocEnv->iAppSrv->PanicMain(aErr);
556     }
557 
558 
559 TInt EpocSdlEnv::AppendCleanupItem(const TSdlCleanupItem& aItem)
560     {
561     TRAPD(err, gEpocEnv->iCleanupItems->AppendL(aItem));
562     return err;
563     }
564 
565 void EpocSdlEnv::RemoveCleanupItem(TAny* aItem)
566     {
567     for(TInt i = 0; i < gEpocEnv->iCleanupItems->Count(); i++)
568         {
569         if(gEpocEnv->iCleanupItems->At(i).iItem == aItem)
570             gEpocEnv->iCleanupItems->Delete(i);
571         }
572     }
573 
574 void EpocSdlEnv::CleanupItems()
575 	{
576 	const TThreadId id = RThread().Id();
577 	TInt last = gEpocEnv->iCleanupItems->Count() - 1;
578 	TInt i;
579 	for(i = last; i >= 0 ; i--)
580         {
581         TSdlCleanupItem& item = gEpocEnv->iCleanupItems->At(i);
582         if(item.iThread == id)
583         	{
584         	item.iThread = TThreadId(0);
585         	item.iOperation(item.iItem);
586         	}
587         }
588     last = gEpocEnv->iCleanupItems->Count() - 1;
589 	for(i = last; i >= 0 ; i--)
590         {
591         TSdlCleanupItem& item = gEpocEnv->iCleanupItems->At(i);
592         if(item.iThread == TThreadId(0))
593         	{
594         	gEpocEnv->iCleanupItems->Delete(i);
595         	}
596         }
597 	}
598 
599 void EpocSdlEnv::FreeSurface()
600 	{
601 	Request(CSdlAppServ::EAppSrvDsaStatus);
602 	gEpocEnv->iDsa->Free();
603 	}
604 
605 void EpocSdlEnv::LockPalette(TBool aLock)
606 	{
607 	gEpocEnv->iDsa->LockPalette(aLock);
608 	}
609 
610 void EpocSdlEnv::ObserverEvent(TInt aService, TInt aParam)
611 	{
612 	const TBool sdlThread = RThread().Id() == gEpocEnv->iId;
613 	const TInt valuea = gEpocEnv->iAppSrv->ObserverEvent(aService, aParam);
614 	gEpocEnv->iAppSrv->HandleObserverValue(aService, valuea, !sdlThread);
615 	if(sdlThread)
616 		{
617 		gEpocEnv->iAppSrv->SetParam(aParam);
618 		const TInt valuet = gEpocEnv->iAppSrv->RequestValue(aService);
619 		gEpocEnv->iAppSrv->HandleObserverValue(aService, valuet, EFalse);
620 		}
621 	}
622 
623 
624 TPoint EpocSdlEnv::WindowCoordinates(const TPoint& aPoint)
625     {
626     return gEpocEnv->iDsa->WindowCoordinates(aPoint);
627     }
628 
629 void EpocSdlEnv::PanicMain(const TDesC& aInfo, TInt aErr)
630     {
631     gEpocEnv->iAppSrv->PanicMain(aInfo, aErr);
632     }
633 //Dsa is a low priority ao, it has to wait if its pending event, but ws
634 //event has been prioritized before it
635 //this is not called from app thread!
636 void EpocSdlEnv::WaitDeviceChange()
637     {
638   	LockPalette(ETrue);
639     gEpocEnv->iAppSrv->RequestValue(CSdlAppServ::EAppSrvWaitDsa);
640     const TSize sz = WindowSize();
641     const TInt param = reinterpret_cast<TInt>(&sz);
642     ObserverEvent(MSDLObserver::EEventScreenSizeChanged, param);
643 
644    // RThread().Suspend();
645     }
646 
647 LOCAL_C TBool CheckSdl()
648     {
649     TInt isExit = ETrue;
650     RThread sdl;
651     if(sdl.Open(gEpocEnv->iId) == KErrNone)
652         {
653         if(sdl.ExitType() == EExitPending)
654             {
655             isExit = EFalse;
656             }
657         sdl.Close();
658         }
659     return isExit;
660     }
661 
662 void EpocSdlEnvData::Free()
663     {
664     if(RThread().Id() == gEpocEnv->iId)
665     	{
666     	iDsa->Free();
667     	return;
668     	}
669 
670     __ASSERT_ALWAYS(iArgv == NULL || CheckSdl(), PANIC(KErrNotReady));
671 
672     for(TInt i = 0; i < iArgc; i++)
673         User::Free( iArgv[i] );
674 
675     User::Free(iArgv);
676 
677 
678     delete iEventQueue;
679 
680     if(iDsa != NULL)
681     	iDsa->Free();
682 
683 	delete iDsa;
684 	delete iAppSrv;
685     }
686 
687 _LIT(KSDLMain, "SDLMain");
688 
689 LOCAL_C int MainL()
690     {
691     gEpocEnv->iCleanupItems = new (ELeave) CArrayFixFlat<TSdlCleanupItem>(8);
692 
693     char** envp=0;
694      /* !! process exits here if there is "exit()" in main! */
695     int ret = 0;
696     for(TInt i = 0; i  < 6; i++)
697         {
698         void* f = (void*) gEpocEnv->iMain[i];
699         if(f != NULL)
700             {
701             switch(i)
702                 {
703                 case 0:
704                     ret = ((mainfunc1)f)();
705                     return ret;
706                 case 3:
707                     ((mainfunc1)f)();
708                     return ret;
709                 case 1:
710                     ret = ((mainfunc2)f)(EpocSdlEnv::Argc(), EpocSdlEnv::Argv());
711                     return ret;
712                 case 4:
713                     ((mainfunc2)f)(EpocSdlEnv::Argc(), EpocSdlEnv::Argv());
714                     return ret;
715                 case 2:
716                     ret = ((mainfunc3)f)(EpocSdlEnv::Argc(), EpocSdlEnv::Argv(), envp);
717                     return ret;
718                 case 5:
719                     ((mainfunc3)f)(EpocSdlEnv::Argc(), EpocSdlEnv::Argv(), envp);
720                     return ret;
721                 }
722             }
723         }
724     PANIC(KErrNotFound);
725     return 0;
726     }
727 
728 LOCAL_C TInt DoMain(TAny* /*aParam*/)
729     {
730 
731 
732     CTrapCleanup* cleanup = CTrapCleanup::New();
733 
734 	TBool fbsconnected = EFalse;
735 	if(RFbsSession::GetSession() == NULL)
736 	    {
737 	    PANIC_IF_ERROR(RFbsSession::Connect());
738 	    fbsconnected = ETrue;
739 	    }
740 
741  	gEpocEnv->iAppSrv->Init();
742 
743 #ifdef SYMBIANC
744     // Create stdlib
745     _REENT;
746 #endif
747 
748     // Call stdlib main
749     int ret = 0;
750 
751     //completes waiting rendesvous
752     RThread::Rendezvous(KErrNone);
753 
754     TRAPD(err, err = MainL());
755 
756     EpocSdlEnv::ObserverEvent(MSDLObserver::EEventMainExit, err);
757 
758     // Free resources and return
759 
760   	EpocSdlEnv::CleanupItems();
761 
762     gEpocEnv->iCleanupItems->Reset();
763     delete gEpocEnv->iCleanupItems;
764     gEpocEnv->iCleanupItems = NULL;
765 
766     gEpocEnv->Free(); //free up in thread resources
767 
768 #ifdef SYMBIANC
769     _cleanup(); //this is normally called at exit, I call it here
770 #endif
771 
772     if(fbsconnected)
773         RFbsSession::Disconnect();
774 
775 #ifdef SYMBIANC
776     CloseSTDLIB();
777 #endif
778 
779  //   delete as;
780    	delete cleanup;
781 
782     return err == KErrNone ? ret : err;;
783     }
784 
785 
786 
787 EXPORT_C CSDL::~CSDL()
788     {
789    	gEpocEnv->Free();
790     User::Free(gEpocEnv);
791     gEpocEnv->iSdl = NULL;
792     }
793 
794 EXPORT_C CSDL* CSDL::NewL(TInt aFlags)
795     {
796     __ASSERT_ALWAYS(gEpocEnv == NULL, PANIC(KErrAlreadyExists));
797     gEpocEnv = (EpocSdlEnvData*) User::AllocL(sizeof(EpocSdlEnvData));
798     Mem::FillZ(gEpocEnv, sizeof(EpocSdlEnvData));
799 
800     gEpocEnv->iEpocEnvFlags = aFlags;
801     gEpocEnv->iEventQueue = CEventQueue::NewL();
802 
803     gEpocEnv->iAppSrv = new (ELeave) CSdlAppServ();
804     gEpocEnv->iAppSrv->ConstructL();
805 
806     CSDL* sdl = new (ELeave) CSDL();
807 
808     gEpocEnv->iSdl = sdl;
809 
810     return sdl;
811     }
812 
813   /*
814 EXPORT_C void CSDL::ReInitL(TFlags aFlags)
815 	{
816 	const TFlags prevFlags = gEpocEnv->iEpocEnvFlags;
817 	gEpocEnv->iEpocEnvFlags = aFlags;
818 	TInt err = KErrNone;
819 	if(((prevFlags & EDrawModeDSB) != (aFlags & EDrawModeDSB)) && gEpocEnv->iDsa)
820 		{
821 		delete gEpocEnv->iDsa;
822 		gEpocEnv->iDsa = NULL;
823 		gEpocEnv->iDsa = CDsa::RecreateL(EpocSdlEnv::Flags(CSDL::EDrawModeDSB));
824 		}
825 	}
826  */
827 
828 
829 EXPORT_C void CSDL::SetContainerWindowL(RWindow& aWindow, RWsSession& aSession, CWsScreenDevice& aDevice)
830     {
831     if(gEpocEnv->iDsa == NULL)
832     	gEpocEnv->iDsa = CDsa::CreateL(aSession);
833     gEpocEnv->iDsa->ConstructL(aWindow, aDevice);
834     }
835 
836 
837 EXPORT_C TThreadId CSDL::CallMainL(const TMainFunc& aFunc, TRequestStatus* const aStatus, const CDesC8Array* const aArg, TInt aFlags, TInt aStackSize)
838     {
839     ASSERT(gEpocEnv != NULL);
840     gEpocEnv->iMain = aFunc;
841     const TBool args = aArg != NULL;
842 
843     gEpocEnv->iArgc = aArg->Count() + 1;
844     gEpocEnv->iArgv = (char**) User::AllocL(sizeof(char*) * (gEpocEnv->iArgc + 1));
845 
846     TInt k = 0;
847     const TFileName processName = RProcess().FileName();
848     const TInt len = processName.Length();
849     gEpocEnv->iArgv[k] = (char*) User::AllocL(len + 1);
850     Mem::Copy(gEpocEnv->iArgv[k], processName.Ptr(), len);
851     gEpocEnv->iArgv[k][len] = 0;
852 
853     for(TInt i =  0; args && (i < aArg->Count()); i++)
854         {
855         k++;
856         const TInt len = aArg->MdcaPoint(i).Length();
857         gEpocEnv->iArgv[k] = (char*) User::AllocL(len + 1);
858         Mem::Copy(gEpocEnv->iArgv[k], aArg->MdcaPoint(i).Ptr(), len);
859         gEpocEnv->iArgv[k][len] = 0;
860         }
861 
862     gEpocEnv->iArgv[gEpocEnv->iArgc] = NULL;
863 
864     RThread thread;
865     User::LeaveIfError(thread.Create(KSDLMain, DoMain, aStackSize, NULL, NULL));
866 
867     if(aStatus != NULL)
868     	{
869     	thread.Logon(*aStatus);
870     	}
871 
872     gEpocEnv->iId = thread.Id();
873     thread.SetPriority(EPriorityLess);
874     if((aFlags & CSDL::ERequestResume) == 0)
875         {
876         thread.Resume();
877         }
878     thread.Close();
879     return gEpocEnv->iId;
880     }
881 
882 EXPORT_C TInt CSDL::AppendWsEvent(const TWsEvent& aEvent)
883     {
884     return EpocSdlEnv::EventQueue().Append(aEvent);
885     }
886 
887 EXPORT_C void CSDL::SDLPanic(const TDesC& aInfo, TInt aErr)
888     {
889     EpocSdlEnv::PanicMain(aInfo, aErr);
890     }
891 
892 EXPORT_C TInt CSDL::GetSDLCode(TInt aScanCode)
893     {
894     if(aScanCode < 0)
895         return MAX_SCANCODE;
896     if(aScanCode >= MAX_SCANCODE)
897         return -1;
898     return KeyMap()[aScanCode];
899     }
900 
901 EXPORT_C TInt CSDL::SDLCodesCount() const
902 	{
903 	return MAX_SCANCODE;
904 	}
905 
906 EXPORT_C void CSDL::ResetSDLCodes()
907 	{
908 	ResetKeyMap();
909 	}
910 
911 EXPORT_C void CSDL::SetOrientation(TOrientationMode aMode)
912 	{
913 	gEpocEnv->iDsa->SetOrientation(aMode);
914 	}
915 
916 EXPORT_C TInt CSDL::SetSDLCode(TInt aScanCode, TInt aSDLCode)
917     {
918     const TInt current = GetSDLCode(aScanCode);
919     if(aScanCode >= 0 && aScanCode < MAX_SCANCODE)
920         KeyMap()[aScanCode] = static_cast<SDLKey>(aSDLCode);
921     return current;
922     }
923 
924 
925 EXPORT_C MSDLObserver* CSDL::Observer()
926 	{
927 	return gEpocEnv->iAppSrv->Observer();
928 	}
929 
930 EXPORT_C void CSDL::SetObserver(MSDLObserver* aObserver)
931 	{
932 	gEpocEnv->iAppSrv->SetObserver(aObserver);
933 	}
934 
935 EXPORT_C void CSDL::Resume()
936 	{
937 	EpocSdlEnv::Resume();
938 	}
939 
940 EXPORT_C void CSDL::Suspend()
941 	{
942 	gEpocEnv->iDsa->DoStop();
943 	}
944 
945 EXPORT_C CSDL::CSDL()
946     {
947     }
948 
949 EXPORT_C void CSDL::DisableKeyBlocking(CAknAppUi& aAppUi) const
950 	{
951 	gEpocEnv->iAppUi = &aAppUi;
952 	EnvUtils::DisableKeyBlocking();
953 	}
954 
955 EXPORT_C TInt CSDL::SetBlitter(MBlitter* aBlitter)
956 	{
957 	if(gEpocEnv && gEpocEnv->iDsa)
958 		{
959 		gEpocEnv->iDsa->SetBlitter(aBlitter);
960 		return KErrNone;
961 		}
962 	return KErrNotReady;
963 	}
964 
965 
966 EXPORT_C TInt CSDL::AppendOverlay(MOverlay& aOverlay, TInt aPriority)
967 	{
968 	if(gEpocEnv && gEpocEnv->iDsa)
969 		{
970 		return gEpocEnv->iDsa->AppendOverlay(aOverlay, aPriority);
971 		}
972 	return KErrNotReady;
973 	}
974 
975 EXPORT_C TInt CSDL::RemoveOverlay(MOverlay& aOverlay)
976 	{
977 	if(gEpocEnv && gEpocEnv->iDsa)
978 		{
979 		return gEpocEnv->iDsa->RemoveOverlay(aOverlay);
980 		}
981 	return KErrNotReady;
982 	}
983 
984 EXPORT_C TInt CSDL::RedrawRequest()
985 	{
986 	if(gEpocEnv && gEpocEnv->iDsa)
987 		{
988 		return gEpocEnv->iDsa->RedrawRequest();
989 		}
990 	return KErrNotReady;
991 	}
992 
993 /*
994 EXPORT_C CSDL* CSDL::Current()
995     {
996     return gEpocEnv != NULL ? gEpocEnv->iSdl : NULL;
997     }
998 
999 
1000 EXPORT_C TInt CSDL::SetVolume(TInt aVolume)
1001     {
1002     return EpocSdlEnv::SetVolume(aVolume);
1003     }
1004 
1005 EXPORT_C TInt CSDL::Volume() const
1006     {
1007     return EpocSdlEnv::Volume();
1008     }
1009 
1010 EXPORT_C TInt CSDL::MaxVolume() const
1011     {
1012     return EpocSdlEnv::MaxVolume();
1013     }
1014 */
1015 
1016 void EnvUtils::DisableKeyBlocking()
1017 	{
1018 	if(gEpocEnv->iAppUi != NULL)
1019 		return CCurrentAppUi::Cast(gEpocEnv->iAppUi)->DisableKeyBlocking();
1020 	}
1021 
1022 TBool EnvUtils::Rendezvous(RThread& aThread, TRequestStatus& aStatus)
1023 	{
1024 	if(gEpocEnv->iId != TThreadId(0) &&
1025     		 	aThread.Open(gEpocEnv->iId) &&
1026     		  	aThread.ExitType() == EExitPending)
1027     			{
1028     			aThread.Rendezvous(aStatus);
1029     			return ETrue;
1030     			}
1031     return EFalse;
1032 	}
1033 
1034 
1035 
1036