<commit_before>/*************************************************************************
 *
 *  $RCSfile: salplug.cxx,v $
 *
 *  $Revision: 1.8 $
 *
 *  last change: $Author: hr $ $Date: 2004-05-17 13:45:37 $
 *
 *  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 OSL_MODULE_H
#include <osl/module.h>
#endif
#ifndef OSL_PROCESS_H
#include <osl/process.h>
#endif
#ifndef RTL_STRING_HXX
#include <rtl/ustrbuf.hxx>
#endif

#include <svunx.h>
#include <prex.h>
#include <X11/Xatom.h>
#include <postx.h>

#include <salinst.hxx>
#include <saldata.hxx>

#include <cstdio>
#include <unistd.h>
#include <dlfcn.h>

using namespace rtl;

typedef SalInstance*(*salFactoryProc)( oslModule pModule);

static oslModule pCloseModule = NULL;

#define DESKTOP_NONE 0
#define DESKTOP_UNKNOWN 1
#define DESKTOP_GNOME 2
#define DESKTOP_KDE 3
#define DESKTOP_CDE 4

static const char * desktop_strings[5] = { "none", "unknown", "GNOME", "KDE", "CDE" };

// NETBSD has no RTLD_GLOBAL
#ifndef RTLD_GLOBAL
#define DLOPEN_MODE (RTLD_LAZY)
#else
#define DLOPEN_MODE (RTLD_GLOBAL | RTLD_LAZY)
#endif

static SalInstance* tryInstance( const OUString& rModuleBase )
{
    SalInstance* pInst = NULL;

    OUStringBuffer aModName( 128 );
    aModName.appendAscii( SAL_DLLPREFIX"vclplug_" );
    aModName.append( rModuleBase );
    aModName.append( (sal_Int32)SUPD );
    aModName.appendAscii( SAL_DLLPOSTFIX );
    aModName.appendAscii( SAL_DLLEXTENSION );
    OUString aModule = aModName.makeStringAndClear();

    oslModule aMod = osl_loadModule( aModule.pData, SAL_LOADMODULE_DEFAULT );
    if( aMod )
    {
        OUString aSym( RTL_CONSTASCII_USTRINGPARAM( "create_SalInstance" ) );
        salFactoryProc aProc = (salFactoryProc)osl_getSymbol( aMod, aSym.pData );
        if( aProc )
        {
            pInst = aProc( aMod );
#if OSL_DEBUG_LEVEL > 1
            fprintf( stderr, "sal plugin %s produced instance %p\n",
                     OUStringToOString( aModule, RTL_TEXTENCODING_ASCII_US ).getStr(),
                     pInst );
#endif
            pCloseModule = aMod;
        }
        else
        {
#if OSL_DEBUG_LEVEL > 1
            fprintf( stderr, "could not load symbol %s from shared object %s\n",
                     OUStringToOString( aSym, RTL_TEXTENCODING_ASCII_US ).getStr(),
                     OUStringToOString( aModule, RTL_TEXTENCODING_ASCII_US ).getStr() );
#endif
            osl_unloadModule( aMod );
        }
    }
#if OSL_DEBUG_LEVEL > 1
    else
        fprintf( stderr, "could not load shared object %s\n",
                 OUStringToOString( aModule, RTL_TEXTENCODING_ASCII_US ).getStr() );
#endif

    return pInst;
}

static bool is_gnome_desktop( Display* pDisplay )
{
    bool ret = false;

    // warning: this check is coincidental, GNOME does not
    // explicitly advertise itself
    Atom nAtom1 = XInternAtom( pDisplay, "GNOME_SM_PROXY", True );
    Atom nAtom2 = XInternAtom( pDisplay, "NAUTILUS_DESKTOP_WINDOW_ID", True );
    if( nAtom1 || nAtom2 )
    {
        int nProperties = 0;
        Atom* pProperties = XListProperties( pDisplay, DefaultRootWindow( pDisplay ), &nProperties );
        if( pProperties && nProperties )
        {
            for( int i = 0; i < nProperties; i++ )
                if( pProperties[ i ] == nAtom1 ||
                    pProperties[ i ] == nAtom2 )
                {
                    ret = true;
                }
            XFree( pProperties );
        }
    }
    if( ! ret )
    {
        Atom nUTFAtom       = XInternAtom( pDisplay, "UTF8_STRING", True );
        Atom nNetWMNameAtom = XInternAtom( pDisplay, "_NET_WM_NAME", True );
        if( nUTFAtom && nNetWMNameAtom )
        {
            // another, more expensive check: search for a gnome-panel
            XLIB_Window aRoot, aParent, *pChildren = NULL;
            unsigned int nChildren = 0;
            XQueryTree( pDisplay, DefaultRootWindow( pDisplay ),
                        &aRoot, &aParent, &pChildren, &nChildren );
            if( pChildren && nChildren )
            {
                for( unsigned int i = 0; i < nChildren && ! ret; i++ )
                {
                    Atom nType = None;
                    int nFormat = 0;
                    unsigned long nItems = 0, nBytes = 0;
                    unsigned char* pProp = NULL;
                    XGetWindowProperty( pDisplay,
                                        pChildren[i],
                                        nNetWMNameAtom,
                                        0, 8,
                                        False,
                                        nUTFAtom,
                                        &nType,
                                        &nFormat,
                                        &nItems,
                                        &nBytes,
                                        &pProp );
                    if( pProp && nType == nUTFAtom )
                    {
                        OString aWMName( (sal_Char*)pProp );
                        if( aWMName.equalsIgnoreAsciiCase( "gnome-panel" ) )
                            ret = true;
                    }
                    if( pProp )
                        XFree( pProp );
                }
                XFree( pChildren );
            }
        }
    }

    return ret;
}

static bool bWasXError = false;

static inline bool WasXError()
{
    bool bRet = bWasXError;
    bWasXError = false;
    return bRet;
}

extern "C"
{
    static int autodect_error_handler( Display*, XErrorEvent* )
    {
        bWasXError = true;
        return 0;
    }

    typedef int(* XErrorHandler)(Display*,XErrorEvent*);
}

static OUString getNetWMName( Display* pDisplay )
{
    OUString aRet;

    Atom nWmCheck   = XInternAtom( pDisplay, "_NET_SUPPORTING_WM_CHECK", True );
    Atom nWmName    = XInternAtom( pDisplay, "_NET_WM_NAME", True );
    if( nWmName && nWmCheck )
    {
        XLIB_Window         aCheckWin   = None;
        Atom                aRealType   = None;
        int                 nFormat     = 8;
        unsigned long       nItems      = 0;
        unsigned long       nBytesLeft  = 0;
        unsigned char*  pProperty   = NULL;
        XGetWindowProperty( pDisplay,
                            DefaultRootWindow( pDisplay ),
                            nWmCheck,
                            0, 1,
                            False,
                            XA_WINDOW,
                            &aRealType,
                            &nFormat,
                            &nItems,
                            &nBytesLeft,
                            &pProperty );
        if( aRealType == XA_WINDOW && nFormat == 32 && nItems != 0 )
            aCheckWin = *(XLIB_Window*)pProperty;
        if( pProperty )
        {
            XFree( pProperty );
            pProperty = NULL;
        }

        // see if that window really exists and has the check property set
        if( aCheckWin != None )
        {
            // clear error flag
            WasXError();
            // get the property
            XGetWindowProperty( pDisplay,
                                aCheckWin,
                                nWmCheck,
                                0, 1,
                                False,
                                XA_WINDOW,
                                &aRealType,
                                &nFormat,
                                &nItems,
                                &nBytesLeft,
                                &pProperty );
            if( ! WasXError() && aRealType == XA_WINDOW && nFormat == 32 && nItems != 0 && pProperty )
            {
                if( aCheckWin == *(XLIB_Window*)pProperty )
                {
                    XFree( pProperty );
                    pProperty = NULL;
                    XGetWindowProperty( pDisplay,
                                        aCheckWin,
                                        nWmName,
                                        0, 256,
                                        False,
                                        AnyPropertyType,
                                        &aRealType,
                                        &nFormat,
                                        &nItems,
                                        &nBytesLeft,
                                        &pProperty );
                    if( !WasXError() && nItems != 0 && pProperty && *pProperty )
                    {
                        if( aRealType == XA_STRING ) // some WM's use this although the should use UTF8_STRING
                        {
                            aRet = rtl::OStringToOUString( rtl::OString( (sal_Char*)pProperty ), RTL_TEXTENCODING_ISO_8859_1 );
                        }
                        else
                            aRet = rtl::OStringToOUString( rtl::OString( (sal_Char*)pProperty ), RTL_TEXTENCODING_UTF8 );
                    }
                }
            }
            if( pProperty )
            {
                XFree( pProperty );
                pProperty = NULL;
            }
        }
    }
    return aRet;
}

static bool is_kde_desktop( Display* pDisplay )
{
    // check for kwin
    rtl::OUString aWM = getNetWMName( pDisplay );
    if( aWM.equalsIgnoreAsciiCaseAscii( "KWin" ) )
        return true;

    return false;
}

static bool is_cde_desktop( Display* pDisplay )
{
    void* pLibrary = NULL;

    Atom nDtAtom = XInternAtom( pDisplay, "_DT_WM_READY", True );
    if( nDtAtom && ( pLibrary = dlopen( "/usr/dt/lib/libDtSvc.so", DLOPEN_MODE ) ) )
    {
        dlclose( pLibrary );
        return true;
    }

    return false;
}

static const char * get_desktop_environment()
{
    static const char *pRet = NULL;

    if ( NULL == pRet )
    {
        // get display to connect to
        const char* pDisplayStr = getenv( "DISPLAY" );
        int nParams = osl_getCommandArgCount();
        OUString aParam;
        OString aBParm;
        for( int i = 0; i < nParams-1; i++ )
        {
            osl_getCommandArg( i, &aParam.pData );
            if( aParam.equalsAscii( "-display" ) || aParam.equalsAscii( "--display" ) )
            {
                osl_getCommandArg( i+1, &aParam.pData );
                aBParm = OUStringToOString( aParam, osl_getThreadTextEncoding() );
                pDisplayStr = aBParm.getStr();
                break;
            }
        }

        // no server at all
        if( ! pDisplayStr || !*pDisplayStr )
            pRet = desktop_strings[DESKTOP_NONE];
        else
        {
            Display* pDisplay = XOpenDisplay( pDisplayStr );
            if( pDisplay )
            {
                XErrorHandler pOldHdl = XSetErrorHandler( autodect_error_handler );

                if ( is_gnome_desktop( pDisplay ) )
                    pRet = desktop_strings[DESKTOP_GNOME];
                else if ( is_kde_desktop( pDisplay ) )
                    pRet = desktop_strings[DESKTOP_KDE];
                else if ( is_cde_desktop( pDisplay ) )
                    pRet = desktop_strings[DESKTOP_CDE];
                else
                    pRet = desktop_strings[DESKTOP_UNKNOWN];

                // set the default handler again
                XSetErrorHandler( pOldHdl );

                XCloseDisplay( pDisplay );
            }
        }
    }

    return pRet;
}

static const char* autodetect_plugin()
{
    const char * desktop = get_desktop_environment();
    const char * pRet = NULL;

    // no server at all: dummy plugin
    if ( desktop == desktop_strings[DESKTOP_NONE] )
        pRet = "dummy";
    else if ( desktop == desktop_strings[DESKTOP_GNOME] )
        pRet = "gtk";
    else if( desktop == desktop_strings[DESKTOP_KDE] )
        pRet = "kde";
    else
        pRet = "gen";

#if OSL_DEBUG_LEVEL > 1
    fprintf( stderr, "plugin autodetection: %s\n", pRet );
#endif

    return pRet;
}

SalInstance *CreateSalInstance()
{
    SalInstance*    pInst = NULL;

    static const char* pUsePlugin = getenv( "SAL_USE_VCLPLUGIN" );

    if( !(pUsePlugin && *pUsePlugin) )
        pUsePlugin = autodetect_plugin();

    if( pUsePlugin && *pUsePlugin )
        pInst = tryInstance( OUString::createFromAscii( pUsePlugin ) );

    // fallback to gen
    if( ! pInst )
        pInst = tryInstance( OUString( RTL_CONSTASCII_USTRINGPARAM( "gen" ) ) );

    if( ! pInst )
    {
        fprintf( stderr, "no suitable windowing system found, exiting.\n" );
        _exit( 1 );
    }

    // acquire SolarMutex
    pInst->AcquireYieldMutex( 1 );

    return pInst;
}

void DestroySalInstance( SalInstance *pInst )
{
    // release SolarMutex
    pInst->ReleaseYieldMutex();

    delete pInst;
    if( pCloseModule )
        osl_unloadModule( pCloseModule );
}

void InitSalData()
{
}

void DeInitSalData()
{
}

void InitSalMain()
{
}

void DeInitSalMain()
{
}

void SalAbort( const XubString& rErrorText )
{
    if( !rErrorText.Len() )
        fprintf( stderr, "Application Error" );
    else
        fprintf( stderr, ByteString( rErrorText, gsl_getSystemTextEncoding() ).GetBuffer() );
    abort();
}

const OUString& SalGetDesktopEnvironment()
{
    static OUString aRet = OStringToOUString(OString(get_desktop_environment()), RTL_TEXTENCODING_ASCII_US);
    return aRet;
}
<commit_msg>#i29781# gtk version: remove dlopen call (joined from CWS vcl23)<commit_after>/*************************************************************************
 *
 *  $RCSfile: salplug.cxx,v $
 *
 *  $Revision: 1.9 $
 *
 *  last change: $Author: rt $ $Date: 2004-06-02 14:55:50 $
 *
 *  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 OSL_MODULE_H
#include <osl/module.h>
#endif
#ifndef OSL_PROCESS_H
#include <osl/process.h>
#endif
#ifndef RTL_STRING_HXX
#include <rtl/ustrbuf.hxx>
#endif

#include <svunx.h>
#include <prex.h>
#include <X11/Xatom.h>
#include <postx.h>

#include <salinst.hxx>
#include <saldata.hxx>

#include <cstdio>
#include <unistd.h>

using namespace rtl;

typedef SalInstance*(*salFactoryProc)( oslModule pModule);

static oslModule pCloseModule = NULL;

#define DESKTOP_NONE 0
#define DESKTOP_UNKNOWN 1
#define DESKTOP_GNOME 2
#define DESKTOP_KDE 3
#define DESKTOP_CDE 4

static const char * desktop_strings[5] = { "none", "unknown", "GNOME", "KDE", "CDE" };

static SalInstance* tryInstance( const OUString& rModuleBase )
{
    SalInstance* pInst = NULL;

    OUStringBuffer aModName( 128 );
    aModName.appendAscii( SAL_DLLPREFIX"vclplug_" );
    aModName.append( rModuleBase );
    aModName.append( (sal_Int32)SUPD );
    aModName.appendAscii( SAL_DLLPOSTFIX );
    aModName.appendAscii( SAL_DLLEXTENSION );
    OUString aModule = aModName.makeStringAndClear();

    oslModule aMod = osl_loadModule( aModule.pData, SAL_LOADMODULE_DEFAULT );
    if( aMod )
    {
        OUString aSym( RTL_CONSTASCII_USTRINGPARAM( "create_SalInstance" ) );
        salFactoryProc aProc = (salFactoryProc)osl_getSymbol( aMod, aSym.pData );
        if( aProc )
        {
            pInst = aProc( aMod );
#if OSL_DEBUG_LEVEL > 1
            fprintf( stderr, "sal plugin %s produced instance %p\n",
                     OUStringToOString( aModule, RTL_TEXTENCODING_ASCII_US ).getStr(),
                     pInst );
#endif
            if( pInst )
                pCloseModule = aMod;
            else
                osl_unloadModule( aMod );
        }
        else
        {
#if OSL_DEBUG_LEVEL > 1
            fprintf( stderr, "could not load symbol %s from shared object %s\n",
                     OUStringToOString( aSym, RTL_TEXTENCODING_ASCII_US ).getStr(),
                     OUStringToOString( aModule, RTL_TEXTENCODING_ASCII_US ).getStr() );
#endif
            osl_unloadModule( aMod );
        }
    }
#if OSL_DEBUG_LEVEL > 1
    else
        fprintf( stderr, "could not load shared object %s\n",
                 OUStringToOString( aModule, RTL_TEXTENCODING_ASCII_US ).getStr() );
#endif

    return pInst;
}

static bool is_gnome_desktop( Display* pDisplay )
{
    bool ret = false;

    // warning: this check is coincidental, GNOME does not
    // explicitly advertise itself
    Atom nAtom1 = XInternAtom( pDisplay, "GNOME_SM_PROXY", True );
    Atom nAtom2 = XInternAtom( pDisplay, "NAUTILUS_DESKTOP_WINDOW_ID", True );
    if( nAtom1 || nAtom2 )
    {
        int nProperties = 0;
        Atom* pProperties = XListProperties( pDisplay, DefaultRootWindow( pDisplay ), &nProperties );
        if( pProperties && nProperties )
        {
            for( int i = 0; i < nProperties; i++ )
                if( pProperties[ i ] == nAtom1 ||
                    pProperties[ i ] == nAtom2 )
                {
                    ret = true;
                }
            XFree( pProperties );
        }
    }
    if( ! ret )
    {
        Atom nUTFAtom       = XInternAtom( pDisplay, "UTF8_STRING", True );
        Atom nNetWMNameAtom = XInternAtom( pDisplay, "_NET_WM_NAME", True );
        if( nUTFAtom && nNetWMNameAtom )
        {
            // another, more expensive check: search for a gnome-panel
            XLIB_Window aRoot, aParent, *pChildren = NULL;
            unsigned int nChildren = 0;
            XQueryTree( pDisplay, DefaultRootWindow( pDisplay ),
                        &aRoot, &aParent, &pChildren, &nChildren );
            if( pChildren && nChildren )
            {
                for( unsigned int i = 0; i < nChildren && ! ret; i++ )
                {
                    Atom nType = None;
                    int nFormat = 0;
                    unsigned long nItems = 0, nBytes = 0;
                    unsigned char* pProp = NULL;
                    XGetWindowProperty( pDisplay,
                                        pChildren[i],
                                        nNetWMNameAtom,
                                        0, 8,
                                        False,
                                        nUTFAtom,
                                        &nType,
                                        &nFormat,
                                        &nItems,
                                        &nBytes,
                                        &pProp );
                    if( pProp && nType == nUTFAtom )
                    {
                        OString aWMName( (sal_Char*)pProp );
                        if( aWMName.equalsIgnoreAsciiCase( "gnome-panel" ) )
                            ret = true;
                    }
                    if( pProp )
                        XFree( pProp );
                }
                XFree( pChildren );
            }
        }
    }

    return ret;
}

static bool bWasXError = false;

static inline bool WasXError()
{
    bool bRet = bWasXError;
    bWasXError = false;
    return bRet;
}

extern "C"
{
    static int autodect_error_handler( Display*, XErrorEvent* )
    {
        bWasXError = true;
        return 0;
    }

    typedef int(* XErrorHandler)(Display*,XErrorEvent*);
}

static OUString getNetWMName( Display* pDisplay )
{
    OUString aRet;

    Atom nWmCheck   = XInternAtom( pDisplay, "_NET_SUPPORTING_WM_CHECK", True );
    Atom nWmName    = XInternAtom( pDisplay, "_NET_WM_NAME", True );
    if( nWmName && nWmCheck )
    {
        XLIB_Window         aCheckWin   = None;
        Atom                aRealType   = None;
        int                 nFormat     = 8;
        unsigned long       nItems      = 0;
        unsigned long       nBytesLeft  = 0;
        unsigned char*  pProperty   = NULL;
        XGetWindowProperty( pDisplay,
                            DefaultRootWindow( pDisplay ),
                            nWmCheck,
                            0, 1,
                            False,
                            XA_WINDOW,
                            &aRealType,
                            &nFormat,
                            &nItems,
                            &nBytesLeft,
                            &pProperty );
        if( aRealType == XA_WINDOW && nFormat == 32 && nItems != 0 )
            aCheckWin = *(XLIB_Window*)pProperty;
        if( pProperty )
        {
            XFree( pProperty );
            pProperty = NULL;
        }

        // see if that window really exists and has the check property set
        if( aCheckWin != None )
        {
            // clear error flag
            WasXError();
            // get the property
            XGetWindowProperty( pDisplay,
                                aCheckWin,
                                nWmCheck,
                                0, 1,
                                False,
                                XA_WINDOW,
                                &aRealType,
                                &nFormat,
                                &nItems,
                                &nBytesLeft,
                                &pProperty );
            if( ! WasXError() && aRealType == XA_WINDOW && nFormat == 32 && nItems != 0 && pProperty )
            {
                if( aCheckWin == *(XLIB_Window*)pProperty )
                {
                    XFree( pProperty );
                    pProperty = NULL;
                    XGetWindowProperty( pDisplay,
                                        aCheckWin,
                                        nWmName,
                                        0, 256,
                                        False,
                                        AnyPropertyType,
                                        &aRealType,
                                        &nFormat,
                                        &nItems,
                                        &nBytesLeft,
                                        &pProperty );
                    if( !WasXError() && nItems != 0 && pProperty && *pProperty )
                    {
                        if( aRealType == XA_STRING ) // some WM's use this although the should use UTF8_STRING
                        {
                            aRet = rtl::OStringToOUString( rtl::OString( (sal_Char*)pProperty ), RTL_TEXTENCODING_ISO_8859_1 );
                        }
                        else
                            aRet = rtl::OStringToOUString( rtl::OString( (sal_Char*)pProperty ), RTL_TEXTENCODING_UTF8 );
                    }
                }
            }
            if( pProperty )
            {
                XFree( pProperty );
                pProperty = NULL;
            }
        }
    }
    return aRet;
}

static bool is_kde_desktop( Display* pDisplay )
{
    // check for kwin
    rtl::OUString aWM = getNetWMName( pDisplay );
    if( aWM.equalsIgnoreAsciiCaseAscii( "KWin" ) )
        return true;

    return false;
}

static bool is_cde_desktop( Display* pDisplay )
{
    void* pLibrary = NULL;

    Atom nDtAtom = XInternAtom( pDisplay, "_DT_WM_READY", True );
    OUString aPathName( RTL_CONSTASCII_USTRINGPARAM( "file:///usr/dt/lib/libDtSvc.so" ) );
    if( nDtAtom && ( pLibrary = osl_loadModule( aPathName.pData, SAL_LOADMODULE_DEFAULT ) ) )
    {
        osl_unloadModule( pLibrary );
        return true;
    }

    return false;
}

static const char * get_desktop_environment()
{
    static const char *pRet = NULL;

    if ( NULL == pRet )
    {
        // get display to connect to
        const char* pDisplayStr = getenv( "DISPLAY" );
        int nParams = osl_getCommandArgCount();
        OUString aParam;
        OString aBParm;
        for( int i = 0; i < nParams-1; i++ )
        {
            osl_getCommandArg( i, &aParam.pData );
            if( aParam.equalsAscii( "-display" ) || aParam.equalsAscii( "--display" ) )
            {
                osl_getCommandArg( i+1, &aParam.pData );
                aBParm = OUStringToOString( aParam, osl_getThreadTextEncoding() );
                pDisplayStr = aBParm.getStr();
                break;
            }
        }

        // no server at all
        if( ! pDisplayStr || !*pDisplayStr )
            pRet = desktop_strings[DESKTOP_NONE];
        else
        {
            Display* pDisplay = XOpenDisplay( pDisplayStr );
            if( pDisplay )
            {
                XErrorHandler pOldHdl = XSetErrorHandler( autodect_error_handler );

                if ( is_gnome_desktop( pDisplay ) )
                    pRet = desktop_strings[DESKTOP_GNOME];
                else if ( is_kde_desktop( pDisplay ) )
                    pRet = desktop_strings[DESKTOP_KDE];
                else if ( is_cde_desktop( pDisplay ) )
                    pRet = desktop_strings[DESKTOP_CDE];
                else
                    pRet = desktop_strings[DESKTOP_UNKNOWN];

                // set the default handler again
                XSetErrorHandler( pOldHdl );

                XCloseDisplay( pDisplay );
            }
        }
    }

    return pRet;
}

static const char* autodetect_plugin()
{
    const char * desktop = get_desktop_environment();
    const char * pRet = NULL;

    // no server at all: dummy plugin
    if ( desktop == desktop_strings[DESKTOP_NONE] )
        pRet = "dummy";
    else if ( desktop == desktop_strings[DESKTOP_GNOME] )
        pRet = "gtk";
    else if( desktop == desktop_strings[DESKTOP_KDE] )
        pRet = "kde";
    else
        pRet = "gen";

#if OSL_DEBUG_LEVEL > 1
    fprintf( stderr, "plugin autodetection: %s\n", pRet );
#endif

    return pRet;
}

SalInstance *CreateSalInstance()
{
    SalInstance*    pInst = NULL;

    static const char* pUsePlugin = getenv( "SAL_USE_VCLPLUGIN" );

    if( !(pUsePlugin && *pUsePlugin) )
        pUsePlugin = autodetect_plugin();

    if( pUsePlugin && *pUsePlugin )
        pInst = tryInstance( OUString::createFromAscii( pUsePlugin ) );

    // fallback to gen
    if( ! pInst )
        pInst = tryInstance( OUString( RTL_CONSTASCII_USTRINGPARAM( "gen" ) ) );

    if( ! pInst )
    {
        fprintf( stderr, "no suitable windowing system found, exiting.\n" );
        _exit( 1 );
    }

    // acquire SolarMutex
    pInst->AcquireYieldMutex( 1 );

    return pInst;
}

void DestroySalInstance( SalInstance *pInst )
{
    // release SolarMutex
    pInst->ReleaseYieldMutex();

    delete pInst;
    if( pCloseModule )
        osl_unloadModule( pCloseModule );
}

void InitSalData()
{
}

void DeInitSalData()
{
}

void InitSalMain()
{
}

void DeInitSalMain()
{
}

void SalAbort( const XubString& rErrorText )
{
    if( !rErrorText.Len() )
        fprintf( stderr, "Application Error" );
    else
        fprintf( stderr, ByteString( rErrorText, gsl_getSystemTextEncoding() ).GetBuffer() );
    abort();
}

const OUString& SalGetDesktopEnvironment()
{
    static OUString aRet = OStringToOUString(OString(get_desktop_environment()), RTL_TEXTENCODING_ASCII_US);
    return aRet;
}
<|endoftext|>


<commit_before><commit_msg>Resolves: #i119458# fix master's subtitle is modified when save .pot template<commit_after><|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: LayerTabBar.cxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: ihi $ $Date: 2006-11-14 14:25:34 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 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
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sd.hxx"

#include "LayerTabBar.hxx"

#ifndef _SVDLAYER_HXX
#include <svx/svdlayer.hxx>
#endif
#ifndef _SVDPAGV_HXX //autogen
#include <svx/svdpagv.hxx>
#endif
#ifndef _SV_MSGBOX_HXX //autogen
#include <vcl/msgbox.hxx>
#endif
#ifndef _SFXDISPATCH_HXX //autogen
#include <sfx2/dispatch.hxx>
#endif

#include "sdattr.hxx"
#include "app.hxx"
#include "helpids.h"
#include "app.hrc"
#include "glob.hrc"
#include "strings.hrc"
#include "res_bmp.hrc"
#ifndef SD_DRAW_VIEW_SHELL_HXX
#include "DrawViewShell.hxx"
#endif
#ifndef SD_WINDOW_HXX
#include "Window.hxx"
#endif
#ifndef SD_VIEW_HXX
#include "View.hxx"
#endif
#include "drawdoc.hxx"
#include "sdresid.hxx"
#include "DrawDocShell.hxx"
#ifndef SD_DRAW_VIEW_HXX
#include "drawview.hxx"
#endif
#include "undolayer.hxx"

namespace sd {

#define SWITCH_TIMEOUT  20

/*************************************************************************
|*
|* Standard-Konstruktor
|*
\************************************************************************/

