<commit_before>/*************************************************************************
 *
 *  $RCSfile: appmain.cxx,v $
 *
 *  $Revision: 1.17 $
 *
 *  last change: $Author: hr $ $Date: 2004-02-03 19:53:21 $
 *
 *  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): _______________________________________
 *
 *
 ************************************************************************/

//#define TF_NEWDESKTOP

#define _SDINTERN_HXX

#pragma hdrstop

#ifndef _PVER_HXX //autogen
#include <svtools/pver.hxx>
#endif
#ifndef _URLOBJ_HXX //autogen
#include <tools/urlobj.hxx>
#endif
#if SUPD<613//MUSTINI
#ifndef _SFXINIMGR_HXX //autogen
#include <svtools/iniman.hxx>
#endif
#endif
#ifndef _CSTITEM_HXX //autogen
#include <svtools/cstitem.hxx>
#endif
#ifndef _CONFIG_HXX
#include <tools/config.hxx>
#endif
#ifndef _EHDL_HXX
#include <svtools/ehdl.hxx>
#endif
#ifndef INCLUDED_SVTOOLS_STARTOPTIONS_HXX
#include <svtools/startoptions.hxx>
#endif
#include <svtools/itempool.hxx>
#include <svtools/urihelper.hxx>
#include <svtools/helpopt.hxx>
#include <vos/process.hxx>

#include "appimp.hxx"
#include "sfxtypes.hxx"
#include "appdata.hxx"
#include "docfac.hxx"
#include "app.hxx"
#include "arrdecl.hxx"
#include "dispatch.hxx"
#include "sfxresid.hxx"
#include "interno.hxx"
#include "fcontnr.hxx"
#include "viewsh.hxx"
#include "intro.hxx"
#include "msgpool.hxx"
#include "cfgmgr.hxx"
#include "accmgr.hxx"
#include "mnumgr.hxx"
#include "stbmgr.hxx"
#include "imgmgr.hxx"
#include "appuno.hxx"
#include "objuno.hxx"
#include "app.hrc"
#include "docfile.hxx"
#if SUPD<613//MUSTINI
#include "inimgr.hxx"
#endif

#ifdef WNT
#include <tools/svwin.h>
#endif

#ifdef UNX
#define stricmp(a,b) strcmp(a,b)
#endif

//===================================================================

/*DBG_NAME(SfxAppMainIntro);
DBG_NAME(SfxAppMainSO_Init);
DBG_NAME(SfxAppMainAppRes);
DBG_NAME(SfxAppMainInit0);
DBG_NAME(SfxAppMainCreateAppWin);
DBG_NAME(SfxAppMainInit1);
DBG_NAME(SfxAppMainCfgMgr);
DBG_NAME(SfxAppMainInitController);
DBG_NAME(SfxAppMainInitException);
DBG_NAME(SfxAppMainRegisterIF);
DBG_NAME(SfxAppMainInit);
DBG_NAME(SfxAppMainLoadBasMgr);
DBG_NAME(SfxAppMainSbxInit);*/
DBG_NAME(SfxAppMainNewMenu);
DBG_NAME(SfxAppMainBmkMenu);
DBG_NAME(SfxAppMainWizMenu);
DBG_NAME(SfxAppMainOLEReg);
DBG_NAME(SfxAppMainCHAOSReg);
/*DBG_NAME(SfxAppMainInitDispatcher);
DBG_NAME(SfxAppMainLoadConfig);
DBG_NAME(SfxAppMainInitAppWin);
DBG_NAME(SfxAppMainAppEvents);*/

//===================================================================

#define SFX_TEMPNAMEBASE_DIR    "soffice.tmp"
#define SFX_KEY_TEMPNAMEBASE    "Temp-Dir"

//===================================================================

#pragma code_seg("STATICS")
static SfxVoidItem aStaticDefault(1);
#pragma code_seg()

static SfxPoolItem* aStaticDefaults[1] =
{
    &aStaticDefault
};

#ifdef TF_POOLABLE
static SfxItemInfo __READONLY_DATA aItemInfos[] =
{
    { 0, 0 }
};
#endif

//===================================================================

typedef Link* LinkPtr;
SV_DECL_PTRARR(SfxInitLinkList, LinkPtr, 4, 4);

TYPEINIT1(SfxSysChangeHint, SfxHint);
TYPEINIT2(SfxApplication,SfxShell,SfxBroadcaster);

//--------------------------------------------------------------------
void SfxApplication::Init
(
)

/*  [Beschreibung]

    Diese virtuelle Methode wird vom SFx aus Application:a:Main() gerufen,
    bevor Execute() ausgef"uhrt wird und
    - das Intro bereits angezeigt ist,
    - das Applikationsfenster exisitiert, aber noch hidden ist,
    - die Bindings bereits existieren (Controller sind anmeldbar),
    - der Ini- und Config-Manager bereits existiert,
    - die Standard-Controller bereits exisitieren,
    - die SFx-Shells ihre Interfaces bereits registriert haben.

    [Querverweise]
    <SfxApplication::Exit()>
    <SfxApplication::OpenClients()>
*/
{
#ifdef DDE_AVAILABLE
#ifdef PRODUCT
    InitializeDde();
#else
    if( !InitializeDde() )
    {
        ByteString aStr( "Kein DDE-Service moeglich. Fehler: " );
        if( GetDdeService() )
            aStr += GetDdeService()->GetError();
        else
            aStr += '?';
        DBG_ASSERT( sal_False, aStr.GetBuffer() )
    }
#endif
#endif
}

//--------------------------------------------------------------------

void SfxApplication::Exit()

/*  [Beschreibung]

    Diese virtuelle Methode wird vom SFx aus Application::Main() gerufen,
    nachdem Execute() beendet ist und
    - die Konfiguration (SfxConfigManager) bereits gespeichert wurde,
    - die Fensterpostionen etc. in den SfxIniManager geschrieben wurden,
    - das Applikationsfenster noch existiert, aber hidden ist
    - s"amtliche Dokumente und deren Views bereits geschlossen sind.
    - Dispatcher, Bindings etc. bereits zerst"ort sind

    [Querverweise]
    <SfxApplication::Init(int,char*[])>
*/

{
}

//---------------------------------------------------------------------------

void SfxApplication::PreInit( )
{
}

USHORT SfxApplication::ParseCommandLine_Impl()
{
    USHORT nEvents = 0;                 // return value ( event mask )

    BOOL   bPrintEvent = FALSE;
    BOOL   bOpenEvent  = TRUE;

    ::vos::OExtCommandLine aCmdLine;
    USHORT nCount = aCmdLine.getCommandArgCount();
    for( USHORT i=0; i < nCount; i++ )
    {
        String aArg;
        ::rtl::OUString aDummy;
        aCmdLine.getCommandArg( i, aDummy );
        aArg = aDummy;

        if ( aArg.EqualsIgnoreCaseAscii("-minimized") == sal_True )
            pAppData_Impl->bMinimized = TRUE;
        else if ( aArg.EqualsIgnoreCaseAscii("-invisible") == sal_True )
            pAppData_Impl->bInvisible = TRUE;
        else if ( aArg.EqualsIgnoreCaseAscii("-embedding") == sal_True )
            pAppData_Impl->nAppEvent |= DISPATCH_SERVER;
        else if ( aArg.EqualsIgnoreCaseAscii("-bean") == sal_True )
        {
            pAppData_Impl->bBean = TRUE;
            pAppData_Impl->bInvisible = TRUE;
        }
        else if ( aArg.EqualsIgnoreCaseAscii("-plugin") == sal_True )
        {
            pAppData_Impl->bBean = TRUE;
            pAppData_Impl->bInvisible = TRUE;
            pAppData_Impl->bPlugged = TRUE;
        }
        else if ( aArg.EqualsIgnoreCaseAscii("-server") )
            pAppData_Impl->bServer = true;
        else if ( aArg.CompareIgnoreCaseToAscii("-portal,",
                                                RTL_CONSTASCII_LENGTH(
                                                    "-portal,"))
                      == COMPARE_EQUAL )
            pAppData_Impl->aPortalConnect
                = aArg.Copy(RTL_CONSTASCII_LENGTH("-portal,"));

        const xub_Unicode* pArg = aArg.GetBuffer();
        // Erstmal nur mit -, da unter Unix Dateinmane auch mit Slasch anfangen koennen
        if ( (*pArg == '-') /* || (*pArg == '/') */ )
        {
            pArg++;

            // Ein Schalter
            if ( (*pArg == 'p') || (*pArg == 'P') )
            {
                bPrintEvent = TRUE;
                bOpenEvent = FALSE;    // Ab hier keine OpenEvents mehr
            }
        }
        else
        {
            // Dies wird als Dateiname interpretiert
            if ( bOpenEvent )
            {
                // Open Event anhaengen
                if ( pAppData_Impl->aOpenList.Len() )
                    pAppData_Impl->aOpenList += APPEVENT_PARAM_DELIMITER;
                pAppData_Impl->aOpenList += aArg;
            }
            else if ( bPrintEvent )
            {
                // Print Event anhaengen
                if( pAppData_Impl->aPrintList.Len() )
                    pAppData_Impl->aPrintList += APPEVENT_PARAM_DELIMITER;
                pAppData_Impl->aPrintList += aArg;
            }
        }
    }

    if ( pAppData_Impl->aOpenList.Len() )
        nEvents |= DISPATCH_OPEN;

    if ( pAppData_Impl->aPrintList.Len() )
        nEvents |= DISPATCH_PRINT;

    return nEvents;
}

//---------------------------------------------------------------------------
void SfxApplication::InitLabelResMgr( const char* pLabelPrefix )
{
    // Label-DLL mit diversen Resourcen fuer OEM-Ver. etc. (Intro, Titel, About)
    pAppData_Impl->bBean = FALSE;
    pAppData_Impl->nAppEvent = ParseCommandLine_Impl();
    if ( pLabelPrefix )
    {
        // versuchen, die Label-DLL zu erzeugen
        pAppData_Impl->pLabelResMgr = CreateResManager( pLabelPrefix );

        // keine separate Label-DLL vorhanden?
        if ( !pAppData_Impl->pLabelResMgr )
            // dann den ResMgr vom Executable verwenden
            pAppData_Impl->pLabelResMgr = new ResMgr;
    }
    else
    {
        pAppData_Impl->bBean = TRUE;
        pAppData_Impl->bInvisible = TRUE;
    }

    // merken, falls Applikation normal gestartet wurde
    if ( 0 == pAppData_Impl->nAppEvent || DISPATCH_OPEN == pAppData_Impl->nAppEvent )
        pAppData_Impl->bDirectAliveCount = TRUE;
}

