Home | History | Annotate | Download | only in EKA2
      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 
   1036