LayerTabBar::LayerTabBar(DrawViewShell* pViewSh, Window* pParent)
    : TabBar( pParent, WinBits( WB_BORDER | WB_3DLOOK | WB_SCROLL | WB_SIZEABLE ) ),
    DropTargetHelper( this ),
    pDrViewSh(pViewSh)
{
    EnableEditMode();
    SetSizePixel(Size(0, 0));
    SetMaxPageWidth( 150 );
    SetHelpId( HID_SD_TABBAR_LAYERS );
}

LayerTabBar::LayerTabBar (
    DrawViewShell* pViewSh,
    Window* pParent,
    const ResId& rResId)
    : TabBar (pParent, rResId.aWinBits),
    DropTargetHelper( this ),
    pDrViewSh(pViewSh)
{
    EnableEditMode();
}

/*************************************************************************
|*
|* Destruktor
|*
\************************************************************************/

LayerTabBar::~LayerTabBar()
{
}

/*************************************************************************
|*
\************************************************************************/

void LayerTabBar::Select()
{
    SfxDispatcher* pDispatcher = pDrViewSh->GetViewFrame()->GetDispatcher();
    pDispatcher->Execute(SID_SWITCHLAYER, SFX_CALLMODE_ASYNCHRON);
}

/*************************************************************************
|*
\************************************************************************/