void SfxApplication::Main( )
{
}

//--------------------------------------------------------------------
#if defined( MAC )
    void InstallAppleScriptHdl();
#endif

//-------------------------------------------------------------------------
void SfxApplication::InsertLateInitHdl(const Link& rLink)
{
    if ( Application::IsInExecute() )
        Application::PostUserEvent( rLink );
    else
    {
        if ( !pAppData_Impl->pInitLinkList )
            pAppData_Impl->pInitLinkList = new SfxInitLinkList;

        Link *pLink = new Link;
        *pLink = rLink;
        USHORT nCount = ( USHORT ) pAppData_Impl->pInitLinkList->Count();
        pAppData_Impl->pInitLinkList->Insert(pLink, nCount);
    }
}

void SfxApplication::ForcePendingInitFactories()
{
    List& rList = Get_Impl()->aPendingInitFactories;
    USHORT nPos = (USHORT) rList.Count();
#if LATEINIT
    DBG_ASSERT( !nPos, "Filter nicht im LateInit" );
#endif
    while( nPos = rList.Count() )
    {
        SfxObjectFactory* pFac = (SfxObjectFactory*)rList.Remove( --nPos );
        pFac->DoInitFactory();
    }
}

//-------------------------------------------------------------------------

IMPL_LINK( SfxApplication, LateInitTimerHdl_Impl, void*, pvoid)
{
    if ( !SfxViewFrame::GetFirst( 0,0,FALSE ) )
    {
        pAppData_Impl->aLateInitTimer.Start();
        return 0;
    }

    // Ersten Link aus der Liste holen und ausf"uhren
    Link *pLink = (*pAppData_Impl->pInitLinkList)[0];
    pLink->Call(0);

    // Link entfernen
    pAppData_Impl->pInitLinkList->Remove(0);
    delete pLink;

    // Timer wieder starten, wenn noch weitere Links da sind
    if ( pAppData_Impl->pInitLinkList->Count() )
        pAppData_Impl->aLateInitTimer.Start();
    else
    {
        // LateInit ist fertig
        DELETEZ (pAppData_Impl->pInitLinkList);
#if SUPD<613//MUSTINI
        pAppIniMgr->ResetLock();
#endif
    }
    return 0;
}

//-------------------------------------------------------------------------

//-------------------------------------------------------------------------

SfxFilterMatcher& SfxApplication::GetFilterMatcher()
{
    if( !pAppData_Impl->pMatcher )
    {
        pAppData_Impl->pMatcher = new SfxFilterMatcher();
        URIHelper::SetMaybeFileHdl( STATIC_LINK(
            pAppData_Impl->pMatcher, SfxFilterMatcher, MaybeFileHdl_Impl ) );
    }
    return *pAppData_Impl->pMatcher;
}<commit_msg>INTEGRATION: CWS layoutmanager (1.14.124); FILE MERGED 2004/02/19 17:08:03 cd 1.14.124.4: RESYNC: (1.16-1.17); FILE MERGED 2004/01/29 19:47:46 cd 1.14.124.3: RESYNC: (1.15-1.16); FILE MERGED 2003/10/06 11:49:24 cd 1.14.124.2: RESYNC: (1.14-1.15); FILE MERGED 2003/08/20 16:05:05 cd 1.14.124.1: 111899# Framework based user interface preparation<commit_after>/*************************************************************************
 *
 *  $RCSfile: appmain.cxx,v $
 *
 *  $Revision: 1.18 $
 *
 *  last change: $Author: kz $ $Date: 2004-02-25 15:41:14 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

//#define TF_NEWDESKTOP

#define _SDINTERN_HXX

#pragma hdrstop

#ifndef _PVER_HXX //autogen
#include <svtools/pver.hxx>
#endif
#ifndef _URLOBJ_HXX //autogen
#include <tools/urlobj.hxx>
#endif
#if SUPD<613//MUSTINI
#ifndef _SFXINIMGR_HXX //autogen
#include <svtools/iniman.hxx>
#endif
#endif
#ifndef _CSTITEM_HXX //autogen
#include <svtools/cstitem.hxx>
#endif
#ifndef _CONFIG_HXX
#include <tools/config.hxx>
#endif
#ifndef _EHDL_HXX
#include <svtools/ehdl.hxx>
#endif
#ifndef INCLUDED_SVTOOLS_STARTOPTIONS_HXX
#include <svtools/startoptions.hxx>
#endif
#include <svtools/itempool.hxx>
#include <svtools/urihelper.hxx>
#include <svtools/helpopt.hxx>
#include <vos/process.hxx>
#include <framework/sfxhelperfunctions.hxx>

#include "appimp.hxx"
#include "sfxtypes.hxx"
#include "appdata.hxx"
#include "docfac.hxx"
#include "app.hxx"
#include "arrdecl.hxx"
#include "dispatch.hxx"
#include "sfxresid.hxx"
#include "interno.hxx"
#include "fcontnr.hxx"
#include "viewsh.hxx"
#include "intro.hxx"
#include "msgpool.hxx"
#include "cfgmgr.hxx"
#include "accmgr.hxx"
#include "mnumgr.hxx"
#include "stbmgr.hxx"
#include "imgmgr.hxx"
#include "appuno.hxx"
#include "objuno.hxx"
#include "app.hrc"
#include "docfile.hxx"
#include "workwin.hxx"
#if SUPD<613//MUSTINI
#include "inimgr.hxx"
#endif

#ifdef WNT
#include <tools/svwin.h>
#endif

#ifdef UNX
#define stricmp(a,b) strcmp(a,b)
#endif

//===================================================================

/*DBG_NAME(SfxAppMainIntro);
DBG_NAME(SfxAppMainSO_Init);
DBG_NAME(SfxAppMainAppRes);
DBG_NAME(SfxAppMainInit0);
DBG_NAME(SfxAppMainCreateAppWin);
DBG_NAME(SfxAppMainInit1);
DBG_NAME(SfxAppMainCfgMgr);
DBG_NAME(SfxAppMainInitController);
DBG_NAME(SfxAppMainInitException);
DBG_NAME(SfxAppMainRegisterIF);
DBG_NAME(SfxAppMainInit);
DBG_NAME(SfxAppMainLoadBasMgr);
DBG_NAME(SfxAppMainSbxInit);*/
DBG_NAME(SfxAppMainNewMenu);
DBG_NAME(SfxAppMainBmkMenu);
DBG_NAME(SfxAppMainWizMenu);
DBG_NAME(SfxAppMainOLEReg);
DBG_NAME(SfxAppMainCHAOSReg);
/*DBG_NAME(SfxAppMainInitDispatcher);
DBG_NAME(SfxAppMainLoadConfig);
DBG_NAME(SfxAppMainInitAppWin);
DBG_NAME(SfxAppMainAppEvents);*/

//===================================================================

#define SFX_TEMPNAMEBASE_DIR    "soffice.tmp"
#define SFX_KEY_TEMPNAMEBASE    "Temp-Dir"

//===================================================================

#pragma code_seg("STATICS")
static SfxVoidItem aStaticDefault(1);
#pragma code_seg()

static SfxPoolItem* aStaticDefaults[1] =
{
    &aStaticDefault
};

#ifdef TF_POOLABLE
static SfxItemInfo __READONLY_DATA aItemInfos[] =
{
    { 0, 0 }
};
#endif

//===================================================================

typedef Link* LinkPtr;
SV_DECL_PTRARR(SfxInitLinkList, LinkPtr, 4, 4);

TYPEINIT1(SfxSysChangeHint, SfxHint);
TYPEINIT2(SfxApplication,SfxShell,SfxBroadcaster);

//--------------------------------------------------------------------
void SfxApplication::Init
(
)

/*  [Beschreibung]

    Diese virtuelle Methode wird vom SFx aus Application:a:Main() gerufen,
    bevor Execute() ausgef"uhrt wird und
    - das Intro bereits angezeigt ist,
    - das Applikationsfenster exisitiert, aber noch hidden ist,
    - die Bindings bereits existieren (Controller sind anmeldbar),
    - der Ini- und Config-Manager bereits existiert,
    - die Standard-Controller bereits exisitieren,
    - die SFx-Shells ihre Interfaces bereits registriert haben.

    [Querverweise]
    <SfxApplication::Exit()>
    <SfxApplication::OpenClients()>
*/
{
#ifdef DDE_AVAILABLE
#ifdef PRODUCT
    InitializeDde();
#else
    if( !InitializeDde() )
    {
        ByteString aStr( "Kein DDE-Service moeglich. Fehler: " );
        if( GetDdeService() )
            aStr += GetDdeService()->GetError();
        else
            aStr += '?';
        DBG_ASSERT( sal_False, aStr.GetBuffer() )
    }
#endif
#endif
    SetToolBoxCreator( CreateToolBox );
}

//--------------------------------------------------------------------

void SfxApplication::Exit()

/*  [Beschreibung]

    Diese virtuelle Methode wird vom SFx aus Application::Main() gerufen,
    nachdem Execute() beendet ist und
    - die Konfiguration (SfxConfigManager) bereits gespeichert wurde,
    - die Fensterpostionen etc. in den SfxIniManager geschrieben wurden,
    - das Applikationsfenster noch existiert, aber hidden ist
    - s"amtliche Dokumente und deren Views bereits geschlossen sind.
    - Dispatcher, Bindings etc. bereits zerst"ort sind

    [Querverweise]
    <SfxApplication::Init(int,char*[])>
*/

{
}

//---------------------------------------------------------------------------

void SfxApplication::PreInit( )
{
}

