<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 .
 */

#include <config_folders.h>

#include "sal/config.h"

#include <boost/shared_ptr.hpp>

#include "com/sun/star/container/XNameAccess.hpp"
#include "com/sun/star/io/XInputStream.hpp"
#include "com/sun/star/lang/Locale.hpp"
#include "com/sun/star/lang/XMultiServiceFactory.hpp"
#include "com/sun/star/packages/zip/ZipFileAccess.hpp"
#include "com/sun/star/uno/Any.hxx"
#include "com/sun/star/uno/Exception.hpp"
#include "com/sun/star/uno/RuntimeException.hpp"
#include "com/sun/star/uno/Sequence.hxx"
#include "comphelper/processfactory.hxx"
#include "osl/file.hxx"
#include "osl/diagnose.h"
#include "rtl/bootstrap.hxx"

#include "tools/stream.hxx"
#include "tools/urlobj.hxx"
#include "vcl/bitmapex.hxx"
#include <vcl/dibtools.hxx>
#include "vcl/pngread.hxx"
#include "vcl/settings.hxx"
#include "vcl/svapp.hxx"
#include "impimagetree.hxx"

namespace {

static OUString createPath(
    OUString const & name, sal_Int32 pos, OUString const & locale)
{
    return name.copy(0, pos + 1) + locale + name.copy(pos);
}

static boost::shared_ptr< SvStream > wrapFile(osl::File & file)
{
    // This could use SvInputStream instead if that did not have a broken
    // SeekPos implementation for an XInputStream that is not also XSeekable
    // (cf. "@@@" at tags/DEV300_m37/svtools/source/misc1/strmadpt.cxx@264807
    // l. 593):
    boost::shared_ptr< SvStream > s(new SvMemoryStream);
    for (;;) {
        void *data[2048];
        sal_uInt64 n;
        file.read(data, 2048, n);
        s->Write(data, n);
        if (n < 2048) {
            break;
        }
    }
    s->Seek(0);
    return s;
}

static boost::shared_ptr< SvStream > wrapStream(
    css::uno::Reference< css::io::XInputStream > const & stream)
{
    // This could use SvInputStream instead if that did not have a broken
    // SeekPos implementation for an XInputStream that is not also XSeekable
    // (cf. "@@@" at tags/DEV300_m37/svtools/source/misc1/strmadpt.cxx@264807
    // l. 593):
    OSL_ASSERT(stream.is());
    boost::shared_ptr< SvStream > s(new SvMemoryStream);
    for (;;) {
        sal_Int32 const size = 2048;
        css::uno::Sequence< sal_Int8 > data(size);
        sal_Int32 n = stream->readBytes(data, size);
        s->Write(data.getConstArray(), n);
        if (n < size) {
            break;
        }
    }
    s->Seek(0);
    return s;
}

static void loadImageFromStream(
    boost::shared_ptr< SvStream > pStream,
    OUString const & rPath, BitmapEx & rBitmap)
{
    if (rPath.endsWith(".png"))
    {
        vcl::PNGReader aPNGReader( *pStream );
        aPNGReader.SetIgnoreGammaChunk( true );
        rBitmap = aPNGReader.Read();
    } else {
        ReadDIBBitmapEx(rBitmap, *pStream);
    }
}

}

ImplImageTree::ImplImageTree() { m_cacheIcons = true; }

ImplImageTree::~ImplImageTree() {}

bool ImplImageTree::checkStyle(OUString const & style)
{
    bool exists;

    // using cache because setStyle is an expensive operation
    // setStyle calls resetPaths => closes any opened zip files with icons, cleans the icon cache, ...
    if (checkStyleCacheLookup(style, exists)) {
        return exists;
    }

    setStyle(style);

    exists = false;
    OUString aURL = m_path.first;

    osl::File aZip(aURL + ".zip");
    if (aZip.open(osl_File_OpenFlag_Read) == ::osl::FileBase::E_None) {
        aZip.close();
        exists = true;
    }

    osl::Directory aLookaside(aURL);
    if (aLookaside.open() == ::osl::FileBase::E_None) {
        aLookaside.close();
        exists = true;
        m_cacheIcons = false;
    } else {
        m_cacheIcons = true;
    }
    m_checkStyleCache[style] = exists;
    return exists;
}

bool ImplImageTree::loadImage(
    OUString const & name, OUString const & style, BitmapEx & bitmap,
    bool localized, bool loadMissing )
{
    bool found = false;
    try {
        found = doLoadImage(name, style, bitmap, localized);
    } catch (css::uno::RuntimeException &) {
        if (!loadMissing)
            throw;
    }
    if (found || !loadMissing)
        return found;

    SAL_INFO("vcl", "ImplImageTree::loadImage exception couldn't load \""
        << name << "\", fetching default image");

    return loadDefaultImage(style, bitmap);
}

bool ImplImageTree::loadDefaultImage(
    OUString const & style,
    BitmapEx& bitmap)
{
    return doLoadImage(
        OUString("res/grafikde.png"),
        style, bitmap, false);
}

bool ImplImageTree::doLoadImage(
    OUString const & name, OUString const & style, BitmapEx & bitmap,
    bool localized)
{
    setStyle(style);
    if (m_cacheIcons && iconCacheLookup(name, localized, bitmap)) {
        return true;
    }
    if (!bitmap.IsEmpty()) {
        bitmap.SetEmpty();
    }
    std::vector< OUString > paths;
    paths.push_back(getRealImageName(name));
    if (localized) {
        sal_Int32 pos = name.lastIndexOf('/');
        if (pos != -1) {
            // find() uses a reverse iterator, so push in reverse order.
            std::vector< OUString > aFallbacks( Application::GetSettings().GetUILanguageTag().getFallbackStrings( true));
            for (std::vector< OUString >::const_reverse_iterator it( aFallbacks.rbegin());
                    it != aFallbacks.rend(); ++it)
            {
                paths.push_back( getRealImageName( createPath(name, pos, *it) ) );
            }
        }
    }
    bool found = false;
    try {
        found = find(paths, bitmap);
    } catch (css::uno::RuntimeException &) {
        throw;
    } catch (const css::uno::Exception & e) {
        SAL_INFO("vcl", "ImplImageTree::doLoadImage exception " << e.Message);
    }
    if (m_cacheIcons && found) {
        m_iconCache[name.intern()] = std::make_pair(localized, bitmap);
    }
    return found;
}

void ImplImageTree::shutDown() {
    m_style = OUString();
        // for safety; empty m_style means "not initialized"
    m_iconCache.clear();
    m_checkStyleCache.clear();
    m_linkHash.clear();
}

void ImplImageTree::setStyle(OUString const & style) {
    OSL_ASSERT(!style.isEmpty()); // empty m_style means "not initialized"
    if (style != m_style) {
        m_style = style;
        resetPaths();
        m_iconCache.clear();
        m_linkHash.clear();
        loadImageLinks();
    }
}

void ImplImageTree::resetPaths() {
    OUString url( "$BRAND_BASE_DIR/" LIBO_SHARE_FOLDER "/config/" );
    rtl::Bootstrap::expandMacros(url);
    if ( m_style != "default" )
    {
        INetURLObject u(url);
        OSL_ASSERT(!u.HasError());
        bool ok = u.Append("images_" + m_style, INetURLObject::ENCODE_ALL);
        OSL_ASSERT(ok); (void) ok;
        url = u.GetMainURL(INetURLObject::NO_DECODE);
    }
    else
        url += "images";
    m_path = std::make_pair(
        url, css::uno::Reference< css::container::XNameAccess >());
}

bool ImplImageTree::checkStyleCacheLookup(
    OUString const & style, bool &exists)
{
    CheckStyleCache::iterator i(m_checkStyleCache.find(style));
    if (i != m_checkStyleCache.end()) {
        exists = i->second;
        return true;
    } else {
        return false;
    }
}

bool ImplImageTree::iconCacheLookup(
    OUString const & name, bool localized, BitmapEx & bitmap)
{
    IconCache::iterator i(m_iconCache.find(getRealImageName(name)));
    if (i != m_iconCache.end() && i->second.first == localized) {
        bitmap = i->second.second;
        return true;
    }
    return false;
}

bool ImplImageTree::find(
    std::vector< OUString > const & paths, BitmapEx & bitmap)
{
    if (!m_cacheIcons) {
        for (std::vector< OUString >::const_reverse_iterator j(
                 paths.rbegin());
             j != paths.rend(); ++j)
        {
            osl::File file(m_path.first + "/" + *j);
            if (file.open(osl_File_OpenFlag_Read) == ::osl::FileBase::E_None) {
                loadImageFromStream( wrapFile(file), *j, bitmap );
                file.close();
                return true;
            }
        }
    }

    if (!m_path.second.is()) {
        try {
            m_path.second = css::packages::zip::ZipFileAccess::createWithURL(comphelper::getProcessComponentContext(), m_path.first + ".zip");
        } catch (const css::uno::RuntimeException &) {
            throw;
        } catch (const css::uno::Exception & e) {
            SAL_INFO("vcl", "ImplImageTree::find exception "
                << e.Message << " for " << m_path.first);
            return false;
        }
    }
    for (std::vector< OUString >::const_reverse_iterator j(paths.rbegin());
         j != paths.rend(); ++j)
    {
        if (m_path.second->hasByName(*j)) {
            css::uno::Reference< css::io::XInputStream > s;
            bool ok = m_path.second->getByName(*j) >>= s;
            OSL_ASSERT(ok); (void) ok;
            loadImageFromStream( wrapStream(s), *j, bitmap );
            return true;
        }
    }
    return false;
}

void ImplImageTree::loadImageLinks()
{
    const OUString aLinkFilename("links.txt");

    if (!m_cacheIcons)
    {
        osl::File file(m_path.first + "/" + aLinkFilename);
        if (file.open(osl_File_OpenFlag_Read) == ::osl::FileBase::E_None)
        {
            parseLinkFile( wrapFile(file) );
            file.close();
            return;
        }
    }

    if ( !m_path.second.is() )
    {
        try
        {
            m_path.second = css::packages::zip::ZipFileAccess::createWithURL(comphelper::getProcessComponentContext(), m_path.first + ".zip");
        } catch (const css::uno::RuntimeException &) {
            throw;
        }
        catch (const css::uno::Exception & e)
        {
            SAL_INFO("vcl", "ImplImageTree::find exception "
                << e.Message << " for " << m_path.first);
            return;
        }
    }
    if ( m_path.second->hasByName(aLinkFilename) )
    {
        css::uno::Reference< css::io::XInputStream > s;
        bool ok = m_path.second->getByName(aLinkFilename) >>= s;
        OSL_ASSERT(ok); (void) ok;

        parseLinkFile( wrapStream(s) );
        return;
    }
}

void ImplImageTree::parseLinkFile(boost::shared_ptr< SvStream > pStream)
{
    OString aLine;
    OUString aLink, aOriginal;
    while ( pStream->ReadLine( aLine ) )
    {
        sal_Int32 nIndex = 0;
        if ( aLine.isEmpty() )
            continue;
        aLink = OStringToOUString( aLine.getToken(0, ' ', nIndex), RTL_TEXTENCODING_UTF8 );
        aOriginal = OStringToOUString( aLine.getToken(0, ' ', nIndex), RTL_TEXTENCODING_UTF8 );
        if ( aLink.isEmpty() || aOriginal.isEmpty() )
        {
            SAL_INFO("vcl", "ImplImageTree::parseLinkFile: icon links.txt parse error. "
                "Link is incomplete." );
            continue;
        }
        m_linkHash[aLink] = aOriginal;
    }
}

