/*************************************************************************
 *
 *  $RCSfile: svapp.hxx,v $
 *
 *  $Revision: 1.27 $
 *
 *  last change: $Author: vg $ $Date: 2003/06/10 14:29:14 $
 *
 *  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
#ifndef _VCL_VCLEVENT_HXX
#include <vcl/vclevent.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;
class KeyEvent;

#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"
#define APPEVENT_SAVEDOCUMENTS_STRING	"SaveDocuments"

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 ),
    aEvent( rEvent ),
    aData( rData ),
    aAppAddr( rAppAddr )
{
}

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 void                 AddEventListener( const Link& rEventListener );
    static void                 RemoveEventListener( const Link& rEventListener );
    static void                 AddKeyListener( const Link& rKeyListener );
    static void                 RemoveKeyListener( const Link& rKeyListener );
    static void                 ImplCallEventListeners( ULONG nEvent, Window* pWin, void* pData );
    static void                 ImplCallEventListeners( VclWindowEvent* pEvent );
    static BOOL                 HandleKey( ULONG nEvent, Window *pWin, KeyEvent* pKeyEvent );
    static void                 PostKeyEvent( ULONG nEvent, Window *pWin, KeyEvent* pKeyEvent );

    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 long                 GetTopWindowCount();
    static Window*              GetTopWindow( long nIndex );
    static Window*              GetActiveTopWindow();

    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 ULONG                GetReservedKeyCodeCount();
    static const KeyCode*       GetReservedKeyCode( ULONG i );
    static String               GetReservedKeyCodeDescription( ULONG i );

    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 - NEW!
    static BOOL                 IsAccessibilityEnabled();

    // Accessibility - OLD!
    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();

    // IME Status Window Control:

    /** Return true if any IME status window can be toggled on and off
        externally.

        Must only be called with the Solar mutex locked.
     */
    static bool CanToggleImeStatusWindow();

    /** Toggle any IME status window on and off.

        This only works if CanToggleImeStatusWinodw returns true (otherwise,
        any calls of this method are ignored).

        Must only be called with the Solar mutex locked.
     */
    static void ShowImeStatusWindow(bool bShow);

    /** Return true if any IME status window should be turned on by default
        (this decision can be locale dependent, for example).

        Can be called without the Solar mutex locked.
     */
    static bool GetShowImeStatusWindowDefault();
};

Application* GetpApp();

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

BOOL InitAccessBridge( BOOL bAllowCancel, BOOL &rCancelled );

// 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