USHORT SfxApplication::ParseCommandLine_Impl()
{
    USHORT nEvents = 0;                 // return value ( event mask )

    BOOL   bPrintEvent = FALSE;
    BOOL   bOpenEvent  = TRUE;

    ::vos::OExtCommandLine aCmdLine;
    USHORT nCount = aCmdLine.getCommandArgCount();
    for( USHORT i=0; i < nCount; i++ )
    {
        String aArg;
        ::rtl::OUString aDummy;
        aCmdLine.getCommandArg( i, aDummy );
        aArg = aDummy;

        if ( aArg.EqualsIgnoreCaseAscii("-minimized") == sal_True )
            pAppData_Impl->bMinimized = TRUE;
        else if ( aArg.EqualsIgnoreCaseAscii("-invisible") == sal_True )
            pAppData_Impl->bInvisible = TRUE;
        else if ( aArg.EqualsIgnoreCaseAscii("-embedding") == sal_True )
            pAppData_Impl->nAppEvent |= DISPATCH_SERVER;
        else if ( aArg.EqualsIgnoreCaseAscii("-bean") == sal_True )
        {
            pAppData_Impl->bBean = TRUE;
            pAppData_Impl->bInvisible = TRUE;
        }
        else if ( aArg.EqualsIgnoreCaseAscii("-plugin") == sal_True )
        {
            pAppData_Impl->bBean = TRUE;
            pAppData_Impl->bInvisible = TRUE;
            pAppData_Impl->bPlugged = TRUE;
        }
        else if ( aArg.EqualsIgnoreCaseAscii("-server") )
            pAppData_Impl->bServer = true;
        else if ( aArg.CompareIgnoreCaseToAscii("-portal,",
                                                RTL_CONSTASCII_LENGTH(
                                                    "-portal,"))
                      == COMPARE_EQUAL )
            pAppData_Impl->aPortalConnect
                = aArg.Copy(RTL_CONSTASCII_LENGTH("-portal,"));

        const xub_Unicode* pArg = aArg.GetBuffer();
        // Erstmal nur mit -, da unter Unix Dateinmane auch mit Slasch anfangen koennen
        if ( (*pArg == '-') /* || (*pArg == '/') */ )
        {
            pArg++;

            // Ein Schalter
            if ( (*pArg == 'p') || (*pArg == 'P') )
            {
                bPrintEvent = TRUE;
                bOpenEvent = FALSE;    // Ab hier keine OpenEvents mehr
            }
        }
        else
        {
            // Dies wird als Dateiname interpretiert
            if ( bOpenEvent )
            {
                // Open Event anhaengen
                if ( pAppData_Impl->aOpenList.Len() )
                    pAppData_Impl->aOpenList += APPEVENT_PARAM_DELIMITER;
                pAppData_Impl->aOpenList += aArg;
            }
            else if ( bPrintEvent )
            {
                // Print Event anhaengen
                if( pAppData_Impl->aPrintList.Len() )
                    pAppData_Impl->aPrintList += APPEVENT_PARAM_DELIMITER;
                pAppData_Impl->aPrintList += aArg;
            }
        }
    }

    if ( pAppData_Impl->aOpenList.Len() )
        nEvents |= DISPATCH_OPEN;

    if ( pAppData_Impl->aPrintList.Len() )
        nEvents |= DISPATCH_PRINT;

    return nEvents;
}

//---------------------------------------------------------------------------
void SfxApplication::InitLabelResMgr( const char* pLabelPrefix )
{
    // Label-DLL mit diversen Resourcen fuer OEM-Ver. etc. (Intro, Titel, About)
    pAppData_Impl->bBean = FALSE;
    pAppData_Impl->nAppEvent = ParseCommandLine_Impl();
    if ( pLabelPrefix )
    {
        // versuchen, die Label-DLL zu erzeugen
        pAppData_Impl->pLabelResMgr = CreateResManager( pLabelPrefix );

        // keine separate Label-DLL vorhanden?
        if ( !pAppData_Impl->pLabelResMgr )
            // dann den ResMgr vom Executable verwenden
            pAppData_Impl->pLabelResMgr = new ResMgr;
    }
    else
    {
        pAppData_Impl->bBean = TRUE;
        pAppData_Impl->bInvisible = TRUE;
    }

    // merken, falls Applikation normal gestartet wurde
    if ( 0 == pAppData_Impl->nAppEvent || DISPATCH_OPEN == pAppData_Impl->nAppEvent )
        pAppData_Impl->bDirectAliveCount = TRUE;
}

void SfxApplication::Main( )
{
}

//--------------------------------------------------------------------
#if defined( MAC )
    void InstallAppleScriptHdl();
#endif

//-------------------------------------------------------------------------
void SfxApplication::InsertLateInitHdl(const Link& rLink)
{
    if ( Application::IsInExecute() )
        Application::PostUserEvent( rLink );
    else
    {
        if ( !pAppData_Impl->pInitLinkList )
            pAppData_Impl->pInitLinkList = new SfxInitLinkList;

        Link *pLink = new Link;
        *pLink = rLink;
        USHORT nCount = ( USHORT ) pAppData_Impl->pInitLinkList->Count();
        pAppData_Impl->pInitLinkList->Insert(pLink, nCount);
    }
}

void SfxApplication::ForcePendingInitFactories()
{
    List& rList = Get_Impl()->aPendingInitFactories;
    USHORT nPos = (USHORT) rList.Count();
#if LATEINIT
    DBG_ASSERT( !nPos, "Filter nicht im LateInit" );
#endif
    while( nPos = rList.Count() )
    {
        SfxObjectFactory* pFac = (SfxObjectFactory*)rList.Remove( --nPos );
        pFac->DoInitFactory();
    }
}

//-------------------------------------------------------------------------

IMPL_LINK( SfxApplication, LateInitTimerHdl_Impl, void*, pvoid)
{
    if ( !SfxViewFrame::GetFirst( 0,0,FALSE ) )
    {
        pAppData_Impl->aLateInitTimer.Start();
        return 0;
    }

    // Ersten Link aus der Liste holen und ausf"uhren
    Link *pLink = (*pAppData_Impl->pInitLinkList)[0];
    pLink->Call(0);

    // Link entfernen
    pAppData_Impl->pInitLinkList->Remove(0);
    delete pLink;

    // Timer wieder starten, wenn noch weitere Links da sind
    if ( pAppData_Impl->pInitLinkList->Count() )
        pAppData_Impl->aLateInitTimer.Start();
    else
    {
        // LateInit ist fertig
        DELETEZ (pAppData_Impl->pInitLinkList);
#if SUPD<613//MUSTINI
        pAppIniMgr->ResetLock();
#endif
    }
    return 0;
}

//-------------------------------------------------------------------------

//-------------------------------------------------------------------------

SfxFilterMatcher& SfxApplication::GetFilterMatcher()
{
    if( !pAppData_Impl->pMatcher )
    {
        pAppData_Impl->pMatcher = new SfxFilterMatcher();
        URIHelper::SetMaybeFileHdl( STATIC_LINK(
            pAppData_Impl->pMatcher, SfxFilterMatcher, MaybeFileHdl_Impl ) );
    }
    return *pAppData_Impl->pMatcher;
}<|endoftext|>


<commit_before>#pragma once

#include <ContinuousArtScroller.h>
#include <MeshFactory.h>
#include <MeshInterface.h>
#include <Texture.h>
#include <sstream>
#include <MY_ResourceManager.h>

ContinuousArtScroller::ContinuousArtScroller(std::string _fileDir, ComponentShaderBase * _shader) :
	ArtLayer(dynamic_cast<ShaderComponentReplace *>(_shader->getComponentAt(2))),
	fileDir(_fileDir),
	imageId(1),
	imageCount(0),
	progress(0),
	numPlanes(4)
{
	while (true){
		++imageCount;
		std::stringstream src;
		src << "assets/textures/" << fileDir << "/";
		if(imageCount < 10){
			src << "0";
		}
		src << imageCount << ".png";
		if (!FileUtils::fileExists(src.str())){
			break;
		}
		Texture * texture = new Texture(src.str(), true, false);
		texture->loadImageData();
		images.push_back(texture);
	}

	MeshInterface * m = MeshFactory::getPlaneMesh();
	m->configureDefaultVertexAttributes(_shader);
	m->pushTexture2D(MY_ResourceManager::scenario->defaultTexture->texture);
	m->scaleModeMag = m->scaleModeMin = GL_NEAREST;

	for(unsigned long int i = 0; i < numPlanes; ++i){
		MeshEntity * plane = new MeshEntity(MeshFactory::getPlaneMesh(), _shader);
		loadTexOntoPlane(i+1, plane);

		plane->mesh->scaleModeMag = plane->mesh->scaleModeMin = GL_NEAREST;
		plane->meshTransform->addChild(m)->translate(0, -1, 0);
		childTransform->addChild(plane)->translate(i,0,0);
		planes.push_back(plane);
	}
	m->referenceCount += numPlanes;

	backPlane = 0;
	frontPlane = numPlanes-1;
}

ContinuousArtScroller::~ContinuousArtScroller(){
	// remove any active textures so they aren't delete twice
	for(MeshEntity * e : planes){
		while(e->mesh->textures.size() > 0){
			e->mesh->textures.at(0)->unload();
			e->mesh->removeTextureAt(0);
		}
	}

	// delete textures
	while (images.size() > 0){
		delete images.back();
		images.pop_back();
	}
}

void ContinuousArtScroller::cycle(signed long int _delta){
	imageId += _delta;

	if (_delta > 0){
		loadTexOntoPlane(imageId+(numPlanes/2+1), planes.at(backPlane));
		planes.at(backPlane)->firstParent()->translate(numPlanes, 0, 0);

		frontPlane = backPlane;
		++backPlane;
		if(backPlane >= numPlanes){
			backPlane = 0;
		}
	}else{
		loadTexOntoPlane(imageId, planes.at(frontPlane));
		planes.at(frontPlane)->firstParent()->translate(-(signed long int)numPlanes, 0, 0);

		backPlane = frontPlane;
		--frontPlane;
		if(frontPlane >= numPlanes){
			frontPlane = numPlanes-1;
		}
	}
}

void ContinuousArtScroller::loadTexOntoPlane(unsigned long int _texId, MeshEntity * _plane){
	while(_plane->mesh->textures.size() > 0){
		_plane->mesh->textures.at(0)->unload();
		_plane->mesh->removeTextureAt(0);
	}
	if (_texId < images.size()){
		_plane->mesh->pushTexture2D(images.at(_texId));
	}else{
		_plane->mesh->pushTexture2D(MY_ResourceManager::scenario->getTexture("DEFAULT")->texture);
	}
	_plane->mesh->textures.at(0)->load();
}