OUString const & ImplImageTree::getRealImageName(OUString const & name)
{
    IconLinkHash::iterator it(m_linkHash.find(name));
    if (it == m_linkHash.end())
        return name;
    return it->second;
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>Can't use const_reverse_iterator here.<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 .
 */

#include <config_folders.h>

#include "sal/config.h"

#include <boost/shared_ptr.hpp>

#include "com/sun/star/container/XNameAccess.hpp"
#include "com/sun/star/io/XInputStream.hpp"
#include "com/sun/star/lang/Locale.hpp"
#include "com/sun/star/lang/XMultiServiceFactory.hpp"
#include "com/sun/star/packages/zip/ZipFileAccess.hpp"
#include "com/sun/star/uno/Any.hxx"
#include "com/sun/star/uno/Exception.hpp"
#include "com/sun/star/uno/RuntimeException.hpp"
#include "com/sun/star/uno/Sequence.hxx"
#include "comphelper/processfactory.hxx"
#include "osl/file.hxx"
#include "osl/diagnose.h"
#include "rtl/bootstrap.hxx"

#include "tools/stream.hxx"
#include "tools/urlobj.hxx"
#include "vcl/bitmapex.hxx"
#include <vcl/dibtools.hxx>
#include "vcl/pngread.hxx"
#include "vcl/settings.hxx"
#include "vcl/svapp.hxx"
#include "impimagetree.hxx"

namespace {

static OUString createPath(
    OUString const & name, sal_Int32 pos, OUString const & locale)
{
    return name.copy(0, pos + 1) + locale + name.copy(pos);
}

static boost::shared_ptr< SvStream > wrapFile(osl::File & file)
{
    // This could use SvInputStream instead if that did not have a broken
    // SeekPos implementation for an XInputStream that is not also XSeekable
    // (cf. "@@@" at tags/DEV300_m37/svtools/source/misc1/strmadpt.cxx@264807
    // l. 593):
    boost::shared_ptr< SvStream > s(new SvMemoryStream);
    for (;;) {
        void *data[2048];
        sal_uInt64 n;
        file.read(data, 2048, n);
        s->Write(data, n);
        if (n < 2048) {
            break;
        }
    }
    s->Seek(0);
    return s;
}

static boost::shared_ptr< SvStream > wrapStream(
    css::uno::Reference< css::io::XInputStream > const & stream)
{
    // This could use SvInputStream instead if that did not have a broken
    // SeekPos implementation for an XInputStream that is not also XSeekable
    // (cf. "@@@" at tags/DEV300_m37/svtools/source/misc1/strmadpt.cxx@264807
    // l. 593):
    OSL_ASSERT(stream.is());
    boost::shared_ptr< SvStream > s(new SvMemoryStream);
    for (;;) {
        sal_Int32 const size = 2048;
        css::uno::Sequence< sal_Int8 > data(size);
        sal_Int32 n = stream->readBytes(data, size);
        s->Write(data.getConstArray(), n);
        if (n < size) {
            break;
        }
    }
    s->Seek(0);
    return s;
}

static void loadImageFromStream(
    boost::shared_ptr< SvStream > pStream,
    OUString const & rPath, BitmapEx & rBitmap)
{
    if (rPath.endsWith(".png"))
    {
        vcl::PNGReader aPNGReader( *pStream );
        aPNGReader.SetIgnoreGammaChunk( true );
        rBitmap = aPNGReader.Read();
    } else {
        ReadDIBBitmapEx(rBitmap, *pStream);
    }
}

}

ImplImageTree::ImplImageTree() { m_cacheIcons = true; }

ImplImageTree::~ImplImageTree() {}

bool ImplImageTree::checkStyle(OUString const & style)
{
    bool exists;

    // using cache because setStyle is an expensive operation
    // setStyle calls resetPaths => closes any opened zip files with icons, cleans the icon cache, ...
    if (checkStyleCacheLookup(style, exists)) {
        return exists;
    }

    setStyle(style);

    exists = false;
    OUString aURL = m_path.first;

    osl::File aZip(aURL + ".zip");
    if (aZip.open(osl_File_OpenFlag_Read) == ::osl::FileBase::E_None) {
        aZip.close();
        exists = true;
    }

    osl::Directory aLookaside(aURL);
    if (aLookaside.open() == ::osl::FileBase::E_None) {
        aLookaside.close();
        exists = true;
        m_cacheIcons = false;
    } else {
        m_cacheIcons = true;
    }
    m_checkStyleCache[style] = exists;
    return exists;
}

bool ImplImageTree::loadImage(
    OUString const & name, OUString const & style, BitmapEx & bitmap,
    bool localized, bool loadMissing )
{
    bool found = false;
    try {
        found = doLoadImage(name, style, bitmap, localized);
    } catch (css::uno::RuntimeException &) {
        if (!loadMissing)
            throw;
    }
    if (found || !loadMissing)
        return found;

    SAL_INFO("vcl", "ImplImageTree::loadImage exception couldn't load \""
        << name << "\", fetching default image");

    return loadDefaultImage(style, bitmap);
}

bool ImplImageTree::loadDefaultImage(
    OUString const & style,
    BitmapEx& bitmap)
{
    return doLoadImage(
        OUString("res/grafikde.png"),
        style, bitmap, false);
}

bool ImplImageTree::doLoadImage(
    OUString const & name, OUString const & style, BitmapEx & bitmap,
    bool localized)
{
    setStyle(style);
    if (m_cacheIcons && iconCacheLookup(name, localized, bitmap)) {
        return true;
    }
    if (!bitmap.IsEmpty()) {
        bitmap.SetEmpty();
    }
    std::vector< OUString > paths;
    paths.push_back(getRealImageName(name));
    if (localized) {
        sal_Int32 pos = name.lastIndexOf('/');
        if (pos != -1) {
            // find() uses a reverse iterator, so push in reverse order.
            std::vector< OUString > aFallbacks( Application::GetSettings().GetUILanguageTag().getFallbackStrings( true));
            for (std::vector< OUString >::reverse_iterator it( aFallbacks.rbegin());
                    it != aFallbacks.rend(); ++it)
            {
                paths.push_back( getRealImageName( createPath(name, pos, *it) ) );
            }
        }
    }
    bool found = false;
    try {
        found = find(paths, bitmap);
    } catch (css::uno::RuntimeException &) {
        throw;
    } catch (const css::uno::Exception & e) {
        SAL_INFO("vcl", "ImplImageTree::doLoadImage exception " << e.Message);
    }
    if (m_cacheIcons && found) {
        m_iconCache[name.intern()] = std::make_pair(localized, bitmap);
    }
    return found;
}

void ImplImageTree::shutDown() {
    m_style = OUString();
        // for safety; empty m_style means "not initialized"
    m_iconCache.clear();
    m_checkStyleCache.clear();
    m_linkHash.clear();
}

void ImplImageTree::setStyle(OUString const & style) {
    OSL_ASSERT(!style.isEmpty()); // empty m_style means "not initialized"
    if (style != m_style) {
        m_style = style;
        resetPaths();
        m_iconCache.clear();
        m_linkHash.clear();
        loadImageLinks();
    }
}

void ImplImageTree::resetPaths() {
    OUString url( "$BRAND_BASE_DIR/" LIBO_SHARE_FOLDER "/config/" );
    rtl::Bootstrap::expandMacros(url);
    if ( m_style != "default" )
    {
        INetURLObject u(url);
        OSL_ASSERT(!u.HasError());
        bool ok = u.Append("images_" + m_style, INetURLObject::ENCODE_ALL);
        OSL_ASSERT(ok); (void) ok;
        url = u.GetMainURL(INetURLObject::NO_DECODE);
    }
    else
        url += "images";
    m_path = std::make_pair(
        url, css::uno::Reference< css::container::XNameAccess >());
}

bool ImplImageTree::checkStyleCacheLookup(
    OUString const & style, bool &exists)
{
    CheckStyleCache::iterator i(m_checkStyleCache.find(style));
    if (i != m_checkStyleCache.end()) {
        exists = i->second;
        return true;
    } else {
        return false;
    }
}

bool ImplImageTree::iconCacheLookup(
    OUString const & name, bool localized, BitmapEx & bitmap)
{
    IconCache::iterator i(m_iconCache.find(getRealImageName(name)));
    if (i != m_iconCache.end() && i->second.first == localized) {
        bitmap = i->second.second;
        return true;
    }
    return false;
}

bool ImplImageTree::find(
    std::vector< OUString > const & paths, BitmapEx & bitmap)
{
    if (!m_cacheIcons) {
        for (std::vector< OUString >::const_reverse_iterator j(
                 paths.rbegin());
             j != paths.rend(); ++j)
        {
            osl::File file(m_path.first + "/" + *j);
            if (file.open(osl_File_OpenFlag_Read) == ::osl::FileBase::E_None) {
                loadImageFromStream( wrapFile(file), *j, bitmap );
                file.close();
                return true;
            }
        }
    }

    if (!m_path.second.is()) {
        try {
            m_path.second = css::packages::zip::ZipFileAccess::createWithURL(comphelper::getProcessComponentContext(), m_path.first + ".zip");
        } catch (const css::uno::RuntimeException &) {
            throw;
        } catch (const css::uno::Exception & e) {
            SAL_INFO("vcl", "ImplImageTree::find exception "
                << e.Message << " for " << m_path.first);
            return false;
        }
    }
    for (std::vector< OUString >::const_reverse_iterator j(paths.rbegin());
         j != paths.rend(); ++j)
    {
        if (m_path.second->hasByName(*j)) {
            css::uno::Reference< css::io::XInputStream > s;
            bool ok = m_path.second->getByName(*j) >>= s;
            OSL_ASSERT(ok); (void) ok;
            loadImageFromStream( wrapStream(s), *j, bitmap );
            return true;
        }
    }
    return false;
}

void ImplImageTree::loadImageLinks()
{
    const OUString aLinkFilename("links.txt");

    if (!m_cacheIcons)
    {
        osl::File file(m_path.first + "/" + aLinkFilename);
        if (file.open(osl_File_OpenFlag_Read) == ::osl::FileBase::E_None)
        {
            parseLinkFile( wrapFile(file) );
            file.close();
            return;
        }
    }

    if ( !m_path.second.is() )
    {
        try
        {
            m_path.second = css::packages::zip::ZipFileAccess::createWithURL(comphelper::getProcessComponentContext(), m_path.first + ".zip");
        } catch (const css::uno::RuntimeException &) {
            throw;
        }
        catch (const css::uno::Exception & e)
        {
            SAL_INFO("vcl", "ImplImageTree::find exception "
                << e.Message << " for " << m_path.first);
            return;
        }
    }
    if ( m_path.second->hasByName(aLinkFilename) )
    {
        css::uno::Reference< css::io::XInputStream > s;
        bool ok = m_path.second->getByName(aLinkFilename) >>= s;
        OSL_ASSERT(ok); (void) ok;

        parseLinkFile( wrapStream(s) );
        return;
    }
}

void ImplImageTree::parseLinkFile(boost::shared_ptr< SvStream > pStream)
{
    OString aLine;
    OUString aLink, aOriginal;
    while ( pStream->ReadLine( aLine ) )
    {
        sal_Int32 nIndex = 0;
        if ( aLine.isEmpty() )
            continue;
        aLink = OStringToOUString( aLine.getToken(0, ' ', nIndex), RTL_TEXTENCODING_UTF8 );
        aOriginal = OStringToOUString( aLine.getToken(0, ' ', nIndex), RTL_TEXTENCODING_UTF8 );
        if ( aLink.isEmpty() || aOriginal.isEmpty() )
        {
            SAL_INFO("vcl", "ImplImageTree::parseLinkFile: icon links.txt parse error. "
                "Link is incomplete." );
            continue;
        }
        m_linkHash[aLink] = aOriginal;
    }
}

OUString const & ImplImageTree::getRealImageName(OUString const & name)
{
    IconLinkHash::iterator it(m_linkHash.find(name));
    if (it == m_linkHash.end())
        return name;
    return it->second;
}

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


<commit_before>/*
 * W.J. van der Laan 2011
 */
#include "bitcoingui.h"

#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    BitcoinGUI window;
    window.setBalance(1234.567890);
    window.setNumConnections(4);
    window.setNumTransactions(4);
    window.setNumBlocks(33);
    window.setAddress("123456789");

    window.show();

    /* Depending on settings: QApplication::setQuitOnLastWindowClosed(false); */

    return app.exec();
}
<commit_msg>go on testnet for now<commit_after>/*
 * W.J. van der Laan 2011
 */