void LayerTabBar::MouseButtonDown(const MouseEvent& rMEvt)
{
    BOOL bSetPageID=FALSE;

    if (rMEvt.IsLeft() && !rMEvt.IsMod1() && !rMEvt.IsMod2())
    {
        Point aPosPixel = rMEvt.GetPosPixel();
        USHORT aLayerId = GetPageId( PixelToLogic(aPosPixel) );

        if (aLayerId == 0)
        {
            SfxDispatcher* pDispatcher = pDrViewSh->GetViewFrame()->GetDispatcher();
            pDispatcher->Execute(SID_INSERTLAYER, SFX_CALLMODE_SYNCHRON);

            bSetPageID=TRUE;
        }
        else if (rMEvt.IsShift())
        {
            // Toggle zw. Layer sichtbar / unsichtbar
            String aName(GetPageText(aLayerId));
            SdrPageView* pPV = pDrViewSh->GetView()->GetSdrPageView();
            BOOL bVisible = pPV->IsLayerVisible(aName);
            pPV->SetLayerVisible(aName, !bVisible);
            pDrViewSh->ResetActualLayer();
        }
    }

    // If you insert a new layer you must not call TabBar::MouseButtonDown(rMEvt);
    // because you want to activate the new layer
    if( !bSetPageID )
        TabBar::MouseButtonDown(rMEvt);
}

/*************************************************************************
|*
\************************************************************************/

void LayerTabBar::DoubleClick()
{
    if (GetCurPageId() != 0)
    {
        SfxDispatcher* pDispatcher = pDrViewSh->GetViewFrame()->GetDispatcher();
        pDispatcher->Execute( SID_MODIFYLAYER, SFX_CALLMODE_SYNCHRON );
    }
}

/*************************************************************************
|*
|* AcceptDrop-Event
|*
\************************************************************************/

sal_Int8 LayerTabBar::AcceptDrop( const AcceptDropEvent& rEvt )
{
    sal_Int8 nRet = DND_ACTION_NONE;

    if( rEvt.mbLeaving )
        EndSwitchPage();

    if( !pDrViewSh->GetDocSh()->IsReadOnly() )
    {
        USHORT          nPageId = SDRPAGE_NOTFOUND;
        Point           aPos( PixelToLogic( rEvt.maPosPixel ) );
        USHORT          nLayerId = pDrViewSh->GetView()->GetDoc()->GetLayerAdmin().GetLayerID( GetPageText( GetPageId( aPos ) ), FALSE );

        nRet = pDrViewSh->AcceptDrop( rEvt, *this, NULL, nPageId, nLayerId );

        SwitchPage( aPos );
    }

    return nRet;
}

/*************************************************************************
|*
|* ExecuteDrop-Event
|*
\************************************************************************/

sal_Int8 LayerTabBar::ExecuteDrop( const ExecuteDropEvent& rEvt )
{
    USHORT          nPageId = SDRPAGE_NOTFOUND;
    USHORT          nLayerId = pDrViewSh->GetView()->GetDoc()->GetLayerAdmin().GetLayerID( GetPageText( GetPageId( PixelToLogic( rEvt.maPosPixel ) ) ), FALSE );
    sal_Int8        nRet = pDrViewSh->ExecuteDrop( rEvt, *this, NULL, nPageId, nLayerId );

    EndSwitchPage();

    return nRet;

}

/*************************************************************************
|*
\************************************************************************/

void  LayerTabBar::Command(const CommandEvent& rCEvt)
{
    if ( rCEvt.GetCommand() == COMMAND_CONTEXTMENU )
    {
        SfxDispatcher* pDispatcher = pDrViewSh->GetViewFrame()->GetDispatcher();
        pDispatcher->ExecutePopup(SdResId(RID_LAYERTAB_POPUP));
    }
}

/*************************************************************************
|*
\************************************************************************/
long LayerTabBar::StartRenaming()
{
    BOOL bOK = TRUE;
    String aLayerName = GetPageText( GetEditPageId() );
    String aLayoutLayer ( SdResId(STR_LAYER_LAYOUT) );
    String aControlsLayer ( SdResId(STR_LAYER_CONTROLS) );
    String aMeasureLinesLayer ( SdResId(STR_LAYER_MEASURELINES) );
    String aBackgroundLayer( SdResId(STR_LAYER_BCKGRND) );
    String aBackgroundObjLayer( SdResId(STR_LAYER_BCKGRNDOBJ) );

    if ( aLayerName == aLayoutLayer       || aLayerName == aControlsLayer  ||
         aLayerName == aMeasureLinesLayer ||
         aLayerName == aBackgroundLayer   || aLayerName == aBackgroundObjLayer )
    {
        // Diese Namen duerfen nicht veraendert werden
        bOK = FALSE;
    }
    else
    {
        ::sd::View* pView = pDrViewSh->GetView();

        if ( pView->IsTextEdit() )
        {
            pView->SdrEndTextEdit();
        }
    }

    return(bOK);
}

/*************************************************************************
|*
\************************************************************************/

long LayerTabBar::AllowRenaming()
{
    BOOL bOK = TRUE;

    // Ueberpruefung auf schon vorhandene Namen
    ::sd::View* pView = pDrViewSh->GetView();
    SdDrawDocument* pDoc = pView->GetDoc();
    String aLayerName = pView->GetActiveLayer();
    SdrLayerAdmin& rLayerAdmin = pDoc->GetLayerAdmin();
    String aNewName( GetEditText() );

    if ( aNewName.Len() == 0 ||
        (rLayerAdmin.GetLayer( aNewName, FALSE ) && aLayerName != aNewName) )
    {
        // Name ist schon vorhanden
        WarningBox aWarningBox( &pDrViewSh->GetViewFrame()->GetWindow(), WinBits( WB_OK ),
                                String(SdResId( STR_WARN_NAME_DUPLICATE ) ) );
        aWarningBox.Execute();
        bOK = FALSE;
    }

    if (bOK)
    {
        String aLayoutLayer ( SdResId(STR_LAYER_LAYOUT) );
        String aControlsLayer ( SdResId(STR_LAYER_CONTROLS) );
        String aMeasureLinesLayer ( SdResId(STR_LAYER_MEASURELINES) );
        String aBackgroundLayer( SdResId(STR_LAYER_BCKGRND) );
        String aBackgroundObjLayer( SdResId(STR_LAYER_BCKGRNDOBJ) );

        if ( aNewName == aLayoutLayer       || aNewName == aControlsLayer  ||
             aNewName == aMeasureLinesLayer ||
             aNewName == aBackgroundLayer   || aNewName == aBackgroundObjLayer )
        {
            // Diese Namen duerfen nicht vergeben werden
            bOK = FALSE;
        }
    }

    return(bOK);
}