void ContinuousArtScroller::update(Step * _step){
	while (imageId - progress < -(signed long int)numPlanes/2){
		cycle(1);
	}while (imageId - progress > -(signed long int)numPlanes/2+1){
		cycle(-1);
	}

	Entity::update(_step);
}<commit_msg>no mipmaps on art layers<commit_after>#pragma once

#include <ContinuousArtScroller.h>
#include <MeshFactory.h>
#include <MeshInterface.h>
#include <Texture.h>
#include <sstream>
#include <MY_ResourceManager.h>

ContinuousArtScroller::ContinuousArtScroller(std::string _fileDir, ComponentShaderBase * _shader) :
	ArtLayer(dynamic_cast<ShaderComponentReplace *>(_shader->getComponentAt(2))),
	fileDir(_fileDir),
	imageId(1),
	imageCount(0),
	progress(0),
	numPlanes(4)
{
	while (true){
		++imageCount;
		std::stringstream src;
		src << "assets/textures/" << fileDir << "/";
		if(imageCount < 10){
			src << "0";
		}
		src << imageCount << ".png";
		if (!FileUtils::fileExists(src.str())){
			break;
		}
		Texture * texture = new Texture(src.str(), true, false, false);
		texture->loadImageData();
		images.push_back(texture);
	}

	MeshInterface * m = MeshFactory::getPlaneMesh();
	m->configureDefaultVertexAttributes(_shader);
	m->pushTexture2D(MY_ResourceManager::scenario->defaultTexture->texture);
	m->scaleModeMag = m->scaleModeMin = GL_NEAREST;

	for(unsigned long int i = 0; i < numPlanes; ++i){
		MeshEntity * plane = new MeshEntity(MeshFactory::getPlaneMesh(), _shader);
		loadTexOntoPlane(i+1, plane);

		plane->mesh->scaleModeMag = plane->mesh->scaleModeMin = GL_NEAREST;
		plane->meshTransform->addChild(m)->translate(0, -1, 0);
		childTransform->addChild(plane)->translate(i,0,0);
		planes.push_back(plane);
	}
	m->referenceCount += numPlanes;

	backPlane = 0;
	frontPlane = numPlanes-1;
}

ContinuousArtScroller::~ContinuousArtScroller(){
	// remove any active textures so they aren't delete twice
	for(MeshEntity * e : planes){
		while(e->mesh->textures.size() > 0){
			e->mesh->textures.at(0)->unload();
			e->mesh->removeTextureAt(0);
		}
	}

	// delete textures
	while (images.size() > 0){
		delete images.back();
		images.pop_back();
	}
}

void ContinuousArtScroller::cycle(signed long int _delta){
	imageId += _delta;

	if (_delta > 0){
		loadTexOntoPlane(imageId+(numPlanes/2+1), planes.at(backPlane));
		planes.at(backPlane)->firstParent()->translate(numPlanes, 0, 0);

		frontPlane = backPlane;
		++backPlane;
		if(backPlane >= numPlanes){
			backPlane = 0;
		}
	}else{
		loadTexOntoPlane(imageId, planes.at(frontPlane));
		planes.at(frontPlane)->firstParent()->translate(-(signed long int)numPlanes, 0, 0);

		backPlane = frontPlane;
		--frontPlane;
		if(frontPlane >= numPlanes){
			frontPlane = numPlanes-1;
		}
	}
}

void ContinuousArtScroller::loadTexOntoPlane(unsigned long int _texId, MeshEntity * _plane){
	while(_plane->mesh->textures.size() > 0){
		_plane->mesh->textures.at(0)->unload();
		_plane->mesh->removeTextureAt(0);
	}
	if (_texId < images.size()){
		_plane->mesh->pushTexture2D(images.at(_texId));
	}else{
		_plane->mesh->pushTexture2D(MY_ResourceManager::scenario->getTexture("DEFAULT")->texture);
	}
	_plane->mesh->textures.at(0)->load();
}

void ContinuousArtScroller::update(Step * _step){
	while (imageId - progress < -(signed long int)numPlanes/2){
		cycle(1);
	}while (imageId - progress > -(signed long int)numPlanes/2+1){
		cycle(-1);
	}

	Entity::update(_step);
}<|endoftext|>


