<commit_before>#define WIN32_LEAN_AND_MEAN

#ifdef _MSC_VER
#pragma warning(disable:4668 4917) // disable warnings for system headers
#endif

#include <windows.h>
#include <windowsx.h>
#include <shellapi.h>
#include <shlobj.h>
#include <tchar.h>

#include <stdio.h>

#define elementsof(buf) (sizeof(buf) / sizeof(buf[0]))

enum PathResult
{
    PATHRESULT_OK,
    PATHRESULT_API_NOT_SUPPORTED,
    PATHRESULT_EXE_NOT_FOUND
};

const int MAXCMDLINELEN = 32768;

static TCHAR       g_szSTInstallationPath[MAX_PATH] = TEXT("");
static TCHAR       g_szOperatingSystem[256]         = TEXT("");

static const TCHAR g_szSTExecutable[256]            = TEXT("stclient.exe");

//***************************************************************************

LONG RegReadValue( HKEY hBaseKey, LPCTSTR lpSubKey, LPCTSTR lpValueName, LPVOID lpData, DWORD cbData )
{
    HKEY    hKey = NULL;
    LONG    lResult( 0 );

    lResult = RegOpenKeyEx( hBaseKey, lpSubKey, 0, KEY_QUERY_VALUE, &hKey );

    if ( ERROR_SUCCESS == lResult )
    {
        lResult = RegQueryValueEx( hKey, lpValueName, NULL, NULL, (LPBYTE)lpData, &cbData );
        RegCloseKey( hKey );
    }

    return lResult;
}

//***************************************************************************

static LPTSTR *GetCommandArgs( int *pArgc )
{
#ifdef UNICODE
    return CommandLineToArgvW( GetCommandLineW(), pArgc );
#else
    *pArgc = __argc;
    return __argv;
#endif
}

//***************************************************************************

static bool IsSupportedPlatform()
{
    OSVERSIONINFO aOsVersion;

    ZeroMemory( &aOsVersion, sizeof( OSVERSIONINFO ));
    aOsVersion.dwOSVersionInfoSize = sizeof( OSVERSIONINFO );

    // Try to determine OS version
    if ( GetVersionEx( &aOsVersion ))
    {
        switch ( aOsVersion.dwPlatformId )
        {
            case VER_PLATFORM_WIN32_NT:     // Windows NT based
                return true;

            case VER_PLATFORM_WIN32_WINDOWS: // Windows Me/98/95.
            case VER_PLATFORM_WIN32s:        // Win32s
                return false;

            default:
                return false;
        }
    }

    return false;
}

//***************************************************************************

static LPCTSTR GetOperatingSystemString()
{
    OSVERSIONINFO aOsVersion;

    ZeroMemory( &aOsVersion, sizeof( OSVERSIONINFO ));
    aOsVersion.dwOSVersionInfoSize = sizeof( OSVERSIONINFO );

    _tcscpy( g_szOperatingSystem, TEXT( "Windows" ));

    // Try to determine OS version
    if ( GetVersionEx( &aOsVersion ))
    {
        switch ( aOsVersion.dwPlatformId )
        {
            // Test for the Windows NT product family.
            case VER_PLATFORM_WIN32_NT:
            {
                if ( aOsVersion.dwMajorVersion == 3 )
                {
                    _tcscat( g_szOperatingSystem, TEXT( " NT 3." ));
                    if ( aOsVersion.dwMinorVersion == 0 )
                        _tcscat( g_szOperatingSystem, TEXT( "0" ));
                    else if ( aOsVersion.dwMinorVersion == 5 )
                        _tcscat( g_szOperatingSystem, TEXT( "5" ));
                    else if ( aOsVersion.dwMinorVersion == 51 )
                        _tcscat( g_szOperatingSystem, TEXT( "51" ));
                }
                else if ( aOsVersion.dwMajorVersion == 4 )
                    _tcscat( g_szOperatingSystem, TEXT( " NT 4.0" ));
                else if ( aOsVersion.dwMajorVersion == 5 )
                {
                    if ( aOsVersion.dwMinorVersion == 0 )
                        _tcscat( g_szOperatingSystem, TEXT( " 2000" ));
                    else if ( aOsVersion.dwMinorVersion == 1 )
                        _tcscat( g_szOperatingSystem, TEXT( " XP" ));
                    else if ( aOsVersion.dwMinorVersion == 2 )
                        _tcscat( g_szOperatingSystem, TEXT( " Server 2003" ));
                }
                else if ( aOsVersion.dwMajorVersion == 6 )
                {
                    if ( aOsVersion.dwMinorVersion == 0 )
                        _tcscat( g_szOperatingSystem, " Vista" );
                }
            }
            break;

            // Test for the Windows Me/98/95.
            case VER_PLATFORM_WIN32_WINDOWS:
            {
                if ( aOsVersion.dwMinorVersion == 0 )
                  _tcscat( g_szOperatingSystem, TEXT( " 95" ));
                else if ( aOsVersion.dwMinorVersion == 10 )
                  _tcscat( g_szOperatingSystem, TEXT( " 98" ));
                else if ( aOsVersion.dwMinorVersion == 90 )
                  _tcscat( g_szOperatingSystem, TEXT( " Me" ));
            }
            break;
        }
        _tcscat( g_szOperatingSystem, aOsVersion.szCSDVersion );
    }

    return g_szOperatingSystem;
}

//***************************************************************************

static bool FileExists( LPCTSTR lpPathToFile )
{
    bool            bResult = false;
    HANDLE          hFind;
    WIN32_FIND_DATA FindFileData;

    hFind = FindFirstFile( lpPathToFile, &FindFileData );

    if ( hFind != INVALID_HANDLE_VALUE )
    {
        FindClose( hFind );
        bResult = true;
    }

    return bResult;
}

//***************************************************************************

static bool GetProgramFilesFolder( LPTSTR strPath )
{
    bool      bRet = false;
    HINSTANCE hLibrary;

    if (( hLibrary = LoadLibrary( "shell32.dll" )) != NULL )
    {
        BOOL (WINAPI *pSHGetSpecialFolderPathA)( HWND, LPSTR, int, BOOL );

        pSHGetSpecialFolderPathA = (BOOL (WINAPI *)(HWND, LPSTR, int, BOOL))GetProcAddress( hLibrary, "SHGetSpecialFolderPathA" );

        if ( pSHGetSpecialFolderPathA )
        {
            if ( pSHGetSpecialFolderPathA( NULL, strPath, CSIDL_PROGRAM_FILES, TRUE ))
                bRet = true;
        }
    }

    FreeLibrary( hLibrary );

    return ( bRet );
}

//***************************************************************************

static PathResult RetrieveExecutablePath( LPTSTR szExecutablePath )
{
    PathResult eRet = PATHRESULT_API_NOT_SUPPORTED;
    TCHAR szProgramFilesFolder[MAX_PATH];

    if ( GetProgramFilesFolder( szProgramFilesFolder ))
    {
        size_t nLen = _tcslen( szProgramFilesFolder );
        if ( nLen > 0 )
        {
            _tcscpy( szExecutablePath, szProgramFilesFolder );
            if ( szProgramFilesFolder[nLen-1] != '\\' )
                _tcscat( szExecutablePath, TEXT( "\\" ));
            _tcscat( szExecutablePath, TEXT( "Sun\\servicetag\\" ));
            _tcscat( szExecutablePath, g_szSTExecutable );
            eRet = FileExists( szExecutablePath ) ? PATHRESULT_OK : PATHRESULT_EXE_NOT_FOUND;
        }
    }

    return eRet;
}

//***************************************************************************

static void SafeCopy( LPTSTR lpTarget, LPCSTR lpSource, size_t nMaxLen )
{
    size_t nLen  = _tcslen( lpSource );
    size_t nCopy = ( nLen < size_t( nMaxLen-1 )) ? nLen : nMaxLen-1;
    _tcsncpy( lpTarget, lpSource, nMaxLen-1 );
    *(lpTarget+nCopy) = 0;
}

//***************************************************************************