#include "bitcoingui.h"
#include "util.h"

#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    /* Testing on testnet */
    fTestNet = true;

    BitcoinGUI window;
    window.setBalance(1234.567890);
    window.setNumConnections(4);
    window.setNumTransactions(4);
    window.setNumBlocks(33);
    window.setAddress("123456789");

    window.show();

    /* Depending on settings: QApplication::setQuitOnLastWindowClosed(false); */

    return app.exec();
}
<|endoftext|>


<commit_before>/****************************************************************************

 This file is part of the GLC-lib library.
 Copyright (C) 2005-2008 Laurent Ribon (laumaya@users.sourceforge.net)
 Version 1.1.0, packaged on March, 2009.

 http://glc-lib.sourceforge.net

 GLC-lib is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation; either version 2 of the License, or
 (at your option) any later version.

 GLC-lib 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 General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with GLC-lib; if not, write to the Free Software
 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

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

//! \file glc_boundingbox.cpp implementation of the GLC_BoundingBox class.

#include "glc_boundingbox.h"
#include "maths/glc_matrix4x4.h"
//////////////////////////////////////////////////////////////////////
// Constructor Destructor
//////////////////////////////////////////////////////////////////////

// Default constructor
GLC_BoundingBox::GLC_BoundingBox()
: m_Lower(0, 0, 0)
, m_Upper(0, 0, 0)
, m_IsEmpty(true)
{

}

// Copy constructor
GLC_BoundingBox::GLC_BoundingBox(const GLC_BoundingBox& boundingBox)
: m_Lower(boundingBox.m_Lower)
, m_Upper(boundingBox.m_Upper)
, m_IsEmpty(boundingBox.m_IsEmpty)
{
}

// Constructor with 2 points.
GLC_BoundingBox::GLC_BoundingBox(const GLC_Point4d& lower, const GLC_Point4d& upper)
: m_Lower(lower)
, m_Upper(upper)
, m_IsEmpty(false)
{

}

//////////////////////////////////////////////////////////////////////
// Get Functions
//////////////////////////////////////////////////////////////////////

// Test if a point is in the bounding Box
bool GLC_BoundingBox::intersect(const GLC_Point4d& point) const
{
	if (!m_IsEmpty)
	{
		bool result= (point.X() < m_Upper.X()) && (point.Y() < m_Upper.Y())
		&& (point.Z() < m_Upper.Z()) && (point.X() > m_Lower.X())
		&& (point.Y() > m_Lower.Y()) && (point.Z() > m_Lower.Z());

		return result;
	}
	else
	{
		return false;
	}
}

// Test if a point is in the bounding Sphere
bool GLC_BoundingBox::intersectBoundingSphere(const GLC_Point4d& point) const
{
	const double distance= (getCenter() - point).norm();
	return distance < boundingSphereRadius();
}

// Get the lower corner of the bounding box
GLC_Point4d GLC_BoundingBox::getLower(void) const
{
	return m_Lower;
}

// Get the upper corner of the bounding box
GLC_Point4d GLC_BoundingBox::getUpper(void) const
{
	return m_Upper;
}

// Get the center of the bounding box
GLC_Point4d GLC_BoundingBox::getCenter(void) const
{
	GLC_Vector4d vectResult = (m_Lower + m_Upper) * (1.0 / 2.0);
	return vectResult;

}

//////////////////////////////////////////////////////////////////////
// Set Functions
//////////////////////////////////////////////////////////////////////

// Combine the bounding Box with new geometry point
GLC_BoundingBox& GLC_BoundingBox::combine(const GLC_Point4d& point)
{
	if (m_IsEmpty)
	{
		m_Lower= point;
		m_Upper= point;
		m_IsEmpty= false;
	}
	else
	{
		double lowerX= fmin(point.X(), m_Lower.X());
		double lowerY= fmin(point.Y(), m_Lower.Y());
		double lowerZ= fmin(point.Z(), m_Lower.Z());
		m_Lower.setVect(lowerX, lowerY, lowerZ);

		double upperX= fmax(point.X(), m_Upper.X());
		double upperY= fmax(point.Y(), m_Upper.Y());
		double upperZ= fmax(point.Z(), m_Upper.Z());
		m_Upper.setVect(upperX, upperY, upperZ);
	}
	return *this;
}

// Combine the bounding Box with new geometry point
GLC_BoundingBox& GLC_BoundingBox::combine(const GLC_Point3d& point)
{
	if (m_IsEmpty)
	{
		m_Lower= point;
		m_Upper= point;
		m_IsEmpty= false;
	}
	else
	{
		double lowerX= fmin(point.X(), m_Lower.X());
		double lowerY= fmin(point.Y(), m_Lower.Y());
		double lowerZ= fmin(point.Z(), m_Lower.Z());
		m_Lower.setVect(lowerX, lowerY, lowerZ);

		double upperX= fmax(point.X(), m_Upper.X());
		double upperY= fmax(point.Y(), m_Upper.Y());
		double upperZ= fmax(point.Z(), m_Upper.Z());
		m_Upper.setVect(upperX, upperY, upperZ);
	}
	return *this;
}

// Combine the bounding Box with new geometry point
GLC_BoundingBox& GLC_BoundingBox::combine(const GLC_Point3df& pointf)
{
	GLC_Point3d point(pointf);
	if (m_IsEmpty)
	{
		m_Lower= point;
		m_Upper= point;
		m_IsEmpty= false;
	}
	else
	{
		double lowerX= fmin(point.X(), m_Lower.X());
		double lowerY= fmin(point.Y(), m_Lower.Y());
		double lowerZ= fmin(point.Z(), m_Lower.Z());
		m_Lower.setVect(lowerX, lowerY, lowerZ);

		double upperX= fmax(point.X(), m_Upper.X());
		double upperY= fmax(point.Y(), m_Upper.Y());
		double upperZ= fmax(point.Z(), m_Upper.Z());
		m_Upper.setVect(upperX, upperY, upperZ);
	}
	return *this;
}

// Combine the bounding Box with another bounding box
GLC_BoundingBox& GLC_BoundingBox::combine(const GLC_BoundingBox& box)
{
	if (m_IsEmpty)
	{
		m_Lower= box.m_Lower;
		m_Upper= box.m_Upper;
		m_IsEmpty= box.m_IsEmpty;
	}
	else
	{
		double lowerX= fmin(box.m_Lower.X(), m_Lower.X());
		double lowerY= fmin(box.m_Lower.Y(), m_Lower.Y());
		double lowerZ= fmin(box.m_Lower.Z(), m_Lower.Z());
		m_Lower.setVect(lowerX, lowerY, lowerZ);

		double upperX= fmax(box.m_Upper.X(), m_Upper.X());
		double upperY= fmax(box.m_Upper.Y(), m_Upper.Y());
		double upperZ= fmax(box.m_Upper.Z(), m_Upper.Z());
		m_Upper.setVect(upperX, upperY, upperZ);
	}

	return *this;
}

// Transform the bounding Box
GLC_BoundingBox& GLC_BoundingBox::transform(const GLC_Matrix4x4& matrix)
{
	// Compute Transformed BoundingBox Corner
	GLC_Point4d corner1(m_Lower);
	GLC_Point4d corner7(m_Upper);
	GLC_Point4d corner2(corner7.X(), corner1.Y(), corner1.Z());
	GLC_Point4d corner3(corner7.X(), corner7.Y(), corner1.Z());
	GLC_Point4d corner4(corner1.X(), corner7.Y(), corner1.Z());
	GLC_Point4d corner5(corner1.X(), corner1.Y(), corner7.Z());
	GLC_Point4d corner6(corner7.X(), corner1.Y(), corner7.Z());
	GLC_Point4d corner8(corner1.X(), corner7.Y(), corner7.Z());

	corner1 = (matrix * corner1);
	corner2 = (matrix * corner2);
	corner3 = (matrix * corner3);
	corner4 = (matrix * corner4);
	corner5 = (matrix * corner5);
	corner6 = (matrix * corner6);
	corner7 = (matrix * corner7);
	corner8 = (matrix * corner8);

	// Compute the new BoundingBox
	GLC_BoundingBox boundingBox;
	boundingBox.combine(corner1);
	boundingBox.combine(corner2);
	boundingBox.combine(corner3);
	boundingBox.combine(corner4);
	boundingBox.combine(corner5);
	boundingBox.combine(corner6);
	boundingBox.combine(corner7);
	boundingBox.combine(corner8);

	m_Lower= boundingBox.m_Lower;
	m_Upper= boundingBox.m_Upper;
	return *this;
}

<commit_msg>Use qMin and Qmax function instead of fmin and fmax.<commit_after>/****************************************************************************

 This file is part of the GLC-lib library.
 Copyright (C) 2005-2008 Laurent Ribon (laumaya@users.sourceforge.net)
 Version 1.1.0, packaged on March, 2009.

 http://glc-lib.sourceforge.net

 GLC-lib is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation; either version 2 of the License, or
 (at your option) any later version.

 GLC-lib 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 General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with GLC-lib; if not, write to the Free Software
 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

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

//! \file glc_boundingbox.cpp implementation of the GLC_BoundingBox class.

#include "glc_boundingbox.h"
#include "maths/glc_matrix4x4.h"
//////////////////////////////////////////////////////////////////////
// Constructor Destructor
//////////////////////////////////////////////////////////////////////

// Default constructor
GLC_BoundingBox::GLC_BoundingBox()
: m_Lower(0, 0, 0)
, m_Upper(0, 0, 0)
, m_IsEmpty(true)
{

}

// Copy constructor
GLC_BoundingBox::GLC_BoundingBox(const GLC_BoundingBox& boundingBox)
: m_Lower(boundingBox.m_Lower)
, m_Upper(boundingBox.m_Upper)
, m_IsEmpty(boundingBox.m_IsEmpty)
{
}

// Constructor with 2 points.
GLC_BoundingBox::GLC_BoundingBox(const GLC_Point4d& lower, const GLC_Point4d& upper)
: m_Lower(lower)
, m_Upper(upper)
, m_IsEmpty(false)
{

}

//////////////////////////////////////////////////////////////////////
// Get Functions
//////////////////////////////////////////////////////////////////////

// Test if a point is in the bounding Box
bool GLC_BoundingBox::intersect(const GLC_Point4d& point) const
{
	if (!m_IsEmpty)
	{
		bool result= (point.X() < m_Upper.X()) && (point.Y() < m_Upper.Y())
		&& (point.Z() < m_Upper.Z()) && (point.X() > m_Lower.X())
		&& (point.Y() > m_Lower.Y()) && (point.Z() > m_Lower.Z());

		return result;
	}
	else
	{
		return false;
	}
}

// Test if a point is in the bounding Sphere
bool GLC_BoundingBox::intersectBoundingSphere(const GLC_Point4d& point) const
{
	const double distance= (getCenter() - point).norm();
	return distance < boundingSphereRadius();
}

// Get the lower corner of the bounding box
GLC_Point4d GLC_BoundingBox::getLower(void) const
{
	return m_Lower;
}

// Get the upper corner of the bounding box
GLC_Point4d GLC_BoundingBox::getUpper(void) const
{
	return m_Upper;
}

// Get the center of the bounding box
GLC_Point4d GLC_BoundingBox::getCenter(void) const
{
	GLC_Vector4d vectResult = (m_Lower + m_Upper) * (1.0 / 2.0);
	return vectResult;

}

//////////////////////////////////////////////////////////////////////
// Set Functions
//////////////////////////////////////////////////////////////////////

// Combine the bounding Box with new geometry point
GLC_BoundingBox& GLC_BoundingBox::combine(const GLC_Point4d& point)
{
	if (m_IsEmpty)
	{
		m_Lower= point;
		m_Upper= point;
		m_IsEmpty= false;
	}
	else
	{
		double lowerX= qMin(point.X(), m_Lower.X());
		double lowerY= qMin(point.Y(), m_Lower.Y());
		double lowerZ= qMin(point.Z(), m_Lower.Z());
		m_Lower.setVect(lowerX, lowerY, lowerZ);

		double upperX= qMax(point.X(), m_Upper.X());
		double upperY= qMax(point.Y(), m_Upper.Y());
		double upperZ= qMax(point.Z(), m_Upper.Z());
		m_Upper.setVect(upperX, upperY, upperZ);
	}
	return *this;
}

// Combine the bounding Box with new geometry point
GLC_BoundingBox& GLC_BoundingBox::combine(const GLC_Point3d& point)
{
	if (m_IsEmpty)
	{
		m_Lower= point;
		m_Upper= point;
		m_IsEmpty= false;
	}
	else
	{
		double lowerX= qMin(point.X(), m_Lower.X());
		double lowerY= qMin(point.Y(), m_Lower.Y());
		double lowerZ= qMin(point.Z(), m_Lower.Z());
		m_Lower.setVect(lowerX, lowerY, lowerZ);

		double upperX= qMax(point.X(), m_Upper.X());
		double upperY= qMax(point.Y(), m_Upper.Y());
		double upperZ= qMax(point.Z(), m_Upper.Z());
		m_Upper.setVect(upperX, upperY, upperZ);
	}
	return *this;
}

// Combine the bounding Box with new geometry point
GLC_BoundingBox& GLC_BoundingBox::combine(const GLC_Point3df& pointf)
{
	GLC_Point3d point(pointf);
	if (m_IsEmpty)
	{
		m_Lower= point;
		m_Upper= point;
		m_IsEmpty= false;
	}
	else
	{
		double lowerX= qMin(point.X(), m_Lower.X());
		double lowerY= qMin(point.Y(), m_Lower.Y());
		double lowerZ= qMin(point.Z(), m_Lower.Z());
		m_Lower.setVect(lowerX, lowerY, lowerZ);

		double upperX= qMax(point.X(), m_Upper.X());
		double upperY= qMax(point.Y(), m_Upper.Y());
		double upperZ= qMax(point.Z(), m_Upper.Z());
		m_Upper.setVect(upperX, upperY, upperZ);
	}
	return *this;
}

// Combine the bounding Box with another bounding box
GLC_BoundingBox& GLC_BoundingBox::combine(const GLC_BoundingBox& box)
{
	if (m_IsEmpty)
	{
		m_Lower= box.m_Lower;
		m_Upper= box.m_Upper;
		m_IsEmpty= box.m_IsEmpty;
	}
	else
	{
		double lowerX= qMin(box.m_Lower.X(), m_Lower.X());
		double lowerY= qMin(box.m_Lower.Y(), m_Lower.Y());
		double lowerZ= qMin(box.m_Lower.Z(), m_Lower.Z());
		m_Lower.setVect(lowerX, lowerY, lowerZ);

		double upperX= qMax(box.m_Upper.X(), m_Upper.X());
		double upperY= qMax(box.m_Upper.Y(), m_Upper.Y());
		double upperZ= qMax(box.m_Upper.Z(), m_Upper.Z());
		m_Upper.setVect(upperX, upperY, upperZ);
	}

	return *this;
}

// Transform the bounding Box
GLC_BoundingBox& GLC_BoundingBox::transform(const GLC_Matrix4x4& matrix)
{
	// Compute Transformed BoundingBox Corner
	GLC_Point4d corner1(m_Lower);
	GLC_Point4d corner7(m_Upper);
	GLC_Point4d corner2(corner7.X(), corner1.Y(), corner1.Z());
	GLC_Point4d corner3(corner7.X(), corner7.Y(), corner1.Z());
	GLC_Point4d corner4(corner1.X(), corner7.Y(), corner1.Z());
	GLC_Point4d corner5(corner1.X(), corner1.Y(), corner7.Z());
	GLC_Point4d corner6(corner7.X(), corner1.Y(), corner7.Z());
	GLC_Point4d corner8(corner1.X(), corner7.Y(), corner7.Z());

	corner1 = (matrix * corner1);
	corner2 = (matrix * corner2);
	corner3 = (matrix * corner3);
	corner4 = (matrix * corner4);
	corner5 = (matrix * corner5);
	corner6 = (matrix * corner6);
	corner7 = (matrix * corner7);
	corner8 = (matrix * corner8);

	// Compute the new BoundingBox
	GLC_BoundingBox boundingBox;
	boundingBox.combine(corner1);
	boundingBox.combine(corner2);
	boundingBox.combine(corner3);
	boundingBox.combine(corner4);
	boundingBox.combine(corner5);
	boundingBox.combine(corner6);
	boundingBox.combine(corner7);
	boundingBox.combine(corner8);

	m_Lower= boundingBox.m_Lower;
	m_Upper= boundingBox.m_Upper;
	return *this;
}

<|endoftext|>


<commit_before>#include "test.hh"

#include <coincident/thread.hh>

using namespace coincident;

class FakeThread
{
public:
	FakeThread() : m_blocked(false)
	{
	}

	void myBlock()
	{
		m_blocked = true;
	}

	void myUnBlock()
	{
		m_blocked = false;
	}

	bool isBlocked()
	{
		return m_blocked;
	}

	bool m_blocked;
};

class Thread : public IThread {
public:
	Thread(void (*exitHook)(),
			int (*fn)(void *), void *arg)
	{
		ON_CALL(*this, isBlocked())
			.WillByDefault(Invoke(&m_fake, &FakeThread::isBlocked));
		ON_CALL(*this, block())
			.WillByDefault(Invoke(&m_fake, &FakeThread::myBlock));
		ON_CALL(*this, unBlock())
			.WillByDefault(Invoke(&m_fake, &FakeThread::myUnBlock));

		EXPECT_CALL(*this, getRegs())
				.Times(AtLeast(1))
				.WillRepeatedly(Return((void *)m_regs))
				;

		EXPECT_CALL(*this, stepOverBreakpoint())
				.Times(AtLeast(1));
		EXPECT_CALL(*this, isBlocked())
			.Times(AnyNumber());
		EXPECT_CALL(*this, block())
			.Times(AnyNumber());
		EXPECT_CALL(*this, unBlock())
			.Times(AnyNumber());
	}

	MOCK_METHOD0(getRegs, void *());
	MOCK_METHOD0(stepOverBreakpoint, void());
	MOCK_METHOD0(saveRegisters, void());
	MOCK_METHOD1(setPc, void(void *));
	MOCK_METHOD1(getArgument,unsigned long(int n));
	MOCK_METHOD0(getReturnValue, unsigned long());

	MOCK_METHOD0(block, void());
	MOCK_METHOD0(unBlock, void());
	MOCK_METHOD0(isBlocked, bool());

	uint8_t m_regs[8];
	FakeThread m_fake;
};

IThread *IThread::createThread(void (*exitHook)(),
				int (*fn)(void *), void *arg)
{
	return new Thread(exitHook, fn, arg);
}

void IThread::releaseThread(IThread *thread)
{
	delete (Thread *)thread;
}
<commit_msg>unit test: Don't set unrealistic expectations on the threads<commit_after>#include "test.hh"

#include <coincident/thread.hh>

using namespace coincident;

class FakeThread
{
public:
	FakeThread() : m_blocked(false)
	{
	}

	void myBlock()
	{
		m_blocked = true;
	}

	void myUnBlock()
	{
		m_blocked = false;
	}

	bool isBlocked()
	{
		return m_blocked;
	}

	bool m_blocked;
};

class Thread : public IThread {
public:
	Thread(void (*exitHook)(),
			int (*fn)(void *), void *arg)
	{
		ON_CALL(*this, isBlocked())
			.WillByDefault(Invoke(&m_fake, &FakeThread::isBlocked));
		ON_CALL(*this, block())
			.WillByDefault(Invoke(&m_fake, &FakeThread::myBlock));
		ON_CALL(*this, unBlock())
			.WillByDefault(Invoke(&m_fake, &FakeThread::myUnBlock));

		EXPECT_CALL(*this, getRegs())
				.Times(AnyNumber())
				.WillRepeatedly(Return((void *)m_regs))
				;

		EXPECT_CALL(*this, stepOverBreakpoint())
				.Times(AnyNumber());
		EXPECT_CALL(*this, isBlocked())
			.Times(AnyNumber());
		EXPECT_CALL(*this, block())
			.Times(AnyNumber());
		EXPECT_CALL(*this, unBlock())
			.Times(AnyNumber());
	}

	MOCK_METHOD0(getRegs, void *());
	MOCK_METHOD0(stepOverBreakpoint, void());
	MOCK_METHOD0(saveRegisters, void());
	MOCK_METHOD1(setPc, void(void *));
	MOCK_METHOD1(getArgument,unsigned long(int n));
	MOCK_METHOD0(getReturnValue, unsigned long());

	MOCK_METHOD0(block, void());
	MOCK_METHOD0(unBlock, void());
	MOCK_METHOD0(isBlocked, bool());

	uint8_t m_regs[8];
	FakeThread m_fake;
};

IThread *IThread::createThread(void (*exitHook)(),
				int (*fn)(void *), void *arg)
{
	return new Thread(exitHook, fn, arg);
}

void IThread::releaseThread(IThread *thread)
{
	delete (Thread *)thread;
}
<|endoftext|>


<commit_before>// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Engine - Network module"
// For conditions of distribution and use, see copyright notice in Config.hpp

#include <Nazara/Network/Win32/IpAddressImpl.hpp>
#include <Nazara/Core/CallOnExit.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Network/Win32/SocketImpl.hpp>
#include <cstring>
#include <Nazara/Network/Debug.hpp>

// some MinGW distributions seem to lack some defines
#ifndef ERROR_NOT_ENOUGH_MEMORY
#define ERROR_NOT_ENOUGH_MEMORY 8L
#endif

#ifndef WSA_NOT_ENOUGH_MEMORY
#define WSA_NOT_ENOUGH_MEMORY (ERROR_NOT_ENOUGH_MEMORY)
#endif

namespace Nz
{
	namespace Detail
	{
		#if NAZARA_CORE_WINDOWS_NT6
		using addrinfoImpl = addrinfoW;

		int GetAddressInfo(const String& hostname, const String& service, const addrinfoImpl* hints, addrinfoImpl** results)
		{
			return GetAddrInfoW(hostname.GetWideString().c_str(), service.GetWideString().c_str(), hints, results);
		}

		int GetHostnameInfo(sockaddr* socketAddress, socklen_t socketLen, String* hostname, String* service, INT flags)
		{
			std::array<wchar_t, NI_MAXHOST> hostnameBuffer;
			std::array<wchar_t, NI_MAXSERV> serviceBuffer;

			int result = GetNameInfoW(socketAddress, socketLen, hostnameBuffer.data(), static_cast<DWORD>(hostnameBuffer.size()), serviceBuffer.data(), static_cast<DWORD>(serviceBuffer.size()), flags);
			if (result == 0)
			{
				if (hostname)
					*hostname = std::move(String::Unicode(hostnameBuffer.data()));

				if (service)
					*service = std::move(String::Unicode(serviceBuffer.data()));
			}

			return result;
		}

		void FreeAddressInfo(addrinfoImpl* results)
		{
			FreeAddrInfoW(results);
		}
		#else
		using addrinfoImpl = addrinfo;

		int GetAddressInfo(const String& hostname, const String& service, const addrinfoImpl* hints, addrinfoImpl** results)
		{
			return getaddrinfo(hostname.GetConstBuffer(), service.GetConstBuffer(), hints, results);
		}

		int GetHostnameInfo(sockaddr* socketAddress, socklen_t socketLen, String* hostname, String* service, INT flags)
		{
			std::array<char, NI_MAXHOST> hostnameBuffer;
			std::array<char, NI_MAXSERV> serviceBuffer;

			int result = getnameinfo(socketAddress, socketLen, hostnameBuffer.data(), static_cast<DWORD>(hostnameBuffer.size()), serviceBuffer.data(), static_cast<DWORD>(serviceBuffer.size()), flags);
			if (result == 0)
			{
				if (hostname)
					hostname->Set(hostnameBuffer.data());

				if (service)
					service->Set(serviceBuffer.data());
			}

			return result;
		}

		void FreeAddressInfo(addrinfoImpl* results)
		{
			freeaddrinfo(results);
		}
		#endif
	}

	IpAddress IpAddressImpl::FromAddrinfo(const addrinfo* info)
	{
		switch (info->ai_family)
		{
			case AF_INET:
			{
				sockaddr_in* ipv4 = reinterpret_cast<sockaddr_in*>(info->ai_addr);

				return FromSockAddr(ipv4);
			}

			case AF_INET6:
			{
				sockaddr_in6* ipv6 = reinterpret_cast<sockaddr_in6*>(info->ai_addr);

				return FromSockAddr(ipv6);
			}
		}

		return IpAddress::Invalid;
	}

	#if NAZARA_CORE_WINDOWS_NT6
	IpAddress IpAddressImpl::FromAddrinfo(const addrinfoW* info)
	{
		switch (info->ai_family)
		{
			case AF_INET:
			{
				sockaddr_in* ipv4 = reinterpret_cast<sockaddr_in*>(info->ai_addr);

				return FromSockAddr(ipv4);
			}

			case AF_INET6:
			{
				sockaddr_in6* ipv6 = reinterpret_cast<sockaddr_in6*>(info->ai_addr);

				return FromSockAddr(ipv6);
			}
		}

		return IpAddress::Invalid;
	}
	#endif

	IpAddress IpAddressImpl::FromSockAddr(const sockaddr* address)
	{
		switch (address->sa_family)
		{
			case AF_INET:
				return FromSockAddr(reinterpret_cast<const sockaddr_in*>(address));

			case AF_INET6:
				return FromSockAddr(reinterpret_cast<const sockaddr_in6*>(address));
		}

		return IpAddress::Invalid;
	}

	IpAddress IpAddressImpl::FromSockAddr(const sockaddr_in* addressv4)
	{
		auto& rawIpV4 = addressv4->sin_addr.S_un.S_un_b;
		return IpAddress(rawIpV4.s_b1, rawIpV4.s_b2, rawIpV4.s_b3, rawIpV4.s_b4, ntohs(addressv4->sin_port));
	}

	IpAddress IpAddressImpl::FromSockAddr(const sockaddr_in6* addressv6)
	{
		auto& rawIpV6 = addressv6->sin6_addr.s6_addr;

		IpAddress::IPv6 ipv6;
		for (unsigned int i = 0; i < 8; ++i)
			ipv6[i] = rawIpV6[i * 2] << 8 | rawIpV6[i * 2 + 1];

		return IpAddress(ipv6, ntohs(addressv6->sin6_port));
	}

	bool IpAddressImpl::ResolveAddress(const IpAddress& ipAddress, String* hostname, String* service, ResolveError* error)
	{
		SockAddrBuffer socketAddress;
		socklen_t socketAddressLen = ToSockAddr(ipAddress, socketAddress.data());

		if (Detail::GetHostnameInfo(reinterpret_cast<sockaddr*>(socketAddress.data()), socketAddressLen, hostname, service, NI_NUMERICSERV) != 0)
		{
			if (error)
				*error = TranslateWSAErrorToResolveError(WSAGetLastError());

			return false;
		}

		if (error)
			*error = ResolveError_NoError;

		return true;
	}

	std::vector<HostnameInfo> IpAddressImpl::ResolveHostname(NetProtocol procol, const String& hostname, const String& service, ResolveError* error)
	{
		std::vector<HostnameInfo> results;

		Detail::addrinfoImpl hints;
		std::memset(&hints, 0, sizeof(Detail::addrinfoImpl));
		hints.ai_family = SocketImpl::TranslateNetProtocolToAF(procol);
		hints.ai_flags = AI_CANONNAME;
		hints.ai_socktype = SOCK_STREAM;

		Detail::addrinfoImpl* servinfo;
		if (Detail::GetAddressInfo(hostname, service, &hints, &servinfo) != 0)
		{
			if (error)
				*error = TranslateWSAErrorToResolveError(WSAGetLastError());

			return results;
		}

		CallOnExit onExit([servinfo]()
		{
			Detail::FreeAddressInfo(servinfo);
		});

		for (Detail::addrinfoImpl* p = servinfo; p != nullptr; p = p->ai_next)
		{
			HostnameInfo result;
			result.address = FromAddrinfo(p);
			result.canonicalName = String::Unicode(p->ai_canonname);
			result.protocol = TranslatePFToNetProtocol(p->ai_family);
			result.socketType = TranslateSockToNetProtocol(p->ai_socktype);

			results.push_back(result);
		}

		if (error)
			*error = ResolveError_NoError;

		return results;
	}

	socklen_t IpAddressImpl::ToSockAddr(const IpAddress& ipAddress, void* buffer)
	{
		if (ipAddress.IsValid())
		{
			switch (ipAddress.GetProtocol())
			{
				case NetProtocol_IPv4:
				{
					sockaddr_in* socketAddress = reinterpret_cast<sockaddr_in*>(buffer);

					std::memset(socketAddress, 0, sizeof(sockaddr_in));
					socketAddress->sin_family = AF_INET;
					socketAddress->sin_port = htons(ipAddress.GetPort());
					socketAddress->sin_addr.s_addr = htonl(ipAddress.ToUInt32());

					return sizeof(sockaddr_in);
				}

				case NetProtocol_IPv6:
				{
					sockaddr_in6* socketAddress = reinterpret_cast<sockaddr_in6*>(buffer);

					std::memset(socketAddress, 0, sizeof(sockaddr_in6));
					socketAddress->sin6_family = AF_INET6;
					socketAddress->sin6_port = htons(ipAddress.GetPort());

					IpAddress::IPv6 address = ipAddress.ToIPv6();
					for (unsigned int i = 0; i < 8; ++i)
					{
						u_short addressPart = htons(address[i]);
						socketAddress->sin6_addr.s6_addr[i * 2 + 0] = addressPart >> 0;
						socketAddress->sin6_addr.s6_addr[i * 2 + 1] = addressPart >> 8;
					}

					return sizeof(sockaddr_in6);
				}

				default:
					NazaraInternalError("Unhandled ip protocol (0x" + String::Number(ipAddress.GetProtocol()) + ')');
					break;
			}
		}

		NazaraError("Invalid ip address");
		return 0;
	}

	NetProtocol IpAddressImpl::TranslatePFToNetProtocol(int family)
	{
		switch (family)
		{
			case PF_INET:
				return NetProtocol_IPv4;

			case PF_INET6:
				return NetProtocol_IPv6;

			default:
				return NetProtocol_Unknown;
		}
	}

	SocketType IpAddressImpl::TranslateSockToNetProtocol(int socketType)
	{
		switch (socketType)
		{
			case SOCK_STREAM:
				return SocketType_TCP;

			case SOCK_DGRAM:
				return SocketType_UDP;

			case SOCK_RAW:
				return SocketType_Raw;

			default:
				return SocketType_Unknown;
		}
	}

	ResolveError IpAddressImpl::TranslateWSAErrorToResolveError(int error)
	{
		switch (error)
		{
			case 0:
				return ResolveError_NoError;

			// Engine error
			case WSAEFAULT:
			case WSAEINVAL:
				return ResolveError_Internal;

			case WSAEAFNOSUPPORT:
			case WSAESOCKTNOSUPPORT:
			case WSASERVICE_NOT_FOUND:
				return ResolveError_ProtocolNotSupported;

			case WSAHOST_NOT_FOUND:
				return ResolveError_NotFound;

			case WSANO_RECOVERY:
				return ResolveError_NonRecoverable;

			case WSANOTINITIALISED:
				return ResolveError_NotInitialized;

			case WSA_NOT_ENOUGH_MEMORY:
				return ResolveError_ResourceError;

			case WSATRY_AGAIN:
				return ResolveError_TemporaryFailure;
		}

		NazaraWarning("Unhandled WinSock error: " + Error::GetLastSystemError(error) + " (" + String::Number(error) + ')');
		return ResolveError_Unknown;
	}
}
<commit_msg>Network/IpAddress: Fix problem with some IPv6<commit_after>// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Engine - Network module"
// For conditions of distribution and use, see copyright notice in Config.hpp

#include <Nazara/Network/Win32/IpAddressImpl.hpp>
#include <Nazara/Core/CallOnExit.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Network/Win32/SocketImpl.hpp>
#include <cstring>
#include <Nazara/Network/Debug.hpp>

// some MinGW distributions seem to lack some defines
#ifndef ERROR_NOT_ENOUGH_MEMORY
#define ERROR_NOT_ENOUGH_MEMORY 8L
#endif

#ifndef WSA_NOT_ENOUGH_MEMORY
#define WSA_NOT_ENOUGH_MEMORY (ERROR_NOT_ENOUGH_MEMORY)
#endif

namespace Nz
{
	namespace Detail
	{
		#if NAZARA_CORE_WINDOWS_NT6
		using addrinfoImpl = addrinfoW;

		int GetAddressInfo(const String& hostname, const String& service, const addrinfoImpl* hints, addrinfoImpl** results)
		{
			return GetAddrInfoW(hostname.GetWideString().c_str(), service.GetWideString().c_str(), hints, results);
		}

		int GetHostnameInfo(sockaddr* socketAddress, socklen_t socketLen, String* hostname, String* service, INT flags)
		{
			std::array<wchar_t, NI_MAXHOST> hostnameBuffer;
			std::array<wchar_t, NI_MAXSERV> serviceBuffer;

			int result = GetNameInfoW(socketAddress, socketLen, hostnameBuffer.data(), static_cast<DWORD>(hostnameBuffer.size()), serviceBuffer.data(), static_cast<DWORD>(serviceBuffer.size()), flags);
			if (result == 0)
			{
				if (hostname)
					*hostname = std::move(String::Unicode(hostnameBuffer.data()));

				if (service)
					*service = std::move(String::Unicode(serviceBuffer.data()));
			}

			return result;
		}

		void FreeAddressInfo(addrinfoImpl* results)
		{
			FreeAddrInfoW(results);
		}
		#else
		using addrinfoImpl = addrinfo;

		int GetAddressInfo(const String& hostname, const String& service, const addrinfoImpl* hints, addrinfoImpl** results)
		{
			return getaddrinfo(hostname.GetConstBuffer(), service.GetConstBuffer(), hints, results);
		}

		int GetHostnameInfo(sockaddr* socketAddress, socklen_t socketLen, String* hostname, String* service, INT flags)
		{
			std::array<char, NI_MAXHOST> hostnameBuffer;
			std::array<char, NI_MAXSERV> serviceBuffer;

			int result = getnameinfo(socketAddress, socketLen, hostnameBuffer.data(), static_cast<DWORD>(hostnameBuffer.size()), serviceBuffer.data(), static_cast<DWORD>(serviceBuffer.size()), flags);
			if (result == 0)
			{
				if (hostname)
					hostname->Set(hostnameBuffer.data());

				if (service)
					service->Set(serviceBuffer.data());
			}

			return result;
		}

		void FreeAddressInfo(addrinfoImpl* results)
		{
			freeaddrinfo(results);
		}
		#endif
	}

	IpAddress IpAddressImpl::FromAddrinfo(const addrinfo* info)
	{
		switch (info->ai_family)
		{
			case AF_INET:
			{
				sockaddr_in* ipv4 = reinterpret_cast<sockaddr_in*>(info->ai_addr);

				return FromSockAddr(ipv4);
			}

			case AF_INET6:
			{
				sockaddr_in6* ipv6 = reinterpret_cast<sockaddr_in6*>(info->ai_addr);

				return FromSockAddr(ipv6);
			}
		}

		return IpAddress::Invalid;
	}

	#if NAZARA_CORE_WINDOWS_NT6
	IpAddress IpAddressImpl::FromAddrinfo(const addrinfoW* info)
	{
		switch (info->ai_family)
		{
			case AF_INET:
			{
				sockaddr_in* ipv4 = reinterpret_cast<sockaddr_in*>(info->ai_addr);

				return FromSockAddr(ipv4);
			}

			case AF_INET6:
			{
				sockaddr_in6* ipv6 = reinterpret_cast<sockaddr_in6*>(info->ai_addr);

				return FromSockAddr(ipv6);
			}
		}

		return IpAddress::Invalid;
	}
	#endif

	IpAddress IpAddressImpl::FromSockAddr(const sockaddr* address)
	{
		switch (address->sa_family)
		{
			case AF_INET:
				return FromSockAddr(reinterpret_cast<const sockaddr_in*>(address));

			case AF_INET6:
				return FromSockAddr(reinterpret_cast<const sockaddr_in6*>(address));
		}

		return IpAddress::Invalid;
	}

	IpAddress IpAddressImpl::FromSockAddr(const sockaddr_in* addressv4)
	{
		auto& rawIpV4 = addressv4->sin_addr.S_un.S_un_b;
		return IpAddress(rawIpV4.s_b1, rawIpV4.s_b2, rawIpV4.s_b3, rawIpV4.s_b4, ntohs(addressv4->sin_port));
	}

	IpAddress IpAddressImpl::FromSockAddr(const sockaddr_in6* addressv6)
	{
		auto& rawIpV6 = addressv6->sin6_addr.s6_addr;

		IpAddress::IPv6 ipv6;
		for (unsigned int i = 0; i < 8; ++i)
			ipv6[i] = Nz::UInt16(rawIpV6[i * 2]) << 8 | rawIpV6[i * 2 + 1];

		return IpAddress(ipv6, ntohs(addressv6->sin6_port));
	}

	bool IpAddressImpl::ResolveAddress(const IpAddress& ipAddress, String* hostname, String* service, ResolveError* error)
	{
		SockAddrBuffer socketAddress;
		socklen_t socketAddressLen = ToSockAddr(ipAddress, socketAddress.data());

		if (Detail::GetHostnameInfo(reinterpret_cast<sockaddr*>(socketAddress.data()), socketAddressLen, hostname, service, NI_NUMERICSERV) != 0)
		{
			if (error)
				*error = TranslateWSAErrorToResolveError(WSAGetLastError());

			return false;
		}

		if (error)
			*error = ResolveError_NoError;

		return true;
	}

	std::vector<HostnameInfo> IpAddressImpl::ResolveHostname(NetProtocol procol, const String& hostname, const String& service, ResolveError* error)
	{
		std::vector<HostnameInfo> results;

		Detail::addrinfoImpl hints;
		std::memset(&hints, 0, sizeof(Detail::addrinfoImpl));
		hints.ai_family = SocketImpl::TranslateNetProtocolToAF(procol);
		hints.ai_flags = AI_CANONNAME;
		hints.ai_socktype = SOCK_STREAM;

		Detail::addrinfoImpl* servinfo;
		if (Detail::GetAddressInfo(hostname, service, &hints, &servinfo) != 0)
		{
			if (error)
				*error = TranslateWSAErrorToResolveError(WSAGetLastError());

			return results;
		}

		CallOnExit onExit([servinfo]()
		{
			Detail::FreeAddressInfo(servinfo);
		});

		for (Detail::addrinfoImpl* p = servinfo; p != nullptr; p = p->ai_next)
		{
			HostnameInfo result;
			result.address = FromAddrinfo(p);
			result.canonicalName = String::Unicode(p->ai_canonname);
			result.protocol = TranslatePFToNetProtocol(p->ai_family);
			result.socketType = TranslateSockToNetProtocol(p->ai_socktype);

			results.push_back(result);
		}

		if (error)
			*error = ResolveError_NoError;

		return results;
	}

	socklen_t IpAddressImpl::ToSockAddr(const IpAddress& ipAddress, void* buffer)
	{
		if (ipAddress.IsValid())
		{
			switch (ipAddress.GetProtocol())
			{
				case NetProtocol_IPv4:
				{
					sockaddr_in* socketAddress = reinterpret_cast<sockaddr_in*>(buffer);

					std::memset(socketAddress, 0, sizeof(sockaddr_in));
					socketAddress->sin_family = AF_INET;
					socketAddress->sin_port = htons(ipAddress.GetPort());
					socketAddress->sin_addr.s_addr = htonl(ipAddress.ToUInt32());

					return sizeof(sockaddr_in);
				}

				case NetProtocol_IPv6:
				{
					sockaddr_in6* socketAddress = reinterpret_cast<sockaddr_in6*>(buffer);

					std::memset(socketAddress, 0, sizeof(sockaddr_in6));
					socketAddress->sin6_family = AF_INET6;
					socketAddress->sin6_port = htons(ipAddress.GetPort());

					IpAddress::IPv6 address = ipAddress.ToIPv6();
					for (unsigned int i = 0; i < 8; ++i)
					{
						u_short addressPart = htons(address[i]);
						socketAddress->sin6_addr.s6_addr[i * 2 + 0] = addressPart >> 0;
						socketAddress->sin6_addr.s6_addr[i * 2 + 1] = addressPart >> 8;
					}

					return sizeof(sockaddr_in6);
				}

				default:
					NazaraInternalError("Unhandled ip protocol (0x" + String::Number(ipAddress.GetProtocol()) + ')');
					break;
			}
		}

		NazaraError("Invalid ip address");
		return 0;
	}

	NetProtocol IpAddressImpl::TranslatePFToNetProtocol(int family)
	{
		switch (family)
		{
			case PF_INET:
				return NetProtocol_IPv4;

			case PF_INET6:
				return NetProtocol_IPv6;

			default:
				return NetProtocol_Unknown;
		}
	}

	SocketType IpAddressImpl::TranslateSockToNetProtocol(int socketType)
	{
		switch (socketType)
		{
			case SOCK_STREAM:
				return SocketType_TCP;

			case SOCK_DGRAM:
				return SocketType_UDP;

			case SOCK_RAW:
				return SocketType_Raw;

			default:
				return SocketType_Unknown;
		}
	}

	ResolveError IpAddressImpl::TranslateWSAErrorToResolveError(int error)
	{
		switch (error)
		{
			case 0:
				return ResolveError_NoError;

			// Engine error
			case WSAEFAULT:
			case WSAEINVAL:
				return ResolveError_Internal;

			case WSAEAFNOSUPPORT:
			case WSAESOCKTNOSUPPORT:
			case WSASERVICE_NOT_FOUND:
				return ResolveError_ProtocolNotSupported;

			case WSAHOST_NOT_FOUND:
				return ResolveError_NotFound;

			case WSANO_RECOVERY:
				return ResolveError_NonRecoverable;

			case WSANOTINITIALISED:
				return ResolveError_NotInitialized;

			case WSA_NOT_ENOUGH_MEMORY:
				return ResolveError_ResourceError;

			case WSATRY_AGAIN:
				return ResolveError_TemporaryFailure;
		}

		NazaraWarning("Unhandled WinSock error: " + Error::GetLastSystemError(error) + " (" + String::Number(error) + ')');
		return ResolveError_Unknown;
	}
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: atkwrapper.hxx,v $
 * $Revision: 1.4 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#ifndef __ATK_WRAPPER_HXX__
#define __ATK_WRAPPER_HXX__

#include <atk/atk.h>
#include <com/sun/star/accessibility/XAccessible.hpp>

extern "C" {

typedef struct _AtkObjectWrapper      AtkObjectWrapper;
typedef struct _AtkObjectWrapperClass AtkObjectWrapperClass;

namespace com { namespace sun { namespace star { namespace accessibility {
    class XAccessibleAction;
    class XAccessibleComponent;
    class XAccessibleEditableText;
    class XAccessibleHypertext;
    class XAccessibleImage;
    class XAccessibleSelection;
    class XAccessibleTable;
    class XAccessibleText;
    class XAccessibleTextAttributes;
    class XAccessibleValue;
} } } }

struct _AtkObjectWrapper
{
    AtkObject aParent;

    ::com::sun::star::accessibility::XAccessible               *mpAccessible;
    ::com::sun::star::accessibility::XAccessibleContext        *mpContext;
    ::com::sun::star::accessibility::XAccessibleAction         *mpAction;
    ::com::sun::star::accessibility::XAccessibleComponent      *mpComponent;
    ::com::sun::star::accessibility::XAccessibleEditableText   *mpEditableText;
    ::com::sun::star::accessibility::XAccessibleHypertext      *mpHypertext;
    ::com::sun::star::accessibility::XAccessibleImage          *mpImage;
    ::com::sun::star::accessibility::XAccessibleSelection      *mpSelection;
    ::com::sun::star::accessibility::XAccessibleTable          *mpTable;
    ::com::sun::star::accessibility::XAccessibleText           *mpText;
    ::com::sun::star::accessibility::XAccessibleTextAttributes *mpTextAttributes;
    ::com::sun::star::accessibility::XAccessibleValue          *mpValue;

//    ::rtl::OString * m_pKeyBindings
};

struct _AtkObjectWrapperClass
{
    AtkObjectClass aParentClass;
};

GType                  atk_object_wrapper_get_type (void) G_GNUC_CONST;
AtkObject *            atk_object_wrapper_ref(
    const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >& rxAccessible,
    bool create = true );

AtkObject *            atk_object_wrapper_new(
    const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >& rxAccessible,
    AtkObject* parent = NULL );

void                   atk_object_wrapper_dispose(AtkObjectWrapper* wrapper);

AtkStateType mapAtkState( sal_Int16 nState );

void                   actionIfaceInit(AtkActionIface *iface);
void                   componentIfaceInit(AtkComponentIface *iface);
void                   editableTextIfaceInit(AtkEditableTextIface *iface);
void                   hypertextIfaceInit(AtkHypertextIface *iface);
void                   imageIfaceInit(AtkImageIface *iface);
void                   selectionIfaceInit(AtkSelectionIface *iface);
void                   tableIfaceInit(AtkTableIface *iface);
void                   textIfaceInit(AtkTextIface *iface);
void                   valueIfaceInit(AtkValueIface *iface);

} // extern "C"

#define ATK_TYPE_OBJECT_WRAPPER atk_object_wrapper_get_type()
#define ATK_OBJECT_WRAPPER(obj) \
    (G_TYPE_CHECK_INSTANCE_CAST ((obj), ATK_TYPE_OBJECT_WRAPPER, AtkObjectWrapper))

static inline gchar *
OUStringToGChar(const rtl::OUString& rString )
{
    rtl::OString aUtf8 = rtl::OUStringToOString( rString, RTL_TEXTENCODING_UTF8 );
    return g_strdup( aUtf8 );
}

#define OUStringToConstGChar( string ) rtl::OUStringToOString( string, RTL_TEXTENCODING_UTF8 ).getStr()

#endif /* __ATK_WRAPPER_HXX__ */
<commit_msg>INTEGRATION: CWS aqua11y02 (1.4.34); FILE MERGED 2008/06/12 13:32:40 obr 1.4.34.2: #i86659# add support for XAccessibleMultiLineText 2008/06/06 10:19:20 obr 1.4.34.1: #i85292# wrapper now cache the name, suppress unload of gtk plugin when atk-bridge module gets loaded as the shutdown symbol is no longer in global address space<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: atkwrapper.hxx,v $
 * $Revision: 1.5 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#ifndef __ATK_WRAPPER_HXX__
#define __ATK_WRAPPER_HXX__

#include <atk/atk.h>
#include <com/sun/star/accessibility/XAccessible.hpp>

extern "C" {

typedef struct _AtkObjectWrapper      AtkObjectWrapper;
typedef struct _AtkObjectWrapperClass AtkObjectWrapperClass;

namespace com { namespace sun { namespace star { namespace accessibility {
    class XAccessibleAction;
    class XAccessibleComponent;
    class XAccessibleEditableText;
    class XAccessibleHypertext;
    class XAccessibleImage;
    class XAccessibleMultiLineText;
    class XAccessibleSelection;
    class XAccessibleTable;
    class XAccessibleText;
    class XAccessibleTextAttributes;
    class XAccessibleValue;
} } } }

struct _AtkObjectWrapper
{
    AtkObject aParent;

    ::com::sun::star::accessibility::XAccessible               *mpAccessible;
    ::com::sun::star::accessibility::XAccessibleContext        *mpContext;
    ::com::sun::star::accessibility::XAccessibleAction         *mpAction;
    ::com::sun::star::accessibility::XAccessibleComponent      *mpComponent;
    ::com::sun::star::accessibility::XAccessibleEditableText   *mpEditableText;
    ::com::sun::star::accessibility::XAccessibleHypertext      *mpHypertext;
    ::com::sun::star::accessibility::XAccessibleImage          *mpImage;
    ::com::sun::star::accessibility::XAccessibleMultiLineText  *mpMultiLineText;
    ::com::sun::star::accessibility::XAccessibleSelection      *mpSelection;
    ::com::sun::star::accessibility::XAccessibleTable          *mpTable;
    ::com::sun::star::accessibility::XAccessibleText           *mpText;
    ::com::sun::star::accessibility::XAccessibleTextAttributes *mpTextAttributes;
    ::com::sun::star::accessibility::XAccessibleValue          *mpValue;

    AtkObject *child_about_to_be_removed;
    gint       index_of_child_about_to_be_removed;
//    ::rtl::OString * m_pKeyBindings
};

struct _AtkObjectWrapperClass
{
    AtkObjectClass aParentClass;
};

GType                  atk_object_wrapper_get_type (void) G_GNUC_CONST;
AtkObject *            atk_object_wrapper_ref(
    const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >& rxAccessible,
    bool create = true );

AtkObject *            atk_object_wrapper_new(
    const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >& rxAccessible,
    AtkObject* parent = NULL );

void                   atk_object_wrapper_add_child(AtkObjectWrapper* wrapper, AtkObject *child, gint index);
void                   atk_object_wrapper_remove_child(AtkObjectWrapper* wrapper, AtkObject *child, gint index);

void                   atk_object_wrapper_dispose(AtkObjectWrapper* wrapper);

AtkStateType mapAtkState( sal_Int16 nState );

void                   actionIfaceInit(AtkActionIface *iface);
void                   componentIfaceInit(AtkComponentIface *iface);
void                   editableTextIfaceInit(AtkEditableTextIface *iface);
void                   hypertextIfaceInit(AtkHypertextIface *iface);
void                   imageIfaceInit(AtkImageIface *iface);
void                   selectionIfaceInit(AtkSelectionIface *iface);
void                   tableIfaceInit(AtkTableIface *iface);
void                   textIfaceInit(AtkTextIface *iface);
void                   valueIfaceInit(AtkValueIface *iface);

} // extern "C"

#define ATK_TYPE_OBJECT_WRAPPER atk_object_wrapper_get_type()
#define ATK_OBJECT_WRAPPER(obj) \
    (G_TYPE_CHECK_INSTANCE_CAST ((obj), ATK_TYPE_OBJECT_WRAPPER, AtkObjectWrapper))

static inline gchar *
OUStringToGChar(const rtl::OUString& rString )
{
    rtl::OString aUtf8 = rtl::OUStringToOString( rString, RTL_TEXTENCODING_UTF8 );
    return g_strdup( aUtf8 );
}

#define OUStringToConstGChar( string ) rtl::OUStringToOString( string, RTL_TEXTENCODING_UTF8 ).getStr()

#endif /* __ATK_WRAPPER_HXX__ */
<|endoftext|>


<commit_before>/* Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. */

#include <memory>
#include <string>
#include <unordered_map>
#include <vector>

#include "paddle/fluid/framework/infershape_utils.h"
#include "paddle/fluid/framework/op_registry.h"
#include "paddle/phi/core/infermeta_utils.h"
#include "paddle/phi/infermeta/ternary.h"
#ifdef PADDLE_WITH_MKLDNN
#include "paddle/fluid/platform/mkldnn_helper.h"
#endif

namespace paddle {
namespace operators {

constexpr int kMULMKLDNNINT8 = 1;

using framework::OpKernelType;

class AddMMOp : public framework::OperatorWithKernel {
 public:
  using framework::OperatorWithKernel::OperatorWithKernel;

  framework::OpKernelType GetExpectedKernelType(
      const framework::ExecutionContext& ctx) const {
    auto input_data_type = OperatorWithKernel::IndicateVarDataType(ctx, "X");
#ifdef PADDLE_WITH_MKLDNN
    if (this->CanMKLDNNBeUsed(ctx, input_data_type)) {
      int customized_type_value =
          framework::OpKernelType::kDefaultCustomizedTypeValue;
      if (input_data_type == framework::DataTypeTrait<int8_t>::DataType() ||
          input_data_type == framework::DataTypeTrait<uint8_t>::DataType()) {
        customized_type_value = kMULMKLDNNINT8;
      }
      return framework::OpKernelType(input_data_type,
                                     ctx.GetPlace(),
                                     framework::DataLayout::kMKLDNN,
                                     framework::LibraryType::kMKLDNN,
                                     customized_type_value);
    }
#endif
    return framework::OpKernelType(input_data_type, ctx.GetPlace());
  }
};

class AddMMOpMaker : public framework::OpProtoAndCheckerMaker {
 public:
  void Make() override {
    AddInput("Input", "(Tensor), tensor to be added to the final result.");
    AddInput("X", "(Tensor), The first input tensor for mul.");
    AddInput("Y", "(Tensor), The second input tensor for mul.");
    AddOutput("Out", "(Tensor), The output tensor of addmm op.");
    AddAttr<float>("Alpha", "coefficient of x*y.").SetDefault(1.0f);
    AddAttr<float>("Beta", "coefficient of input.").SetDefault(1.0f);
    AddComment(R"DOC(
AddMM Operator.
This operator is used to perform matrix multiplication for input $x$ and $y$ with coefficient $alpha$.
$input$ with coefficient $beta$ is added to the final result.
The equation is:

$$Out = alpha * x * y + beta * input$$

$x$ and $y$ must be two-dimensional, and $input$ can be broadcastable.
)DOC");
  }
};

class AddMMGradOp : public framework::OperatorWithKernel {
 public:
  using framework::OperatorWithKernel::OperatorWithKernel;

  void InferShape(framework::InferShapeContext* ctx) const override {
    PADDLE_ENFORCE_EQ(
        ctx->HasInput("Input"),
        true,
        platform::errors::NotFound("Input(Input) should not be null"));
    PADDLE_ENFORCE_EQ(
        ctx->HasInput("X"),
        true,
        platform::errors::NotFound("Input(X) should not be null"));
    PADDLE_ENFORCE_EQ(
        ctx->HasInput("Y"),
        true,
        platform::errors::NotFound("Input(Y) should not be null"));
    PADDLE_ENFORCE_EQ(
        ctx->HasInput(framework::GradVarName("Out")),
        true,
        platform::errors::NotFound("Input(Out@GRAD) should not be null"));
    const auto& input_dims = ctx->GetInputDim("Input");
    const auto& x_dims = ctx->GetInputDim("X");
    const auto& y_dims = ctx->GetInputDim("Y");

    auto input_grad_name = framework::GradVarName("Input");
    auto x_grad_name = framework::GradVarName("X");
    auto y_grad_name = framework::GradVarName("Y");

    if (ctx->HasOutput(input_grad_name)) {
      ctx->SetOutputDim(input_grad_name, input_dims);
    }
    if (ctx->HasOutput(x_grad_name)) {
      ctx->SetOutputDim(x_grad_name, x_dims);
    }
    if (ctx->HasOutput(y_grad_name)) {
      ctx->SetOutputDim(y_grad_name, y_dims);
    }
  }
};

template <typename T>
class AddMMOpGradMaker : public framework::SingleGradOpMaker<T> {
 public:
  using framework::SingleGradOpMaker<T>::SingleGradOpMaker;

 protected:
  void Apply(GradOpPtr<T> retv) const override {
    retv->SetType("addmm_grad");
    retv->SetInput("Input", this->Input("Input"));
    retv->SetInput("X", this->Input("X"));
    retv->SetInput("Y", this->Input("Y"));
    retv->SetInput(framework::GradVarName("Out"), this->OutputGrad("Out"));
    retv->SetOutput(framework::GradVarName("Input"), this->InputGrad("Input"));
    retv->SetOutput(framework::GradVarName("X"), this->InputGrad("X"));
    retv->SetOutput(framework::GradVarName("Y"), this->InputGrad("Y"));
    retv->SetAttrMap(this->Attrs());
  }
};

}  // namespace operators
}  // namespace paddle

namespace ops = paddle::operators;
DECLARE_INFER_SHAPE_FUNCTOR(addmm,
                            AddmmInferShapeFunctor,
                            PD_INFER_META(phi::AddmmInferMeta));
REGISTER_OPERATOR(addmm,
                  ops::AddMMOp,
                  ops::AddMMOpMaker,
                  ops::AddMMOpGradMaker<paddle::framework::OpDesc>,
                  ops::AddMMOpGradMaker<paddle::imperative::OpBase>,
                  AddmmInferShapeFunctor);

REGISTER_OPERATOR(addmm_grad, ops::AddMMGradOp);
<commit_msg>remove MKLDNN hard code in addmm (#46660)<commit_after>/* Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. */

#include <memory>
#include <string>
#include <unordered_map>
#include <vector>

#include "paddle/fluid/framework/infershape_utils.h"
#include "paddle/fluid/framework/op_registry.h"
#include "paddle/phi/core/infermeta_utils.h"
#include "paddle/phi/infermeta/ternary.h"

namespace paddle {
namespace operators {

using framework::OpKernelType;

class AddMMOp : public framework::OperatorWithKernel {
 public:
  using framework::OperatorWithKernel::OperatorWithKernel;

  framework::OpKernelType GetExpectedKernelType(
      const framework::ExecutionContext& ctx) const {
    auto input_data_type = OperatorWithKernel::IndicateVarDataType(ctx, "X");
    return framework::OpKernelType(input_data_type, ctx.GetPlace());
  }
};

class AddMMOpMaker : public framework::OpProtoAndCheckerMaker {
 public:
  void Make() override {
    AddInput("Input", "(Tensor), tensor to be added to the final result.");
    AddInput("X", "(Tensor), The first input tensor for mul.");
    AddInput("Y", "(Tensor), The second input tensor for mul.");
    AddOutput("Out", "(Tensor), The output tensor of addmm op.");
    AddAttr<float>("Alpha", "coefficient of x*y.").SetDefault(1.0f);
    AddAttr<float>("Beta", "coefficient of input.").SetDefault(1.0f);
    AddComment(R"DOC(
AddMM Operator.
This operator is used to perform matrix multiplication for input $x$ and $y$ with coefficient $alpha$.
$input$ with coefficient $beta$ is added to the final result.
The equation is:

$$Out = alpha * x * y + beta * input$$

$x$ and $y$ must be two-dimensional, and $input$ can be broadcastable.
)DOC");
  }
};

class AddMMGradOp : public framework::OperatorWithKernel {
 public:
  using framework::OperatorWithKernel::OperatorWithKernel;

  void InferShape(framework::InferShapeContext* ctx) const override {
    PADDLE_ENFORCE_EQ(
        ctx->HasInput("Input"),
        true,
        platform::errors::NotFound("Input(Input) should not be null"));
    PADDLE_ENFORCE_EQ(
        ctx->HasInput("X"),
        true,
        platform::errors::NotFound("Input(X) should not be null"));
    PADDLE_ENFORCE_EQ(
        ctx->HasInput("Y"),
        true,
        platform::errors::NotFound("Input(Y) should not be null"));
    PADDLE_ENFORCE_EQ(
        ctx->HasInput(framework::GradVarName("Out")),
        true,
        platform::errors::NotFound("Input(Out@GRAD) should not be null"));
    const auto& input_dims = ctx->GetInputDim("Input");
    const auto& x_dims = ctx->GetInputDim("X");
    const auto& y_dims = ctx->GetInputDim("Y");

    auto input_grad_name = framework::GradVarName("Input");
    auto x_grad_name = framework::GradVarName("X");
    auto y_grad_name = framework::GradVarName("Y");

    if (ctx->HasOutput(input_grad_name)) {
      ctx->SetOutputDim(input_grad_name, input_dims);
    }
    if (ctx->HasOutput(x_grad_name)) {
      ctx->SetOutputDim(x_grad_name, x_dims);
    }
    if (ctx->HasOutput(y_grad_name)) {
      ctx->SetOutputDim(y_grad_name, y_dims);
    }
  }
};

template <typename T>
class AddMMOpGradMaker : public framework::SingleGradOpMaker<T> {
 public:
  using framework::SingleGradOpMaker<T>::SingleGradOpMaker;

 protected:
  void Apply(GradOpPtr<T> retv) const override {
    retv->SetType("addmm_grad");
    retv->SetInput("Input", this->Input("Input"));
    retv->SetInput("X", this->Input("X"));
    retv->SetInput("Y", this->Input("Y"));
    retv->SetInput(framework::GradVarName("Out"), this->OutputGrad("Out"));
    retv->SetOutput(framework::GradVarName("Input"), this->InputGrad("Input"));
    retv->SetOutput(framework::GradVarName("X"), this->InputGrad("X"));
    retv->SetOutput(framework::GradVarName("Y"), this->InputGrad("Y"));
    retv->SetAttrMap(this->Attrs());
  }
};

}  // namespace operators
}  // namespace paddle

namespace ops = paddle::operators;
DECLARE_INFER_SHAPE_FUNCTOR(addmm,
                            AddmmInferShapeFunctor,
                            PD_INFER_META(phi::AddmmInferMeta));
REGISTER_OPERATOR(addmm,
                  ops::AddMMOp,
                  ops::AddMMOpMaker,
                  ops::AddMMOpGradMaker<paddle::framework::OpDesc>,
                  ops::AddMMOpGradMaker<paddle::imperative::OpBase>,
                  AddmmInferShapeFunctor);

REGISTER_OPERATOR(addmm_grad, ops::AddMMGradOp);
<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 .
 */

#include <svsys.h>
#include <win/saldata.hxx>
#include <win/saltimer.h>
#include <win/salinst.h>

#if defined ( __MINGW32__ )
#include <sehandler.hxx>
#endif

// maximum period
#define MAX_SYSPERIOD     65533

void CALLBACK SalTimerProc(PVOID pParameter, BOOLEAN bTimerOrWaitFired);

// See http://msdn.microsoft.com/en-us/library/windows/desktop/ms687003%28v=vs.85%29.aspx
// (and related pages) for details about the Timer Queues.

void ImplSalStopTimer(SalData* pSalData)
{
    HANDLE hTimer = pSalData->mnTimerId;
    pSalData->mnTimerId = 0;
    DeleteTimerQueueTimer(NULL, hTimer, INVALID_HANDLE_VALUE);
}

void ImplSalStartTimer( sal_uLong nMS, bool bMutex )
{
    SalData* pSalData = GetSalData();

    // Remember the time of the timer
    pSalData->mnTimerMS = nMS;
    if (!bMutex)
        pSalData->mnTimerOrgMS = nMS;

    // duration has to fit into Window's sal_uInt16
    if (nMS > MAX_SYSPERIOD)
        nMS = MAX_SYSPERIOD;

    // change if it exists, create if not
    if (pSalData->mnTimerId)
        ChangeTimerQueueTimer(NULL, pSalData->mnTimerId, nMS, nMS);
    else
        CreateTimerQueueTimer(&pSalData->mnTimerId, NULL, SalTimerProc, NULL, nMS, nMS, WT_EXECUTEDEFAULT);

    pSalData->mnNextTimerTime = pSalData->mnLastEventTime + nMS;
}

WinSalTimer::~WinSalTimer()
{
}

void WinSalTimer::Start( sal_uLong nMS )
{
    // switch to main thread
    SalData* pSalData = GetSalData();
    if ( pSalData->mpFirstInstance )
    {
        if ( pSalData->mnAppThreadId != GetCurrentThreadId() )
            PostMessageW( pSalData->mpFirstInstance->mhComWnd, SAL_MSG_STARTTIMER, 0, (LPARAM)nMS );
        else
            SendMessageW( pSalData->mpFirstInstance->mhComWnd, SAL_MSG_STARTTIMER, 0, (LPARAM)nMS );
    }
    else
        ImplSalStartTimer( nMS, FALSE );
}

void WinSalTimer::Stop()
{
    SalData* pSalData = GetSalData();

    // If we have a timer, than
    if ( pSalData->mnTimerId )
    {
        ImplSalStopTimer(pSalData);
        pSalData->mnNextTimerTime = 0;
    }
}

/** This gets invoked from a Timer Queue thread.

Don't acquire the SolarMutex to avoid deadlocks, just wake up the main thread
at better resolution than 10ms.
*/
void CALLBACK SalTimerProc(PVOID, BOOLEAN)
{
#if defined ( __MINGW32__ ) && !defined ( _WIN64 )
    jmp_buf jmpbuf;
    __SEHandler han;
    if (__builtin_setjmp(jmpbuf) == 0)
    {
        han.Set(jmpbuf, NULL, (__SEHandler::PF)EXCEPTION_EXECUTE_HANDLER);
#else
    __try
    {
#endif

        SalData* pSalData = GetSalData();

        // always post message when the timer fires, we will remove the ones
        // that happened during execution of the callback later directly from
        // the message queue
        PostMessageW(pSalData->mpFirstInstance->mhComWnd, SAL_MSG_TIMER_CALLBACK, 0, 0);

#if defined ( __MINGW32__ ) && !defined ( _WIN64 )
    }
    han.Reset();
#else
    }
    __except(WinSalInstance::WorkaroundExceptionHandlingInUSER32Lib(GetExceptionCode(), GetExceptionInformation()))
    {
    }
#endif
}

/** Called in the main thread.

We assured that by posting the message from the SalTimeProc only, the real
call then happens when the main thread gets SAL_MSG_TIMER_CALLBACK.
*/
void EmitTimerCallback()
{
    SalData* pSalData = GetSalData();
    ImplSVData* pSVData = ImplGetSVData();

    // Test for MouseLeave
    SalTestMouseLeave();

    // Try to acquire the mutex. If we don't get the mutex then we
    // try this a short time later again.
    if (pSVData->mpSalTimer && ImplSalYieldMutexTryToAcquire())
    {
        pSVData->mpSalTimer->CallCallback();
        ImplSalYieldMutexRelease();

        // Run the timer in the correct time, if we started this
        // with a small timeout, because we didn't get the mutex
        if (pSalData->mnTimerId && (pSalData->mnTimerMS != pSalData->mnTimerOrgMS))
            ImplSalStartTimer(pSalData->mnTimerOrgMS, false);
    }
    else
    {
        ImplSalStartTimer(10, true);
    }
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>vcl: use WT_EXECUTEINTIMERTHREAD for Timer Queue<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 .
 */

#include <svsys.h>
#include <win/saldata.hxx>
#include <win/saltimer.h>
#include <win/salinst.h>

#if defined ( __MINGW32__ )
#include <sehandler.hxx>
#endif

// maximum period
#define MAX_SYSPERIOD     65533

void CALLBACK SalTimerProc(PVOID pParameter, BOOLEAN bTimerOrWaitFired);

// See http://msdn.microsoft.com/en-us/library/windows/desktop/ms687003%28v=vs.85%29.aspx
// (and related pages) for details about the Timer Queues.

void ImplSalStopTimer(SalData* pSalData)
{
    HANDLE hTimer = pSalData->mnTimerId;
    pSalData->mnTimerId = 0;
    DeleteTimerQueueTimer(NULL, hTimer, INVALID_HANDLE_VALUE);
}

void ImplSalStartTimer( sal_uLong nMS, bool bMutex )
{
    SalData* pSalData = GetSalData();

    // Remember the time of the timer
    pSalData->mnTimerMS = nMS;
    if (!bMutex)
        pSalData->mnTimerOrgMS = nMS;

    // duration has to fit into Window's sal_uInt16
    if (nMS > MAX_SYSPERIOD)
        nMS = MAX_SYSPERIOD;

    // change if it exists, create if not
    if (pSalData->mnTimerId)
        ChangeTimerQueueTimer(NULL, pSalData->mnTimerId, nMS, nMS);
    else
        CreateTimerQueueTimer(&pSalData->mnTimerId, NULL, SalTimerProc, NULL, nMS, nMS, WT_EXECUTEINTIMERTHREAD);

    pSalData->mnNextTimerTime = pSalData->mnLastEventTime + nMS;
}

WinSalTimer::~WinSalTimer()
{
}

void WinSalTimer::Start( sal_uLong nMS )
{
    // switch to main thread
    SalData* pSalData = GetSalData();
    if ( pSalData->mpFirstInstance )
    {
        if ( pSalData->mnAppThreadId != GetCurrentThreadId() )
            PostMessageW( pSalData->mpFirstInstance->mhComWnd, SAL_MSG_STARTTIMER, 0, (LPARAM)nMS );
        else
            SendMessageW( pSalData->mpFirstInstance->mhComWnd, SAL_MSG_STARTTIMER, 0, (LPARAM)nMS );
    }
    else
        ImplSalStartTimer( nMS, FALSE );
}

void WinSalTimer::Stop()
{
    SalData* pSalData = GetSalData();

    // If we have a timer, than
    if ( pSalData->mnTimerId )
    {
        ImplSalStopTimer(pSalData);
        pSalData->mnNextTimerTime = 0;
    }
}

/** This gets invoked from a Timer Queue thread.

Don't acquire the SolarMutex to avoid deadlocks, just wake up the main thread
at better resolution than 10ms.
*/
void CALLBACK SalTimerProc(PVOID, BOOLEAN)
{
#if defined ( __MINGW32__ ) && !defined ( _WIN64 )
    jmp_buf jmpbuf;
    __SEHandler han;
    if (__builtin_setjmp(jmpbuf) == 0)
    {
        han.Set(jmpbuf, NULL, (__SEHandler::PF)EXCEPTION_EXECUTE_HANDLER);
#else
    __try
    {
#endif

        SalData* pSalData = GetSalData();

        // always post message when the timer fires, we will remove the ones
        // that happened during execution of the callback later directly from
        // the message queue
        PostMessageW(pSalData->mpFirstInstance->mhComWnd, SAL_MSG_TIMER_CALLBACK, 0, 0);

#if defined ( __MINGW32__ ) && !defined ( _WIN64 )
    }
    han.Reset();
#else
    }
    __except(WinSalInstance::WorkaroundExceptionHandlingInUSER32Lib(GetExceptionCode(), GetExceptionInformation()))
    {
    }
#endif
}

/** Called in the main thread.

We assured that by posting the message from the SalTimeProc only, the real
call then happens when the main thread gets SAL_MSG_TIMER_CALLBACK.
*/
void EmitTimerCallback()
{
    SalData* pSalData = GetSalData();
    ImplSVData* pSVData = ImplGetSVData();

    // Test for MouseLeave
    SalTestMouseLeave();

    // Try to acquire the mutex. If we don't get the mutex then we
    // try this a short time later again.
    if (pSVData->mpSalTimer && ImplSalYieldMutexTryToAcquire())
    {
        pSVData->mpSalTimer->CallCallback();
        ImplSalYieldMutexRelease();

        // Run the timer in the correct time, if we started this
        // with a small timeout, because we didn't get the mutex
        if (pSalData->mnTimerId && (pSalData->mnTimerMS != pSalData->mnTimerOrgMS))
            ImplSalStartTimer(pSalData->mnTimerOrgMS, false);
    }
    else
    {
        ImplSalStartTimer(10, true);
    }
}

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