<commit_before>/*
 * This file is part of Maliit Plugins
 *
 * Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
 *
 * Contact: Mohammad Anwari <Mohammad.Anwari@nokia.com>
 *
 * 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 Nokia Corporation 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 OWNER 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 "wordengine.h"
#include "spellchecker.h"

#ifdef HAVE_PRESAGE
#include <presage.h>
#endif

namespace MaliitKeyboard {
namespace Logic {

#ifdef HAVE_PRESAGE
class CandidatesCallback
    : public PresageCallback
{
private:
    const std::string& m_past_context;
    const std::string m_empty;

public:
    explicit CandidatesCallback(const std::string& past_context);

    std::string get_past_stream() const;
    std::string get_future_stream() const;
};

CandidatesCallback::CandidatesCallback(const std::string &past_context)
    : m_past_context(past_context)
    , m_empty()
{}

std::string CandidatesCallback::get_past_stream() const
{
    return m_past_context;
}

std::string CandidatesCallback::get_future_stream() const
{
    return m_empty;
}
#endif

class WordEnginePrivate
{
public:
    QStringList candidates;
    SpellChecker spell_checker;
#ifdef HAVE_PRESAGE
    std::string candidates_context;
    CandidatesCallback presage_candidates;
    Presage presage;
#endif

    explicit WordEnginePrivate();
};

WordEnginePrivate::WordEnginePrivate()
    : candidates()
    , spell_checker()
#ifdef HAVE_PRESAGE
    , candidates_context()
    , presage_candidates(CandidatesCallback(candidates_context))
    , presage(&presage_candidates)
#endif
{}

WordEngine::WordEngine(QObject *parent)
    : QObject(parent)
    , d_ptr(new WordEnginePrivate)
{}

WordEngine::~WordEngine()
{}

void WordEngine::onTextChanged(const Model::SharedText &text)
{
    if (text.isNull()) {
        qWarning() << __PRETTY_FUNCTION__
                   << "No text model specified.";
    }

    Q_D(WordEngine);

    const QString &preedit(text->preedit());
    if (preedit.isEmpty()) {
        if (not d->candidates.isEmpty()) {
            d->candidates.clear();
            Q_EMIT candidatesUpdated(d->candidates);
        }
        return;
    }

    d->candidates.clear();

#ifdef HAVE_PRESAGE
    // FIXME: Using surroundingLeft + preedit throws an exception in presage.
    // Using only preedit for now.
    const QString &context = preedit;
    d->candidates_context = context.toStdString();

    const std::vector<std::string> predictions = d->presage.predict();

    // TODO: Fine-tune presage behaviour to also perform error correction, not just word prediction.
    if (not context.isEmpty()) {
        // FIXME: max_candidates should come from style, too:
        const static unsigned int max_candidates = 7;
        const int count(qMin<int>(predictions.size(), max_candidates));
        for (int index = 0; index < count; ++index) {
            const QString &prediction(QString::fromStdString(predictions.at(index)));

            if (d->candidates.contains(prediction)) {
                continue;
            }

            d->candidates.append(prediction);
        }
    }
#endif

    if (d->candidates.isEmpty()) {
        d->candidates.append(d->spell_checker.suggest(preedit, 5));
    }

    Q_EMIT candidatesUpdated(d->candidates);
}

}} // namespace Logic, MaliitKeyboard
<commit_msg>Set Presage config and use surrounding text<commit_after>/*
 * This file is part of Maliit Plugins
 *
 * Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
 *
 * Contact: Mohammad Anwari <Mohammad.Anwari@nokia.com>
 *
 * 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 Nokia Corporation 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 OWNER 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 "wordengine.h"
#include "spellchecker.h"

#include <iostream>
#ifdef HAVE_PRESAGE
#include <presage.h>
#endif

namespace MaliitKeyboard {
namespace Logic {

#ifdef HAVE_PRESAGE
class CandidatesCallback
    : public PresageCallback
{
private:
    const std::string& m_past_context;
    const std::string m_empty;

public:
    explicit CandidatesCallback(const std::string& past_context);

    std::string get_past_stream() const;
    std::string get_future_stream() const;
};

CandidatesCallback::CandidatesCallback(const std::string &past_context)
    : m_past_context(past_context)
    , m_empty()
{}

std::string CandidatesCallback::get_past_stream() const
{
    return m_past_context;
}

std::string CandidatesCallback::get_future_stream() const
{
    return m_empty;
}
#endif

class WordEnginePrivate
{
public:
    QStringList candidates;
    SpellChecker spell_checker;
#ifdef HAVE_PRESAGE
    std::string candidates_context;
    CandidatesCallback presage_candidates;
    Presage presage;
#endif

    explicit WordEnginePrivate();
};

WordEnginePrivate::WordEnginePrivate()
    : candidates()
    , spell_checker()
#ifdef HAVE_PRESAGE
    , candidates_context()
    , presage_candidates(CandidatesCallback(candidates_context))
    , presage(&presage_candidates)
#endif
{
#ifdef HAVE_PRESAGE
    presage.config("Presage.Selector.SUGGESTIONS", "6");
    presage.config("Presage.Selector.REPEAT_SUGGESTIONS", "yes");
#endif
}

WordEngine::WordEngine(QObject *parent)
    : QObject(parent)
    , d_ptr(new WordEnginePrivate)
{}

WordEngine::~WordEngine()
{}

void WordEngine::onTextChanged(const Model::SharedText &text)
{
    if (text.isNull()) {
        qWarning() << __PRETTY_FUNCTION__
                   << "No text model specified.";
    }

    Q_D(WordEngine);

    const QString &preedit(text->preedit());
    if (preedit.isEmpty()) {
        if (not d->candidates.isEmpty()) {
            d->candidates.clear();
            Q_EMIT candidatesUpdated(d->candidates);
        }
        return;
    }

    d->candidates.clear();

#ifdef HAVE_PRESAGE
    // FIXME: Using surroundingLeft + preedit throws an exception in presage.
    // Using only preedit for now.
    const QString &context = (text->surroundingLeft() + preedit);
    d->candidates_context = context.toStdString();
    const std::vector<std::string> predictions = d->presage.predict();

    // TODO: Fine-tune presage behaviour to also perform error correction, not just word prediction.
    if (not context.isEmpty()) {
        // FIXME: max_candidates should come from style, too:
        const static unsigned int max_candidates = 7;
        const int count(qMin<int>(predictions.size(), max_candidates));
        for (int index = 0; index < count; ++index) {
            const QString &prediction(QString::fromStdString(predictions.at(index)));

            if (d->candidates.contains(prediction)) {
                continue;
            }

            d->candidates.append(prediction);
        }
    }
#endif

    if (d->candidates.isEmpty()) {
        d->candidates.append(d->spell_checker.suggest(preedit, 5));
    }

    Q_EMIT candidatesUpdated(d->candidates);
}

}} // namespace Logic, MaliitKeyboard
<|endoftext|>


<commit_before>//===------------------------- incomplete_type.cpp --------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// http://mentorembedded.github.io/cxx-abi/abi.html#rtti-layout

// Two abi::__pbase_type_info objects can always be compared for equality
// (i.e. of the types represented) or ordering by comparison of their name
// NTBS addresses. In addition, unless either or both have either of the
// incomplete flags set, equality can be tested by comparing the type_info
// addresses.

// RUN: %cxx %flags %compile_flags -c %s -o %t.one.o
// RUN: %cxx %flags %compile_flags -c %s -o %t.two.o -DTU_ONE
// RUN: %cxx %flags %link_flags -o %t.exe %t.one.o %t.two.o
// RUN: %exec %t.exe

#include <stdio.h>
#include <cstring>
#include <cassert>
#include <typeinfo>

// Check that the addresses of the typeinfo differ but still compare equal
// via their NTBS.
inline void
AssertIncompleteTypeInfoEquals(std::type_info const& LHS, std::type_info const& RHS)
{
  assert(&LHS != &RHS);
  assert(strcmp(LHS.name(), RHS.name()) == 0);
}

struct NeverDefined;
void ThrowNeverDefinedMP();
std::type_info const& ReturnTypeInfoNeverDefinedMP();

struct IncompleteAtThrow;
void ThrowIncompleteMP();
void ThrowIncompletePP();
void ThrowIncompletePMP();
std::type_info const& ReturnTypeInfoIncompleteMP();
std::type_info const& ReturnTypeInfoIncompletePP();

struct CompleteAtThrow;
void ThrowCompleteMP();
void ThrowCompletePP();
void ThrowCompletePMP();
std::type_info const& ReturnTypeInfoCompleteMP();
std::type_info const& ReturnTypeInfoCompletePP();

void ThrowNullptr();

#ifndef TU_ONE

void ThrowNeverDefinedMP() { throw (int NeverDefined::*)nullptr; }
std::type_info const& ReturnTypeInfoNeverDefinedMP() { return typeid(int NeverDefined::*); }

void ThrowIncompleteMP() { throw (int IncompleteAtThrow::*)nullptr; }
void ThrowIncompletePP() { throw (IncompleteAtThrow**)nullptr; }
void ThrowIncompletePMP() { throw (int IncompleteAtThrow::**)nullptr; }
std::type_info const& ReturnTypeInfoIncompleteMP() { return typeid(int IncompleteAtThrow::*); }
std::type_info const& ReturnTypeInfoIncompletePP() { return typeid(IncompleteAtThrow**); }

struct CompleteAtThrow {};
void ThrowCompleteMP() { throw (int CompleteAtThrow::*)nullptr; }
void ThrowCompletePP() { throw (CompleteAtThrow**)nullptr; }
void ThrowCompletePMP() { throw (int CompleteAtThrow::**)nullptr; }
std::type_info const& ReturnTypeInfoCompleteMP() { return typeid(int CompleteAtThrow::*); }
std::type_info const& ReturnTypeInfoCompletePP() { return typeid(CompleteAtThrow**); }

void ThrowNullptr() { throw nullptr; }

#else

struct IncompleteAtThrow {};

int main() {
  AssertIncompleteTypeInfoEquals(ReturnTypeInfoNeverDefinedMP(), typeid(int NeverDefined::*));
  try {
    ThrowNeverDefinedMP();
    assert(false);
  } catch (int IncompleteAtThrow::*) {
    assert(false);
  } catch (int CompleteAtThrow::*) {
    assert(false);
  } catch (int NeverDefined::*) {}
  AssertIncompleteTypeInfoEquals(ReturnTypeInfoIncompleteMP(), typeid(int IncompleteAtThrow::*));
  try {
    ThrowIncompleteMP();
    assert(false);
  } catch (CompleteAtThrow**) {
    assert(false);
  } catch (int CompleteAtThrow::*) {
    assert(false);
  } catch (IncompleteAtThrow**) {
    assert(false);
  } catch (int IncompleteAtThrow::*) {}

  AssertIncompleteTypeInfoEquals(ReturnTypeInfoIncompletePP(), typeid(IncompleteAtThrow**));
  try {
    ThrowIncompletePP();
    assert(false);
  } catch (int IncompleteAtThrow::*) {
    assert(false);
  } catch (IncompleteAtThrow**) {}

  try {
    ThrowIncompletePMP();
    assert(false);
  } catch (int IncompleteAtThrow::*) {
    assert(false);
  } catch (IncompleteAtThrow**) {
    assert(false);
  } catch (int IncompleteAtThrow::**) {}

  AssertIncompleteTypeInfoEquals(ReturnTypeInfoCompleteMP(), typeid(int CompleteAtThrow::*));
  try {
    ThrowCompleteMP();
    assert(false);
  } catch (IncompleteAtThrow**) {
    assert(false);
  } catch (int IncompleteAtThrow::*) {
    assert(false);
  } catch (CompleteAtThrow**) {
    assert(false);
  } catch (int CompleteAtThrow::*) {}

  AssertIncompleteTypeInfoEquals(ReturnTypeInfoCompletePP(), typeid(CompleteAtThrow**));
  try {
    ThrowCompletePP();
    assert(false);
  } catch (IncompleteAtThrow**) {
    assert(false);
  } catch (int IncompleteAtThrow::*) {
    assert(false);
  } catch (int CompleteAtThrow::*) {
    assert(false);
  } catch (CompleteAtThrow**) {}

  try {
    ThrowCompletePMP();
    assert(false);
  } catch (IncompleteAtThrow**) {
    assert(false);
  } catch (int IncompleteAtThrow::*) {
    assert(false);
  } catch (int CompleteAtThrow::*) {
    assert(false);
  } catch (CompleteAtThrow**) {
    assert(false);
  } catch (int CompleteAtThrow::**) {}

#if __cplusplus >= 201103L
  // Catch nullptr as complete type
  try {
    ThrowNullptr();
  } catch (int IncompleteAtThrow::*) {}

  // Catch nullptr as an incomplete type
  try {
    ThrowNullptr();
  } catch (int CompleteAtThrow::*) {}
  // Catch nullptr as a type that is never complete.
  try {
    ThrowNullptr();
  } catch (int NeverDefined::*) {}
#endif
}
#endif
<commit_msg>Fix link flags order in RUN command.<commit_after>//===------------------------- incomplete_type.cpp --------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// http://mentorembedded.github.io/cxx-abi/abi.html#rtti-layout

// Two abi::__pbase_type_info objects can always be compared for equality
// (i.e. of the types represented) or ordering by comparison of their name
// NTBS addresses. In addition, unless either or both have either of the
// incomplete flags set, equality can be tested by comparing the type_info
// addresses.

// RUN: %cxx %flags %compile_flags -c %s -o %t.one.o
// RUN: %cxx %flags %compile_flags -c %s -o %t.two.o -DTU_ONE
// RUN: %cxx %flags %t.one.o %t.two.o %link_flags -o %t.exe
// RUN: %exec %t.exe

#include <stdio.h>
#include <cstring>
#include <cassert>
#include <typeinfo>

// Check that the addresses of the typeinfo differ but still compare equal
// via their NTBS.
inline void
AssertIncompleteTypeInfoEquals(std::type_info const& LHS, std::type_info const& RHS)
{
  assert(&LHS != &RHS);
  assert(strcmp(LHS.name(), RHS.name()) == 0);
}

struct NeverDefined;
void ThrowNeverDefinedMP();
std::type_info const& ReturnTypeInfoNeverDefinedMP();

struct IncompleteAtThrow;
void ThrowIncompleteMP();
void ThrowIncompletePP();
void ThrowIncompletePMP();
std::type_info const& ReturnTypeInfoIncompleteMP();
std::type_info const& ReturnTypeInfoIncompletePP();

struct CompleteAtThrow;
void ThrowCompleteMP();
void ThrowCompletePP();
void ThrowCompletePMP();
std::type_info const& ReturnTypeInfoCompleteMP();
std::type_info const& ReturnTypeInfoCompletePP();

void ThrowNullptr();

#ifndef TU_ONE

void ThrowNeverDefinedMP() { throw (int NeverDefined::*)nullptr; }
std::type_info const& ReturnTypeInfoNeverDefinedMP() { return typeid(int NeverDefined::*); }

void ThrowIncompleteMP() { throw (int IncompleteAtThrow::*)nullptr; }
void ThrowIncompletePP() { throw (IncompleteAtThrow**)nullptr; }
void ThrowIncompletePMP() { throw (int IncompleteAtThrow::**)nullptr; }
std::type_info const& ReturnTypeInfoIncompleteMP() { return typeid(int IncompleteAtThrow::*); }
std::type_info const& ReturnTypeInfoIncompletePP() { return typeid(IncompleteAtThrow**); }

struct CompleteAtThrow {};
void ThrowCompleteMP() { throw (int CompleteAtThrow::*)nullptr; }
void ThrowCompletePP() { throw (CompleteAtThrow**)nullptr; }
void ThrowCompletePMP() { throw (int CompleteAtThrow::**)nullptr; }
std::type_info const& ReturnTypeInfoCompleteMP() { return typeid(int CompleteAtThrow::*); }
std::type_info const& ReturnTypeInfoCompletePP() { return typeid(CompleteAtThrow**); }

void ThrowNullptr() { throw nullptr; }

#else

struct IncompleteAtThrow {};

int main() {
  AssertIncompleteTypeInfoEquals(ReturnTypeInfoNeverDefinedMP(), typeid(int NeverDefined::*));
  try {
    ThrowNeverDefinedMP();
    assert(false);
  } catch (int IncompleteAtThrow::*) {
    assert(false);
  } catch (int CompleteAtThrow::*) {
    assert(false);
  } catch (int NeverDefined::*) {}
  AssertIncompleteTypeInfoEquals(ReturnTypeInfoIncompleteMP(), typeid(int IncompleteAtThrow::*));
  try {
    ThrowIncompleteMP();
    assert(false);
  } catch (CompleteAtThrow**) {
    assert(false);
  } catch (int CompleteAtThrow::*) {
    assert(false);
  } catch (IncompleteAtThrow**) {
    assert(false);
  } catch (int IncompleteAtThrow::*) {}

  AssertIncompleteTypeInfoEquals(ReturnTypeInfoIncompletePP(), typeid(IncompleteAtThrow**));
  try {
    ThrowIncompletePP();
    assert(false);
  } catch (int IncompleteAtThrow::*) {
    assert(false);
  } catch (IncompleteAtThrow**) {}

  try {
    ThrowIncompletePMP();
    assert(false);
  } catch (int IncompleteAtThrow::*) {
    assert(false);
  } catch (IncompleteAtThrow**) {
    assert(false);
  } catch (int IncompleteAtThrow::**) {}

  AssertIncompleteTypeInfoEquals(ReturnTypeInfoCompleteMP(), typeid(int CompleteAtThrow::*));
  try {
    ThrowCompleteMP();
    assert(false);
  } catch (IncompleteAtThrow**) {
    assert(false);
  } catch (int IncompleteAtThrow::*) {
    assert(false);
  } catch (CompleteAtThrow**) {
    assert(false);
  } catch (int CompleteAtThrow::*) {}

  AssertIncompleteTypeInfoEquals(ReturnTypeInfoCompletePP(), typeid(CompleteAtThrow**));
  try {
    ThrowCompletePP();
    assert(false);
  } catch (IncompleteAtThrow**) {
    assert(false);
  } catch (int IncompleteAtThrow::*) {
    assert(false);
  } catch (int CompleteAtThrow::*) {
    assert(false);
  } catch (CompleteAtThrow**) {}

  try {
    ThrowCompletePMP();
    assert(false);
  } catch (IncompleteAtThrow**) {
    assert(false);
  } catch (int IncompleteAtThrow::*) {
    assert(false);
  } catch (int CompleteAtThrow::*) {
    assert(false);
  } catch (CompleteAtThrow**) {
    assert(false);
  } catch (int CompleteAtThrow::**) {}

#if __cplusplus >= 201103L
  // Catch nullptr as complete type
  try {
    ThrowNullptr();
  } catch (int IncompleteAtThrow::*) {}

  // Catch nullptr as an incomplete type
  try {
    ThrowNullptr();
  } catch (int CompleteAtThrow::*) {}
  // Catch nullptr as a type that is never complete.
  try {
    ThrowNullptr();
  } catch (int NeverDefined::*) {}
#endif
}
#endif
<|endoftext|>


<commit_before>/*
Copyright (c) 2016 Erik Rigtorp <erik@rigtorp.se>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
 */

#include <cstring>
#include <iostream>
#include <net/ethernet.h>
#include <net/if.h>
#include <netinet/ip.h>
#include <netinet/udp.h>
#include <pcap/pcap.h>
#include <unistd.h>

int main(int argc, char *argv[]) {
  int ifindex = 0;
  int loopback = 0;
  double speed = 1;
  int ttl = -1;

  int opt;
  while ((opt = getopt(argc, argv, "i:ls:t:")) != -1) {
    switch (opt) {
    case 'i':
      ifindex = if_nametoindex(optarg);
      if (ifindex == 0) {
        std::cerr << "if_nametoindex: " << strerror(errno) << std::endl;
        return 1;
      }
      break;
    case 'l':
      loopback = 1;
      break;
    case 's':
      speed = std::stod(optarg);
      break;
    case 't':
      ttl = std::stoi(optarg);
      break;
    default:
      std::cerr << "usage: " << argv[0]
                << " [-i iface] [-l] [-s speed] [-t ttl] pcap" << std::endl;
      return 1;
    }
  }
  if (optind >= argc) {
    std::cerr << "usage: " << argv[0]
              << " [-i iface] [-l] [-s speed] [-t ttl] pcap" << std::endl;
    return 1;
  }

  int fd = socket(AF_INET, SOCK_DGRAM, 0);
  if (fd == -1) {
    std::cerr << "socket: " << strerror(errno) << std::endl;
    return 1;
  }

  if (ifindex != 0) {
    ip_mreqn mreqn;
    memset(&mreqn, 0, sizeof(mreqn));
    mreqn.imr_ifindex = ifindex;
    if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, &mreqn, sizeof(mreqn)) ==
        -1) {
      std::cerr << "setsockopt: " << strerror(errno) << std::endl;
      return 1;
    }
  }

  if (loopback != 0) {
    if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, &loopback,
                   sizeof(loopback)) == -1) {
      std::cerr << "setsockopt: " << strerror(errno) << std::endl;
      return 1;
    }
  }

  if (ttl != -1) {
    if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)) == -1) {
      std::cerr << "setsockopt: " << strerror(errno) << std::endl;
      return 1;
    }
  }

  char errbuf[PCAP_ERRBUF_SIZE];
  pcap_t *handle = pcap_open_offline(argv[optind], errbuf);
  if (handle == nullptr) {
    std::cerr << "pcap_open: " << errbuf << std::endl;
    return 1;
  }

  pcap_pkthdr header;
  const u_char *p;
  timeval tv = {0, 0};
  while ((p = pcap_next(handle, &header))) {
    if (header.len != header.caplen) {
      continue;
    }
    auto eth = reinterpret_cast<const ether_header *>(p);
    if (ntohs(eth->ether_type) != ETHERTYPE_IP) {
      continue;
    }
    auto ip = reinterpret_cast<const iphdr *>(p + sizeof(ether_header));
    if (ip->version != 4) {
      continue;
    }
    if (ip->protocol != IPPROTO_UDP) {
      continue;
    }
    auto udp = reinterpret_cast<const udphdr *>(p + sizeof(ether_header) +
                                                ip->ihl * 4);

    if (tv.tv_sec == 0) {
      tv = header.ts;
    }
    timeval diff;
    timersub(&header.ts, &tv, &diff);
    usleep((diff.tv_sec * 1000000 + diff.tv_usec) * speed);

    ssize_t len = ntohs(udp->len) - 8;
    const u_char *d = &p[sizeof(ether_header) + ip->ihl * 4 + sizeof(udphdr)];

    sockaddr_in addr;
    memset(&addr, 0, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_port = udp->dest;
    addr.sin_addr = {ip->daddr};
    auto n = sendto(fd, d, len, 0, reinterpret_cast<sockaddr *>(&addr),
                    sizeof(addr));
    if (n != len) {
      std::cerr << "sendto: " << strerror(errno) << std::endl;
      return 1;
    }
  }

  return 0;
}
<commit_msg>Add usage to executable<commit_after>/*
Copyright (c) 2016 Erik Rigtorp <erik@rigtorp.se>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
 */

#include <cstring>
#include <iostream>
#include <net/ethernet.h>
#include <net/if.h>
#include <netinet/ip.h>
#include <netinet/udp.h>
#include <pcap/pcap.h>
#include <unistd.h>

int main(int argc, char *argv[]) {
  static const char usage[] =
      " [-i iface] [-l] [-s speed] [-t ttl] pcap\n"
      "\n"
      "  -i iface    interface to send packets through\n"
      "  -l          enable loopback\n"
      "  -s speed    replay speed relative to pcap timestamps\n"
      "  -t ttl      packet ttl";

  int ifindex = 0;
  int loopback = 0;
  double speed = 1;
  int ttl = -1;

  int opt;
  while ((opt = getopt(argc, argv, "i:ls:t:")) != -1) {
    switch (opt) {
    case 'i':
      ifindex = if_nametoindex(optarg);
      if (ifindex == 0) {
        std::cerr << "if_nametoindex: " << strerror(errno) << std::endl;
        return 1;
      }
      break;
    case 'l':
      loopback = 1;
      break;
    case 's':
      speed = std::stod(optarg);
      break;
    case 't':
      ttl = std::stoi(optarg);
      break;
    default:
      std::cerr << "usage: " << argv[0] << usage << std::endl;
      return 1;
    }
  }
  if (optind >= argc) {
    std::cerr << "usage: " << argv[0] << usage << std::endl;
    return 1;
  }

  int fd = socket(AF_INET, SOCK_DGRAM, 0);
  if (fd == -1) {
    std::cerr << "socket: " << strerror(errno) << std::endl;
    return 1;
  }

  if (ifindex != 0) {
    ip_mreqn mreqn;
    memset(&mreqn, 0, sizeof(mreqn));
    mreqn.imr_ifindex = ifindex;
    if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, &mreqn, sizeof(mreqn)) ==
        -1) {
      std::cerr << "setsockopt: " << strerror(errno) << std::endl;
      return 1;
    }
  }

  if (loopback != 0) {
    if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, &loopback,
                   sizeof(loopback)) == -1) {
      std::cerr << "setsockopt: " << strerror(errno) << std::endl;
      return 1;
    }
  }

  if (ttl != -1) {
    if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)) == -1) {
      std::cerr << "setsockopt: " << strerror(errno) << std::endl;
      return 1;
    }
  }

  char errbuf[PCAP_ERRBUF_SIZE];
  pcap_t *handle = pcap_open_offline(argv[optind], errbuf);
  if (handle == nullptr) {
    std::cerr << "pcap_open: " << errbuf << std::endl;
    return 1;
  }

  pcap_pkthdr header;
  const u_char *p;
  timeval tv = {0, 0};
  while ((p = pcap_next(handle, &header))) {
    if (header.len != header.caplen) {
      continue;
    }
    auto eth = reinterpret_cast<const ether_header *>(p);
    if (ntohs(eth->ether_type) != ETHERTYPE_IP) {
      continue;
    }
    auto ip = reinterpret_cast<const iphdr *>(p + sizeof(ether_header));
    if (ip->version != 4) {
      continue;
    }
    if (ip->protocol != IPPROTO_UDP) {
      continue;
    }
    auto udp = reinterpret_cast<const udphdr *>(p + sizeof(ether_header) +
                                                ip->ihl * 4);

    if (tv.tv_sec == 0) {
      tv = header.ts;
    }
    timeval diff;
    timersub(&header.ts, &tv, &diff);
    usleep((diff.tv_sec * 1000000 + diff.tv_usec) * speed);

    ssize_t len = ntohs(udp->len) - 8;
    const u_char *d = &p[sizeof(ether_header) + ip->ihl * 4 + sizeof(udphdr)];

    sockaddr_in addr;
    memset(&addr, 0, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_port = udp->dest;
    addr.sin_addr = {ip->daddr};
    auto n = sendto(fd, d, len, 0, reinterpret_cast<sockaddr *>(&addr),
                    sizeof(addr));
    if (n != len) {
      std::cerr << "sendto: " << strerror(errno) << std::endl;
      return 1;
    }
  }

  return 0;
}
<|endoftext|>


<commit_before>// Ylikuutio - A 3D game and simulation engine.
//
// Copyright (C) 2015-2021 Antti Nuortimo.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program 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 Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.

#ifndef __YLIKUUTIO_TRIANGULATION_TRIANGULATION_TEMPLATES_HPP_INCLUDED
#define __YLIKUUTIO_TRIANGULATION_TRIANGULATION_TEMPLATES_HPP_INCLUDED

// Include GLM
#ifndef __GLM_GLM_HPP_INCLUDED
#define __GLM_GLM_HPP_INCLUDED
#include <glm/glm.hpp> // glm
#endif

// Include standard headers
#include <cmath>    // NAN, std::isnan, std::pow
#include <cstddef>  // std::size_t
#include <iostream> // std::cout, std::cin, std::cerr
#include <vector>   // std::vector

namespace yli::triangulation
{
    template<class T1>
        T1 get_y(
                const T1* const vertex_data,
                const std::size_t x,
                const std::size_t z,
                const std::size_t image_width)
        {
            // This function returns the altitude value based on x & z coordinates.
            // This works only for a raw heightmap data (for a 2D array of altitudes).
            const T1* const vertex_pointer = vertex_data + z * image_width + x;
            return static_cast<T1>(*vertex_pointer);
        }

    // for bilinear interpolation.
    template<class T1>
        float southwest_y(const std::size_t x, const std::size_t z, const T1* const input_vertex_pointer, const std::size_t image_width, const std::size_t x_step, const std::size_t z_step)
        {
            return static_cast<float>(yli::triangulation::get_y(input_vertex_pointer, x - x_step, z - z_step, image_width));
        }
    template<class T1>
        float southeast_y(const std::size_t x, const std::size_t z, const T1* const input_vertex_pointer, const std::size_t image_width, const std::size_t x_step, const std::size_t z_step)
        {
            return static_cast<float>(yli::triangulation::get_y(input_vertex_pointer, x, z - z_step, image_width));
        }
    template<class T1>
        float northwest_y(const std::size_t x, const std::size_t z, const T1* const input_vertex_pointer, const std::size_t image_width, const std::size_t x_step, const std::size_t z_step)
        {
            return static_cast<float>(yli::triangulation::get_y(input_vertex_pointer, x - x_step, z, image_width));
        }
    template<class T1>
        float northeast_y(const std::size_t x, const std::size_t z, const T1* const input_vertex_pointer, const std::size_t image_width, const std::size_t x_step, const std::size_t z_step)
        {
            return static_cast<float>(yli::triangulation::get_y(input_vertex_pointer, x, z, image_width));
        }
    template<class T1>
        float center_y(const std::size_t x, const std::size_t z, const T1* const input_vertex_pointer, const std::size_t image_width, const std::size_t x_step, const std::size_t z_step)
        {
            return static_cast<float>(southwest_y(x, z, input_vertex_pointer, image_width, x_step, z_step) +
                    southeast_y(x, z, input_vertex_pointer, image_width, x_step, z_step) +
                    northwest_y(x, z, input_vertex_pointer, image_width, x_step, z_step) +
                    northeast_y(x, z, input_vertex_pointer, image_width, x_step, z_step)) / 4.0f;
        }

    template<class T1>
        bool compute_range(
                const T1* const input_vertex_pointer,
                const std::size_t image_width,
                const std::size_t image_height,
                const std::size_t x_step,
                const std::size_t z_step,
                float& min_y_value,
                float& max_y_value,
                float& divisor)
        {
            for (std::size_t z = 0; z < image_height; z += z_step)
            {
                for (std::size_t x = 0; x < image_width; x += x_step)
                {
                    const T1& vertex_height = input_vertex_pointer[image_width * z + x];

                    if (std::isnan(min_y_value) || vertex_height < min_y_value)
                    {
                        min_y_value = vertex_height;
                    }

                    if (std::isnan(max_y_value) || vertex_height > max_y_value)
                    {
                        max_y_value = vertex_height;
                    }
                }
            }

            divisor = max_y_value - min_y_value;

            if (std::isnan(divisor))
            {
                std::cerr << "ERROR: the value of `divisor` is `NAN`.\n";
                return false;
            }

            if (divisor == 0)
            {
                std::cerr << "ERROR: the value of `divisor` is 0.\n";
                return false;
            }

            return true;
        }

    template<class T1>
        bool define_vertices(
                const T1* const input_vertex_pointer,
                const std::size_t image_width,
                const std::size_t image_height,
                const std::size_t x_step,
                const std::size_t z_step,
                const bool use_real_texture_coordinates,
                std::vector<glm::vec3>& temp_vertices,
                std::vector<glm::vec2>& temp_uvs)
        {
            if (image_width < 2 || image_height < 2)
            {
                // Can not define vertices if image width < 2 or image height < 2.
                return false;
            }

            if (x_step == 0 || z_step == 0)
            {
                // Can not define vertices if x_step == 0 or z_step == 0.
                return false;
            }

            // Elevation maps are created using a mapping from [min_y_value, max_y_value] to [0, 1].
            // `min_y_value` & `max_y_value` are needed only for elevation maps.
            float min_y_value = NAN;
            float max_y_value = NAN;
            float divisor = NAN;

            if (!use_real_texture_coordinates)
            {
                bool result = yli::triangulation::compute_range(
                        input_vertex_pointer,
                        image_width,
                        image_height,
                        x_step,
                        z_step,
                        min_y_value,
                        max_y_value,
                        divisor);

                if (!result)
                {
                    return false;
                }
            }

            const std::size_t actual_image_width = image_width / x_step;
            const std::size_t actual_image_height = image_height / z_step;
            std::size_t number_of_vertices = actual_image_width * actual_image_height;
            temp_vertices.reserve(number_of_vertices);
            temp_uvs.reserve(number_of_vertices);

            // Define the temporary vertices in a double loop.
            std::size_t texture_y = 0;

            for (std::size_t z = 0; z < image_height; z += z_step)
            {
                std::size_t texture_x = 0;

                for (std::size_t x = 0; x < image_width; x += x_step)
                {
                    // current x,z coordinates).
                    float y = static_cast<float>(yli::triangulation::get_y(input_vertex_pointer, x, z, image_width));

                    // This corresponds to "v": specify one vertex.
                    glm::vec3 vertex;
                    vertex.x = static_cast<float>(x);
                    vertex.y = static_cast<float>(y);
                    vertex.z = static_cast<float>(z);
                    temp_vertices.emplace_back(vertex);

                    // This corresponds to "vt": specify texture coordinates of one vertex.
                    glm::vec2 uv;

                    if (use_real_texture_coordinates)
                    {
                        uv.x = round(static_cast<float>(texture_x));
                        uv.y = round(static_cast<float>(texture_y));
                    }
                    else
                    {
                        uv.x = static_cast<float>(y - min_y_value) / divisor;
                        uv.y = 0.0f;
                    }

                    temp_uvs.emplace_back(uv);

                    // `uv.x` is repeated 0, 1, 0, 1 ... when moving eastward.
                    // this causes the texture be mirrored horizontally for every other quad.
                    texture_x ^= 1;
                }

                // `uv.y` is repeated 0, 1, 0, 1 ... when moving southward.
                // this causes the texture be mirrored vertically for every other quad.
                texture_y ^= 1;
            }

            return true;
        }

    template<class T1>
        bool interpolate_and_define_vertices_using_bilinear_interpolation(
                const T1* const input_vertex_pointer,
                const std::size_t image_width,
                const std::size_t image_height,
                const std::size_t x_step,
                const std::size_t z_step,
                const bool use_real_texture_coordinates,
                std::vector<glm::vec3>& temp_vertices,
                std::vector<glm::vec2>& temp_uvs)
        {
            std::cout << "Interpolating center vertices.\n";

            if (image_width < 2 || image_height < 2)
            {
                // Can not interpolate center vertices if image width < 2 or image height < 2.
                return false;
            }

            if (x_step <= 0 || z_step <= 0)
            {
                // Can not interpolate center vertices if x_step <= 0 or z_step <= 0.
                return false;
            }

            // Elevation maps are created using a mapping from [min_y_value, max_y_value] to [0, 1].
            // `min_y_value` & `max_y_value` are needed only for elevation maps.
            float min_y_value = NAN;
            float max_y_value = NAN;
            float divisor = NAN;

            if (!use_real_texture_coordinates)
            {
                bool result = yli::triangulation::compute_range(
                        input_vertex_pointer,
                        image_width,
                        image_height,
                        x_step,
                        z_step,
                        min_y_value,
                        max_y_value,
                        divisor);

                if (!result)
                {
                    return false;
                }
            }

            // Then, define the faces in a double loop.
            // Begin from index `z_step`.
            for (std::size_t z = z_step; z < image_height; z += z_step)
            {
                // Begin from index `x_step`.
                for (std::size_t x = x_step; x < image_width; x += x_step)
                {
                    // This corresponds to "f": specify a face (but here we specify 2 faces instead!).

                    // Interpolate y coordinate (altitude).
                    const float y = center_y(x, z, input_vertex_pointer, image_width, x_step, z_step);

                    // Create a new vertex using bilinear interpolation.
                    // This corresponds to "v": specify one vertex.
                    glm::vec3 vertex;
                    vertex.x = static_cast<float>(x) - 0.5f * x_step;
                    vertex.y = static_cast<float>(y);
                    vertex.z = static_cast<float>(z) - 0.5f * z_step;
                    temp_vertices.emplace_back(vertex);

                    // This corresponds to "vt": specify texture coordinates of one vertex.
                    glm::vec2 uv;

                    if (use_real_texture_coordinates)
                    {
                        uv.x = 0.5f;
                        uv.y = 0.5f;
                    }
                    else
                    {
                        uv.x = static_cast<float>(y - min_y_value) / divisor;
                        uv.y = 0.0f;
                    }

                    temp_uvs.emplace_back(uv);
                }
            }

            return true;
        }
}

#endif
<commit_msg>Bugfix: do not use `<= 0` for unsigned variables.<commit_after>// Ylikuutio - A 3D game and simulation engine.
//
// Copyright (C) 2015-2021 Antti Nuortimo.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program 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 Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.

#ifndef __YLIKUUTIO_TRIANGULATION_TRIANGULATION_TEMPLATES_HPP_INCLUDED
#define __YLIKUUTIO_TRIANGULATION_TRIANGULATION_TEMPLATES_HPP_INCLUDED

// Include GLM
#ifndef __GLM_GLM_HPP_INCLUDED
#define __GLM_GLM_HPP_INCLUDED
#include <glm/glm.hpp> // glm
#endif

// Include standard headers
#include <cmath>    // NAN, std::isnan, std::pow
#include <cstddef>  // std::size_t
#include <iostream> // std::cout, std::cin, std::cerr
#include <vector>   // std::vector

namespace yli::triangulation
{
    template<class T1>
        T1 get_y(
                const T1* const vertex_data,
                const std::size_t x,
                const std::size_t z,
                const std::size_t image_width)
        {
            // This function returns the altitude value based on x & z coordinates.
            // This works only for a raw heightmap data (for a 2D array of altitudes).
            const T1* const vertex_pointer = vertex_data + z * image_width + x;
            return static_cast<T1>(*vertex_pointer);
        }

    // for bilinear interpolation.
    template<class T1>
        float southwest_y(const std::size_t x, const std::size_t z, const T1* const input_vertex_pointer, const std::size_t image_width, const std::size_t x_step, const std::size_t z_step)
        {
            return static_cast<float>(yli::triangulation::get_y(input_vertex_pointer, x - x_step, z - z_step, image_width));
        }
    template<class T1>
        float southeast_y(const std::size_t x, const std::size_t z, const T1* const input_vertex_pointer, const std::size_t image_width, const std::size_t x_step, const std::size_t z_step)
        {
            return static_cast<float>(yli::triangulation::get_y(input_vertex_pointer, x, z - z_step, image_width));
        }
    template<class T1>
        float northwest_y(const std::size_t x, const std::size_t z, const T1* const input_vertex_pointer, const std::size_t image_width, const std::size_t x_step, const std::size_t z_step)
        {
            return static_cast<float>(yli::triangulation::get_y(input_vertex_pointer, x - x_step, z, image_width));
        }
    template<class T1>
        float northeast_y(const std::size_t x, const std::size_t z, const T1* const input_vertex_pointer, const std::size_t image_width, const std::size_t x_step, const std::size_t z_step)
        {
            return static_cast<float>(yli::triangulation::get_y(input_vertex_pointer, x, z, image_width));
        }
    template<class T1>
        float center_y(const std::size_t x, const std::size_t z, const T1* const input_vertex_pointer, const std::size_t image_width, const std::size_t x_step, const std::size_t z_step)
        {
            return static_cast<float>(southwest_y(x, z, input_vertex_pointer, image_width, x_step, z_step) +
                    southeast_y(x, z, input_vertex_pointer, image_width, x_step, z_step) +
                    northwest_y(x, z, input_vertex_pointer, image_width, x_step, z_step) +
                    northeast_y(x, z, input_vertex_pointer, image_width, x_step, z_step)) / 4.0f;
        }

    template<class T1>
        bool compute_range(
                const T1* const input_vertex_pointer,
                const std::size_t image_width,
                const std::size_t image_height,
                const std::size_t x_step,
                const std::size_t z_step,
                float& min_y_value,
                float& max_y_value,
                float& divisor)
        {
            for (std::size_t z = 0; z < image_height; z += z_step)
            {
                for (std::size_t x = 0; x < image_width; x += x_step)
                {
                    const T1& vertex_height = input_vertex_pointer[image_width * z + x];

                    if (std::isnan(min_y_value) || vertex_height < min_y_value)
                    {
                        min_y_value = vertex_height;
                    }

                    if (std::isnan(max_y_value) || vertex_height > max_y_value)
                    {
                        max_y_value = vertex_height;
                    }
                }
            }

            divisor = max_y_value - min_y_value;

            if (std::isnan(divisor))
            {
                std::cerr << "ERROR: the value of `divisor` is `NAN`.\n";
                return false;
            }

            if (divisor == 0)
            {
                std::cerr << "ERROR: the value of `divisor` is 0.\n";
                return false;
            }

            return true;
        }

    template<class T1>
        bool define_vertices(
                const T1* const input_vertex_pointer,
                const std::size_t image_width,
                const std::size_t image_height,
                const std::size_t x_step,
                const std::size_t z_step,
                const bool use_real_texture_coordinates,
                std::vector<glm::vec3>& temp_vertices,
                std::vector<glm::vec2>& temp_uvs)
        {
            if (image_width < 2 || image_height < 2)
            {
                // Can not define vertices if image width < 2 or image height < 2.
                return false;
            }

            if (x_step == 0 || z_step == 0)
            {
                // Can not define vertices if x_step == 0 or z_step == 0.
                return false;
            }

            // Elevation maps are created using a mapping from [min_y_value, max_y_value] to [0, 1].
            // `min_y_value` & `max_y_value` are needed only for elevation maps.
            float min_y_value = NAN;
            float max_y_value = NAN;
            float divisor = NAN;

            if (!use_real_texture_coordinates)
            {
                bool result = yli::triangulation::compute_range(
                        input_vertex_pointer,
                        image_width,
                        image_height,
                        x_step,
                        z_step,
                        min_y_value,
                        max_y_value,
                        divisor);

                if (!result)
                {
                    return false;
                }
            }

            const std::size_t actual_image_width = image_width / x_step;
            const std::size_t actual_image_height = image_height / z_step;
            std::size_t number_of_vertices = actual_image_width * actual_image_height;
            temp_vertices.reserve(number_of_vertices);
            temp_uvs.reserve(number_of_vertices);

            // Define the temporary vertices in a double loop.
            std::size_t texture_y = 0;

            for (std::size_t z = 0; z < image_height; z += z_step)
            {
                std::size_t texture_x = 0;

                for (std::size_t x = 0; x < image_width; x += x_step)
                {
                    // current x,z coordinates).
                    float y = static_cast<float>(yli::triangulation::get_y(input_vertex_pointer, x, z, image_width));

                    // This corresponds to "v": specify one vertex.
                    glm::vec3 vertex;
                    vertex.x = static_cast<float>(x);
                    vertex.y = static_cast<float>(y);
                    vertex.z = static_cast<float>(z);
                    temp_vertices.emplace_back(vertex);

                    // This corresponds to "vt": specify texture coordinates of one vertex.
                    glm::vec2 uv;

                    if (use_real_texture_coordinates)
                    {
                        uv.x = round(static_cast<float>(texture_x));
                        uv.y = round(static_cast<float>(texture_y));
                    }
                    else
                    {
                        uv.x = static_cast<float>(y - min_y_value) / divisor;
                        uv.y = 0.0f;
                    }

                    temp_uvs.emplace_back(uv);

                    // `uv.x` is repeated 0, 1, 0, 1 ... when moving eastward.
                    // this causes the texture be mirrored horizontally for every other quad.
                    texture_x ^= 1;
                }

                // `uv.y` is repeated 0, 1, 0, 1 ... when moving southward.
                // this causes the texture be mirrored vertically for every other quad.
                texture_y ^= 1;
            }

            return true;
        }

    template<class T1>
        bool interpolate_and_define_vertices_using_bilinear_interpolation(
                const T1* const input_vertex_pointer,
                const std::size_t image_width,
                const std::size_t image_height,
                const std::size_t x_step,
                const std::size_t z_step,
                const bool use_real_texture_coordinates,
                std::vector<glm::vec3>& temp_vertices,
                std::vector<glm::vec2>& temp_uvs)
        {
            std::cout << "Interpolating center vertices.\n";

            if (image_width < 2 || image_height < 2)
            {
                // Can not interpolate center vertices if image width < 2 or image height < 2.
                return false;
            }

            if (x_step == 0 || z_step == 0)
            {
                // Can not interpolate center vertices if x_step == 0 or z_step == 0.
                return false;
            }

            // Elevation maps are created using a mapping from [min_y_value, max_y_value] to [0, 1].
            // `min_y_value` & `max_y_value` are needed only for elevation maps.
            float min_y_value = NAN;
            float max_y_value = NAN;
            float divisor = NAN;

            if (!use_real_texture_coordinates)
            {
                bool result = yli::triangulation::compute_range(
                        input_vertex_pointer,
                        image_width,
                        image_height,
                        x_step,
                        z_step,
                        min_y_value,
                        max_y_value,
                        divisor);

                if (!result)
                {
                    return false;
                }
            }

            // Then, define the faces in a double loop.
            // Begin from index `z_step`.
            for (std::size_t z = z_step; z < image_height; z += z_step)
            {
                // Begin from index `x_step`.
                for (std::size_t x = x_step; x < image_width; x += x_step)
                {
                    // This corresponds to "f": specify a face (but here we specify 2 faces instead!).

                    // Interpolate y coordinate (altitude).
                    const float y = center_y(x, z, input_vertex_pointer, image_width, x_step, z_step);

                    // Create a new vertex using bilinear interpolation.
                    // This corresponds to "v": specify one vertex.
                    glm::vec3 vertex;
                    vertex.x = static_cast<float>(x) - 0.5f * x_step;
                    vertex.y = static_cast<float>(y);
                    vertex.z = static_cast<float>(z) - 0.5f * z_step;
                    temp_vertices.emplace_back(vertex);

                    // This corresponds to "vt": specify texture coordinates of one vertex.
                    glm::vec2 uv;

                    if (use_real_texture_coordinates)
                    {
                        uv.x = 0.5f;
                        uv.y = 0.5f;
                    }
                    else
                    {
                        uv.x = static_cast<float>(y - min_y_value) / divisor;
                        uv.y = 0.0f;
                    }

                    temp_uvs.emplace_back(uv);
                }
            }

            return true;
        }
}

#endif
<|endoftext|>