int WINAPI _tWinMain( HINSTANCE /*hInstance*/, HINSTANCE, LPTSTR, int )
{
    DWORD dwExitCode = (DWORD)1;

    int     nArgs  = 0;
    LPTSTR* lpArgs = GetCommandArgs( &nArgs );

    if ( !IsSupportedPlatform() )
    {
        // Return 0 for a successful run on not supported platforms
        // We don't want that the Office tries to start us forever.
        return 0;
    }

    if ( nArgs == 11 )
    {
        TCHAR szTargetURN[1024]         = {0};
        TCHAR szProductName[1024]       = {0};
        TCHAR szProductVersion[1024]    = {0};
        TCHAR szParentProductName[1024] = {0};
        TCHAR szProductSource[1024]     = {0};

//      -t)  TARGET_URN="$2"; shift;;
//      -p)  PRODUCT_NAME="$2"; shift;;
//      -e)  PRODUCT_VERSION="$2"; shift;;
//      -P)  PARENT_PRODUCT_NAME="$2"; shift;;
//      -S)  PRODUCT_SOURCE="$2"; shift;;
//      "usage: $0 -p <product name> -e <product version> -t <urn> -S <source> -P <parent product name>"

        int i = 1;
        while ( i < nArgs )
        {
            LPTSTR lpArg = lpArgs[i];
            if ( _tcslen( lpArg ) >= 2 )
            {
                if ( lpArg[0] == '-' )
                {
                    switch ( lpArg[1] )
                    {
                        case 't':
                        {
                            if ( i < nArgs )
                                ++i;
                            SafeCopy( szTargetURN, lpArgs[i], elementsof( szTargetURN ));
                            break;
                        }
                        case 'p':
                        {
                            if ( i < nArgs )
                                ++i;
                            SafeCopy( szProductName, lpArgs[i], elementsof( szProductName ));
                            break;
                        }
                        case 'e':
                        {
                            if ( i < nArgs )
                                ++i;
                            SafeCopy( szProductVersion, lpArgs[i], elementsof( szProductVersion ));
                            break;
                        }
                        case 'P':
                        {
                            if ( i < nArgs )
                                ++i;
                            SafeCopy( szParentProductName, lpArgs[i], elementsof( szParentProductName ));
                            break;
                        }
                        case 'S':
                        {
                            if ( i < nArgs )
                                ++i;
                            SafeCopy( szProductSource, lpArgs[i], elementsof( szProductSource ));
                            break;
                        }

                        default:
                            break;
                    } // switch
                }
            }

            ++i;
        }

        if ( RetrieveExecutablePath( g_szSTInstallationPath ) == PATHRESULT_OK )
        {
            STARTUPINFO         aStartupInfo;
            PROCESS_INFORMATION aProcessInfo;

            ZeroMemory( &aStartupInfo, sizeof( aStartupInfo ));
            aStartupInfo.cb = sizeof( aStartupInfo );

            // TEST=`${STCLIENT} -f -t ${TARGET_URN}`
            LPTSTR lpCommandLine = new TCHAR[MAXCMDLINELEN];

            _tcscpy( lpCommandLine, TEXT( "\"" ));
            _tcscat( lpCommandLine, g_szSTInstallationPath );
            _tcscat( lpCommandLine, TEXT( "\"" ));
            _tcscat( lpCommandLine, TEXT( " -f" ));
            _tcscat( lpCommandLine, TEXT( " -t "));
            _tcscat( lpCommandLine, TEXT( "\"" ));
            _tcscat( lpCommandLine, szTargetURN );
            _tcscat( lpCommandLine, TEXT( "\"" ));

            BOOL bSuccess = FALSE;
            bSuccess = CreateProcess(
                               NULL,
                               lpCommandLine,
                               NULL,
                               NULL,
                               TRUE,
                               CREATE_NO_WINDOW,
                               NULL,
                               NULL,
                               &aStartupInfo,
                               &aProcessInfo );

            // wait until process ends to receive exit code
            WaitForSingleObject( aProcessInfo.hProcess, INFINITE );

            delete []lpCommandLine;

            if ( bSuccess )
            {
                DWORD dwSTClientExitCode = 0;
                GetExitCodeProcess( aProcessInfo.hProcess, &dwSTClientExitCode );

                CloseHandle( aProcessInfo.hProcess );
                CloseHandle( aProcessInfo.hThread );

                if ( dwSTClientExitCode != 0 )
                {
                    // output=`${STCLIENT} -a -p "${PRODUCT_NAME}" -e "${PRODUCT_VERSION}" -t "${TARGET_URN}" -S "${PRODUCT_SOURCE}" -P "${PARENT_PRODUCT_NAME}" -m "Sun Microsystems, Inc." -A ${uname} -z global`
                    lpCommandLine = new TCHAR[MAXCMDLINELEN];

                    _tcscpy( lpCommandLine, TEXT( "\"" ));
                    _tcscat( lpCommandLine, g_szSTInstallationPath );
                    _tcscat( lpCommandLine, TEXT( "\"" ));
                    _tcscat( lpCommandLine, TEXT( " -a" ));
                    _tcscat( lpCommandLine, TEXT( " -p " ));
                    _tcscat( lpCommandLine, TEXT( "\"" ));
                    _tcscat( lpCommandLine, szProductName );
                    _tcscat( lpCommandLine, TEXT( "\"" ));
                    _tcscat( lpCommandLine, TEXT( " -e " ));
                    _tcscat( lpCommandLine, TEXT( "\"" ));
                    _tcscat( lpCommandLine, szProductVersion );
                    _tcscat( lpCommandLine, TEXT( "\"" ));
                    _tcscat( lpCommandLine, TEXT( " -t " ));
                    _tcscat( lpCommandLine, TEXT( "\"" ));
                    _tcscat( lpCommandLine, szTargetURN );
                    _tcscat( lpCommandLine, TEXT( "\"" ));
                    _tcscat( lpCommandLine, TEXT( " -S " ));
                    _tcscat( lpCommandLine, TEXT( "\"" ));
                    _tcscat( lpCommandLine, szProductSource );
                    _tcscat( lpCommandLine, TEXT( "\"" ));
                    _tcscat( lpCommandLine, TEXT( " -P " ));
                    _tcscat( lpCommandLine, TEXT( "\"" ));
                    _tcscat( lpCommandLine, szParentProductName );
                    _tcscat( lpCommandLine, TEXT( "\"" ));
                    _tcscat( lpCommandLine, TEXT( " -m \"Sun Microsystems, Inc.\"" ));
                    _tcscat( lpCommandLine, TEXT( " -A " ));
                    _tcscat( lpCommandLine, TEXT( "\"" ));
                    _tcscat( lpCommandLine, GetOperatingSystemString() );
                    _tcscat( lpCommandLine, TEXT( "\"" ));
                    _tcscat( lpCommandLine, TEXT( " -z global" ));

                    ZeroMemory( &aStartupInfo, sizeof( aStartupInfo ));
                    aStartupInfo.cb = sizeof(aStartupInfo);
                    ZeroMemory( &aProcessInfo, sizeof( aProcessInfo ));

                    bSuccess = CreateProcess(
                                       NULL,
                                       lpCommandLine,
                                       NULL,
                                       NULL,
                                       TRUE,
                                       CREATE_NO_WINDOW,
                                       NULL,
                                       NULL,
                                       &aStartupInfo,
                                       &aProcessInfo );

                    delete []lpCommandLine;

                    // wait until process ends to receive exit code
                    WaitForSingleObject( aProcessInfo.hProcess, INFINITE );

                    dwSTClientExitCode = 0;
                    GetExitCodeProcess( aProcessInfo.hProcess, &dwSTClientExitCode );

                    CloseHandle( aProcessInfo.hProcess );
                    CloseHandle( aProcessInfo.hThread );
                    return dwSTClientExitCode;
                }
                else
                    dwExitCode = 0; // we are already registered
            }
        }
        else
            dwExitCode = 1; // no executable found
    }
    else
        dwExitCode = 0; // wrong number of arguments

    return dwExitCode;
}
<commit_msg>INTEGRATION: CWS fwk84_SRC680 (1.3.22); FILE MERGED 2008/02/01 13:00:37 cd 1.3.22.1: #153871# Make argument -i <instance urn> optional. Check error code of stclient<commit_after>#define WIN32_LEAN_AND_MEAN

#ifdef _MSC_VER
#pragma warning(disable:4668 4917) // disable warnings for system headers
#endif

#include <windows.h>
#include <windowsx.h>
#include <shellapi.h>
#include <shlobj.h>
#include <tchar.h>

#include <stdio.h>

#define elementsof(buf) (sizeof(buf) / sizeof(buf[0]))

enum PathResult
{
    PATHRESULT_OK,
    PATHRESULT_API_NOT_SUPPORTED,
    PATHRESULT_EXE_NOT_FOUND
};

const int MAXCMDLINELEN = 32768;

static TCHAR       g_szSTInstallationPath[MAX_PATH] = TEXT("");
static TCHAR       g_szOperatingSystem[256]         = TEXT("");

static const TCHAR g_szSTExecutable[256]            = TEXT("stclient.exe");

//***************************************************************************

LONG RegReadValue( HKEY hBaseKey, LPCTSTR lpSubKey, LPCTSTR lpValueName, LPVOID lpData, DWORD cbData )
{
    HKEY    hKey = NULL;
    LONG    lResult( 0 );

    lResult = RegOpenKeyEx( hBaseKey, lpSubKey, 0, KEY_QUERY_VALUE, &hKey );

    if ( ERROR_SUCCESS == lResult )
    {
        lResult = RegQueryValueEx( hKey, lpValueName, NULL, NULL, (LPBYTE)lpData, &cbData );
        RegCloseKey( hKey );
    }

    return lResult;
}

//***************************************************************************

static LPTSTR *GetCommandArgs( int *pArgc )
{
#ifdef UNICODE
    return CommandLineToArgvW( GetCommandLineW(), pArgc );
#else
    *pArgc = __argc;
    return __argv;
#endif
}

//***************************************************************************

static bool IsSupportedPlatform()
{
    OSVERSIONINFO aOsVersion;

    ZeroMemory( &aOsVersion, sizeof( OSVERSIONINFO ));
    aOsVersion.dwOSVersionInfoSize = sizeof( OSVERSIONINFO );

    // Try to determine OS version
    if ( GetVersionEx( &aOsVersion ))
    {
        switch ( aOsVersion.dwPlatformId )
        {
            case VER_PLATFORM_WIN32_NT:     // Windows NT based
                return true;

            case VER_PLATFORM_WIN32_WINDOWS: // Windows Me/98/95.
            case VER_PLATFORM_WIN32s:        // Win32s
                return false;

            default:
                return false;
        }
    }

    return false;
}

//***************************************************************************

static LPCTSTR GetOperatingSystemString()
{
    OSVERSIONINFO aOsVersion;

    ZeroMemory( &aOsVersion, sizeof( OSVERSIONINFO ));
    aOsVersion.dwOSVersionInfoSize = sizeof( OSVERSIONINFO );

    _tcscpy( g_szOperatingSystem, TEXT( "Microsoft Windows" ));

    // Try to determine OS version
    if ( GetVersionEx( &aOsVersion ))
    {
        switch ( aOsVersion.dwPlatformId )
        {
            // Test for the Windows NT product family.
            case VER_PLATFORM_WIN32_NT:
            {
                if ( aOsVersion.dwMajorVersion == 3 )
                {
                    _tcscat( g_szOperatingSystem, TEXT( " NT 3." ));
                    if ( aOsVersion.dwMinorVersion == 0 )
                        _tcscat( g_szOperatingSystem, TEXT( "0" ));
                    else if ( aOsVersion.dwMinorVersion == 5 )
                        _tcscat( g_szOperatingSystem, TEXT( "5" ));
                    else if ( aOsVersion.dwMinorVersion == 51 )
                        _tcscat( g_szOperatingSystem, TEXT( "51" ));
                }
                else if ( aOsVersion.dwMajorVersion == 4 )
                    _tcscat( g_szOperatingSystem, TEXT( " NT 4.0" ));
                else if ( aOsVersion.dwMajorVersion == 5 )
                {
                    if ( aOsVersion.dwMinorVersion == 0 )
                        _tcscat( g_szOperatingSystem, TEXT( " 2000" ));
                    else if ( aOsVersion.dwMinorVersion == 1 )
                        _tcscat( g_szOperatingSystem, TEXT( " XP" ));
                    else if ( aOsVersion.dwMinorVersion == 2 )
                        _tcscat( g_szOperatingSystem, TEXT( " Server 2003" ));
                }
                else if ( aOsVersion.dwMajorVersion == 6 )
                {
                    if ( aOsVersion.dwMinorVersion == 0 )
                        _tcscat( g_szOperatingSystem, " Vista" );
                }
            }
            break;

            // Test for the Windows Me/98/95.
            case VER_PLATFORM_WIN32_WINDOWS:
            {
                if ( aOsVersion.dwMinorVersion == 0 )
                  _tcscat( g_szOperatingSystem, TEXT( " 95" ));
                else if ( aOsVersion.dwMinorVersion == 10 )
                  _tcscat( g_szOperatingSystem, TEXT( " 98" ));
                else if ( aOsVersion.dwMinorVersion == 90 )
                  _tcscat( g_szOperatingSystem, TEXT( " Me" ));
            }
            break;
        }
    }

    return g_szOperatingSystem;
}

//***************************************************************************

