summaryrefslogtreecommitdiffstats
path: root/vcl/ios/source/app/salinst.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'vcl/ios/source/app/salinst.cxx')
-rw-r--r--vcl/ios/source/app/salinst.cxx828
1 files changed, 828 insertions, 0 deletions
diff --git a/vcl/ios/source/app/salinst.cxx b/vcl/ios/source/app/salinst.cxx
new file mode 100644
index 000000000000..b4c944cd31a4
--- /dev/null
+++ b/vcl/ios/source/app/salinst.cxx
@@ -0,0 +1,828 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_vcl.hxx"
+
+#include <stdio.h>
+
+#include "tools/fsys.hxx"
+#include "tools/getprocessworkingdir.hxx"
+#include <tools/solarmutex.hxx>
+
+#include "osl/process.h"
+
+#include "rtl/ustrbuf.hxx"
+
+#include "vcl/svapp.hxx"
+#include "vcl/window.hxx"
+#include "vcl/timer.hxx"
+#include "vcl/solarmutex.hxx"
+
+#include "ios/saldata.hxx"
+#include "ios/salinst.h"
+#include "ios/salframe.h"
+#include "ios/salobj.h"
+#include "ios/salsys.h"
+#include "ios/salvd.h"
+#include "ios/salbmp.h"
+#include "ios/salprn.h"
+#include "ios/saltimer.h"
+#include "ios/vcluiapp.h"
+
+#include "print.h"
+#include "impbmp.hxx"
+#include "salimestatus.hxx"
+
+#include <comphelper/processfactory.hxx>
+
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/uri/XExternalUriReferenceTranslator.hpp>
+#include <com/sun/star/uri/ExternalUriReferenceTranslator.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+
+using namespace std;
+using namespace ::com::sun::star;
+
+extern sal_Bool ImplSVMain();
+
+static int* gpnInit = 0;
+static bool bNoSVMain = true;
+static bool bLeftMain = false;
+// -----------------------------------------------------------------------
+
+class IosDelayedSettingsChanged : public Timer
+{
+ bool mbInvalidate;
+ public:
+ IosDelayedSettingsChanged( bool bInvalidate ) :
+ mbInvalidate( bInvalidate )
+ {
+ }
+
+ virtual void Timeout()
+ {
+ SalData* pSalData = GetSalData();
+ if( ! pSalData->maFrames.empty() )
+ pSalData->maFrames.front()->CallCallback( SALEVENT_SETTINGSCHANGED, NULL );
+
+ if( mbInvalidate )
+ {
+ for( std::list< IosSalFrame* >::iterator it = pSalData->maFrames.begin();
+ it != pSalData->maFrames.end(); ++it )
+ {
+ if( (*it)->mbShown )
+ (*it)->SendPaintEvent( NULL );
+ }
+ }
+ Stop();
+ delete this;
+ }
+};
+
+void IosSalInstance::delayedSettingsChanged( bool bInvalidate )
+{
+ osl::SolarGuard aGuard( *mpSalYieldMutex );
+ IosDelayedSettingsChanged* pTimer = new IosDelayedSettingsChanged( bInvalidate );
+ pTimer->SetTimeout( 50 );
+ pTimer->Start();
+}
+
+
+// the AppEventList must be available before any SalData/SalInst/etc. objects are ready
+typedef std::list<const ApplicationEvent*> AppEventList;
+AppEventList IosSalInstance::aAppEventList;
+
+// initialize the VCL_UIApplication object
+static void initUIApp()
+{
+ [VCL_UIApplication sharedApplication];
+
+ SalData::ensureThreadAutoreleasePool();
+}
+
+sal_Bool ImplSVMainHook( int * pnInit )
+{
+ gpnInit = pnInit;
+
+ bNoSVMain = false;
+ initUIApp();
+
+ char* pArgv[] = { "main", NULL };
+ UIApplicationMain( 1, pArgv, NULL, NULL );
+
+ return TRUE; // indicate that ImplSVMainHook is implemented
+}
+
+// =======================================================================
+
+void SalAbort( const XubString& rErrorText )
+{
+ if( !rErrorText.Len() )
+ fprintf( stderr, "Application Error " );
+ else
+ fprintf( stderr, "%s ",
+ ByteString( rErrorText, gsl_getSystemTextEncoding() ).GetBuffer() );
+ abort();
+}
+
+// -----------------------------------------------------------------------
+
+void InitSalData()
+{
+ SalData *pSalData = new SalData;
+ SetSalData( pSalData );
+}
+
+// -----------------------------------------------------------------------
+
+const ::rtl::OUString& SalGetDesktopEnvironment()
+{
+ static OUString aDesktopEnvironment(RTL_CONSTASCII_USTRINGPARAM( "CocoaTouch" ));
+ return aDesktopEnvironment;
+}
+
+// -----------------------------------------------------------------------
+
+void DeInitSalData()
+{
+ SalData *pSalData = GetSalData();
+ delete pSalData;
+ SetSalData( NULL );
+}
+
+// -----------------------------------------------------------------------
+
+void InitSalMain()
+{
+ rtl::OUString urlWorkDir;
+ rtl_uString *sysWorkDir = NULL;
+ if (tools::getProcessWorkingDir(urlWorkDir))
+ {
+ oslFileError err2 = osl_getSystemPathFromFileURL(urlWorkDir.pData, &sysWorkDir);
+ if (err2 == osl_File_E_None)
+ {
+ ByteString aPath( getenv( "PATH" ) );
+ ByteString aResPath( getenv( "STAR_RESOURCEPATH" ) );
+ ByteString aCmdPath( OUStringToOString(OUString(sysWorkDir), RTL_TEXTENCODING_UTF8).getStr() );
+ ByteString aTmpPath;
+ // Get absolute path of command's directory
+ if ( aCmdPath.Len() ) {
+ DirEntry aCmdDirEntry( aCmdPath );
+ aCmdDirEntry.ToAbs();
+ aCmdPath = ByteString( aCmdDirEntry.GetPath().GetFull(), RTL_TEXTENCODING_ASCII_US );
+ }
+ // Assign to PATH environment variable
+ if ( aCmdPath.Len() )
+ {
+ aTmpPath = ByteString( "PATH=" );
+ aTmpPath += aCmdPath;
+ if ( aPath.Len() )
+ aTmpPath += ByteString( DirEntry::GetSearchDelimiter(), RTL_TEXTENCODING_ASCII_US );
+ aTmpPath += aPath;
+ putenv( (char*)aTmpPath.GetBuffer() );
+ }
+ // Assign to STAR_RESOURCEPATH environment variable
+ if ( aCmdPath.Len() )
+ {
+ aTmpPath = ByteString( "STAR_RESOURCEPATH=" );
+ aTmpPath += aCmdPath;
+ if ( aResPath.Len() )
+ aTmpPath += ByteString( DirEntry::GetSearchDelimiter(), RTL_TEXTENCODING_ASCII_US );
+ aTmpPath += aResPath;
+ putenv( (char*)aTmpPath.GetBuffer() );
+ }
+ }
+ }
+}
+
+// -----------------------------------------------------------------------
+
+void DeInitSalMain()
+{
+}
+
+// =======================================================================
+
+SalYieldMutex::SalYieldMutex()
+{
+ mnCount = 0;
+ mnThreadId = 0;
+}
+
+void SalYieldMutex::acquire()
+{
+ SolarMutexObject::acquire();
+ mnThreadId = osl::Thread::getCurrentIdentifier();
+ mnCount++;
+}
+
+void SalYieldMutex::release()
+{
+ if ( mnThreadId == osl::Thread::getCurrentIdentifier() )
+ {
+ if ( mnCount == 1 )
+ mnThreadId = 0;
+ mnCount--;
+ }
+ SolarMutexObject::release();
+}
+
+sal_Bool SalYieldMutex::tryToAcquire()
+{
+ if ( SolarMutexObject::tryToAcquire() )
+ {
+ mnThreadId = osl::Thread::getCurrentIdentifier();
+ mnCount++;
+ return sal_True;
+ }
+ else
+ return sal_False;
+}
+
+// -----------------------------------------------------------------------
+
+// some convenience functions regarding the yield mutex, aka solar mutex
+
+sal_Bool ImplSalYieldMutexTryToAcquire()
+{
+ IosSalInstance* pInst = (IosSalInstance*) GetSalData()->mpFirstInstance;
+ if ( pInst )
+ return pInst->mpSalYieldMutex->tryToAcquire();
+ else
+ return FALSE;
+}
+
+void ImplSalYieldMutexAcquire()
+{
+ IosSalInstance* pInst = (IosSalInstance*) GetSalData()->mpFirstInstance;
+ if ( pInst )
+ pInst->mpSalYieldMutex->acquire();
+}
+
+void ImplSalYieldMutexRelease()
+{
+ IosSalInstance* pInst = (IosSalInstance*) GetSalData()->mpFirstInstance;
+ if ( pInst )
+ pInst->mpSalYieldMutex->release();
+}
+
+// =======================================================================
+
+SalInstance* CreateSalInstance()
+{
+ // this is the case for not using SVMain
+ // not so good
+ if( bNoSVMain )
+ initUIApp();
+
+ SalData* pSalData = GetSalData();
+ DBG_ASSERT( pSalData->mpFirstInstance == NULL, "more than one instance created" );
+ IosSalInstance* pInst = new IosSalInstance;
+
+ // init instance (only one instance in this version !!!)
+ pSalData->mpFirstInstance = pInst;
+ // this one is for outside IosSalInstance::Yield
+ SalData::ensureThreadAutoreleasePool();
+ // no focus rects on NWF ios
+ ImplGetSVData()->maNWFData.mbNoFocusRects = true;
+ ImplGetSVData()->maNWFData.mbNoBoldTabFocus = true;
+ ImplGetSVData()->maNWFData.mbNoActiveTabTextRaise = true;
+ ImplGetSVData()->maNWFData.mbCenteredTabs = true;
+ ImplGetSVData()->maNWFData.mbProgressNeedsErase = true;
+ ImplGetSVData()->maNWFData.mbCheckBoxNeedsErase = true;
+ ImplGetSVData()->maNWFData.mnStatusBarLowerRightOffset = 10;
+ ImplGetSVData()->maGDIData.mbNoXORClipping = true;
+ ImplGetSVData()->maWinData.mbNoSaveBackground = true;
+
+ return pInst;
+}
+
+// -----------------------------------------------------------------------
+
+void DestroySalInstance( SalInstance* pInst )
+{
+ delete pInst;
+}
+
+// -----------------------------------------------------------------------
+
+IosSalInstance::IosSalInstance()
+{
+ mpSalYieldMutex = new SalYieldMutex;
+ mpSalYieldMutex->acquire();
+ ::tools::SolarMutex::SetSolarMutex( mpSalYieldMutex );
+ maMainThread = osl::Thread::getCurrentIdentifier();
+ mbWaitingYield = false;
+ maUserEventListMutex = osl_createMutex();
+ mnActivePrintJobs = 0;
+ maWaitingYieldCond = osl_createCondition();
+}
+
+// -----------------------------------------------------------------------
+
+IosSalInstance::~IosSalInstance()
+{
+ ::tools::SolarMutex::SetSolarMutex( 0 );
+ mpSalYieldMutex->release();
+ delete mpSalYieldMutex;
+ osl_destroyMutex( maUserEventListMutex );
+ osl_destroyCondition( maWaitingYieldCond );
+}
+
+// -----------------------------------------------------------------------
+
+void IosSalInstance::wakeupYield()
+{
+}
+
+// -----------------------------------------------------------------------
+
+void IosSalInstance::PostUserEvent( IosSalFrame* pFrame, sal_uInt16 nType, void* pData )
+{
+ osl_acquireMutex( maUserEventListMutex );
+ maUserEvents.push_back( SalUserEvent( pFrame, pData, nType ) );
+ osl_releaseMutex( maUserEventListMutex );
+
+ // notify main loop that an event has arrived
+ wakeupYield();
+}
+
+// -----------------------------------------------------------------------
+
+osl::SolarMutex* IosSalInstance::GetYieldMutex()
+{
+ return mpSalYieldMutex;
+}
+
+// -----------------------------------------------------------------------
+
+sal_uLong IosSalInstance::ReleaseYieldMutex()
+{
+ SalYieldMutex* pYieldMutex = mpSalYieldMutex;
+ if ( pYieldMutex->GetThreadId() ==
+ osl::Thread::getCurrentIdentifier() )
+ {
+ sal_uLong nCount = pYieldMutex->GetAcquireCount();
+ sal_uLong n = nCount;
+ while ( n )
+ {
+ pYieldMutex->release();
+ n--;
+ }
+
+ return nCount;
+ }
+ else
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+
+void IosSalInstance::AcquireYieldMutex( sal_uLong nCount )
+{
+ SalYieldMutex* pYieldMutex = mpSalYieldMutex;
+ while ( nCount )
+ {
+ pYieldMutex->acquire();
+ nCount--;
+ }
+}
+
+// -----------------------------------------------------------------------
+
+bool IosSalInstance::CheckYieldMutex()
+{
+ bool bRet = true;
+
+ SalYieldMutex* pYieldMutex = mpSalYieldMutex;
+ if ( pYieldMutex->GetThreadId() != osl::Thread::getCurrentIdentifier())
+ {
+ bRet = false;
+ }
+
+ return bRet;
+}
+
+// -----------------------------------------------------------------------
+
+bool IosSalInstance::isUIAppThread() const
+{
+ return osl::Thread::getCurrentIdentifier() == maMainThread;
+}
+
+// -----------------------------------------------------------------------
+
+class ReleasePoolHolder
+{
+ NSAutoreleasePool* mpPool;
+ public:
+ ReleasePoolHolder() : mpPool( [[NSAutoreleasePool alloc] init] ) {}
+ ~ReleasePoolHolder() { [mpPool release]; }
+};
+
+void IosSalInstance::Yield( bool bWait, bool bHandleAllCurrentEvents )
+{
+ // ensure that the per thread autorelease pool is top level and
+ // will therefore not be destroyed by cocoa implicitly
+ SalData::ensureThreadAutoreleasePool();
+
+ // NSAutoreleasePool documentation suggests we should have
+ // an own pool for each yield level
+ ReleasePoolHolder aReleasePool;
+
+ // Release all locks so that we don't deadlock when we pull pending
+ // events from the event queue
+ bool bDispatchUser = true;
+ while( bDispatchUser )
+ {
+ sal_uLong nCount = ReleaseYieldMutex();
+
+ // get one user event
+ osl_acquireMutex( maUserEventListMutex );
+ SalUserEvent aEvent( NULL, NULL, 0 );
+ if( ! maUserEvents.empty() )
+ {
+ aEvent = maUserEvents.front();
+ maUserEvents.pop_front();
+ }
+ else
+ bDispatchUser = false;
+ osl_releaseMutex( maUserEventListMutex );
+
+ AcquireYieldMutex( nCount );
+
+ // dispatch it
+ if( aEvent.mpFrame && IosSalFrame::isAlive( aEvent.mpFrame ) )
+ {
+ aEvent.mpFrame->CallCallback( aEvent.mnType, aEvent.mpData );
+ osl_setCondition( maWaitingYieldCond );
+ // return if only one event is asked for
+ if( ! bHandleAllCurrentEvents )
+ return;
+ }
+ }
+
+ // handle event queue
+ // events mye be only handled in the thread the app was created
+ if( mnActivePrintJobs == 0 )
+ {
+ // we need to be woken up by a cocoa-event
+ // if a user event should be posted by the event handling below
+ bool bOldWaitingYield = mbWaitingYield;
+ mbWaitingYield = bWait;
+
+ mbWaitingYield = bOldWaitingYield;
+
+ // collect update rectangles
+ const std::list< IosSalFrame* > rFrames( GetSalData()->maFrames );
+ for( std::list< IosSalFrame* >::const_iterator it = rFrames.begin(); it != rFrames.end(); ++it )
+ {
+ if( (*it)->mbShown && ! (*it)->maInvalidRect.IsEmpty() )
+ {
+ (*it)->Flush( (*it)->maInvalidRect );
+ (*it)->maInvalidRect.SetEmpty();
+ }
+ }
+ osl_setCondition( maWaitingYieldCond );
+ }
+}
+
+// -----------------------------------------------------------------------
+
+bool IosSalInstance::AnyInput( sal_uInt16 nType )
+{
+ if( nType & INPUT_APPEVENT )
+ {
+ if( ! aAppEventList.empty() )
+ return true;
+ if( nType == INPUT_APPEVENT )
+ return false;
+ }
+
+ if( nType & INPUT_TIMER )
+ {
+ if( IosSalTimer::pRunningTimer )
+ {
+ NSDate* pDt = [IosSalTimer::pRunningTimer fireDate];
+ if( pDt && [pDt timeIntervalSinceNow] < 0 )
+ {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+// -----------------------------------------------------------------------
+
+SalFrame* IosSalInstance::CreateChildFrame( SystemParentData*, sal_uLong /*nSalFrameStyle*/ )
+{
+ return NULL;
+}
+
+// -----------------------------------------------------------------------
+
+SalFrame* IosSalInstance::CreateFrame( SalFrame* pParent, sal_uLong nSalFrameStyle )
+{
+ SalData::ensureThreadAutoreleasePool();
+
+ SalFrame* pFrame = new IosSalFrame( pParent, nSalFrameStyle );
+ return pFrame;
+}
+
+// -----------------------------------------------------------------------
+
+void IosSalInstance::DestroyFrame( SalFrame* pFrame )
+{
+ delete pFrame;
+}
+
+// -----------------------------------------------------------------------
+
+SalObject* IosSalInstance::CreateObject( SalFrame* pParent, SystemWindowData* /* pWindowData */, sal_Bool /* bShow */ )
+{
+ // SystemWindowData is meaningless on Mac OS X
+ IosSalObject *pObject = NULL;
+
+ if ( pParent )
+ pObject = new IosSalObject( static_cast<IosSalFrame*>(pParent) );
+
+ return pObject;
+}
+
+// -----------------------------------------------------------------------
+
+void IosSalInstance::DestroyObject( SalObject* pObject )
+{
+ delete ( pObject );
+}
+
+SalSystem* IosSalInstance::CreateSystem()
+{
+ return new IosSalSystem();
+}
+
+// -----------------------------------------------------------------------
+
+void IosSalInstance::DestroySystem( SalSystem* pSystem )
+{
+ delete pSystem;
+}
+
+// -----------------------------------------------------------------------
+
+void IosSalInstance::SetEventCallback( void*, bool(*)(void*,void*,int) )
+{
+}
+
+// -----------------------------------------------------------------------
+
+void IosSalInstance::SetErrorEventCallback( void*, bool(*)(void*,void*,int) )
+{
+}
+
+// -----------------------------------------------------------------------
+
+void* IosSalInstance::GetConnectionIdentifier( ConnectionIdentifierType& rReturnedType, int& rReturnedBytes )
+{
+ rReturnedBytes = 1;
+ rReturnedType = AsciiCString;
+ return (void*)"";
+}
+
+// We need to re-encode file urls because osl_getFileURLFromSystemPath converts
+// to UTF-8 before encoding non ascii characters, which is not what other apps expect.
+static rtl::OUString translateToExternalUrl(const rtl::OUString& internalUrl)
+{
+ rtl::OUString extUrl;
+
+ uno::Reference< lang::XMultiServiceFactory > sm = comphelper::getProcessServiceFactory();
+ if (sm.is())
+ {
+ uno::Reference< beans::XPropertySet > pset;
+ sm->queryInterface( getCppuType( &pset )) >>= pset;
+ if (pset.is())
+ {
+ uno::Reference< uno::XComponentContext > context;
+ static const rtl::OUString DEFAULT_CONTEXT( RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" ) );
+ pset->getPropertyValue(DEFAULT_CONTEXT) >>= context;
+ if (context.is())
+ extUrl = uri::ExternalUriReferenceTranslator::create(context)->translateToExternal(internalUrl);
+ }
+ }
+ return extUrl;
+}
+
+// #i104525# many versions of OSX have problems with some URLs:
+// when an app requests OSX to add one of these URLs to the "Recent Items" list
+// then this app gets killed (TextEdit, Preview, etc. and also OOo)
+static bool isDangerousUrl( const rtl::OUString& rUrl )
+{
+ // use a heuristic that detects all known cases since there is no official comment
+ // on the exact impact and root cause of the OSX bug
+ const int nLen = rUrl.getLength();
+ const sal_Unicode* p = rUrl.getStr();
+ for( int i = 0; i < nLen-3; ++i, ++p ) {
+ if( p[0] != '%' )
+ continue;
+ // escaped percent?
+ if( (p[1] == '2') && (p[2] == '5') )
+ return true;
+ // escapes are considered to be UTF-8 encoded
+ // => check for invalid UTF-8 leading byte
+ if( (p[1] != 'f') && (p[1] != 'F') )
+ continue;
+ int cLowNibble = p[2];
+ if( (cLowNibble >= '0' ) && (cLowNibble <= '9'))
+ return false;
+ if( cLowNibble >= 'a' )
+ cLowNibble -= 'a' - 'A';
+ if( (cLowNibble < 'A') || (cLowNibble >= 'C'))
+ return true;
+ }
+
+ return false;
+}
+
+void IosSalInstance::AddToRecentDocumentList(const rtl::OUString& rFileUrl, const rtl::OUString& /*rMimeType*/)
+{
+}
+
+// -----------------------------------------------------------------------
+
+SalTimer* IosSalInstance::CreateSalTimer()
+{
+ return new IosSalTimer();
+}
+
+// -----------------------------------------------------------------------
+
+SalSystem* IosSalInstance::CreateSalSystem()
+{
+ return new IosSalSystem();
+}
+
+// -----------------------------------------------------------------------
+
+SalBitmap* IosSalInstance::CreateSalBitmap()
+{
+ return new IosSalBitmap();
+}
+
+// -----------------------------------------------------------------------
+
+SalSession* IosSalInstance::CreateSalSession()
+{
+ return NULL;
+}
+
+// -----------------------------------------------------------------------
+
+// YieldMutexReleaser
+YieldMutexReleaser::YieldMutexReleaser() : mnCount( 0 )
+{
+ SalData* pSalData = GetSalData();
+ if( ! pSalData->mpFirstInstance->isUIAppThread() )
+ {
+ SalData::ensureThreadAutoreleasePool();
+ mnCount = pSalData->mpFirstInstance->ReleaseYieldMutex();
+ }
+}
+
+YieldMutexReleaser::~YieldMutexReleaser()
+{
+ if( mnCount != 0 )
+ GetSalData()->mpFirstInstance->AcquireYieldMutex( mnCount );
+}
+
+//////////////////////////////////////////////////////////////
+rtl::OUString GetOUString( CFStringRef rStr )
+{
+ if( rStr == 0 )
+ return rtl::OUString();
+ CFIndex nLength = CFStringGetLength( rStr );
+ if( nLength == 0 )
+ return rtl::OUString();
+ const UniChar* pConstStr = CFStringGetCharactersPtr( rStr );
+ if( pConstStr )
+ return rtl::OUString( pConstStr, nLength );
+ UniChar* pStr = reinterpret_cast<UniChar*>( rtl_allocateMemory( sizeof(UniChar)*nLength ) );
+ CFRange aRange = { 0, nLength };
+ CFStringGetCharacters( rStr, aRange, pStr );
+ rtl::OUString aRet( pStr, nLength );
+ rtl_freeMemory( pStr );
+ return aRet;
+}
+
+rtl::OUString GetOUString( NSString* pStr )
+{
+ if( ! pStr )
+ return rtl::OUString();
+ int nLen = [pStr length];
+ if( nLen == 0 )
+ return rtl::OUString();
+
+ rtl::OUStringBuffer aBuf( nLen+1 );
+ aBuf.setLength( nLen );
+ [pStr getCharacters: const_cast<sal_Unicode*>(aBuf.getStr())];
+ return aBuf.makeStringAndClear();
+}
+
+CFStringRef CreateCFString( const rtl::OUString& rStr )
+{
+ return CFStringCreateWithCharacters(kCFAllocatorDefault, rStr.getStr(), rStr.getLength() );
+}
+
+NSString* CreateNSString( const rtl::OUString& rStr )
+{
+ return [[NSString alloc] initWithCharacters: rStr.getStr() length: rStr.getLength()];
+}
+
+CGImageRef CreateCGImage( const Image& rImage )
+{
+ BitmapEx aBmpEx( rImage.GetBitmapEx() );
+ Bitmap aBmp( aBmpEx.GetBitmap() );
+
+ if( ! aBmp || ! aBmp.ImplGetImpBitmap() )
+ return NULL;
+
+ // simple case, no transparency
+ IosSalBitmap* pSalBmp = static_cast<IosSalBitmap*>(aBmp.ImplGetImpBitmap()->ImplGetSalBitmap());
+
+ if( ! pSalBmp )
+ return NULL;
+
+ CGImageRef xImage = NULL;
+ if( ! (aBmpEx.IsAlpha() || aBmpEx.IsTransparent() ) )
+ xImage = pSalBmp->CreateCroppedImage( 0, 0, pSalBmp->mnWidth, pSalBmp->mnHeight );
+ else if( aBmpEx.IsAlpha() )
+ {
+ AlphaMask aAlphaMask( aBmpEx.GetAlpha() );
+ Bitmap aMask( aAlphaMask.GetBitmap() );
+ IosSalBitmap* pMaskBmp = static_cast<IosSalBitmap*>(aMask.ImplGetImpBitmap()->ImplGetSalBitmap());
+ if( pMaskBmp )
+ xImage = pSalBmp->CreateWithMask( *pMaskBmp, 0, 0, pSalBmp->mnWidth, pSalBmp->mnHeight );
+ else
+ xImage = pSalBmp->CreateCroppedImage( 0, 0, pSalBmp->mnWidth, pSalBmp->mnHeight );
+ }
+ else if( aBmpEx.GetTransparentType() == TRANSPARENT_BITMAP )
+ {
+ Bitmap aMask( aBmpEx.GetMask() );
+ IosSalBitmap* pMaskBmp = static_cast<IosSalBitmap*>(aMask.ImplGetImpBitmap()->ImplGetSalBitmap());
+ if( pMaskBmp )
+ xImage = pSalBmp->CreateWithMask( *pMaskBmp, 0, 0, pSalBmp->mnWidth, pSalBmp->mnHeight );
+ else
+ xImage = pSalBmp->CreateCroppedImage( 0, 0, pSalBmp->mnWidth, pSalBmp->mnHeight );
+ }
+ else if( aBmpEx.GetTransparentType() == TRANSPARENT_COLOR )
+ {
+ Color aTransColor( aBmpEx.GetTransparentColor() );
+ SalColor nTransColor = MAKE_SALCOLOR( aTransColor.GetRed(), aTransColor.GetGreen(), aTransColor.GetBlue() );
+ xImage = pSalBmp->CreateColorMask( 0, 0, pSalBmp->mnWidth, pSalBmp->mnHeight, nTransColor );
+ }
+
+ return xImage;
+}
+
+UIImage* CreateNSImage( const Image& rImage )
+{
+ CGImageRef xImage = CreateCGImage( rImage );
+
+ if( ! xImage )
+ return nil;
+
+ Size aSize( rImage.GetSizePixel() );
+ UIImage* pImage = [[UIImage alloc] initWithCGImage: xImage];
+ CGImageRelease( xImage );
+
+ return pImage;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */