SDL-1.2.14
[sdl_omap.git] / src / main / symbian / EKA2 / SDL_main.cpp
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
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