static bool FileExists( LPCTSTR lpPathToFile )
{
    bool            bResult = false;
    HANDLE          hFind;
    WIN32_FIND_DATA FindFileData;

    hFind = FindFirstFile( lpPathToFile, &FindFileData );

    if ( hFind != INVALID_HANDLE_VALUE )
    {
        FindClose( hFind );
        bResult = true;
    }

    return bResult;
}

//***************************************************************************

static bool GetProgramFilesFolder( LPTSTR strPath )
{
    bool      bRet = false;
    HINSTANCE hLibrary;

    if (( hLibrary = LoadLibrary( "shell32.dll" )) != NULL )
    {
        BOOL (WINAPI *pSHGetSpecialFolderPathA)( HWND, LPSTR, int, BOOL );

        pSHGetSpecialFolderPathA = (BOOL (WINAPI *)(HWND, LPSTR, int, BOOL))GetProcAddress( hLibrary, "SHGetSpecialFolderPathA" );

        if ( pSHGetSpecialFolderPathA )
        {
            if ( pSHGetSpecialFolderPathA( NULL, strPath, CSIDL_PROGRAM_FILES, TRUE ))
                bRet = true;
        }
    }

    FreeLibrary( hLibrary );

    return ( bRet );
}

//***************************************************************************

static PathResult RetrieveExecutablePath( LPTSTR szExecutablePath )
{
    PathResult eRet = PATHRESULT_API_NOT_SUPPORTED;
    TCHAR szProgramFilesFolder[MAX_PATH];

    if ( GetProgramFilesFolder( szProgramFilesFolder ))
    {
        size_t nLen = _tcslen( szProgramFilesFolder );
        if ( nLen > 0 )
        {
            _tcscpy( szExecutablePath, szProgramFilesFolder );
            if ( szProgramFilesFolder[nLen-1] != '\\' )
                _tcscat( szExecutablePath, TEXT( "\\" ));
            _tcscat( szExecutablePath, TEXT( "Sun\\servicetag\\" ));
            _tcscat( szExecutablePath, g_szSTExecutable );
            eRet = FileExists( szExecutablePath ) ? PATHRESULT_OK : PATHRESULT_EXE_NOT_FOUND;
        }
    }

    return eRet;
}

//***************************************************************************

static void SafeCopy( LPTSTR lpTarget, LPCSTR lpSource, size_t nMaxLen )
{
    size_t nLen  = _tcslen( lpSource );
    size_t nCopy = ( nLen < size_t( nMaxLen-1 )) ? nLen : nMaxLen-1;
    _tcsncpy( lpTarget, lpSource, nMaxLen-1 );
    *(lpTarget+nCopy) = 0;
}

//***************************************************************************

int WINAPI _tWinMain( HINSTANCE /*hInstance*/, HINSTANCE, LPTSTR, int )
{
    const DWORD ERR_NO_RECORDS_FOUND = 225;
    const DWORD ERR_DUP_RECORD       = 226;

    DWORD dwExitCode = (DWORD)1;

    int     nArgs  = 0;
    LPTSTR* lpArgs = GetCommandArgs( &nArgs );

    if ( !IsSupportedPlatform() )
    {
        // Return 0 for a successful run on not supported platforms
        // We don't want that the Office tries to start us forever.
        return 0;
    }

    if ( nArgs >= 11 )
    {
        TCHAR szTargetURN[1024]         = {0};
        TCHAR szProductName[1024]       = {0};
        TCHAR szProductVersion[1024]    = {0};
        TCHAR szParentProductName[1024] = {0};
        TCHAR szProductSource[1024]     = {0};
        TCHAR szInstanceURN[1024]       = {0};

//      -i)  INSTANCE_URN="$2"; shift;;
//      -t)  TARGET_URN="$2"; shift;;
//      -p)  PRODUCT_NAME="$2"; shift;;
//      -e)  PRODUCT_VERSION="$2"; shift;;
//      -P)  PARENT_PRODUCT_NAME="$2"; shift;;
//      -S)  PRODUCT_SOURCE="$2"; shift;;
//      "usage: $0 [-i <instance urn>] -p <product name> -e <product version> -t <urn> -S <source> -P <parent product name>"

        int i = 1;
        while ( i < nArgs )
        {
            LPTSTR lpArg = lpArgs[i];
            if ( _tcslen( lpArg ) >= 2 )
            {
                if ( lpArg[0] == '-' )
                {
                    switch ( lpArg[1] )
                    {
                        case 'i':
                        {
                            if ( i < nArgs )
                                ++i;
                            SafeCopy( szInstanceURN, lpArgs[i], elementsof( szInstanceURN ));
                            break;
                        }

                        case 't':
                        {
                            if ( i < nArgs )
                                ++i;
                            SafeCopy( szTargetURN, lpArgs[i], elementsof( szTargetURN ));
                            break;
                        }
                        case 'p':
                        {
                            if ( i < nArgs )
                                ++i;
                            SafeCopy( szProductName, lpArgs[i], elementsof( szProductName ));
                            break;
                        }
                        case 'e':
                        {
                            if ( i < nArgs )
                                ++i;
                            SafeCopy( szProductVersion, lpArgs[i], elementsof( szProductVersion ));
                            break;
                        }
                        case 'P':
                        {
                            if ( i < nArgs )
                                ++i;
                            SafeCopy( szParentProductName, lpArgs[i], elementsof( szParentProductName ));
                            break;
                        }
                        case 'S':
                        {
                            if ( i < nArgs )
                                ++i;
                            SafeCopy( szProductSource, lpArgs[i], elementsof( szProductSource ));
                            break;
                        }

                        default:
                            break;
                    } // switch
                }
            }

            ++i;
        }

        if ( RetrieveExecutablePath( g_szSTInstallationPath ) == PATHRESULT_OK )
        {
            BOOL bSuccess = TRUE;
            BOOL bProcessStarted = FALSE;

            STARTUPINFO         aStartupInfo;
            PROCESS_INFORMATION aProcessInfo;
            LPTSTR              lpCommandLine = 0;

            ZeroMemory( &aStartupInfo, sizeof( aStartupInfo ));
            aStartupInfo.cb = sizeof( aStartupInfo );
            ZeroMemory( &aProcessInfo, sizeof( aProcessInfo ));

            if ( _tcslen( szInstanceURN ) == 0 )
            {
                // TEST=`${STCLIENT} -f -t ${TARGET_URN}`
                lpCommandLine = new TCHAR[MAXCMDLINELEN];

                _tcscpy( lpCommandLine, TEXT( "\"" ));
                _tcscat( lpCommandLine, g_szSTInstallationPath );
                _tcscat( lpCommandLine, TEXT( "\"" ));
                _tcscat( lpCommandLine, TEXT( " -f" ));
                _tcscat( lpCommandLine, TEXT( " -t "));
                _tcscat( lpCommandLine, TEXT( "\"" ));
                _tcscat( lpCommandLine, szTargetURN );
                _tcscat( lpCommandLine, TEXT( "\"" ));

                bSuccess = CreateProcess(
                                   NULL,
                                   lpCommandLine,
                                   NULL,
                                   NULL,
                                   TRUE,
                                   CREATE_NO_WINDOW,
                                   NULL,
                                   NULL,
                                   &aStartupInfo,
                                   &aProcessInfo );

                bProcessStarted = TRUE;

                // wait until process ends to receive exit code
                WaitForSingleObject( aProcessInfo.hProcess, INFINITE );

                delete []lpCommandLine;
            }

            if ( bSuccess )
            {
                DWORD dwSTClientExitCode( ERR_NO_RECORDS_FOUND );
                if ( bProcessStarted )
                {
                    GetExitCodeProcess( aProcessInfo.hProcess, &dwSTClientExitCode );
                    dwSTClientExitCode &= 0x000000ff;

                    CloseHandle( aProcessInfo.hProcess );
                    CloseHandle( aProcessInfo.hThread );
                }

                if ( dwSTClientExitCode == ERR_NO_RECORDS_FOUND )
                {
                    // output=`${STCLIENT} -a [-i "${INSTANCE_URN}"] -p "${PRODUCT_NAME}" -e "${PRODUCT_VERSION}" -t "${TARGET_URN}" -S "${PRODUCT_SOURCE}" -P "${PARENT_PRODUCT_NAME}" -m "Sun Microsystems, Inc." -A ${uname} -z global`
                    lpCommandLine = new TCHAR[MAXCMDLINELEN];

                    _tcscpy( lpCommandLine, TEXT( "\"" ));
                    _tcscat( lpCommandLine, g_szSTInstallationPath );
                    _tcscat( lpCommandLine, TEXT( "\"" ));
                    _tcscat( lpCommandLine, TEXT( " -a" ));
                    if ( _tcslen( szInstanceURN ) > 0 )
                    {
                        _tcscat( lpCommandLine, TEXT( " -i " ));
                        _tcscat( lpCommandLine, TEXT( "\"" ));
                        _tcscat( lpCommandLine, szInstanceURN );
                        _tcscat( lpCommandLine, TEXT( "\"" ));
                    }
                    _tcscat( lpCommandLine, TEXT( " -p " ));
                    _tcscat( lpCommandLine, TEXT( "\"" ));
                    _tcscat( lpCommandLine, szProductName );
                    _tcscat( lpCommandLine, TEXT( "\"" ));
                    _tcscat( lpCommandLine, TEXT( " -e " ));
                    _tcscat( lpCommandLine, TEXT( "\"" ));
                    _tcscat( lpCommandLine, szProductVersion );
                    _tcscat( lpCommandLine, TEXT( "\"" ));
                    _tcscat( lpCommandLine, TEXT( " -t " ));
                    _tcscat( lpCommandLine, TEXT( "\"" ));
                    _tcscat( lpCommandLine, szTargetURN );
                    _tcscat( lpCommandLine, TEXT( "\"" ));
                    _tcscat( lpCommandLine, TEXT( " -S " ));
                    _tcscat( lpCommandLine, TEXT( "\"" ));
                    _tcscat( lpCommandLine, szProductSource );
                    _tcscat( lpCommandLine, TEXT( "\"" ));
                    _tcscat( lpCommandLine, TEXT( " -P " ));
                    _tcscat( lpCommandLine, TEXT( "\"" ));
                    _tcscat( lpCommandLine, szParentProductName );
                    _tcscat( lpCommandLine, TEXT( "\"" ));
                    _tcscat( lpCommandLine, TEXT( " -m \"Sun Microsystems, Inc.\"" ));
                    _tcscat( lpCommandLine, TEXT( " -A " ));
                    _tcscat( lpCommandLine, TEXT( "\"" ));
                    _tcscat( lpCommandLine, GetOperatingSystemString() );
                    _tcscat( lpCommandLine, TEXT( "\"" ));
                    _tcscat( lpCommandLine, TEXT( " -z global" ));

                    ZeroMemory( &aStartupInfo, sizeof( aStartupInfo ));
                    aStartupInfo.cb = sizeof(aStartupInfo);
                    ZeroMemory( &aProcessInfo, sizeof( aProcessInfo ));

                    bSuccess = CreateProcess(
                                       NULL,
                                       lpCommandLine,
                                       NULL,
                                       NULL,
                                       TRUE,
                                       CREATE_NO_WINDOW,
                                       NULL,
                                       NULL,
                                       &aStartupInfo,
                                       &aProcessInfo );

                    delete []lpCommandLine;

                    // wait until process ends to receive exit code
                    WaitForSingleObject( aProcessInfo.hProcess, INFINITE );

                    dwSTClientExitCode = 0;
                    GetExitCodeProcess( aProcessInfo.hProcess, &dwSTClientExitCode );
                    dwSTClientExitCode &= 0x000000ff;

                    CloseHandle( aProcessInfo.hProcess );
                    CloseHandle( aProcessInfo.hThread );

                    if ( !bSuccess )
                        dwExitCode = 1; // couldn't start stclient process
                    else
                    {
                        if ( _tcslen( szInstanceURN ) > 0 )
                        {
                            // don't register again if we registered in a previous run
                            // or we called stclient successfully.
                            if (( dwSTClientExitCode == ERR_DUP_RECORD ) ||
                                ( dwSTClientExitCode == 0 ))
                                dwExitCode = 0;
                            else
                                dwExitCode = 1; // other errors
                        }
                        else
                            dwExitCode = ( dwSTClientExitCode == 0 ) ? 0 : 1;
                    }
                }
                else if ( dwSTClientExitCode == 0 )
                    dwExitCode = 0; // already registered
                else
                    dwExitCode = 1; // other errors
            }
            else
                dwExitCode = 1; // couldn't start stclient
        }
        else
            dwExitCode = 1; // no executable found
    }
    else
        dwExitCode = 0; // wrong number of arguments

    return dwExitCode;
}
<|endoftext|>


<commit_before>//
// Name:	 canvas.cpp
// Purpose:	 Implements the canvas class for the wxWindows application.
//
// Copyright (c) 2001 Virtual Terrain Project
// Free for all uses, see license.txt for details.
//

// For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"

#ifndef WX_PRECOMP
#include "wx/wx.h"
#endif

#include "vtlib/vtlib.h"
#include "vtlib/core/TimeEngines.h"
#include "vtlib/core/TerrainScene.h"
#include "vtdata/vtLog.h"
#include "../Enviro.h"			// for g_App, GetTerrainScene
#include "canvas.h"
#include "frame.h"
#include "app.h"

DECLARE_APP(vtApp)

/*
 * vtGLCanvas implementation
 */
	BEGIN_EVENT_TABLE(vtGLCanvas, wxGLCanvas)
EVT_CLOSE(vtGLCanvas::OnClose)
EVT_SIZE(vtGLCanvas::OnSize)
EVT_PAINT(vtGLCanvas::OnPaint)
EVT_CHAR(vtGLCanvas::OnChar)
EVT_MOUSE_EVENTS(vtGLCanvas::OnMouseEvent)
EVT_ERASE_BACKGROUND(vtGLCanvas::OnEraseBackground)
END_EVENT_TABLE()

static vtGLCanvas *s_canvas = NULL;

vtGLCanvas::vtGLCanvas(wxWindow *parent, wxWindowID id,
	const wxPoint& pos, const wxSize& size, long style, const wxString& name, int* gl_attrib):
wxGLCanvas(parent, id, pos, size, style, name, gl_attrib)
{
	VTLOG("Constructing vtGLCanvas\n");
	parent->Show(TRUE);
	SetCurrent();

	m_StatusTimer.SetFrame((wxFrame *)parent);
	m_StatusTimer.Start(1000);

	m_bPainting = false;
	m_bRunning = true;
	m_bShowFrameRateChart = false;

	s_canvas = this;
}

vtGLCanvas::~vtGLCanvas(void)
{
}

void EnableContinuousRendering(bool bTrue)
{
	VTLOG("EnableContinuousRendering %d\n", bTrue);
	if (!s_canvas)
		return;

	bool bNeedRefresh = (s_canvas->m_bRunning == false && bTrue == true);
	s_canvas->m_bRunning = bTrue;
	if (bNeedRefresh)
		s_canvas->Refresh(FALSE);
}

void vtGLCanvas::QueueRefresh(bool eraseBackground)
	// A Refresh routine we can call from inside OnPaint.
	//   (queues the events rather than dispatching them immediately).
{
	// With wxGTK, you can't do a Refresh() in OnPaint because it doesn't
	//   queue (post) a Refresh event for later.  Rather it dispatches
	//   (processes) the underlying events immediately via ProcessEvent
	//   (read, recursive call).  See the wxPostEvent docs and Refresh code
	//   for more details.
	if ( eraseBackground )
	{
		wxEraseEvent eevent( GetId() );
		eevent.SetEventObject( this );
		wxPostEvent( GetEventHandler(), eevent );
	}

	wxPaintEvent event( GetId() );
	event.SetEventObject( this );
	wxPostEvent( GetEventHandler(), event );
}

void StatusTimer::Notify()
{
	if (!m_pFrame || !m_pFrame->GetStatusBar()) return;

	vtScene *scene = vtGetScene();
	if (!scene) return;

	wxString str, str2;

	// get framerate
	float fps = scene->GetFrameRate();

	// only show 3 significant digits
	if (fps < 10)
		str.Printf(_T("fps %1.2f, "), fps);
	else if (fps < 80)
		str.Printf(_T("fps %2.1f, "), fps);
	else
		str.Printf(_T("fps %3.0f, "), fps);

	// get time of day
	TimeEngine *te = GetTerrainScene()->GetTimeEngine();
	if (te->GetEnabled())
	{
		int hr, min, sec;
		te->GetTime(hr, min, sec);

		str2.Printf(_T("time %02d:%02d:%02d, "), hr, min, sec);
		str += str2;
	}

	vtString vs;
	g_App.DescribeCoordinates(vs);
	str += wxString::FromAscii((const char *)vs);

	// get CLOD triangle counts, if appropriate
	g_App.DescribeCLOD(vs);
	str += wxString::FromAscii((const char *)vs);

	str += wxString::FromAscii((const char *)g_App.m_strMessage);

	m_pFrame->SetStatusText(str);
}

void vtGLCanvas::OnPaint( wxPaintEvent& event )
{
	vtScene *pScene = vtGetScene();

	if (!pScene->HasWinInfo())
	{
		VTLOG("First OnPaint message.\n");
#ifdef WIN32
		HWND handle = (HWND) GetHandle();
		pScene->SetWinInfo(handle, m_glContext);
#else
		pScene->SetWinInfo(NULL, NULL);
#endif
//		CreateScene();
	}

	// place the dc inside a scope, to delete it before the end of function
	if (1)
	{
		// This is a dummy, to avoid an endless succession of paint messages.
		// OnPaint handlers must always create a wxPaintDC.
		wxPaintDC dc(this);
#ifdef __WXMSW__
		if (!GetContext()) return;
#endif

		if (m_bPainting || !m_bRunning) return;

#if !VTLIB_PSM
		m_bPainting = true;

		// Render the Scene Graph
		vtGetScene()->DoUpdate();

		if (m_bShowFrameRateChart)
			vtGetScene()->DrawFrameRateChart();

		SwapBuffers();

#ifdef WIN32
		// Call Refresh again for continuous rendering,
		if (m_bRunning)
			Refresh(FALSE);
#else
		// Queue another refresh for continuous rendering.
		//   (Yield first so we don't starve out keyboard & mouse events.)
		//
		// FIXME: We may want to use a frame timer instead of immediate-
		//   redraw so we don't eat so much CPU on machines that can
		//   easily handle the frame rate.
		wxYield();
		QueueRefresh(FALSE);
#endif

		// update the status bar every 1/10 of a second
		static float last_stat = 0.0f;
		static vtString last_msg;
		float cur = vtGetTime();
		if (cur - last_stat > 0.1f || g_App.GetMessage() != last_msg)
		{
			last_msg = g_App.GetMessage();
			last_stat = cur;
			m_StatusTimer.Notify();
		}

		m_bPainting = false;
#endif // VTLIB_PSM
	}

	// Must allow some idle processing to occur - or the toolbars will not
	// update, and the close box will not respond!
	bool go = true;
	while (go)
	{
		go = wxGetApp().ProcessIdle();
	}
}

void vtGLCanvas::OnClose(wxCloseEvent& event)
{
	m_bRunning = false;
}

void vtGLCanvas::OnSize(wxSizeEvent& event)
{
  // Presumably this is a wxMSWism.
  // For wxGTK & wxMotif, all canvas resize events occur before the context
  //   is set.  So ignore this context check and grab the window width/height
  //   when we get it so it (and derived values such as aspect ratio and
  //   viewport parms) are computed correctly.
#ifdef __WXMSW__
	if (!GetContext()) return;
#endif

	SetCurrent();
	int width, height;
	GetClientSize(& width, & height);

	vtGetScene()->SetWindowSize(width, height);

	wxGLCanvas::OnSize(event);
}

void vtGLCanvas::OnChar(wxKeyEvent& event)
{
	long key = event.KeyCode();

	// pass the char to the frame for it to do "accelerator" shortcuts
	vtFrame *frame = (vtFrame*) GetParent();
	frame->OnChar(event);

	int flags = 0;

	if (event.ControlDown())
		flags |= VT_CONTROL;

	if (event.ShiftDown())
		flags |= VT_SHIFT;

	if (event.AltDown())
		flags |= VT_ALT;

	// pass the char to the vtlib Scene
	vtGetScene()->OnKey(key, flags);
}

