/*************************************************************************
 *
 *  $RCSfile: svapp.hxx,v $
 *
 *  $Revision: 1.15 $
 *
 *  last change: $Author: mh $ $Date: 2001/10/18 12:05:30 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library 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 for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _SV_SVAPP_HXX
#define _SV_SVAPP_HXX

#ifndef _VOS_THREAD_HXX
#include <vos/thread.hxx>
#endif
#ifndef _STRING_HXX
#include <tools/string.hxx>
#endif
#ifndef _LINK_HXX
#include <tools/link.hxx>
#endif
#ifndef _UNQID_HXX
#include <tools/unqid.hxx>
#endif
#ifndef _RTTI_HXX
#include <tools/rtti.hxx>
#endif
#ifndef _SV_SV_H
#include <vcl/sv.h>
#endif
#ifndef _VCL_APPTYPES_HXX
#include <vcl/apptypes.hxx>
#endif
#ifndef _VCL_SETTINGS_HXX
#include <vcl/settings.hxx>
#endif

class Link;
class International;
class AllSettings;
class DataChangedEvent;
class Accelerator;
class Help;
class OutputDevice;
class Window;
class WorkWindow;
class MenuBar;
class UnoWrapperBase;
class AccessNotification;
class Reflection;
class KeyCode;
class NotifyEvent;

#ifndef NOOLDSV
class Font;
class ApplicationAddress;
class ApplicationEvent;
#endif
namespace vos { class IMutex; }

#ifndef _COM_SUN_STAR_UNO_REFERENCE_H_
#include <com/sun/star/uno/Reference.h>
#endif
#ifndef _COM_SUN_STAR_CONNECTION_XCONNECTION_HPP_
#include <com/sun/star/connection/XConnection.hpp>
#endif

namespace com {
namespace sun {
namespace star {
namespace lang {
    class XMultiServiceFactory;
}
namespace awt {
    class XToolkit;
    class XDisplayConnection;
}
} } }

// ------------------
// - SystemInfoType -
// ------------------

typedef ULONG SystemInfoType;
#define SYSTEMINFO_SYSTEM_WINDOWS           ((SystemInfoType)0x00000001)
#define SYSTEMINFO_SYSTEM_OS2               ((SystemInfoType)0x00000002)
#define SYSTEMINFO_SYSTEM_MAC               ((SystemInfoType)0x00000003)
#define SYSTEMINFO_SYSTEM_UNIX              ((SystemInfoType)0x00000004)

#define SYSTEMINFO_SYSTEMBASE_LINUX         ((SystemInfoType)0x00000010)
#define SYSTEMINFO_SYSTEMBASE_SOLARIS       ((SystemInfoType)0x00000020)
#define SYSTEMINFO_SYSTEMBASE_SCO           ((SystemInfoType)0x00000030)
#define SYSTEMINFO_SYSTEMBASE_NETBSD        ((SystemInfoType)0x00000040)
#define SYSTEMINFO_SYSTEMBASE_AIX           ((SystemInfoType)0x00000050)
#define SYSTEMINFO_SYSTEMBASE_IRIX          ((SystemInfoType)0x00000060)
#define SYSTEMINFO_SYSTEMBASE_HPUX          ((SystemInfoType)0x00000070)
#define SYSTEMINFO_SYSTEMBASE_FREEBSD       ((SystemInfoType)0x00000080)
#define SYSTEMINFO_SYSTEMBASE_NT            ((SystemInfoType)0x00000090)
#define SYSTEMINFO_SYSTEMBASE_DOS           ((SystemInfoType)0x000000A0)
#define SYSTEMINFO_SYSTEMBASE_MACOSX        ((SystemInfoType)0x000000B0)

#define SYSTEMINFO_INFO_JAVA                ((SystemInfoType)0x02000000)

#define SYSTEMINFO_TYPE_SYSTEM              ((SystemInfoType)0x0000000F)
#define SYSTEMINFO_TYPE_SYSTEMBASE          ((SystemInfoType)0x000000F0)
#define SYSTEMINFO_TYPE_INFO                ((SystemInfoType)0xFF000000)

// --------------------
// - SystemWindowMode -
// --------------------

#define SYSTEMWINDOW_MODE_NOAUTOMODE    ((USHORT)0x0001)
#define SYSTEMWINDOW_MODE_DIALOG        ((USHORT)0x0002)

// -------------
// - EventHook -
// -------------

typedef long (*VCLEventHookProc)( NotifyEvent& rEvt, void* pData );

// --------------------
// - ApplicationEvent -
// --------------------

// Erstmal wieder eingebaut, damit AppEvents auf dem MAC funktionieren
#ifdef UNX
// enum Doppelt in daemon.cxx unter unix Achtung !!!
enum Service { SERVICE_OLE, SERVICE_APPEVENT, SERVICE_IPC };
#endif

class ApplicationAddress
{
friend class Application;
protected:
    UniString           aHostName;
    UniString           aDisplayName;
    UniString           aDomainName;
    int                 nPID;

public:
                        ApplicationAddress();
                        ApplicationAddress( const UniString& rDomain );
                        ApplicationAddress( const UniString& rHost,
                                            const UniString& rDisp,
                                            const UniString& rDomain );
                        ApplicationAddress( const UniString& rHost, int nPID );

    const UniString&    GetHost() const     { return aHostName; }
    const UniString&    GetDisplay() const  { return aDisplayName; }
    const UniString&    GetDomain() const   { return aDomainName; }
    int                 GetPID() const      { return nPID; }

    BOOL                IsConnectToSame( const ApplicationAddress& rAdr ) const;
};

inline ApplicationAddress::ApplicationAddress()
{
    nPID = 0;
}

inline ApplicationAddress::ApplicationAddress( const UniString& rDomain )
{
    aDomainName     = rDomain;
    nPID            = 0;
}

inline ApplicationAddress::ApplicationAddress( const UniString& rHost,
                                               const UniString& rDisp,
                                               const UniString& rDomain )
{
    aHostName       = rHost;
    aDisplayName    = rDisp;
    aDomainName     = rDomain;
    nPID            = 0;
}

inline ApplicationAddress::ApplicationAddress( const UniString& rHost, int nPIDPar )
{
    aHostName       = rHost;
    nPID            = nPIDPar;
}

inline BOOL ApplicationAddress::IsConnectToSame( const ApplicationAddress& rAdr ) const
{
    if ( nPID && ((nPID == rAdr.nPID) && (aHostName.Equals( rAdr.aHostName))) )
        return TRUE;
    else
        return FALSE;
}

#define APPEVENT_PARAM_DELIMITER    '\n'

#define APPEVENT_OPEN_STRING        "Open"
#define APPEVENT_PRINT_STRING       "Print"
#define APPEVENT_DISKINSERT_STRING  "DiskInsert"

class ApplicationEvent
{
private:
    UniString           aSenderAppName; // Absender Applikationsname
    ByteString          aEvent;         // Event
    UniString           aData;          // Uebertragene Daten
    ApplicationAddress  aAppAddr;       // Absender Addresse

public:
                        ApplicationEvent() {}
                        ApplicationEvent( const UniString& rSenderAppName,
                                          const ApplicationAddress& rAppAddr,
                                          const ByteString& rEvent,
                                          const UniString& rData );

    const UniString&    GetSenderAppName() const { return aSenderAppName; }
    const ByteString&   GetEvent() const { return aEvent; }
    const UniString&    GetData() const { return aData; }
    const ApplicationAddress& GetAppAddress() const { return aAppAddr; }

    BOOL                IsOpenEvent() const;
    BOOL                IsPrintEvent() const;
    BOOL                IsDiskInsertEvent() const;

    USHORT              GetParamCount() const { return aData.GetTokenCount( APPEVENT_PARAM_DELIMITER ); }
    UniString           GetParam( USHORT nParam ) const { return aData.GetToken( nParam, APPEVENT_PARAM_DELIMITER ); }
};

inline ApplicationEvent::ApplicationEvent( const UniString& rSenderAppName,
                                           const ApplicationAddress& rAppAddr,
                                           const ByteString& rEvent,
                                           const UniString& rData ) :
    aSenderAppName( rSenderAppName ),
    aAppAddr( rAppAddr ),
    aEvent( rEvent ),
    aData( rData )
{
}

inline BOOL ApplicationEvent::IsOpenEvent() const
{
    if ( aEvent.Equals( APPEVENT_OPEN_STRING ))
        return TRUE;
    else
        return FALSE;
}

inline BOOL ApplicationEvent::IsPrintEvent() const
{
    if ( aEvent.Equals( APPEVENT_PRINT_STRING ))
        return TRUE;
    else
        return FALSE;
}

inline BOOL ApplicationEvent::IsDiskInsertEvent() const
{
    if ( aEvent.Equals( APPEVENT_DISKINSERT_STRING ))
        return TRUE;
    else
        return FALSE;
}

class PropertyHandler
{
public:
    virtual void                Property( ApplicationProperty& ) = 0;
};

// ---------------
// - Application -
// ---------------

class Application
{
public:
                                Application();
                                ~Application();

    virtual void                Main() = 0;

    virtual BOOL                QueryExit();

    virtual void                UserEvent( ULONG nEvent, void* pEventData );

    virtual void                ActivateExtHelp();
    virtual void                DeactivateExtHelp();

    virtual void                ShowStatusText( const XubString& rText );
    virtual void                HideStatusText();

    virtual void                ShowHelpStatusText( const XubString& rText );
    virtual void                HideHelpStatusText();

    virtual void                FocusChanged();
    virtual void                DataChanged( const DataChangedEvent& rDCEvt );

    virtual void                Init();
    virtual void                DeInit();

    static void                 InitAppRes( const ResId& rResId );

    static USHORT               GetCommandLineParamCount();
    static XubString            GetCommandLineParam( USHORT nParam );
    static const XubString&     GetAppFileName();

    virtual USHORT              Exception( USHORT nError );
    static void                 Abort( const XubString& rErrorText );

    static void                 Execute();
    static void                 Quit();
    static void                 Reschedule();
    static void                 Yield();
    static void                 EndYield();
    static vos::IMutex&                     GetSolarMutex();
    static vos::OThread::TThreadIdentifier  GetMainThreadIdentifier();
    static ULONG                ReleaseSolarMutex();
    static void                 AcquireSolarMutex( ULONG nCount );

    static BOOL                 IsInMain();
    static BOOL                 IsInExecute();
    static BOOL                 IsShutDown();
    static BOOL                 IsInModalMode();

    static USHORT               GetDispatchLevel();
    static BOOL                 AnyInput( USHORT nType = INPUT_ANY );
    static ULONG                GetLastInputInterval();
    static BOOL                 IsUICaptured();
    static BOOL                 IsUserActive( USHORT nTest = USERACTIVE_ALL );

    virtual void                SystemSettingsChanging( AllSettings& rSettings,
                                                        Window* pFrame );
    static void                 MergeSystemSettings( AllSettings& rSettings );

    static void                 SetSettings( const AllSettings& rSettings );
    static const AllSettings&   GetSettings();
    static void                 NotifyAllWindows( DataChangedEvent& rDCEvt );

    static ULONG                PostUserEvent( ULONG nEvent, void* pEventData = NULL );
    static ULONG                PostUserEvent( const Link& rLink, void* pCaller = NULL );
    static BOOL                 PostUserEvent( ULONG& rEventId, ULONG nEvent, void* pEventData = NULL );
    static BOOL                 PostUserEvent( ULONG& rEventId, const Link& rLink, void* pCaller = NULL );
    static void                 RemoveUserEvent( ULONG nUserEvent );

    static BOOL                 InsertIdleHdl( const Link& rLink, USHORT nPriority );
    static void                 RemoveIdleHdl( const Link& rLink );

    static USHORT               DispatchAppEvents( int nArgc, char* pArgv[] );
    static USHORT               DispatchAppEvents();
    virtual void                AppEvent( const ApplicationEvent& rAppEvent );

#ifndef NOOLDSV
    // Erstmal wieder drin, sollte aber evt. mal entfernt werden
    static BOOL                 PostAppEvent( const String& rAppName,
                                              const ApplicationAddress& rAppAddr,
                                              const String& rEventName,
                                              const String& rData,
                                              BOOL  bStartApp=TRUE,
                                              const String* pParameters=0 );
    static BOOL                 StartApplication( const String& rFileName,
                                                  const String& rParameters,
                                                  const String& rCreator,
                                                  ApplicationAddress* pAddr=0);
#endif
    virtual void                Property( ApplicationProperty& );
    void                        SetPropertyHandler( PropertyHandler* pHandler );

#ifndef NOOLDSV
    static void                 EnterWait();
    static void                 LeaveWait();
    static BOOL                 IsWait();
#endif

#ifndef NO_GETAPPWINDOW
    static WorkWindow*          GetAppWindow();
#endif
    static Window*              GetFocusWindow();
    static OutputDevice*        GetDefaultDevice();

    static Window*              GetFirstTopLevelWindow();
    static Window*              GetNextTopLevelWindow( Window* pWindow );

    static void                 SetAppName( const String& rUniqueName );
    static String               GetAppName();

    static void                 SetDisplayName( const UniString& rDisplayName );
    static UniString            GetDisplayName();

    static const International& GetAppInternational();

    static BOOL                 InsertAccel( Accelerator* pAccel );
    static void                 RemoveAccel( Accelerator* pAccel );
    static void                 FlushAccel();
    static BOOL                 CallAccel( const KeyCode& rKeyCode, USHORT nRepeat = 0 );

    static ULONG                AddHotKey( const KeyCode& rKeyCode, const Link& rLink, void* pData = NULL );
    static void                 RemoveHotKey( ULONG nId );
    static ULONG                AddEventHook( VCLEventHookProc pProc, void* pData = NULL );
    static void                 RemoveEventHook( ULONG nId );
    static long                 CallEventHooks( NotifyEvent& rEvt );
    static long                 CallPreNotify( NotifyEvent& rEvt );
    static long                 CallEvent( NotifyEvent& rEvt );

    static void                 SetHelp( Help* pHelp = NULL );
    static Help*                GetHelp();

    static void                 EnableAutoHelpId( BOOL bEnabled = TRUE );
    static BOOL                 IsAutoHelpIdEnabled();

    static void                 EnableAutoMnemonic( BOOL bEnabled = TRUE );
    static BOOL                 IsAutoMnemonicEnabled();

    static void                 SetDefDialogParent( Window* pWindow );
    static Window*              GetDefDialogParent();

    static void                 EnableDialogCancel( BOOL bDialogCancel = TRUE );
    static BOOL                 IsDialogCancelEnabled();

    static void                 SetSystemWindowMode( USHORT nMode );
    static USHORT               GetSystemWindowMode();

    static void                 SetDialogScaleX( short nScale );
    static short                GetDialogScaleX();

    static void                 SetResourcePath( const XubString& rPath );
    static const XubString&     GetResourcePath();

    static void                 SetFontPath( const String& rPath );
    static const String&        GetFontPath();

#ifndef NOOLDSV
    static BOOL                 IsMDIApp() { return FALSE; }
#endif

    static UniqueItemId         CreateUniqueId();

    static SystemInfoType       GetClientSystem();
    static SystemInfoType       GetServerSystem();
    static BOOL                 IsRemoteServer();
    static void*                GetRemoteEnvironment();

    static ::com::sun::star::uno::Reference< ::com::sun::star::awt::XDisplayConnection > GetDisplayConnection();
    // The global service manager has to be created before!
    static ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > GetUnoInstance(
        ::com::sun::star::uno::Reference< ::com::sun::star::connection::XConnection > rConnection,
        const rtl::OUString& );

    // Der globale Service-Manager muss vorher erzeugt sein!
    static ::com::sun::star::uno::Reference< ::com::sun::star::awt::XToolkit > GetVCLToolkit();
    static UnoWrapperBase*      GetUnoWrapper( BOOL bCreateIfNotExists = TRUE );
    static void                 SetUnoWrapper( UnoWrapperBase* pWrapper );

    static void                 SetFilterHdl( const Link& rLink );
    static const Link&          GetFilterHdl();

    // Accessibility
    static void                 AccessNotify( const AccessNotification& rNotification );
    static void                 AddAccessHdl( const Link& rLink );
    static void                 RemoveAccessHdl( const Link& rLink );
    static USHORT               GetAccessHdlCount();
    static Link                 GetFirstAccessHdl();
    static void                 CallNextAccessHdl( AccessNotification* pData );
    static BOOL                 GenerateAccessEvent( ULONG nAccessEvent,
                                                     long Data1 = 0L, long Data2 = 0L, long nData3 = 0L );
    static void                 EnableHeadlessMode( BOOL bEnable = TRUE );
    static BOOL                 IsHeadlessModeEnabled();
    void                        WaitForClientConnect();
};

Application* GetpApp();

BOOL InitVCL( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > & );
void DeInitVCL();

// only allowed to call, if no thread is running. You must call JoinMainLoopThread to free all memory.
void CreateMainLoopThread( oslWorkerFunction pWorker, void * pThreadData );
void JoinMainLoopThread();

inline void Application::EndYield()
{
    PostUserEvent( Link() );
}

#ifndef NOOLDSV
class AppSettings;
#define SETTINGS_CHANGE_FONTCOUNT     ((USHORT)0x0001)
#define SETTINGS_CHANGE_COLORS        ((USHORT)0x0002)
#define SETTINGS_CHANGE_SYSCOLORS     ((USHORT)0x0004)
#define SETTINGS_CHANGE_PRINTER       ((USHORT)0x0008)
#define SETTINGS_CHANGE_APP           ((USHORT)0x4000)
#define SETTINGS_CHANGE_OTHER         ((USHORT)0x8000)

inline BOOL Application::PostAppEvent( const String&, const ApplicationAddress&,
                                       const String&, const String&, BOOL,
                                       const String* ) { return FALSE; }

#define SetDefModalDialogParent         SetDefDialogParent
#define GetDefModalDialogParent         GetDefDialogParent

#endif

#endif // _APP_HXX