/*************************************************************************
|*
\************************************************************************/

void LayerTabBar::EndRenaming()
{
    if( !IsEditModeCanceled() )
    {
        ::sd::View* pView = pDrViewSh->GetView();
        DrawView* pDrView = PTR_CAST( DrawView, pView );

        SdDrawDocument* pDoc = pView->GetDoc();
        String aLayerName = pView->GetActiveLayer();
        SdrLayerAdmin& rLayerAdmin = pDoc->GetLayerAdmin();
        SdrLayer* pLayer = rLayerAdmin.GetLayer(aLayerName, FALSE);

        if (pLayer)
        {
            String aNewName( GetEditText() );

            DBG_ASSERT( pDrView, "Rename layer undo action is only working with a SdDrawView" );
            if( pDrView )
            {
                SfxUndoManager* pManager = pDoc->GetDocSh()->GetUndoManager();
                SdLayerModifyUndoAction* pAction = new SdLayerModifyUndoAction(
                    pDoc,
                    pLayer,
                    aLayerName,
                    pDrView->IsLayerVisible(aLayerName),
                    pDrView->IsLayerLocked(aLayerName),
                    pDrView->IsLayerPrintable(aLayerName),
                    aNewName,
                    pDrView->IsLayerVisible(aLayerName),
                    pDrView->IsLayerLocked(aLayerName),
                    pDrView->IsLayerPrintable(aLayerName)
                    );
                pManager->AddUndoAction( pAction );
            }

            // Zuerst View benachrichtigen, da innerhalb von SetName() schon
            // ResetActualLayer() gerufen wird und an der View der Layer dann
            // schon bekannt sein muss.
            pView->SetActiveLayer(aNewName);
            pLayer->SetName(aNewName);
            pDoc->SetChanged(TRUE);
        }
    }
}

/*************************************************************************
|*
\************************************************************************/

void LayerTabBar::ActivatePage()
{
    if ( /*IsInSwitching*/ 1 && pDrViewSh!=NULL)
    {

        SfxDispatcher* pDispatcher = pDrViewSh->GetViewFrame()->GetDispatcher();
        pDispatcher->Execute(SID_SWITCHLAYER, SFX_CALLMODE_ASYNCHRON);
    }
}

void LayerTabBar::SendActivatePageEvent (void)
{
    CallEventListeners (VCLEVENT_TABBAR_PAGEACTIVATED,
        reinterpret_cast<void*>(GetCurPageId()));
}

void LayerTabBar::SendDeactivatePageEvent (void)
{
    CallEventListeners (VCLEVENT_TABBAR_PAGEDEACTIVATED,
        reinterpret_cast<void*>(GetCurPageId()));
}

} // end of namespace sd
<commit_msg>INTEGRATION: CWS residcleanup (1.5.88); FILE MERGED 2007/03/04 10:26:08 pl 1.5.88.1: #i74635# ResId cleanup<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: LayerTabBar.cxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: rt $ $Date: 2007-04-26 08:36:45 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 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
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sd.hxx"

#include "LayerTabBar.hxx"

#ifndef _SVDLAYER_HXX
#include <svx/svdlayer.hxx>
#endif
#ifndef _SVDPAGV_HXX //autogen
#include <svx/svdpagv.hxx>
#endif
#ifndef _SV_MSGBOX_HXX //autogen
#include <vcl/msgbox.hxx>
#endif
#ifndef _SFXDISPATCH_HXX //autogen
#include <sfx2/dispatch.hxx>
#endif

#include "sdattr.hxx"
#include "app.hxx"
#include "helpids.h"
#include "app.hrc"
#include "glob.hrc"
#include "strings.hrc"
#include "res_bmp.hrc"
#ifndef SD_DRAW_VIEW_SHELL_HXX
#include "DrawViewShell.hxx"
#endif
#ifndef SD_WINDOW_HXX
#include "Window.hxx"
#endif
#ifndef SD_VIEW_HXX
#include "View.hxx"
#endif
#include "drawdoc.hxx"
#include "sdresid.hxx"
#include "DrawDocShell.hxx"
#ifndef SD_DRAW_VIEW_HXX
#include "drawview.hxx"
#endif
#include "undolayer.hxx"

namespace sd {

#define SWITCH_TIMEOUT  20

/*************************************************************************
|*
|* Standard-Konstruktor
|*
\************************************************************************/

LayerTabBar::LayerTabBar(DrawViewShell* pViewSh, Window* pParent)
    : TabBar( pParent, WinBits( WB_BORDER | WB_3DLOOK | WB_SCROLL | WB_SIZEABLE ) ),
    DropTargetHelper( this ),
    pDrViewSh(pViewSh)
{
    EnableEditMode();
    SetSizePixel(Size(0, 0));
    SetMaxPageWidth( 150 );
    SetHelpId( HID_SD_TABBAR_LAYERS );
}

LayerTabBar::LayerTabBar (
    DrawViewShell* pViewSh,
    Window* pParent,
    const ResId& rResId)
    : TabBar (pParent, rResId.GetWinBits()),
    DropTargetHelper( this ),
    pDrViewSh(pViewSh)
{
    EnableEditMode();
}

/*************************************************************************
|*
|* Destruktor
|*
\************************************************************************/

LayerTabBar::~LayerTabBar()
{
}

/*************************************************************************
|*
\************************************************************************/

void LayerTabBar::Select()
{
    SfxDispatcher* pDispatcher = pDrViewSh->GetViewFrame()->GetDispatcher();
    pDispatcher->Execute(SID_SWITCHLAYER, SFX_CALLMODE_ASYNCHRON);
}

/*************************************************************************
|*
\************************************************************************/

void LayerTabBar::MouseButtonDown(const MouseEvent& rMEvt)
{
    BOOL bSetPageID=FALSE;

    if (rMEvt.IsLeft() && !rMEvt.IsMod1() && !rMEvt.IsMod2())
    {
        Point aPosPixel = rMEvt.GetPosPixel();
        USHORT aLayerId = GetPageId( PixelToLogic(aPosPixel) );

        if (aLayerId == 0)
        {
            SfxDispatcher* pDispatcher = pDrViewSh->GetViewFrame()->GetDispatcher();
            pDispatcher->Execute(SID_INSERTLAYER, SFX_CALLMODE_SYNCHRON);

            bSetPageID=TRUE;
        }
        else if (rMEvt.IsShift())
        {
            // Toggle zw. Layer sichtbar / unsichtbar
            String aName(GetPageText(aLayerId));
            SdrPageView* pPV = pDrViewSh->GetView()->GetSdrPageView();
            BOOL bVisible = pPV->IsLayerVisible(aName);
            pPV->SetLayerVisible(aName, !bVisible);
            pDrViewSh->ResetActualLayer();
        }
    }

    // If you insert a new layer you must not call TabBar::MouseButtonDown(rMEvt);
    // because you want to activate the new layer
    if( !bSetPageID )
        TabBar::MouseButtonDown(rMEvt);
}

/*************************************************************************
|*
\************************************************************************/

void LayerTabBar::DoubleClick()
{
    if (GetCurPageId() != 0)
    {
        SfxDispatcher* pDispatcher = pDrViewSh->GetViewFrame()->GetDispatcher();
        pDispatcher->Execute( SID_MODIFYLAYER, SFX_CALLMODE_SYNCHRON );
    }
}

/*************************************************************************
|*
|* AcceptDrop-Event
|*
\************************************************************************/

sal_Int8 LayerTabBar::AcceptDrop( const AcceptDropEvent& rEvt )
{
    sal_Int8 nRet = DND_ACTION_NONE;

    if( rEvt.mbLeaving )
        EndSwitchPage();

    if( !pDrViewSh->GetDocSh()->IsReadOnly() )
    {
        USHORT          nPageId = SDRPAGE_NOTFOUND;
        Point           aPos( PixelToLogic( rEvt.maPosPixel ) );
        USHORT          nLayerId = pDrViewSh->GetView()->GetDoc()->GetLayerAdmin().GetLayerID( GetPageText( GetPageId( aPos ) ), FALSE );

        nRet = pDrViewSh->AcceptDrop( rEvt, *this, NULL, nPageId, nLayerId );

        SwitchPage( aPos );
    }

    return nRet;
}

/*************************************************************************
|*
|* ExecuteDrop-Event
|*
\************************************************************************/

sal_Int8 LayerTabBar::ExecuteDrop( const ExecuteDropEvent& rEvt )
{
    USHORT          nPageId = SDRPAGE_NOTFOUND;
    USHORT          nLayerId = pDrViewSh->GetView()->GetDoc()->GetLayerAdmin().GetLayerID( GetPageText( GetPageId( PixelToLogic( rEvt.maPosPixel ) ) ), FALSE );
    sal_Int8        nRet = pDrViewSh->ExecuteDrop( rEvt, *this, NULL, nPageId, nLayerId );

    EndSwitchPage();

    return nRet;

}

/*************************************************************************
|*
\************************************************************************/

void  LayerTabBar::Command(const CommandEvent& rCEvt)
{
    if ( rCEvt.GetCommand() == COMMAND_CONTEXTMENU )
    {
        SfxDispatcher* pDispatcher = pDrViewSh->GetViewFrame()->GetDispatcher();
        pDispatcher->ExecutePopup(SdResId(RID_LAYERTAB_POPUP));
    }
}

/*************************************************************************
|*
\************************************************************************/
long LayerTabBar::StartRenaming()
{
    BOOL bOK = TRUE;
    String aLayerName = GetPageText( GetEditPageId() );
    String aLayoutLayer ( SdResId(STR_LAYER_LAYOUT) );
    String aControlsLayer ( SdResId(STR_LAYER_CONTROLS) );
    String aMeasureLinesLayer ( SdResId(STR_LAYER_MEASURELINES) );
    String aBackgroundLayer( SdResId(STR_LAYER_BCKGRND) );
    String aBackgroundObjLayer( SdResId(STR_LAYER_BCKGRNDOBJ) );

    if ( aLayerName == aLayoutLayer       || aLayerName == aControlsLayer  ||
         aLayerName == aMeasureLinesLayer ||
         aLayerName == aBackgroundLayer   || aLayerName == aBackgroundObjLayer )
    {
        // Diese Namen duerfen nicht veraendert werden
        bOK = FALSE;
    }
    else
    {
        ::sd::View* pView = pDrViewSh->GetView();

        if ( pView->IsTextEdit() )
        {
            pView->SdrEndTextEdit();
        }
    }

    return(bOK);
}

/*************************************************************************
|*
\************************************************************************/

long LayerTabBar::AllowRenaming()
{
    BOOL bOK = TRUE;

    // Ueberpruefung auf schon vorhandene Namen
    ::sd::View* pView = pDrViewSh->GetView();
    SdDrawDocument* pDoc = pView->GetDoc();
    String aLayerName = pView->GetActiveLayer();
    SdrLayerAdmin& rLayerAdmin = pDoc->GetLayerAdmin();
    String aNewName( GetEditText() );

    if ( aNewName.Len() == 0 ||
        (rLayerAdmin.GetLayer( aNewName, FALSE ) && aLayerName != aNewName) )
    {
        // Name ist schon vorhanden
        WarningBox aWarningBox( &pDrViewSh->GetViewFrame()->GetWindow(), WinBits( WB_OK ),
                                String(SdResId( STR_WARN_NAME_DUPLICATE ) ) );
        aWarningBox.Execute();
        bOK = FALSE;
    }

    if (bOK)
    {
        String aLayoutLayer ( SdResId(STR_LAYER_LAYOUT) );
        String aControlsLayer ( SdResId(STR_LAYER_CONTROLS) );
        String aMeasureLinesLayer ( SdResId(STR_LAYER_MEASURELINES) );
        String aBackgroundLayer( SdResId(STR_LAYER_BCKGRND) );
        String aBackgroundObjLayer( SdResId(STR_LAYER_BCKGRNDOBJ) );

        if ( aNewName == aLayoutLayer       || aNewName == aControlsLayer  ||
             aNewName == aMeasureLinesLayer ||
             aNewName == aBackgroundLayer   || aNewName == aBackgroundObjLayer )
        {
            // Diese Namen duerfen nicht vergeben werden
            bOK = FALSE;
        }
    }

    return(bOK);
}

/*************************************************************************
|*
\************************************************************************/

void LayerTabBar::EndRenaming()
{
    if( !IsEditModeCanceled() )
    {
        ::sd::View* pView = pDrViewSh->GetView();
        DrawView* pDrView = PTR_CAST( DrawView, pView );

        SdDrawDocument* pDoc = pView->GetDoc();
        String aLayerName = pView->GetActiveLayer();
        SdrLayerAdmin& rLayerAdmin = pDoc->GetLayerAdmin();
        SdrLayer* pLayer = rLayerAdmin.GetLayer(aLayerName, FALSE);

        if (pLayer)
        {
            String aNewName( GetEditText() );

            DBG_ASSERT( pDrView, "Rename layer undo action is only working with a SdDrawView" );
            if( pDrView )
            {
                SfxUndoManager* pManager = pDoc->GetDocSh()->GetUndoManager();
                SdLayerModifyUndoAction* pAction = new SdLayerModifyUndoAction(
                    pDoc,
                    pLayer,
                    aLayerName,
                    pDrView->IsLayerVisible(aLayerName),
                    pDrView->IsLayerLocked(aLayerName),
                    pDrView->IsLayerPrintable(aLayerName),
                    aNewName,
                    pDrView->IsLayerVisible(aLayerName),
                    pDrView->IsLayerLocked(aLayerName),
                    pDrView->IsLayerPrintable(aLayerName)
                    );
                pManager->AddUndoAction( pAction );
            }

            // Zuerst View benachrichtigen, da innerhalb von SetName() schon
            // ResetActualLayer() gerufen wird und an der View der Layer dann
            // schon bekannt sein muss.
            pView->SetActiveLayer(aNewName);
            pLayer->SetName(aNewName);
            pDoc->SetChanged(TRUE);
        }
    }
}

/*************************************************************************
|*
\************************************************************************/

void LayerTabBar::ActivatePage()
{
    if ( /*IsInSwitching*/ 1 && pDrViewSh!=NULL)
    {

        SfxDispatcher* pDispatcher = pDrViewSh->GetViewFrame()->GetDispatcher();
        pDispatcher->Execute(SID_SWITCHLAYER, SFX_CALLMODE_ASYNCHRON);
    }
}

void LayerTabBar::SendActivatePageEvent (void)
{
    CallEventListeners (VCLEVENT_TABBAR_PAGEACTIVATED,
        reinterpret_cast<void*>(GetCurPageId()));
}

void LayerTabBar::SendDeactivatePageEvent (void)
{
    CallEventListeners (VCLEVENT_TABBAR_PAGEDEACTIVATED,
        reinterpret_cast<void*>(GetCurPageId()));
}

} // end of namespace sd
<|endoftext|>