void vtGLCanvas::OnMouseEvent(wxMouseEvent& event1)
{
	static bool bCapture = false;

	// turn WX mouse event into a VT mouse event
	vtMouseEvent event;
	wxEventType  ev = event1.GetEventType();
	if (ev == wxEVT_LEFT_DOWN) {
		event.type = VT_DOWN;
		event.button = VT_LEFT;
	} else if (ev == wxEVT_LEFT_UP) {
		event.type = VT_UP;
		event.button = VT_LEFT;
	} else if (ev == wxEVT_MIDDLE_DOWN) {
		event.type = VT_DOWN;
		event.button = VT_MIDDLE;
	} else if (ev == wxEVT_MIDDLE_UP) {
		event.type = VT_UP;
		event.button = VT_MIDDLE;
	} else if (ev == wxEVT_RIGHT_DOWN) {
		event.type = VT_DOWN;
		event.button = VT_RIGHT;
	} else if (ev == wxEVT_RIGHT_UP) {
		event.type = VT_UP;
		event.button = VT_RIGHT;
	} else if (ev == wxEVT_MOTION) {
		event.type = VT_MOVE;
		event.button = VT_NONE;
	} else {
		// ignored mouse events, such as wxEVT_LEAVE_WINDOW
		return;
	}

	if (ev == wxEVT_LEFT_DOWN || ev == wxEVT_MIDDLE_DOWN || ev == wxEVT_RIGHT_DOWN)
	{
//		VTLOG("DOWN: capture %d", bCapture);
		if (!bCapture)
		{
			CaptureMouse();
			bCapture = true;
//			VTLOG(" -> true");
		}
//		VTLOG("\n");
	}
	if (ev == wxEVT_LEFT_UP || ev == wxEVT_MIDDLE_UP || ev == wxEVT_RIGHT_UP)
	{
//		VTLOG("  UP: capture %d", bCapture);
		if (bCapture)
		{
			ReleaseMouse();
			bCapture = false;
//			VTLOG(" -> false");
		}
//		VTLOG("\n");
	}

	event.flags = 0;
	wxCoord xpos, ypos;
	event1.GetPosition(&xpos, &ypos);
	event.pos.Set(xpos, ypos);

	if (event1.ControlDown())
		event.flags |= VT_CONTROL;

	if (event1.ShiftDown())
		event.flags |= VT_SHIFT;

	if (event1.AltDown())
		event.flags |= VT_ALT;

	// inform Enviro app
	g_App.OnMouse(event);

	vtGetScene()->OnMouse(event);
}

void vtGLCanvas::OnEraseBackground(wxEraseEvent& event)
{
	// Do nothing, to avoid flashing.
}
<commit_msg>added safety check<commit_after>//
// Name:	 canvas.cpp
// Purpose:	 Implements the canvas class for the wxWindows application.
//
// Copyright (c) 2001 Virtual Terrain Project
// Free for all uses, see license.txt for details.
//

// For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"

#ifndef WX_PRECOMP
#include "wx/wx.h"
#endif

#include "vtlib/vtlib.h"
#include "vtlib/core/TimeEngines.h"
#include "vtlib/core/TerrainScene.h"
#include "vtdata/vtLog.h"
#include "../Enviro.h"			// for g_App, GetTerrainScene
#include "canvas.h"
#include "frame.h"
#include "app.h"

DECLARE_APP(vtApp)

/*
 * vtGLCanvas implementation
 */
	BEGIN_EVENT_TABLE(vtGLCanvas, wxGLCanvas)
EVT_CLOSE(vtGLCanvas::OnClose)
EVT_SIZE(vtGLCanvas::OnSize)
EVT_PAINT(vtGLCanvas::OnPaint)
EVT_CHAR(vtGLCanvas::OnChar)
EVT_MOUSE_EVENTS(vtGLCanvas::OnMouseEvent)
EVT_ERASE_BACKGROUND(vtGLCanvas::OnEraseBackground)
END_EVENT_TABLE()

static vtGLCanvas *s_canvas = NULL;

vtGLCanvas::vtGLCanvas(wxWindow *parent, wxWindowID id,
	const wxPoint& pos, const wxSize& size, long style, const wxString& name, int* gl_attrib):
wxGLCanvas(parent, id, pos, size, style, name, gl_attrib)
{
	VTLOG("Constructing vtGLCanvas\n");
	parent->Show(TRUE);
	SetCurrent();

	m_StatusTimer.SetFrame((wxFrame *)parent);
	m_StatusTimer.Start(1000);

	m_bPainting = false;
	m_bRunning = true;
	m_bShowFrameRateChart = false;

	s_canvas = this;
}

vtGLCanvas::~vtGLCanvas(void)
{
}

void EnableContinuousRendering(bool bTrue)
{
	VTLOG("EnableContinuousRendering %d\n", bTrue);
	if (!s_canvas)
		return;

	bool bNeedRefresh = (s_canvas->m_bRunning == false && bTrue == true);
	s_canvas->m_bRunning = bTrue;
	if (bNeedRefresh)
		s_canvas->Refresh(FALSE);
}

void vtGLCanvas::QueueRefresh(bool eraseBackground)
	// A Refresh routine we can call from inside OnPaint.
	//   (queues the events rather than dispatching them immediately).
{
	// With wxGTK, you can't do a Refresh() in OnPaint because it doesn't
	//   queue (post) a Refresh event for later.  Rather it dispatches
	//   (processes) the underlying events immediately via ProcessEvent
	//   (read, recursive call).  See the wxPostEvent docs and Refresh code
	//   for more details.
	if ( eraseBackground )
	{
		wxEraseEvent eevent( GetId() );
		eevent.SetEventObject( this );
		wxPostEvent( GetEventHandler(), eevent );
	}

	wxPaintEvent event( GetId() );
	event.SetEventObject( this );
	wxPostEvent( GetEventHandler(), event );
}

void StatusTimer::Notify()
{
	if (!m_pFrame || !m_pFrame->GetStatusBar()) return;

	vtScene *scene = vtGetScene();
	if (!scene) return;

	wxString str, str2;

	// get framerate
	float fps = scene->GetFrameRate();

	// only show 3 significant digits
	if (fps < 10)
		str.Printf(_T("fps %1.2f, "), fps);
	else if (fps < 80)
		str.Printf(_T("fps %2.1f, "), fps);
	else
		str.Printf(_T("fps %3.0f, "), fps);

	// get time of day
	TimeEngine *te = GetTerrainScene()->GetTimeEngine();
	if (te && te->GetEnabled())
	{
		int hr, min, sec;
		te->GetTime(hr, min, sec);

		str2.Printf(_T("time %02d:%02d:%02d, "), hr, min, sec);
		str += str2;
	}

	vtString vs;
	g_App.DescribeCoordinates(vs);
	str += wxString::FromAscii((const char *)vs);

	// get CLOD triangle counts, if appropriate
	g_App.DescribeCLOD(vs);
	str += wxString::FromAscii((const char *)vs);

	str += wxString::FromAscii((const char *)g_App.m_strMessage);

	m_pFrame->SetStatusText(str);
}

void vtGLCanvas::OnPaint( wxPaintEvent& event )
{
	vtScene *pScene = vtGetScene();

	if (!pScene->HasWinInfo())
	{
		VTLOG("First OnPaint message.\n");
#ifdef WIN32
		HWND handle = (HWND) GetHandle();
		pScene->SetWinInfo(handle, m_glContext);
#else
		pScene->SetWinInfo(NULL, NULL);
#endif
//		CreateScene();
	}

	// place the dc inside a scope, to delete it before the end of function
	if (1)
	{
		// This is a dummy, to avoid an endless succession of paint messages.
		// OnPaint handlers must always create a wxPaintDC.
		wxPaintDC dc(this);
#ifdef __WXMSW__
		if (!GetContext()) return;
#endif

		if (m_bPainting || !m_bRunning) return;

#if !VTLIB_PSM
		m_bPainting = true;

		// Render the Scene Graph
		vtGetScene()->DoUpdate();

		if (m_bShowFrameRateChart)
			vtGetScene()->DrawFrameRateChart();

		SwapBuffers();

#ifdef WIN32
		// Call Refresh again for continuous rendering,
		if (m_bRunning)
			Refresh(FALSE);
#else
		// Queue another refresh for continuous rendering.
		//   (Yield first so we don't starve out keyboard & mouse events.)
		//
		// FIXME: We may want to use a frame timer instead of immediate-
		//   redraw so we don't eat so much CPU on machines that can
		//   easily handle the frame rate.
		wxYield();
		QueueRefresh(FALSE);
#endif

		// update the status bar every 1/10 of a second
		static float last_stat = 0.0f;
		static vtString last_msg;
		float cur = vtGetTime();
		if (cur - last_stat > 0.1f || g_App.GetMessage() != last_msg)
		{
			last_msg = g_App.GetMessage();
			last_stat = cur;
			m_StatusTimer.Notify();
		}

		m_bPainting = false;
#endif // VTLIB_PSM
	}

	// Must allow some idle processing to occur - or the toolbars will not
	// update, and the close box will not respond!
	bool go = true;
	while (go)
	{
		go = wxGetApp().ProcessIdle();
	}
}

void vtGLCanvas::OnClose(wxCloseEvent& event)
{
	m_bRunning = false;
}

void vtGLCanvas::OnSize(wxSizeEvent& event)
{
  // Presumably this is a wxMSWism.
  // For wxGTK & wxMotif, all canvas resize events occur before the context
  //   is set.  So ignore this context check and grab the window width/height
  //   when we get it so it (and derived values such as aspect ratio and
  //   viewport parms) are computed correctly.
#ifdef __WXMSW__
	if (!GetContext()) return;
#endif

	SetCurrent();
	int width, height;
	GetClientSize(& width, & height);

	vtGetScene()->SetWindowSize(width, height);

	wxGLCanvas::OnSize(event);
}

void vtGLCanvas::OnChar(wxKeyEvent& event)
{
	long key = event.KeyCode();

	// pass the char to the frame for it to do "accelerator" shortcuts
	vtFrame *frame = (vtFrame*) GetParent();
	frame->OnChar(event);

	int flags = 0;

	if (event.ControlDown())
		flags |= VT_CONTROL;

	if (event.ShiftDown())
		flags |= VT_SHIFT;

	if (event.AltDown())
		flags |= VT_ALT;

	// pass the char to the vtlib Scene
	vtGetScene()->OnKey(key, flags);
}

void vtGLCanvas::OnMouseEvent(wxMouseEvent& event1)
{
	static bool bCapture = false;

	// turn WX mouse event into a VT mouse event
	vtMouseEvent event;
	wxEventType  ev = event1.GetEventType();
	if (ev == wxEVT_LEFT_DOWN) {
		event.type = VT_DOWN;
		event.button = VT_LEFT;
	} else if (ev == wxEVT_LEFT_UP) {
		event.type = VT_UP;
		event.button = VT_LEFT;
	} else if (ev == wxEVT_MIDDLE_DOWN) {
		event.type = VT_DOWN;
		event.button = VT_MIDDLE;
	} else if (ev == wxEVT_MIDDLE_UP) {
		event.type = VT_UP;
		event.button = VT_MIDDLE;
	} else if (ev == wxEVT_RIGHT_DOWN) {
		event.type = VT_DOWN;
		event.button = VT_RIGHT;
	} else if (ev == wxEVT_RIGHT_UP) {
		event.type = VT_UP;
		event.button = VT_RIGHT;
	} else if (ev == wxEVT_MOTION) {
		event.type = VT_MOVE;
		event.button = VT_NONE;
	} else {
		// ignored mouse events, such as wxEVT_LEAVE_WINDOW
		return;
	}

	if (ev == wxEVT_LEFT_DOWN || ev == wxEVT_MIDDLE_DOWN || ev == wxEVT_RIGHT_DOWN)
	{
//		VTLOG("DOWN: capture %d", bCapture);
		if (!bCapture)
		{
			CaptureMouse();
			bCapture = true;
//			VTLOG(" -> true");
		}
//		VTLOG("\n");
	}
	if (ev == wxEVT_LEFT_UP || ev == wxEVT_MIDDLE_UP || ev == wxEVT_RIGHT_UP)
	{
//		VTLOG("  UP: capture %d", bCapture);
		if (bCapture)
		{
			ReleaseMouse();
			bCapture = false;
//			VTLOG(" -> false");
		}
//		VTLOG("\n");
	}

	event.flags = 0;
	wxCoord xpos, ypos;
	event1.GetPosition(&xpos, &ypos);
	event.pos.Set(xpos, ypos);

	if (event1.ControlDown())
		event.flags |= VT_CONTROL;

	if (event1.ShiftDown())
		event.flags |= VT_SHIFT;

	if (event1.AltDown())
		event.flags |= VT_ALT;

	// inform Enviro app
	g_App.OnMouse(event);

	vtGetScene()->OnMouse(event);
}

void vtGLCanvas::OnEraseBackground(wxEraseEvent& event)
{
	// Do nothing, to avoid flashing.
}
<|endoftext|>


<commit_before>// ---------------------------------------------------------------------
//
// Copyright (C) 2009 - 2015 by the deal.II authors
//
// This file is part of the deal.II library.
//
// The deal.II library is free software; you can use it, redistribute
// it, and/or modify it under the terms of 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 full text of the license can be found in the file LICENSE at
// the top level of the deal.II distribution.
//
// ---------------------------------------------------------------------

// same as deal.II/assemble_matrix_parallel_01, but for trilinos matrices

#include "../tests.h"

#include <deal.II/base/quadrature_lib.h>
#include <deal.II/base/function.h>
#include <deal.II/base/logstream.h>
#include <deal.II/base/utilities.h>
#include <deal.II/base/work_stream.h>
#include <deal.II/base/graph_coloring.h>
#include <deal.II/lac/vector.h>
#include <deal.II/lac/full_matrix.h>
#include <deal.II/lac/trilinos_sparse_matrix.h>
#include <deal.II/grid/tria.h>
#include <deal.II/grid/grid_generator.h>
#include <deal.II/grid/tria_accessor.h>
#include <deal.II/grid/tria_iterator.h>
#include <deal.II/grid/grid_refinement.h>
#include <deal.II/dofs/dof_accessor.h>
#include <deal.II/dofs/dof_tools.h>
#include <deal.II/lac/constraint_matrix.h>
#include <deal.II/fe/fe_q.h>
#include <deal.II/numerics/vector_tools.h>
#include <deal.II/numerics/matrix_tools.h>
#include <deal.II/numerics/error_estimator.h>
#include <deal.II/lac/compressed_simple_sparsity_pattern.h>
#include <deal.II/hp/dof_handler.h>
#include <deal.II/hp/fe_values.h>

#include <fstream>
#include <iostream>
#include <complex>

std::ofstream logfile("output");

using namespace dealii;

namespace Assembly
{
  namespace Scratch
  {
    template <int dim>
    struct Data
    {
      Data (const hp::FECollection<dim> &fe,
            const hp::QCollection<dim>  &quadrature)
        :
        hp_fe_values(fe,
                     quadrature,
                     update_values    |  update_gradients |
                     update_quadrature_points  |  update_JxW_values)
      {}

      Data (const Data &data)
        :
        hp_fe_values(data.hp_fe_values.get_mapping_collection(),
                     data.hp_fe_values.get_fe_collection(),
                     data.hp_fe_values.get_quadrature_collection(),
                     data.hp_fe_values.get_update_flags())
      {}

      hp::FEValues<dim>               hp_fe_values;
    };
  }

  namespace Copy
  {
    struct Data
    {
      std::vector<types::global_dof_index> local_dof_indices;
      FullMatrix<double> local_matrix;
      Vector<double> local_rhs;
    };
  }
}

template <int dim>
class LaplaceProblem
{
public:
  LaplaceProblem ();
  ~LaplaceProblem ();

  void run ();

private:
  void setup_system ();
  void test_equality ();
  void assemble_reference ();
  void assemble_test ();
  void solve ();
  void create_coarse_grid ();
  void postprocess ();

  void local_assemble (const typename hp::DoFHandler<dim>::active_cell_iterator &cell,
                       Assembly::Scratch::Data<dim>  &scratch,
                       Assembly::Copy::Data          &data);
  void copy_local_to_global (const Assembly::Copy::Data &data);

  std::vector<types::global_dof_index>
  get_conflict_indices (typename hp::DoFHandler<dim>::active_cell_iterator const &cell) const;

  Triangulation<dim>   triangulation;

  hp::DoFHandler<dim>      dof_handler;
  hp::FECollection<dim>    fe_collection;
  hp::QCollection<dim>     quadrature_collection;
  hp::QCollection<dim-1>   face_quadrature_collection;

  ConstraintMatrix     constraints;

  TrilinosWrappers::SparseMatrix reference_matrix;
  TrilinosWrappers::SparseMatrix test_matrix;

  Vector<double>       reference_rhs;
  Vector<double>       test_rhs;

  std::vector<std::vector<typename hp::DoFHandler<dim>::active_cell_iterator> > graph;

  const unsigned int max_degree;
};

template <int dim>
class BoundaryValues : public Function<dim>
{
public:
  BoundaryValues () : Function<dim> () {}

  virtual double value (const Point<dim>   &p,
                        const unsigned int  component) const;
};

template <int dim>
double
BoundaryValues<dim>::value (const Point<dim>   &p,
                            const unsigned int  /*component*/) const
{
  double sum = 0;
  for (unsigned int d=0; d<dim; ++d)
    sum += std::sin(numbers::PI*p[d]);
  return sum;
}

template <int dim>
class RightHandSide : public Function<dim>
{
public:
  RightHandSide () : Function<dim> () {}

  virtual double value (const Point<dim>   &p,
                        const unsigned int  component) const;
};

template <int dim>
double
RightHandSide<dim>::value (const Point<dim>   &p,
                           const unsigned int  /*component*/) const
{
  double product = 1;
  for (unsigned int d=0; d<dim; ++d)
    product *= (p[d]+1);
  return product;
}

template <int dim>
LaplaceProblem<dim>::LaplaceProblem ()
  :
  dof_handler (triangulation),
  max_degree (5)
{
  if (dim == 2)
    for (unsigned int degree=2; degree<=max_degree; ++degree)
      {
        fe_collection.push_back (FE_Q<dim>(degree));
        quadrature_collection.push_back (QGauss<dim>(degree+1));
        face_quadrature_collection.push_back (QGauss<dim-1>(degree+1));
      }
  else
    for (unsigned int degree=1; degree<max_degree-1; ++degree)
      {
        fe_collection.push_back (FE_Q<dim>(degree));
        quadrature_collection.push_back (QGauss<dim>(degree+1));
        face_quadrature_collection.push_back (QGauss<dim-1>(degree+1));
      }
}

template <int dim>
LaplaceProblem<dim>::~LaplaceProblem ()
{
  dof_handler.clear ();
}

template <int dim>
std::vector<types::global_dof_index>
LaplaceProblem<dim>::
get_conflict_indices (typename hp::DoFHandler<dim>::active_cell_iterator const &cell) const
{
  std::vector<types::global_dof_index> local_dof_indices(cell->get_fe().dofs_per_cell);
  cell->get_dof_indices(local_dof_indices);

  constraints.resolve_indices(local_dof_indices);
  return local_dof_indices;
}

template <int dim>
void LaplaceProblem<dim>::setup_system ()
{
  reference_matrix.clear();
  test_matrix.clear();
  dof_handler.distribute_dofs (fe_collection);

  reference_rhs.reinit (dof_handler.n_dofs());
  test_rhs.reinit (dof_handler.n_dofs());

  constraints.clear ();

  DoFTools::make_hanging_node_constraints (dof_handler, constraints);

  // add boundary conditions as inhomogeneous constraints here, do it after
  // having added the hanging node constraints in order to be consistent and
  // skip dofs that are already constrained (i.e., are hanging nodes on the
  // boundary in 3D). In contrast to step-27, we choose a sine function.
  VectorTools::interpolate_boundary_values (dof_handler,
                                            0,
                                            BoundaryValues<dim>(),
                                            constraints);
  constraints.close ();

  graph = GraphColoring::make_graph_coloring(dof_handler.begin_active(),dof_handler.end(),
                                             static_cast<std_cxx11::function<std::vector<types::global_dof_index>
                                             (typename hp::DoFHandler<dim>::active_cell_iterator const &)> >
                                             (std_cxx11::bind(&LaplaceProblem<dim>::get_conflict_indices, this,std_cxx11::_1)));

  CompressedSimpleSparsityPattern csp (dof_handler.n_dofs(),
                                       dof_handler.n_dofs());
  DoFTools::make_sparsity_pattern (dof_handler, csp,
                                   constraints, false);
  reference_matrix.reinit (dof_handler.locally_owned_dofs(), csp, MPI_COMM_WORLD);
  test_matrix.reinit (reference_matrix);
}

template <int dim>
void
LaplaceProblem<dim>::local_assemble (const typename hp::DoFHandler<dim>::active_cell_iterator &cell,
                                     Assembly::Scratch::Data<dim>  &scratch,
                                     Assembly::Copy::Data          &data)
{
  const unsigned int   dofs_per_cell = cell->get_fe().dofs_per_cell;

  data.local_matrix.reinit (dofs_per_cell, dofs_per_cell);
  data.local_matrix = 0;

  data.local_rhs.reinit (dofs_per_cell);
  data.local_rhs = 0;

  scratch.hp_fe_values.reinit (cell);

  const FEValues<dim> &fe_values = scratch.hp_fe_values.get_present_fe_values ();

  const RightHandSide<dim> rhs_function;

  for (unsigned int q_point=0;
       q_point<fe_values.n_quadrature_points;
       ++q_point)
    {
      const double rhs_value = rhs_function.value(fe_values.quadrature_point(q_point),0);
      for (unsigned int i=0; i<dofs_per_cell; ++i)
        {
          for (unsigned int j=0; j<dofs_per_cell; ++j)
            data.local_matrix(i,j) += (fe_values.shape_grad(i,q_point) *
                                       fe_values.shape_grad(j,q_point) *
                                       fe_values.JxW(q_point));

            data.local_rhs(i) += (fe_values.shape_value(i,q_point) *
                                  rhs_value *
                                  fe_values.JxW(q_point));
        }
    }

  data.local_dof_indices.resize (dofs_per_cell);
  cell->get_dof_indices (data.local_dof_indices);
}

template <int dim>
void
LaplaceProblem<dim>::copy_local_to_global (const Assembly::Copy::Data &data)
{
  constraints.distribute_local_to_global(data.local_matrix, data.local_rhs,
                                         data.local_dof_indices,
                                         test_matrix, test_rhs);
}

template <int dim>
void LaplaceProblem<dim>::assemble_reference ()
{
  test_matrix = 0;
  test_rhs = 0;

  Assembly::Copy::Data copy_data;
  Assembly::Scratch::Data<dim> assembly_data(fe_collection, quadrature_collection);

  for (unsigned int color=0; color<graph.size(); ++color)
    for (typename std::vector<typename hp::DoFHandler<dim>::active_cell_iterator>::const_iterator p = graph[color].begin();
         p != graph[color].end(); ++p)
      {
        local_assemble(*p, assembly_data, copy_data);
        copy_local_to_global(copy_data);
      }

  reference_matrix.add(1., test_matrix);
  reference_rhs = test_rhs;
}

template <int dim>
void LaplaceProblem<dim>::assemble_test ()
{
  test_matrix = 0;
  test_rhs = 0;

  WorkStream::
    run (graph,
         std_cxx11::bind (&LaplaceProblem<dim>::
                          local_assemble,
                          this,
                          std_cxx11::_1,
                          std_cxx11::_2,
                          std_cxx11::_3),
         std_cxx11::bind (&LaplaceProblem<dim>::
                          copy_local_to_global,
                          this,
                          std_cxx11::_1),
         Assembly::Scratch::Data<dim>(fe_collection, quadrature_collection),
         Assembly::Copy::Data (),
         2*MultithreadInfo::n_threads(),
         1);

  test_matrix.add(-1, reference_matrix);

  // there should not even be roundoff difference between matrices
  deallog.threshold_double(1.e-30);
  deallog << "error in matrix: " << test_matrix.frobenius_norm() << std::endl;
  test_rhs.add(-1., reference_rhs);
  deallog << "error in vector: " << test_rhs.l2_norm() << std::endl;
}

template <int dim>
void LaplaceProblem<dim>::postprocess ()
{
  Vector<float> estimated_error_per_cell (triangulation.n_active_cells());
  for (unsigned int i=0; i<estimated_error_per_cell.size(); ++i)
    estimated_error_per_cell(i) = i;

  GridRefinement::refine_and_coarsen_fixed_number (triangulation,
                                                   estimated_error_per_cell,
                                                   0.3, 0.03);
  triangulation.execute_coarsening_and_refinement ();

  for (typename hp::DoFHandler<dim>::active_cell_iterator cell = dof_handler.begin_active();
       cell != dof_handler.end(); ++cell)
    cell->set_active_fe_index (rand() % fe_collection.size());
}

template <int dim>
void LaplaceProblem<dim>::run ()
{
  for (unsigned int cycle=0; cycle<3; ++cycle)
    {
      if (cycle == 0)
        {
          GridGenerator::hyper_cube(triangulation, 0, 1/* ,
                                     Point<dim>(),
                                     0.5, 1., (dim==3) ? 96 : 12, false*/);
          triangulation.refine_global(2);
        }

      setup_system ();

      assemble_reference ();
      assemble_test ();

      if (cycle < 2)
        postprocess ();
    }
}

int main (int argc, char **argv)
{
  deallog << std::setprecision (2);
  logfile << std::setprecision (2);
  deallog.attach(logfile);
  deallog.depth_console(0);

  Utilities::MPI::MPI_InitFinalize init(argc, argv, numbers::invalid_unsigned_int);

  {
    deallog.push("2d");
    LaplaceProblem<2> laplace_problem;
    laplace_problem.run ();
    deallog.pop();
  }

  {
    deallog.push("3d");
    LaplaceProblem<3> laplace_problem;
    laplace_problem.run ();
    deallog.pop();
  }
}

<commit_msg>Make sure to call compress() in test<commit_after>// ---------------------------------------------------------------------
//
// Copyright (C) 2009 - 2015 by the deal.II authors
//
// This file is part of the deal.II library.
//
// The deal.II library is free software; you can use it, redistribute
// it, and/or modify it under the terms of 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 full text of the license can be found in the file LICENSE at
// the top level of the deal.II distribution.
//
// ---------------------------------------------------------------------

// same as deal.II/assemble_matrix_parallel_01, but for trilinos matrices

#include "../tests.h"

#include <deal.II/base/quadrature_lib.h>
#include <deal.II/base/function.h>
#include <deal.II/base/logstream.h>
#include <deal.II/base/utilities.h>
#include <deal.II/base/work_stream.h>
#include <deal.II/base/graph_coloring.h>
#include <deal.II/lac/vector.h>
#include <deal.II/lac/full_matrix.h>
#include <deal.II/lac/trilinos_sparse_matrix.h>
#include <deal.II/grid/tria.h>
#include <deal.II/grid/grid_generator.h>
#include <deal.II/grid/tria_accessor.h>
#include <deal.II/grid/tria_iterator.h>
#include <deal.II/grid/grid_refinement.h>
#include <deal.II/dofs/dof_accessor.h>
#include <deal.II/dofs/dof_tools.h>
#include <deal.II/lac/constraint_matrix.h>
#include <deal.II/fe/fe_q.h>
#include <deal.II/numerics/vector_tools.h>
#include <deal.II/numerics/matrix_tools.h>
#include <deal.II/numerics/error_estimator.h>
#include <deal.II/lac/compressed_simple_sparsity_pattern.h>
#include <deal.II/hp/dof_handler.h>
#include <deal.II/hp/fe_values.h>

#include <fstream>
#include <iostream>
#include <complex>

std::ofstream logfile("output");

using namespace dealii;

namespace Assembly
{
  namespace Scratch
  {
    template <int dim>
    struct Data
    {
      Data (const hp::FECollection<dim> &fe,
            const hp::QCollection<dim>  &quadrature)
        :
        hp_fe_values(fe,
                     quadrature,
                     update_values    |  update_gradients |
                     update_quadrature_points  |  update_JxW_values)
      {}

      Data (const Data &data)
        :
        hp_fe_values(data.hp_fe_values.get_mapping_collection(),
                     data.hp_fe_values.get_fe_collection(),
                     data.hp_fe_values.get_quadrature_collection(),
                     data.hp_fe_values.get_update_flags())
      {}

      hp::FEValues<dim>               hp_fe_values;
    };
  }

  namespace Copy
  {
    struct Data
    {
      std::vector<types::global_dof_index> local_dof_indices;
      FullMatrix<double> local_matrix;
      Vector<double> local_rhs;
    };
  }
}

template <int dim>
class LaplaceProblem
{
public:
  LaplaceProblem ();
  ~LaplaceProblem ();

  void run ();

private:
  void setup_system ();
  void test_equality ();
  void assemble_reference ();
  void assemble_test ();
  void solve ();
  void create_coarse_grid ();
  void postprocess ();

  void local_assemble (const typename hp::DoFHandler<dim>::active_cell_iterator &cell,
                       Assembly::Scratch::Data<dim>  &scratch,
                       Assembly::Copy::Data          &data);
  void copy_local_to_global (const Assembly::Copy::Data &data);

  std::vector<types::global_dof_index>
  get_conflict_indices (typename hp::DoFHandler<dim>::active_cell_iterator const &cell) const;

  Triangulation<dim>   triangulation;

  hp::DoFHandler<dim>      dof_handler;
  hp::FECollection<dim>    fe_collection;
  hp::QCollection<dim>     quadrature_collection;
  hp::QCollection<dim-1>   face_quadrature_collection;

  ConstraintMatrix     constraints;

  TrilinosWrappers::SparseMatrix reference_matrix;
  TrilinosWrappers::SparseMatrix test_matrix;

  Vector<double>       reference_rhs;
  Vector<double>       test_rhs;

  std::vector<std::vector<typename hp::DoFHandler<dim>::active_cell_iterator> > graph;

  const unsigned int max_degree;
};

template <int dim>
class BoundaryValues : public Function<dim>
{
public:
  BoundaryValues () : Function<dim> () {}

  virtual double value (const Point<dim>   &p,
                        const unsigned int  component) const;
};

template <int dim>
double
BoundaryValues<dim>::value (const Point<dim>   &p,
                            const unsigned int  /*component*/) const
{
  double sum = 0;
  for (unsigned int d=0; d<dim; ++d)
    sum += std::sin(numbers::PI*p[d]);
  return sum;
}

template <int dim>
class RightHandSide : public Function<dim>
{
public:
  RightHandSide () : Function<dim> () {}

  virtual double value (const Point<dim>   &p,
                        const unsigned int  component) const;
};

template <int dim>
double
RightHandSide<dim>::value (const Point<dim>   &p,
                           const unsigned int  /*component*/) const
{
  double product = 1;
  for (unsigned int d=0; d<dim; ++d)
    product *= (p[d]+1);
  return product;
}

template <int dim>
LaplaceProblem<dim>::LaplaceProblem ()
  :
  dof_handler (triangulation),
  max_degree (5)
{
  if (dim == 2)
    for (unsigned int degree=2; degree<=max_degree; ++degree)
      {
        fe_collection.push_back (FE_Q<dim>(degree));
        quadrature_collection.push_back (QGauss<dim>(degree+1));
        face_quadrature_collection.push_back (QGauss<dim-1>(degree+1));
      }
  else
    for (unsigned int degree=1; degree<max_degree-1; ++degree)
      {
        fe_collection.push_back (FE_Q<dim>(degree));
        quadrature_collection.push_back (QGauss<dim>(degree+1));
        face_quadrature_collection.push_back (QGauss<dim-1>(degree+1));
      }
}

template <int dim>
LaplaceProblem<dim>::~LaplaceProblem ()
{
  dof_handler.clear ();
}

template <int dim>
std::vector<types::global_dof_index>
LaplaceProblem<dim>::
get_conflict_indices (typename hp::DoFHandler<dim>::active_cell_iterator const &cell) const
{
  std::vector<types::global_dof_index> local_dof_indices(cell->get_fe().dofs_per_cell);
  cell->get_dof_indices(local_dof_indices);

  constraints.resolve_indices(local_dof_indices);
  return local_dof_indices;
}

