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
33extern SDLKey* KeyMap();
34extern void ResetKeyMap();
35
36class CCurrentAppUi;
37
38//const TUid KSDLUid =  { 0xF01F3D69 };
39
40NONSHARABLE_CLASS(EnvUtils)
41	{
42	public:
43	static void DisableKeyBlocking();
44	static TBool Rendezvous(RThread& aThread, TRequestStatus& aStatus);
45	};
46
47TInt 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
56NONSHARABLE_CLASS(CCurrentAppUi) : public CAknAppUi
57	{
58	public:
59	static CCurrentAppUi* Cast(CEikAppUi* aUi);
60	void DisableKeyBlocking();
61	};
62
63
64CCurrentAppUi* CCurrentAppUi::Cast(CEikAppUi* aUi)
65	{
66	return static_cast<CCurrentAppUi*>(aUi);
67	}
68
69void CCurrentAppUi::DisableKeyBlocking()
70	{
71	SetKeyBlockMode(ENoKeyBlock);
72	}
73
74
75class 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
100CEventQueue::~CEventQueue()
101    {
102    iCS.Close();
103    }
104
105TInt 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
114TBool CEventQueue::HasData()
115    {
116    return iVector.Size() > 0;
117    }
118
119
120void CEventQueue::Lock()
121	{
122    iCS.Wait();
123	}
124
125void CEventQueue::Unlock()
126	{
127	iCS.Signal();
128	}
129
130const TWsEvent& CEventQueue::Shift()
131    {
132    const TWsEvent& event =  iVector.Shift();
133    return event;
134    }
135
136
137TSdlCleanupItem::TSdlCleanupItem(TSdlCleanupOperation aOperation, TAny* aItem) :
138iOperation(aOperation), iItem(aItem), iThread(RThread().Id())
139    {
140    }
141
142class CEikonEnv;
143class CSdlAppServ;
144
145
146NONSHARABLE_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
164EpocSdlEnvData* gEpocEnv;
165
166#define MAINFUNC(x) EXPORT_C TMainFunc::TMainFunc(mainfunc##x aFunc){Mem::FillZ(iMainFunc, sizeof(iMainFunc)); iMainFunc[x - 1] = (void*) aFunc;}
167
168MAINFUNC(1)
169MAINFUNC(2)
170MAINFUNC(3)
171MAINFUNC(4)
172MAINFUNC(5)
173MAINFUNC(6)
174
175EXPORT_C TMainFunc::TMainFunc()
176	{
177	Mem::FillZ(iMainFunc, sizeof(iMainFunc));
178	}
179
180
181const void* TMainFunc::operator[](TInt aIndex) const
182	{
183	return iMainFunc[aIndex];
184	}
185
186
187NONSHARABLE_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
227CSdlAppServ::CSdlAppServ() : CActive(CActive::EPriorityHigh), iMainId(RThread().Id())
228    {
229    }
230
231
232
233MSDLObserver* CSdlAppServ::Observer()
234	{
235	return iObserver;
236	}
237
238
239void CSdlAppServ::SetObserver(MSDLObserver* aObserver)
240	{
241	iObserver = aObserver;
242	}
243
244TInt 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
261void CSdlAppServ::PanicMain(TInt aReason)
262    {
263    iAppThread.Panic(RThread().Name(), aReason);
264    }
265
266void CSdlAppServ::PanicMain(const TDesC& aInfo, TInt aReason)
267    {
268    iAppThread.Panic(aInfo, aReason);
269    }
270
271void 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
289TInt 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
301TInt CSdlAppServ::RequestValue(TInt aService)
302    {
303    Request(aService);
304    Request(EAppSrvNoop);
305    return iReturnValue;
306    }
307
308void CSdlAppServ::Init()
309    {
310    PANIC_IF_ERROR(iAppThread.Open(iMainId));
311    }
312
313void CSdlAppServ::SetParam(TInt aParam)
314	{
315	iReturnValue = aParam;
316	}
317
318void 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
340void 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
393void CSdlAppServ::DoCancel()
394    {
395    iSema.Wait();
396    TRequestStatus* s = &iStatus;
397    iAppThread.RequestComplete(s, KErrCancel);
398    }
399
400
401
402MEventQueue& EpocSdlEnv::EventQueue()
403    {
404    __ASSERT_DEBUG(gEpocEnv != NULL, PANIC(KErrNotReady));
405    return *gEpocEnv->iEventQueue;
406    }
407
408
409TBool EpocSdlEnv::Flags(TInt aFlag)
410    {
411	const TInt flag = gEpocEnv->iEpocEnvFlags & aFlag;
412	return flag == aFlag;
413    }
414
415TInt EpocSdlEnv::Argc()
416    {
417    __ASSERT_DEBUG(gEpocEnv != NULL, PANIC(KErrNotReady));
418    return gEpocEnv->iArgc;
419    }
420
421
422char** EpocSdlEnv::Argv()
423    {
424    __ASSERT_DEBUG(gEpocEnv != NULL, PANIC(KErrNotReady));
425    return gEpocEnv->iArgv;
426    }
427
428
429TBool EpocSdlEnv::IsDsaAvailable()
430    {
431    __ASSERT_DEBUG(gEpocEnv != NULL, PANIC(KErrNotReady));
432    return gEpocEnv->iDsa != NULL && gEpocEnv->iDsa->IsDsaAvailable();
433    }
434
435
436void 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
446void 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
457void 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
469void 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
482TInt EpocSdlEnv::AllocSwSurface(const TSize& aSize, TDisplayMode aMode)
483	{
484	return gEpocEnv->iDsa->AllocSurface(EFalse, aSize, aMode);
485	}
486
487TInt EpocSdlEnv::AllocHwSurface(const TSize& aSize, TDisplayMode aMode)
488	{
489	return gEpocEnv->iDsa->AllocSurface(ETrue, aSize, aMode);
490	}
491
492
493void EpocSdlEnv::UnlockHwSurface()
494	{
495	gEpocEnv->iDsa->UnlockHwSurface();
496	}
497
498TUint8* EpocSdlEnv::LockHwSurface()
499	{
500	return gEpocEnv->iDsa->LockHwSurface();
501	}
502
503
504void EpocSdlEnv::UpdateSwSurface()
505	{
506	gEpocEnv->iDsa->UpdateSwSurface();
507	}
508
509TBool EpocSdlEnv::AddUpdateRect(TUint8* aAddress, const TRect& aUpdateRect, const TRect& aRect)
510	{
511	return gEpocEnv->iDsa->AddUpdateRect(aAddress, aUpdateRect, aRect);
512	}
513
514void EpocSdlEnv::Request(TInt aService)
515    {
516    __ASSERT_DEBUG(gEpocEnv != NULL, PANIC(KErrNotReady));
517    gEpocEnv->iAppSrv->Request(aService);
518    }
519
520
521TSize 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
537TDisplayMode EpocSdlEnv::DisplayMode()
538    {
539    return gEpocEnv->iDsa->DisplayMode();
540    }
541
542TPointerCursorMode EpocSdlEnv::PointerMode()
543    {
544    return static_cast<TPointerCursorMode>
545    (gEpocEnv->iAppSrv->RequestValue(CSdlAppServ::EAppSrvWindowPointerCursorMode));
546    }
547
548TInt EpocSdlEnv::SetPalette(TInt aFirstcolor, TInt aColorCount, TUint32* aPalette)
549	{
550	return 	gEpocEnv->iDsa->SetPalette(aFirstcolor, aColorCount, aPalette);
551	}
552
553void EpocSdlEnv::PanicMain(TInt aErr)
554    {
555    gEpocEnv->iAppSrv->PanicMain(aErr);
556    }
557
558
559TInt EpocSdlEnv::AppendCleanupItem(const TSdlCleanupItem& aItem)
560    {
561    TRAPD(err, gEpocEnv->iCleanupItems->AppendL(aItem));
562    return err;
563    }
564
565void 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
574void 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
599void EpocSdlEnv::FreeSurface()
600	{
601	Request(CSdlAppServ::EAppSrvDsaStatus);
602	gEpocEnv->iDsa->Free();
603	}
604
605void EpocSdlEnv::LockPalette(TBool aLock)
606	{
607	gEpocEnv->iDsa->LockPalette(aLock);
608	}
609
610void 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
624TPoint EpocSdlEnv::WindowCoordinates(const TPoint& aPoint)
625    {
626    return gEpocEnv->iDsa->WindowCoordinates(aPoint);
627    }
628
629void 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!
636void 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
647LOCAL_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
662void 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
689LOCAL_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
728LOCAL_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
787EXPORT_C CSDL::~CSDL()
788    {
789   	gEpocEnv->Free();
790    User::Free(gEpocEnv);
791    gEpocEnv->iSdl = NULL;
792    }
793
794EXPORT_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  /*
814EXPORT_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
829EXPORT_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
837EXPORT_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
882EXPORT_C TInt CSDL::AppendWsEvent(const TWsEvent& aEvent)
883    {
884    return EpocSdlEnv::EventQueue().Append(aEvent);
885    }
886
887EXPORT_C void CSDL::SDLPanic(const TDesC& aInfo, TInt aErr)
888    {
889    EpocSdlEnv::PanicMain(aInfo, aErr);
890    }
891
892EXPORT_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
901EXPORT_C TInt CSDL::SDLCodesCount() const
902	{
903	return MAX_SCANCODE;
904	}
905
906EXPORT_C void CSDL::ResetSDLCodes()
907	{
908	ResetKeyMap();
909	}
910
911EXPORT_C void CSDL::SetOrientation(TOrientationMode aMode)
912	{
913	gEpocEnv->iDsa->SetOrientation(aMode);
914	}
915
916EXPORT_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
925EXPORT_C MSDLObserver* CSDL::Observer()
926	{
927	return gEpocEnv->iAppSrv->Observer();
928	}
929
930EXPORT_C void CSDL::SetObserver(MSDLObserver* aObserver)
931	{
932	gEpocEnv->iAppSrv->SetObserver(aObserver);
933	}
934
935EXPORT_C void CSDL::Resume()
936	{
937	EpocSdlEnv::Resume();
938	}
939
940EXPORT_C void CSDL::Suspend()
941	{
942	gEpocEnv->iDsa->DoStop();
943	}
944
945EXPORT_C CSDL::CSDL()
946    {
947    }
948
949EXPORT_C void CSDL::DisableKeyBlocking(CAknAppUi& aAppUi) const
950	{
951	gEpocEnv->iAppUi = &aAppUi;
952	EnvUtils::DisableKeyBlocking();
953	}
954
955EXPORT_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
966EXPORT_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
975EXPORT_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
984EXPORT_C TInt CSDL::RedrawRequest()
985	{
986	if(gEpocEnv && gEpocEnv->iDsa)
987		{
988		return gEpocEnv->iDsa->RedrawRequest();
989		}
990	return KErrNotReady;
991	}
992
993/*
994EXPORT_C CSDL* CSDL::Current()
995    {
996    return gEpocEnv != NULL ? gEpocEnv->iSdl : NULL;
997    }
998
999
1000EXPORT_C TInt CSDL::SetVolume(TInt aVolume)
1001    {
1002    return EpocSdlEnv::SetVolume(aVolume);
1003    }
1004
1005EXPORT_C TInt CSDL::Volume() const
1006    {
1007    return EpocSdlEnv::Volume();
1008    }
1009
1010EXPORT_C TInt CSDL::MaxVolume() const
1011    {
1012    return EpocSdlEnv::MaxVolume();
1013    }
1014*/
1015
1016void EnvUtils::DisableKeyBlocking()
1017	{
1018	if(gEpocEnv->iAppUi != NULL)
1019		return CCurrentAppUi::Cast(gEpocEnv->iAppUi)->DisableKeyBlocking();
1020	}
1021
1022TBool 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