<commit_before><commit_msg>LOKit: ensure DrawViewShell is available (prevent crash)<commit_after><|endoftext|>


<commit_before><commit_msg>coverity#1209611 Explicit null dereferenced<commit_after><|endoftext|>


<commit_before><commit_msg>tdf#91721: fix crash during listbox control editing in database form<commit_after><|endoftext|>


<commit_before>/***********************************************************************************************************************
**
** Copyright (c) 2011, 2015 ETH Zurich
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
** following conditions are met:
**
**    * Redistributions of source code must retain the above copyright notice, this list of conditions and the following
**      disclaimer.
**    * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
**      following disclaimer in the documentation and/or other materials provided with the distribution.
**    * Neither the name of the ETH Zurich nor the names of its contributors may be used to endorse or promote products
**      derived from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
** INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
** DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
** SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**
***********************************************************************************************************************/

#include "APIPrinter.h"

void APIPrinter::print()
{
	printHeaders();
	out_ << "namespace InformationScripting {" << endl << endl;
	out_ << "using namespace boost::python;" << endl << endl;
	out_ << "BOOST_PYTHON_MODULE(AstApi) {" << endl << endl;
	printClasses();
	printTypedListWrappers();
	out_ << endl << "}" << endl;
	out_ << endl << "} /* namespace InformationScripting */" << endl;
}

void APIPrinter::printHeaders()
{
	for (QString includePath : data_.includePaths_)
		out_ << "#include \"" << includePath << "\"" << endl;
	out_ << endl;
}

void APIPrinter::printClasses()
{
	for (const auto& cData : data_.classes()) printClass(cData);
}

void APIPrinter::printClass(const ClassData& cData)
{
	// each class gets it's own scope:
	out_ << "{" << endl;
	indent();
	QString classString;
	if (cData.enums_.size()) // We only need a scope variable if we have enums
		classString = QString("scope %1scope = ").arg(cData.className_);
	classString += "class_<" + cData.qualifiedName_;
	// print bases:
	if (cData.baseClasses_.size())
		classString += ", bases<" + cData.baseClasses_.join(", ") + ">";
	else if (cData.abstract_)
		classString += ", boost::noncopyable";
	classString += ">";
	// print name:
	classString += "(\"" + cData.className_ + "\"";
	// print constructors: // TODO
	if (cData.abstract_) // abstract classes have no constructor
		classString += ", no_init";
	classString += ")";
	printPossiblyLongString(classString);

	// printProperties
	indent();
	int propertyCount = cData.attributes_.size();
	if (propertyCount > 0)
	{
		out_ << endl;
		for (int i = 0; i < propertyCount - 1; ++i)
		{
			printAttribute(cData.attributes_[i]);
			out_ << endl;
		}
		printAttribute(cData.attributes_[propertyCount-1]);
	}
	out_ << ";" << endl;
	unIndent();

	printEnumsOfClass(cData);
	// close scope
	unIndent();
	out_ << "}" << endl << endl;
}

void APIPrinter::printEnumsOfClass(const ClassData& cData)
{
	for (const auto& eData : cData.enums_) printEnum(eData);
}

void APIPrinter::printEnum(const EnumData& eData)
{
	out_ << indent_ <<"enum_<" << eData.qualifiedName_ << ">(\"" << eData.enumName_ << "\")";
	indent();
	int valueCount = eData.values_.size();
	if (valueCount > 0)
	{
		out_ << endl;
		for (int i = 0; i < valueCount - 1; ++i)
		{
			auto enumConstant = eData.values_[i];
			QString enumValue = ".value(\"" + enumConstant.first + "\", " + enumConstant.second + ")";
			printPossiblyLongString(enumValue);
			out_ << endl;
		}
		auto enumConstant = eData.values_[valueCount-1];
		QString enumValue = ".value(\"" + enumConstant.first + "\", " + enumConstant.second + ")";
		printPossiblyLongString(enumValue, 1);
	}
	out_ << ";" << endl;
	unIndent();
}

void APIPrinter::printAttribute(const ClassAttribute& attr)
{
	out_ << indent_ << ".add_property(\"" << attr.name_ << "\", " << endl;
	indent();
	printPossiblyLongString(attr.getterQualified_ + ",");
	out_ << endl;
	out_ << indent_ << attr.setterQualified_ << ")";
	unIndent();
}

void APIPrinter::printTypedListWrappers()
{
	auto typedLists = data_.typedLists();
	if (typedLists.empty()) return;

	out_ << "{" << endl;
	indent();
	for (auto it = typedLists.begin(); it != typedLists.end(); ++it)
	{
		out_ << indent_ << "using " << it.value() << " = " << it.key() << ";" << endl;
		out_ << indent_ << "class_<" << it.key() << ">" << "(\"" << it.value() << "\")" << endl;
		indent();
		out_ << indent_ << ".def(\"__len__\", &" << it.value() << "::size)" << endl;
		out_ << indent_ << ".def(\"__iter__\", iterator<" << it.value() << ", return_internal_reference<>>())";
		out_ << ";" << endl << endl;
		unIndent();
	}
	unIndent();
	out_ << "}" << endl;
}

void APIPrinter::printPossiblyLongString(const QString& data, int additionalLength)
{
	if (data.length() + indent_.length() + additionalLength > maxLineLength_)
	{
		int commaIndex = data.indexOf(',');
		QString firstPart = data.mid(0, commaIndex + 1);
		QString secondPart = data.mid(commaIndex + 1);
		out_ << indent_ << firstPart << endl;
		indent();
		out_ << indent_ << secondPart;
		unIndent();
	}
	else
	{
		out_ << indent_ << data;
	}
}

void APIPrinter::indent()
{
	indent_.append('\t');
}

void APIPrinter::unIndent()
{
	indent_.remove(indent_.size()-1, 1);
}
<commit_msg>Remove space before newline<commit_after>/***********************************************************************************************************************
**
** Copyright (c) 2011, 2015 ETH Zurich
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
** following conditions are met:
**
**    * Redistributions of source code must retain the above copyright notice, this list of conditions and the following
**      disclaimer.
**    * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
**      following disclaimer in the documentation and/or other materials provided with the distribution.
**    * Neither the name of the ETH Zurich nor the names of its contributors may be used to endorse or promote products
**      derived from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
** INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
** DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
** SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**
***********************************************************************************************************************/

#include "APIPrinter.h"

void APIPrinter::print()
{
	printHeaders();
	out_ << "namespace InformationScripting {" << endl << endl;
	out_ << "using namespace boost::python;" << endl << endl;
	out_ << "BOOST_PYTHON_MODULE(AstApi) {" << endl << endl;
	printClasses();
	printTypedListWrappers();
	out_ << endl << "}" << endl;
	out_ << endl << "} /* namespace InformationScripting */" << endl;
}

void APIPrinter::printHeaders()
{
	for (QString includePath : data_.includePaths_)
		out_ << "#include \"" << includePath << "\"" << endl;
	out_ << endl;
}

void APIPrinter::printClasses()
{
	for (const auto& cData : data_.classes()) printClass(cData);
}

void APIPrinter::printClass(const ClassData& cData)
{
	// each class gets it's own scope:
	out_ << "{" << endl;
	indent();
	QString classString;
	if (cData.enums_.size()) // We only need a scope variable if we have enums
		classString = QString("scope %1scope = ").arg(cData.className_);
	classString += "class_<" + cData.qualifiedName_;
	// print bases:
	if (cData.baseClasses_.size())
		classString += ", bases<" + cData.baseClasses_.join(", ") + ">";
	else if (cData.abstract_)
		classString += ", boost::noncopyable";
	classString += ">";
	// print name:
	classString += "(\"" + cData.className_ + "\"";
	// print constructors: // TODO
	if (cData.abstract_) // abstract classes have no constructor
		classString += ", no_init";
	classString += ")";
	printPossiblyLongString(classString);

	// printProperties
	indent();
	int propertyCount = cData.attributes_.size();
	if (propertyCount > 0)
	{
		out_ << endl;
		for (int i = 0; i < propertyCount - 1; ++i)
		{
			printAttribute(cData.attributes_[i]);
			out_ << endl;
		}
		printAttribute(cData.attributes_[propertyCount-1]);
	}
	out_ << ";" << endl;
	unIndent();

	printEnumsOfClass(cData);
	// close scope
	unIndent();
	out_ << "}" << endl << endl;
}

void APIPrinter::printEnumsOfClass(const ClassData& cData)
{
	for (const auto& eData : cData.enums_) printEnum(eData);
}

void APIPrinter::printEnum(const EnumData& eData)
{
	out_ << indent_ <<"enum_<" << eData.qualifiedName_ << ">(\"" << eData.enumName_ << "\")";
	indent();
	int valueCount = eData.values_.size();
	if (valueCount > 0)
	{
		out_ << endl;
		for (int i = 0; i < valueCount - 1; ++i)
		{
			auto enumConstant = eData.values_[i];
			QString enumValue = ".value(\"" + enumConstant.first + "\", " + enumConstant.second + ")";
			printPossiblyLongString(enumValue);
			out_ << endl;
		}
		auto enumConstant = eData.values_[valueCount-1];
		QString enumValue = ".value(\"" + enumConstant.first + "\", " + enumConstant.second + ")";
		printPossiblyLongString(enumValue, 1);
	}
	out_ << ";" << endl;
	unIndent();
}

void APIPrinter::printAttribute(const ClassAttribute& attr)
{
	out_ << indent_ << ".add_property(\"" << attr.name_ << "\"," << endl;
	indent();
	printPossiblyLongString(attr.getterQualified_ + ",");
	out_ << endl;
	out_ << indent_ << attr.setterQualified_ << ")";
	unIndent();
}

void APIPrinter::printTypedListWrappers()
{
	auto typedLists = data_.typedLists();
	if (typedLists.empty()) return;

	out_ << "{" << endl;
	indent();
	for (auto it = typedLists.begin(); it != typedLists.end(); ++it)
	{
		out_ << indent_ << "using " << it.value() << " = " << it.key() << ";" << endl;
		out_ << indent_ << "class_<" << it.key() << ">" << "(\"" << it.value() << "\")" << endl;
		indent();
		out_ << indent_ << ".def(\"__len__\", &" << it.value() << "::size)" << endl;
		out_ << indent_ << ".def(\"__iter__\", iterator<" << it.value() << ", return_internal_reference<>>())";
		out_ << ";" << endl << endl;
		unIndent();
	}
	unIndent();
	out_ << "}" << endl;
}

void APIPrinter::printPossiblyLongString(const QString& data, int additionalLength)
{
	if (data.length() + indent_.length() + additionalLength > maxLineLength_)
	{
		int commaIndex = data.indexOf(',');
		QString firstPart = data.mid(0, commaIndex + 1);
		QString secondPart = data.mid(commaIndex + 1);
		out_ << indent_ << firstPart << endl;
		indent();
		out_ << indent_ << secondPart;
		unIndent();
	}
	else
	{
		out_ << indent_ << data;
	}
}

void APIPrinter::indent()
{
	indent_.append('\t');
}

void APIPrinter::unIndent()
{
	indent_.remove(indent_.size()-1, 1);
}
<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#ifndef INCLUDED_O3TL_SORTED_VECTOR_HXX
#define INCLUDED_O3TL_SORTED_VECTOR_HXX

#include <vector>
#include <functional>
#include <algorithm>

namespace o3tl
{

/** Helper template */
template <class Value, class Compare>
class sorted_vector_compare : public Compare
{
public:
    bool operator()(const Value& lhs, const Value& rhs) const
    {
        return Compare::operator()(lhs, rhs);
    }
};

/** Represents a sorted vector of values.

    @tpl Value class of item to be stored in container
    @tpl Compare comparison method
*/
template <class Value, class Compare = std::less<Value> >
class sorted_vector : public std::vector<Value>, private sorted_vector_compare<Value, Compare>
{
public:
    typedef typename std::vector<Value>::iterator  iterator;
    typedef typename std::vector<Value>::const_iterator  const_iterator;
    typedef typename std::vector<Value>::size_type  size_type;
    typedef sorted_vector_compare<Value, Compare> MyCompare;

    using std::vector<Value>::begin;
    using std::vector<Value>::end;
    using std::vector<Value>::clear;
    using std::vector<Value>::insert;
    using std::vector<Value>::erase;

    // MODIFIERS

    std::pair<iterator,bool> insert( const Value& x )
    {
        const MyCompare& me = *this;
        iterator it = std::lower_bound( begin(), end(), x, me );
        if( it == end() || less_than(x, *it) )
        {
            it = insert( it, x );
            return std::make_pair( it, true );
        }
        return std::make_pair( it, false );
    }

    size_type erase( const Value& x )
    {
        iterator it = find(x);
        if( it != end() )
        {
            erase( it );
            return 1;
        }
        return 0;
    }

    // OPERATIONS

    /* Searches the container for an element with a value of x
     * and returns an iterator to it if found, otherwise it returns an
     * iterator to sorted_vector::end (the element past the end of the container).
     */
    const_iterator find( const Value& x ) const
    {
        const MyCompare& me = *this;
        const_iterator it = std::lower_bound( begin(), end(), x, me );
        if( it == end() || less_than(x, *it) )
        {
            return end();
        }
        return it;
    }
    iterator find( const Value& x )
    {
        const MyCompare& me = *this;
        iterator it = std::lower_bound( begin(), end(), x, me );
        if( it == end() || less_than(x, *it) )
        {
            return end();
        }
        return it;
    }

    /* Clear() elements in the vector, and free them one by one. */
    void DeleteAndDestroyAll()
    {
        for( const_iterator it = begin(); it != end(); ++it )
            delete *it;
        clear();
    }

private:
    /** just makes the code easier to read */
    bool less_than(const Value& lhs, const Value& rhs) const
    {
        const MyCompare& me = *this;
        return me.operator()(lhs, rhs);
    }
};

/** Implements an ordering function over a pointer, where the comparison uses the < operator on the pointed-to types.
    Very useful for the cases where we put pointers to objects inside a sorted_vector.
*/
template <class T> struct less_ptr_to : public std::binary_function <T*,T*,bool>
{
    bool operator() ( T* const& lhs, T* const& rhs ) const
    {
        return (*lhs) < (*rhs);
    }
};

}   // namespace o3tl
#endif

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>sorted_vector should not inherit public std::vector<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#ifndef INCLUDED_O3TL_SORTED_VECTOR_HXX
#define INCLUDED_O3TL_SORTED_VECTOR_HXX

#include <vector>
#include <functional>
#include <algorithm>

namespace o3tl
{

/** Helper template */
template <class Value, class Compare>
class sorted_vector_compare : public Compare
{
public:
    bool operator()(const Value& lhs, const Value& rhs) const
    {
        return Compare::operator()(lhs, rhs);
    }
};

/** Represents a sorted vector of values.

    @tpl Value class of item to be stored in container
    @tpl Compare comparison method
*/
template <class Value, class Compare = std::less<Value> >
class sorted_vector
    : private std::vector<Value>
    , private sorted_vector_compare<Value, Compare>
{
public:
    typedef typename std::vector<Value>::iterator  iterator;
    typedef typename std::vector<Value>::const_iterator  const_iterator;
    typedef typename std::vector<Value>::size_type  size_type;
    typedef sorted_vector_compare<Value, Compare> MyCompare;

    using std::vector<Value>::begin;
    using std::vector<Value>::end;
    using std::vector<Value>::clear;
    using std::vector<Value>::erase;
    using std::vector<Value>::empty;
    using std::vector<Value>::size;
    using std::vector<Value>::operator[];

    // MODIFIERS

    std::pair<iterator,bool> insert( const Value& x )
    {
        const MyCompare& me = *this;
        iterator it = std::lower_bound( begin(), end(), x, me );
        if( it == end() || less_than(x, *it) )
        {
            it = std::vector<Value>::insert( it, x );
            return std::make_pair( it, true );
        }
        return std::make_pair( it, false );
    }

    size_type erase( const Value& x )
    {
        iterator it = find(x);
        if( it != end() )
        {
            erase( it );
            return 1;
        }
        return 0;
    }

    // OPERATIONS

    /* Searches the container for an element with a value of x
     * and returns an iterator to it if found, otherwise it returns an
     * iterator to sorted_vector::end (the element past the end of the container).
     */
    const_iterator find( const Value& x ) const
    {
        const MyCompare& me = *this;
        const_iterator it = std::lower_bound( begin(), end(), x, me );
        if( it == end() || less_than(x, *it) )
        {
            return end();
        }
        return it;
    }
    iterator find( const Value& x )
    {
        const MyCompare& me = *this;
        iterator it = std::lower_bound( begin(), end(), x, me );
        if( it == end() || less_than(x, *it) )
        {
            return end();
        }
        return it;
    }

    /* Clear() elements in the vector, and free them one by one. */
    void DeleteAndDestroyAll()
    {
        for( const_iterator it = begin(); it != end(); ++it )
            delete *it;
        clear();
    }

private:
    /** just makes the code easier to read */
    bool less_than(const Value& lhs, const Value& rhs) const
    {
        const MyCompare& me = *this;
        return me.operator()(lhs, rhs);
    }
};

/** Implements an ordering function over a pointer, where the comparison uses the < operator on the pointed-to types.
    Very useful for the cases where we put pointers to objects inside a sorted_vector.
*/
template <class T> struct less_ptr_to : public std::binary_function <T*,T*,bool>
{
    bool operator() ( T* const& lhs, T* const& rhs ) const
    {
        return (*lhs) < (*rhs);
    }
};

}   // namespace o3tl
#endif

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<|endoftext|>


<commit_before>/*************************************************************************
 *                                                                       *
 * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith.       *
 * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
 *                                                                       *
 * This library is free software; you can redistribute it and/or         *
 * modify it under the terms of EITHER:                                  *
 *   (1) The GNU Lesser General Public License as published by the Free  *
 *       Software Foundation; either version 2.1 of the License, or (at  *
 *       your option) any later version. The text of the GNU Lesser      *
 *       General Public License is included with this library in the     *
 *       file LICENSE.TXT.                                               *
 *   (2) The BSD-style license that is included with this library in     *
 *       the file LICENSE-BSD.TXT.                                       *
 *                                                                       *
 * 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 files    *
 * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
 *                                                                       *
 *************************************************************************/

#include <ode/ode.h>
#include <drawstuff/drawstuff.h>
#include "texturepath.h"
#include "bunny_geom.h"
#include "convex_bunny_geom.h"

#ifdef _MSC_VER
#pragma warning(disable:4244 4305)  // for VC++, no precision loss complaints
#endif

// select correct drawing functions

#ifdef dDOUBLE
#define dsDrawBox dsDrawBoxD
#define dsDrawSphere dsDrawSphereD
#define dsDrawCylinder dsDrawCylinderD
#define dsDrawCapsule dsDrawCapsuleD
#define dsDrawLine dsDrawLineD
#define dsDrawTriangle dsDrawTriangleD
#endif

// some constants

#define NUM 200			// max number of objects
#define DENSITY (5.0)		// density of all objects
#define GPB 3			// maximum number of geometries per body
#define MAX_CONTACTS 64		// maximum number of contact points per body

// dynamics and collision objects

struct MyObject
{
	dBodyID body;			// the body
	dGeomID geom[GPB];		// geometries representing this body
};

static int num=0;		// number of objects in simulation
static int nextobj=0;		// next object to recycle if num==NUM
static dWorldID world;
static dSpaceID space;
static MyObject obj[NUM];
static dJointGroupID contactgroup;
static int selected = -1;	// selected object
static int show_aabb = 0;	// show geom AABBs?
static int show_contacts = 0;	// show contact points?
static int random_pos = 1;	// drop objects from random position?

typedef dReal dVector3R[3];

// this is called by dSpaceCollide when two objects in space are
// potentially colliding.

static void nearCallback( void *data, dGeomID o1, dGeomID o2 )
{
	int i;
	// if (o1->body && o2->body) return;

	// exit without doing anything if the two bodies are connected by a joint
	dBodyID b1 = dGeomGetBody( o1 );
	dBodyID b2 = dGeomGetBody( o2 );
	if ( b1 && b2 && dAreConnectedExcluding( b1,b2,dJointTypeContact ) ) return;

	dContact contact[MAX_CONTACTS];   // up to MAX_CONTACTS contacts per box-box
	for ( i=0; i<MAX_CONTACTS; i++ )
	{
		contact[i].surface.mode = dContactBounce | dContactSoftCFM;
		contact[i].surface.mu = dInfinity;
		contact[i].surface.mu2 = 0;
		contact[i].surface.bounce = 0.1;
		contact[i].surface.bounce_vel = 0.1;
		contact[i].surface.soft_cfm = 0.01;
	}
	if ( int numc = dCollide( o1,o2,MAX_CONTACTS,&contact[0].geom,
	                          sizeof( dContact ) ) )
	{
		dMatrix3 RI;
		dRSetIdentity( RI );
		const dReal ss[3] = {0.02,0.02,0.02};
		for ( i=0; i<numc; i++ )
		{
			dJointID c = dJointCreateContact( world,contactgroup,contact+i );
			dJointAttach( c,b1,b2 );
			if ( show_contacts ) dsDrawBox( contact[i].geom.pos,RI,ss );
		}
	}
}

// start simulation - set viewpoint

static void start()
{
	dAllocateODEDataForThread( dAllocateMaskAll );

	static float xyz[3] = {2.1640f,-1.3079f,1.7600f};
	static float hpr[3] = {125.5000f,-17.0000f,0.0000f};
	dsSetViewpoint( xyz,hpr );
	printf( "To drop another object, press:\n" );
	printf( "   b for box.\n" );
	printf( "   s for sphere.\n" );
	printf( "   c for capsule.\n" );
	printf( "   v for a convex.\n" );
	printf( "To select an object, press space.\n" );
	printf( "To disable the selected object, press d.\n" );
	printf( "To enable the selected object, press e.\n" );
	printf( "To toggle showing the geom AABBs, press a.\n" );
	printf( "To toggle showing the contact points, press t.\n" );
	printf( "To toggle dropping from random position/orientation, press r.\n" );
}

char locase( char c )
{
	if ( c >= 'A' && c <= 'Z' ) return c - ( 'a'-'A' );
	else return c;
}

// called when a key pressed
static void command( int cmd )
{
	int i,j,k;
	dReal sides[3];
	dMass m;

	cmd = locase( cmd );
	if ( cmd == 'v' || cmd == 'b' || cmd == 'c' || cmd == 's' )
	{
		if ( num < NUM )
		{
			i = num;
			num++;
		}
		else
		{
			i = nextobj;
			nextobj++;
			if ( nextobj >= num ) nextobj = 0;

			// destroy the body and geoms for slot i
			dBodyDestroy( obj[i].body );
			for ( k=0; k < GPB; k++ )
			{
				if ( obj[i].geom[k] ) dGeomDestroy( obj[i].geom[k] );
			}
			memset( &obj[i],0,sizeof( obj[i] ) );
		}

		obj[i].body = dBodyCreate( world );
		for ( k=0; k<3; k++ ) sides[k] = dRandReal()*0.5+0.1;

		dMatrix3 R;
		if ( random_pos )
		{
			dBodySetPosition( obj[i].body,
			                  dRandReal()*2-1,dRandReal()*2-1,dRandReal()+3 );
			dRFromAxisAndAngle( R,dRandReal()*2.0-1.0,dRandReal()*2.0-1.0,
			                    dRandReal()*2.0-1.0,dRandReal()*10.0-5.0 );
		}
		else
		{
			dReal maxheight = 0;
			for ( k=0; k<num; k++ )
			{
				const dReal *pos = dBodyGetPosition( obj[k].body );
				if ( pos[2] > maxheight ) maxheight = pos[2];
			}
			dBodySetPosition( obj[i].body, 0,0,maxheight+1 );
			dRFromAxisAndAngle( R,0,0,1,dRandReal()*10.0-5.0 );
		}
		dBodySetRotation( obj[i].body,R );
		dBodySetData( obj[i].body,( void* )( size_t )i );

		if ( cmd == 'b' )
		{
			dMassSetBox( &m,DENSITY,sides[0],sides[1],sides[2] );
			obj[i].geom[0] = dCreateBox( space,sides[0],sides[1],sides[2] );
		}
		else if ( cmd == 'c' )
		{
			sides[0] *= 0.5;
			dMassSetCapsule( &m,DENSITY,3,sides[0],sides[1] );
			obj[i].geom[0] = dCreateCapsule( space,sides[0],sides[1] );
		}
		else if ( cmd == 's' )
		{
			sides[0] *= 0.5;
			dMassSetSphere( &m,DENSITY,sides[0] );
			obj[i].geom[0] = dCreateSphere( space,sides[0] );
		}
		else  if ( cmd == 'v' )
		{
			obj[i].geom[0] = dCreateConvex( space,
			                                convexBunnyPlanes,
			                                convexBunnyPlaneCount,
			                                convexBunnyPoints,
			                                convexBunnyPointCount,
			                                convexBunnyPolygons );

			/// Use equivalent TriMesh to set mass
			dTriMeshDataID new_tmdata = dGeomTriMeshDataCreate();
			dGeomTriMeshDataBuildSingle( new_tmdata, &Vertices[0], 3 * sizeof( float ), VertexCount,
			                             ( dTriIndex* )&Indices[0], IndexCount, 3 * sizeof( dTriIndex ) );

			dGeomID triMesh = dCreateTriMesh( 0, new_tmdata, 0, 0, 0 );

			dMassSetTrimesh( &m, DENSITY, triMesh );

			dGeomDestroy( triMesh );
			dGeomTriMeshDataDestroy( new_tmdata );

			printf( "mass at %f %f %f\n", m.c[0], m.c[1], m.c[2] );
			dGeomSetPosition( obj[i].geom[0], -m.c[0], -m.c[1], -m.c[2] );
			dMassTranslate( &m, -m.c[0], -m.c[1], -m.c[2] );
		}

		for ( k=0; k < GPB; k++ )
		{
			if ( obj[i].geom[k] ) dGeomSetBody( obj[i].geom[k],obj[i].body );
		}

		dBodySetMass( obj[i].body,&m );
	}

	if ( cmd == ' ' )
	{
		selected++;
		if ( selected >= num ) selected = 0;
		if ( selected < 0 ) selected = 0;
	}
	else if ( cmd == 'd' && selected >= 0 && selected < num )
	{
		dBodyDisable( obj[selected].body );
	}
	else if ( cmd == 'e' && selected >= 0 && selected < num )
	{
		dBodyEnable( obj[selected].body );
	}
	else if ( cmd == 'a' )
	{
		show_aabb ^= 1;
	}
	else if ( cmd == 't' )
	{
		show_contacts ^= 1;
	}
	else if ( cmd == 'r' )
	{
		random_pos ^= 1;
	}
}

// draw a geom
void drawGeom( dGeomID g, const dReal *pos, const dReal *R, int show_aabb )
{
	if ( !g ) return;
	if ( !pos ) pos = dGeomGetPosition( g );
	if ( !R ) R = dGeomGetRotation( g );

	int type = dGeomGetClass( g );
	if ( type == dBoxClass )
	{
		dVector3 sides;
		dGeomBoxGetLengths( g,sides );
		dsDrawBox( pos,R,sides );
	}
	else if ( type == dSphereClass )
	{
		dsDrawSphere( pos,R,dGeomSphereGetRadius( g ) );
	}
	else if ( type == dCapsuleClass )
	{
		dReal radius,length;
		dGeomCapsuleGetParams( g,&radius,&length );
		dsDrawCapsule( pos,R,length,radius );
	}
	else if ( type == dConvexClass )
	{
		dsDrawConvex( pos,R,
		              convexBunnyPlanes,
		              convexBunnyPlaneCount,
		              convexBunnyPoints,
		              convexBunnyPointCount,
		              convexBunnyPolygons );
	}

	if ( show_aabb )
	{
		// draw the bounding box for this geom
		dReal aabb[6];
		dGeomGetAABB( g,aabb );
		dVector3 bbpos;
		for ( int i=0; i<3; i++ ) bbpos[i] = 0.5*( aabb[i*2] + aabb[i*2+1] );
		dVector3 bbsides;
		for ( int j=0; j<3; j++ ) bbsides[j] = aabb[j*2+1] - aabb[j*2];
		dMatrix3 RI;
		dRSetIdentity( RI );
		dsSetColorAlpha( 1,0,0,0.5 );
		dsDrawBox( bbpos,RI,bbsides );
	}
}

// simulation loop

static void simLoop( int pause )
{
	dsSetColor( 0,0,2 );
	dSpaceCollide( space,0,&nearCallback );

	if ( !pause ) dWorldStepFast1( world,0.05, 5 );

	for ( int j = 0; j < dSpaceGetNumGeoms( space ); j++ )
	{
		dSpaceGetGeom( space, j );
	}

	// remove all contact joints
	dJointGroupEmpty( contactgroup );

	dsSetColor( 1,1,0 );
	dsSetTexture( DS_WOOD );
	for ( int i=0; i<num; i++ )
	{
		for ( int j=0; j < GPB; j++ )
		{
			if ( obj[i].geom[j] )
			{
				if ( i==selected )
				{
					dsSetColor( 0,0.7,1 );
				}
				else if ( ! dBodyIsEnabled( obj[i].body ) )
				{
					dsSetColor( 1,0,0 );
				}
				else
				{
					dsSetColor( 1,1,0 );
				}

				drawGeom( obj[i].geom[j],0,0,show_aabb );
			}
		}
	}
}

int main( int argc, char **argv )
{
	// setup pointers to drawstuff callback functions
	dsFunctions fn;
	fn.version = DS_VERSION;
	fn.start = &start;
	fn.step = &simLoop;
	fn.command = &command;
	fn.stop = 0;
	fn.path_to_textures = DRAWSTUFF_TEXTURE_PATH;
	if ( argc==2 )
	{
		fn.path_to_textures = argv[1];
	}

	// create world
	dInitODE2( 0 );
	world = dWorldCreate();

	space = dSimpleSpaceCreate( 0 );
	contactgroup = dJointGroupCreate( 0 );
	dWorldSetGravity( world,0,0,-0.5 );
	dWorldSetCFM( world,1e-5 );
	dCreatePlane( space,0,0,1,0 );
	memset( obj,0,sizeof( obj ) );

	// run simulation
	dsSimulationLoop( argc,argv,352,288,&fn );

	dJointGroupDestroy( contactgroup );
	dSpaceDestroy( space );
	dWorldDestroy( world );
	dCloseODE();
	return 0;
}

<commit_msg>fixed compilation for double precision<commit_after>/*************************************************************************
 *                                                                       *
 * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith.       *
 * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
 *                                                                       *
 * This library is free software; you can redistribute it and/or         *
 * modify it under the terms of EITHER:                                  *
 *   (1) The GNU Lesser General Public License as published by the Free  *
 *       Software Foundation; either version 2.1 of the License, or (at  *
 *       your option) any later version. The text of the GNU Lesser      *
 *       General Public License is included with this library in the     *
 *       file LICENSE.TXT.                                               *
 *   (2) The BSD-style license that is included with this library in     *
 *       the file LICENSE-BSD.TXT.                                       *
 *                                                                       *
 * 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 files    *
 * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
 *                                                                       *
 *************************************************************************/

#include <ode/ode.h>
#include <drawstuff/drawstuff.h>
#include "texturepath.h"
#include "bunny_geom.h"
#include "convex_bunny_geom.h"

#ifdef _MSC_VER
#pragma warning(disable:4244 4305)  // for VC++, no precision loss complaints
#endif

// select correct drawing functions

#ifdef dDOUBLE
#define dsDrawBox dsDrawBoxD
#define dsDrawSphere dsDrawSphereD
#define dsDrawCylinder dsDrawCylinderD
#define dsDrawCapsule dsDrawCapsuleD
#define dsDrawLine dsDrawLineD
#define dsDrawTriangle dsDrawTriangleD
#define dsDrawConvex dsDrawConvexD
#endif

// some constants

#define NUM 200			// max number of objects
#define DENSITY (5.0)		// density of all objects
#define GPB 3			// maximum number of geometries per body
#define MAX_CONTACTS 64		// maximum number of contact points per body

// dynamics and collision objects

struct MyObject
{
	dBodyID body;			// the body
	dGeomID geom[GPB];		// geometries representing this body
};

static int num=0;		// number of objects in simulation
static int nextobj=0;		// next object to recycle if num==NUM
static dWorldID world;
static dSpaceID space;
static MyObject obj[NUM];
static dJointGroupID contactgroup;
static int selected = -1;	// selected object
static int show_aabb = 0;	// show geom AABBs?
static int show_contacts = 0;	// show contact points?
static int random_pos = 1;	// drop objects from random position?

typedef dReal dVector3R[3];

// this is called by dSpaceCollide when two objects in space are
// potentially colliding.

static void nearCallback( void *data, dGeomID o1, dGeomID o2 )
{
	int i;
	// if (o1->body && o2->body) return;

	// exit without doing anything if the two bodies are connected by a joint
	dBodyID b1 = dGeomGetBody( o1 );
	dBodyID b2 = dGeomGetBody( o2 );
	if ( b1 && b2 && dAreConnectedExcluding( b1,b2,dJointTypeContact ) ) return;

	dContact contact[MAX_CONTACTS];   // up to MAX_CONTACTS contacts per box-box
	for ( i=0; i<MAX_CONTACTS; i++ )
	{
		contact[i].surface.mode = dContactBounce | dContactSoftCFM;
		contact[i].surface.mu = dInfinity;
		contact[i].surface.mu2 = 0;
		contact[i].surface.bounce = 0.1;
		contact[i].surface.bounce_vel = 0.1;
		contact[i].surface.soft_cfm = 0.01;
	}
	if ( int numc = dCollide( o1,o2,MAX_CONTACTS,&contact[0].geom,
	                          sizeof( dContact ) ) )
	{
		dMatrix3 RI;
		dRSetIdentity( RI );
		const dReal ss[3] = {0.02,0.02,0.02};
		for ( i=0; i<numc; i++ )
		{
			dJointID c = dJointCreateContact( world,contactgroup,contact+i );
			dJointAttach( c,b1,b2 );
			if ( show_contacts ) dsDrawBox( contact[i].geom.pos,RI,ss );
		}
	}
}

// start simulation - set viewpoint

static void start()
{
	dAllocateODEDataForThread( dAllocateMaskAll );

	static float xyz[3] = {2.1640f,-1.3079f,1.7600f};
	static float hpr[3] = {125.5000f,-17.0000f,0.0000f};
	dsSetViewpoint( xyz,hpr );
	printf( "To drop another object, press:\n" );
	printf( "   b for box.\n" );
	printf( "   s for sphere.\n" );
	printf( "   c for capsule.\n" );
	printf( "   v for a convex.\n" );
	printf( "To select an object, press space.\n" );
	printf( "To disable the selected object, press d.\n" );
	printf( "To enable the selected object, press e.\n" );
	printf( "To toggle showing the geom AABBs, press a.\n" );
	printf( "To toggle showing the contact points, press t.\n" );
	printf( "To toggle dropping from random position/orientation, press r.\n" );
}

char locase( char c )
{
	if ( c >= 'A' && c <= 'Z' ) return c - ( 'a'-'A' );
	else return c;
}

// called when a key pressed
static void command( int cmd )
{
	int i,j,k;
	dReal sides[3];
	dMass m;

	cmd = locase( cmd );
	if ( cmd == 'v' || cmd == 'b' || cmd == 'c' || cmd == 's' )
	{
		if ( num < NUM )
		{
			i = num;
			num++;
		}
		else
		{
			i = nextobj;
			nextobj++;
			if ( nextobj >= num ) nextobj = 0;

			// destroy the body and geoms for slot i
			dBodyDestroy( obj[i].body );
			for ( k=0; k < GPB; k++ )
			{
				if ( obj[i].geom[k] ) dGeomDestroy( obj[i].geom[k] );
			}
			memset( &obj[i],0,sizeof( obj[i] ) );
		}

		obj[i].body = dBodyCreate( world );
		for ( k=0; k<3; k++ ) sides[k] = dRandReal()*0.5+0.1;

		dMatrix3 R;
		if ( random_pos )
		{
			dBodySetPosition( obj[i].body,
			                  dRandReal()*2-1,dRandReal()*2-1,dRandReal()+3 );
			dRFromAxisAndAngle( R,dRandReal()*2.0-1.0,dRandReal()*2.0-1.0,
			                    dRandReal()*2.0-1.0,dRandReal()*10.0-5.0 );
		}
		else
		{
			dReal maxheight = 0;
			for ( k=0; k<num; k++ )
			{
				const dReal *pos = dBodyGetPosition( obj[k].body );
				if ( pos[2] > maxheight ) maxheight = pos[2];
			}
			dBodySetPosition( obj[i].body, 0,0,maxheight+1 );
			dRFromAxisAndAngle( R,0,0,1,dRandReal()*10.0-5.0 );
		}
		dBodySetRotation( obj[i].body,R );
		dBodySetData( obj[i].body,( void* )( size_t )i );

		if ( cmd == 'b' )
		{
			dMassSetBox( &m,DENSITY,sides[0],sides[1],sides[2] );
			obj[i].geom[0] = dCreateBox( space,sides[0],sides[1],sides[2] );
		}
		else if ( cmd == 'c' )
		{
			sides[0] *= 0.5;
			dMassSetCapsule( &m,DENSITY,3,sides[0],sides[1] );
			obj[i].geom[0] = dCreateCapsule( space,sides[0],sides[1] );
		}
		else if ( cmd == 's' )
		{
			sides[0] *= 0.5;
			dMassSetSphere( &m,DENSITY,sides[0] );
			obj[i].geom[0] = dCreateSphere( space,sides[0] );
		}
		else  if ( cmd == 'v' )
		{
			obj[i].geom[0] = dCreateConvex( space,
			                                convexBunnyPlanes,
			                                convexBunnyPlaneCount,
			                                convexBunnyPoints,
			                                convexBunnyPointCount,
			                                convexBunnyPolygons );

			/// Use equivalent TriMesh to set mass
			dTriMeshDataID new_tmdata = dGeomTriMeshDataCreate();
			dGeomTriMeshDataBuildSingle( new_tmdata, &Vertices[0], 3 * sizeof( float ), VertexCount,
			                             ( dTriIndex* )&Indices[0], IndexCount, 3 * sizeof( dTriIndex ) );

			dGeomID triMesh = dCreateTriMesh( 0, new_tmdata, 0, 0, 0 );

			dMassSetTrimesh( &m, DENSITY, triMesh );

			dGeomDestroy( triMesh );
			dGeomTriMeshDataDestroy( new_tmdata );

			printf( "mass at %f %f %f\n", m.c[0], m.c[1], m.c[2] );
			dGeomSetPosition( obj[i].geom[0], -m.c[0], -m.c[1], -m.c[2] );
			dMassTranslate( &m, -m.c[0], -m.c[1], -m.c[2] );
		}

		for ( k=0; k < GPB; k++ )
		{
			if ( obj[i].geom[k] ) dGeomSetBody( obj[i].geom[k],obj[i].body );
		}

		dBodySetMass( obj[i].body,&m );
	}

	if ( cmd == ' ' )
	{
		selected++;
		if ( selected >= num ) selected = 0;
		if ( selected < 0 ) selected = 0;
	}
	else if ( cmd == 'd' && selected >= 0 && selected < num )
	{
		dBodyDisable( obj[selected].body );
	}
	else if ( cmd == 'e' && selected >= 0 && selected < num )
	{
		dBodyEnable( obj[selected].body );
	}
	else if ( cmd == 'a' )
	{
		show_aabb ^= 1;
	}
	else if ( cmd == 't' )
	{
		show_contacts ^= 1;
	}
	else if ( cmd == 'r' )
	{
		random_pos ^= 1;
	}
}

// draw a geom
void drawGeom( dGeomID g, const dReal *pos, const dReal *R, int show_aabb )
{
	if ( !g ) return;
	if ( !pos ) pos = dGeomGetPosition( g );
	if ( !R ) R = dGeomGetRotation( g );

	int type = dGeomGetClass( g );
	if ( type == dBoxClass )
	{
		dVector3 sides;
		dGeomBoxGetLengths( g,sides );
		dsDrawBox( pos,R,sides );
	}
	else if ( type == dSphereClass )
	{
		dsDrawSphere( pos,R,dGeomSphereGetRadius( g ) );
	}
	else if ( type == dCapsuleClass )
	{
		dReal radius,length;
		dGeomCapsuleGetParams( g,&radius,&length );
		dsDrawCapsule( pos,R,length,radius );
	}
	else if ( type == dConvexClass )
	{
		dsDrawConvex( pos,R,
		              convexBunnyPlanes,
		              convexBunnyPlaneCount,
		              convexBunnyPoints,
		              convexBunnyPointCount,
		              convexBunnyPolygons );
	}

	if ( show_aabb )
	{
		// draw the bounding box for this geom
		dReal aabb[6];
		dGeomGetAABB( g,aabb );
		dVector3 bbpos;
		for ( int i=0; i<3; i++ ) bbpos[i] = 0.5*( aabb[i*2] + aabb[i*2+1] );
		dVector3 bbsides;
		for ( int j=0; j<3; j++ ) bbsides[j] = aabb[j*2+1] - aabb[j*2];
		dMatrix3 RI;
		dRSetIdentity( RI );
		dsSetColorAlpha( 1,0,0,0.5 );
		dsDrawBox( bbpos,RI,bbsides );
	}
}

// simulation loop

static void simLoop( int pause )
{
	dsSetColor( 0,0,2 );
	dSpaceCollide( space,0,&nearCallback );

	if ( !pause ) dWorldStepFast1( world,0.05, 5 );

	for ( int j = 0; j < dSpaceGetNumGeoms( space ); j++ )
	{
		dSpaceGetGeom( space, j );
	}

	// remove all contact joints
	dJointGroupEmpty( contactgroup );

	dsSetColor( 1,1,0 );
	dsSetTexture( DS_WOOD );
	for ( int i=0; i<num; i++ )
	{
		for ( int j=0; j < GPB; j++ )
		{
			if ( obj[i].geom[j] )
			{
				if ( i==selected )
				{
					dsSetColor( 0,0.7,1 );
				}
				else if ( ! dBodyIsEnabled( obj[i].body ) )
				{
					dsSetColor( 1,0,0 );
				}
				else
				{
					dsSetColor( 1,1,0 );
				}

				drawGeom( obj[i].geom[j],0,0,show_aabb );
			}
		}
	}
}

int main( int argc, char **argv )
{
	// setup pointers to drawstuff callback functions
	dsFunctions fn;
	fn.version = DS_VERSION;
	fn.start = &start;
	fn.step = &simLoop;
	fn.command = &command;
	fn.stop = 0;
	fn.path_to_textures = DRAWSTUFF_TEXTURE_PATH;
	if ( argc==2 )
	{
		fn.path_to_textures = argv[1];
	}

	// create world
	dInitODE2( 0 );
	world = dWorldCreate();

	space = dSimpleSpaceCreate( 0 );
	contactgroup = dJointGroupCreate( 0 );
	dWorldSetGravity( world,0,0,-0.5 );
	dWorldSetCFM( world,1e-5 );
	dCreatePlane( space,0,0,1,0 );
	memset( obj,0,sizeof( obj ) );

	// run simulation
	dsSimulationLoop( argc,argv,352,288,&fn );

	dJointGroupDestroy( contactgroup );
	dSpaceDestroy( space );
	dWorldDestroy( world );
	dCloseODE();
	return 0;
}

<|endoftext|>