template <int dim>
void LaplaceProblem<dim>::setup_system ()
{
  reference_matrix.clear();
  test_matrix.clear();
  dof_handler.distribute_dofs (fe_collection);

  reference_rhs.reinit (dof_handler.n_dofs());
  test_rhs.reinit (dof_handler.n_dofs());

  constraints.clear ();

  DoFTools::make_hanging_node_constraints (dof_handler, constraints);

  // add boundary conditions as inhomogeneous constraints here, do it after
  // having added the hanging node constraints in order to be consistent and
  // skip dofs that are already constrained (i.e., are hanging nodes on the
  // boundary in 3D). In contrast to step-27, we choose a sine function.
  VectorTools::interpolate_boundary_values (dof_handler,
                                            0,
                                            BoundaryValues<dim>(),
                                            constraints);
  constraints.close ();

  graph = GraphColoring::make_graph_coloring(dof_handler.begin_active(),dof_handler.end(),
                                             static_cast<std_cxx11::function<std::vector<types::global_dof_index>
                                             (typename hp::DoFHandler<dim>::active_cell_iterator const &)> >
                                             (std_cxx11::bind(&LaplaceProblem<dim>::get_conflict_indices, this,std_cxx11::_1)));

  CompressedSimpleSparsityPattern csp (dof_handler.n_dofs(),
                                       dof_handler.n_dofs());
  DoFTools::make_sparsity_pattern (dof_handler, csp,
                                   constraints, false);
  reference_matrix.reinit (dof_handler.locally_owned_dofs(), csp, MPI_COMM_WORLD);
  test_matrix.reinit (reference_matrix);
}

template <int dim>
void
LaplaceProblem<dim>::local_assemble (const typename hp::DoFHandler<dim>::active_cell_iterator &cell,
                                     Assembly::Scratch::Data<dim>  &scratch,
                                     Assembly::Copy::Data          &data)
{
  const unsigned int   dofs_per_cell = cell->get_fe().dofs_per_cell;

  data.local_matrix.reinit (dofs_per_cell, dofs_per_cell);
  data.local_matrix = 0;

  data.local_rhs.reinit (dofs_per_cell);
  data.local_rhs = 0;

  scratch.hp_fe_values.reinit (cell);

  const FEValues<dim> &fe_values = scratch.hp_fe_values.get_present_fe_values ();

  const RightHandSide<dim> rhs_function;

  for (unsigned int q_point=0;
       q_point<fe_values.n_quadrature_points;
       ++q_point)
    {
      const double rhs_value = rhs_function.value(fe_values.quadrature_point(q_point),0);
      for (unsigned int i=0; i<dofs_per_cell; ++i)
        {
          for (unsigned int j=0; j<dofs_per_cell; ++j)
            data.local_matrix(i,j) += (fe_values.shape_grad(i,q_point) *
                                       fe_values.shape_grad(j,q_point) *
                                       fe_values.JxW(q_point));

            data.local_rhs(i) += (fe_values.shape_value(i,q_point) *
                                  rhs_value *
                                  fe_values.JxW(q_point));
        }
    }

  data.local_dof_indices.resize (dofs_per_cell);
  cell->get_dof_indices (data.local_dof_indices);
}

template <int dim>
void
LaplaceProblem<dim>::copy_local_to_global (const Assembly::Copy::Data &data)
{
  constraints.distribute_local_to_global(data.local_matrix, data.local_rhs,
                                         data.local_dof_indices,
                                         test_matrix, test_rhs);
}

template <int dim>
void LaplaceProblem<dim>::assemble_reference ()
{
  test_matrix = 0;
  test_rhs = 0;

  Assembly::Copy::Data copy_data;
  Assembly::Scratch::Data<dim> assembly_data(fe_collection, quadrature_collection);

  for (unsigned int color=0; color<graph.size(); ++color)
    for (typename std::vector<typename hp::DoFHandler<dim>::active_cell_iterator>::const_iterator p = graph[color].begin();
         p != graph[color].end(); ++p)
      {
        local_assemble(*p, assembly_data, copy_data);
        copy_local_to_global(copy_data);
      }
  test_matrix.compress(VectorOperation::add);
  test_rhs.compress(VectorOperation::add);

  reference_matrix.add(1., test_matrix);
  reference_rhs = test_rhs;
}

template <int dim>
void LaplaceProblem<dim>::assemble_test ()
{
  test_matrix = 0;
  test_rhs = 0;

  WorkStream::
    run (graph,
         std_cxx11::bind (&LaplaceProblem<dim>::
                          local_assemble,
                          this,
                          std_cxx11::_1,
                          std_cxx11::_2,
                          std_cxx11::_3),
         std_cxx11::bind (&LaplaceProblem<dim>::
                          copy_local_to_global,
                          this,
                          std_cxx11::_1),
         Assembly::Scratch::Data<dim>(fe_collection, quadrature_collection),
         Assembly::Copy::Data (),
         2*MultithreadInfo::n_threads(),
         1);
  test_matrix.compress(VectorOperation::add);
  test_rhs.compress(VectorOperation::add);

  test_matrix.add(-1, reference_matrix);

  // there should not even be roundoff difference between matrices
  deallog.threshold_double(1.e-30);
  deallog << "error in matrix: " << test_matrix.frobenius_norm() << std::endl;
  test_rhs.add(-1., reference_rhs);
  deallog << "error in vector: " << test_rhs.l2_norm() << std::endl;
}

template <int dim>
void LaplaceProblem<dim>::postprocess ()
{
  Vector<float> estimated_error_per_cell (triangulation.n_active_cells());
  for (unsigned int i=0; i<estimated_error_per_cell.size(); ++i)
    estimated_error_per_cell(i) = i;

  GridRefinement::refine_and_coarsen_fixed_number (triangulation,
                                                   estimated_error_per_cell,
                                                   0.3, 0.03);
  triangulation.execute_coarsening_and_refinement ();

  for (typename hp::DoFHandler<dim>::active_cell_iterator cell = dof_handler.begin_active();
       cell != dof_handler.end(); ++cell)
    cell->set_active_fe_index (rand() % fe_collection.size());
}

template <int dim>
void LaplaceProblem<dim>::run ()
{
  for (unsigned int cycle=0; cycle<3; ++cycle)
    {
      if (cycle == 0)
        {
          GridGenerator::hyper_cube(triangulation, 0, 1/* ,
                                     Point<dim>(),
                                     0.5, 1., (dim==3) ? 96 : 12, false*/);
          triangulation.refine_global(2);
        }

      setup_system ();

      assemble_reference ();
      assemble_test ();

      if (cycle < 2)
        postprocess ();
    }
}

int main (int argc, char **argv)
{
  deallog << std::setprecision (2);
  logfile << std::setprecision (2);
  deallog.attach(logfile);
  deallog.depth_console(0);

  Utilities::MPI::MPI_InitFinalize init(argc, argv, numbers::invalid_unsigned_int);

  {
    deallog.push("2d");
    LaplaceProblem<2> laplace_problem;
    laplace_problem.run ();
    deallog.pop();
  }

  {
    deallog.push("3d");
    LaplaceProblem<3> laplace_problem;
    laplace_problem.run ();
    deallog.pop();
  }
}

<|endoftext|>


<commit_before>// Copyright (c) 2020 Slack Technologies, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.

#include "shell/renderer/api/context_bridge/object_cache.h"

#include <utility>

#include "shell/common/api/object_life_monitor.h"

namespace electron {

namespace api {

namespace context_bridge {

ObjectCachePairNode::ObjectCachePairNode(ObjectCachePair&& pair) {
  this->pair = std::move(pair);
}

ObjectCachePairNode::~ObjectCachePairNode() = default;

ObjectCache::ObjectCache() {}
ObjectCache::~ObjectCache() = default;

void ObjectCache::CacheProxiedObject(v8::Local<v8::Value> from,
                                     v8::Local<v8::Value> proxy_value) {
  if (from->IsObject() && !from->IsNullOrUndefined()) {
    auto obj = v8::Local<v8::Object>::Cast(from);
    int hash = obj->GetIdentityHash();

    auto* node = new ObjectCachePairNode(std::make_pair(from, proxy_value));
    proxy_map_[hash].Append(node);
  }
}

v8::MaybeLocal<v8::Value> ObjectCache::GetCachedProxiedObject(
    v8::Local<v8::Value> from) const {
  if (!from->IsObject() || from->IsNullOrUndefined())
    return v8::MaybeLocal<v8::Value>();

  auto obj = v8::Local<v8::Object>::Cast(from);
  int hash = obj->GetIdentityHash();
  auto iter = proxy_map_.find(hash);
  if (iter == proxy_map_.end())
    return v8::MaybeLocal<v8::Value>();

  auto& list = iter->second;
  for (auto* node = list.head(); node != list.end(); node = node->next()) {
    auto& pair = node->value()->pair;
    auto from_cmp = pair.first;
    if (from_cmp == from) {
      if (pair.second.IsEmpty())
        return v8::MaybeLocal<v8::Value>();
      return pair.second;
    }
  }
  return v8::MaybeLocal<v8::Value>();
}

}  // namespace context_bridge

}  // namespace api

}  // namespace electron
<commit_msg>fix: clean up base::LinkedList in context_bridge::ObjectCache (#27630)<commit_after>// Copyright (c) 2020 Slack Technologies, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.

#include "shell/renderer/api/context_bridge/object_cache.h"

#include <utility>

#include "shell/common/api/object_life_monitor.h"

namespace electron {

namespace api {

namespace context_bridge {

ObjectCachePairNode::ObjectCachePairNode(ObjectCachePair&& pair) {
  this->pair = std::move(pair);
}

ObjectCachePairNode::~ObjectCachePairNode() = default;

ObjectCache::ObjectCache() {}
ObjectCache::~ObjectCache() {
  for (const auto& pair : proxy_map_) {
    while (!pair.second.empty()) {
      ObjectCachePairNode* node = pair.second.head()->value();
      node->RemoveFromList();
      delete node;
    }
  }
}

void ObjectCache::CacheProxiedObject(v8::Local<v8::Value> from,
                                     v8::Local<v8::Value> proxy_value) {
  if (from->IsObject() && !from->IsNullOrUndefined()) {
    auto obj = v8::Local<v8::Object>::Cast(from);
    int hash = obj->GetIdentityHash();

    auto* node = new ObjectCachePairNode(std::make_pair(from, proxy_value));
    proxy_map_[hash].Append(node);
  }
}

v8::MaybeLocal<v8::Value> ObjectCache::GetCachedProxiedObject(
    v8::Local<v8::Value> from) const {
  if (!from->IsObject() || from->IsNullOrUndefined())
    return v8::MaybeLocal<v8::Value>();

  auto obj = v8::Local<v8::Object>::Cast(from);
  int hash = obj->GetIdentityHash();
  auto iter = proxy_map_.find(hash);
  if (iter == proxy_map_.end())
    return v8::MaybeLocal<v8::Value>();

  auto& list = iter->second;
  for (auto* node = list.head(); node != list.end(); node = node->next()) {
    auto& pair = node->value()->pair;
    auto from_cmp = pair.first;
    if (from_cmp == from) {
      if (pair.second.IsEmpty())
        return v8::MaybeLocal<v8::Value>();
      return pair.second;
    }
  }
  return v8::MaybeLocal<v8::Value>();
}

}  // namespace context_bridge

}  // namespace api

}  // namespace electron
<|endoftext|>