<commit_before>/*
 * Copyright (C) 2012 Google Inc. All rights reserved.
 * Copyright (C) 2013 Apple Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1.  Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 * 2.  Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"
#include "InternalSettings.h"

#include "RuntimeEnabledFeatures.h"
#include "bindings/v8/ExceptionState.h"
#include "core/dom/ExceptionCode.h"
#include "core/page/Page.h"
#include "core/frame/Settings.h"
#include "platform/ColorChooser.h"
#include "platform/Supplementable.h"
#include "platform/text/LocaleToScriptMapping.h"

#define InternalSettingsGuardForSettingsReturn(returnValue) \
    if (!settings()) { \
        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError); \
        return returnValue; \
    }

#define InternalSettingsGuardForSettings()  \
    if (!settings()) { \
        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError); \
        return; \
    }

#define InternalSettingsGuardForPage() \
    if (!page()) { \
        exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError); \
        return; \
    }

namespace WebCore {

InternalSettings::Backup::Backup(Settings* settings)
    : m_originalCSSExclusionsEnabled(RuntimeEnabledFeatures::cssExclusionsEnabled())
    , m_originalAuthorShadowDOMForAnyElementEnabled(RuntimeEnabledFeatures::authorShadowDOMForAnyElementEnabled())
    , m_originalExperimentalWebSocketEnabled(settings->experimentalWebSocketEnabled())
    , m_originalStyleScoped(RuntimeEnabledFeatures::styleScopedEnabled())
    , m_originalCSP(RuntimeEnabledFeatures::experimentalContentSecurityPolicyFeaturesEnabled())
    , m_originalOverlayScrollbarsEnabled(RuntimeEnabledFeatures::overlayScrollbarsEnabled())
    , m_originalEditingBehavior(settings->editingBehaviorType())
    , m_originalTextAutosizingEnabled(settings->textAutosizingEnabled())
    , m_originalTextAutosizingWindowSizeOverride(settings->textAutosizingWindowSizeOverride())
    , m_originalAccessibilityFontScaleFactor(settings->accessibilityFontScaleFactor())
    , m_originalMediaTypeOverride(settings->mediaTypeOverride())
    , m_originalMockScrollbarsEnabled(settings->mockScrollbarsEnabled())
    , m_langAttributeAwareFormControlUIEnabled(RuntimeEnabledFeatures::langAttributeAwareFormControlUIEnabled())
    , m_imagesEnabled(settings->imagesEnabled())
    , m_shouldDisplaySubtitles(settings->shouldDisplaySubtitles())
    , m_shouldDisplayCaptions(settings->shouldDisplayCaptions())
    , m_shouldDisplayTextDescriptions(settings->shouldDisplayTextDescriptions())
    , m_defaultVideoPosterURL(settings->defaultVideoPosterURL())
    , m_originalCompositorDrivenAcceleratedScrollEnabled(settings->compositorDrivenAcceleratedScrollingEnabled())
    , m_originalLayerSquashingEnabled(settings->layerSquashingEnabled())
    , m_originalPasswordGenerationDecorationEnabled(settings->passwordGenerationDecorationEnabled())
{
}

void InternalSettings::Backup::restoreTo(Settings* settings)
{
    RuntimeEnabledFeatures::setCSSExclusionsEnabled(m_originalCSSExclusionsEnabled);
    RuntimeEnabledFeatures::setAuthorShadowDOMForAnyElementEnabled(m_originalAuthorShadowDOMForAnyElementEnabled);
    settings->setExperimentalWebSocketEnabled(m_originalExperimentalWebSocketEnabled);
    RuntimeEnabledFeatures::setStyleScopedEnabled(m_originalStyleScoped);
    RuntimeEnabledFeatures::setExperimentalContentSecurityPolicyFeaturesEnabled(m_originalCSP);
    RuntimeEnabledFeatures::setOverlayScrollbarsEnabled(m_originalOverlayScrollbarsEnabled);
    settings->setEditingBehaviorType(m_originalEditingBehavior);
    settings->setTextAutosizingEnabled(m_originalTextAutosizingEnabled);
    settings->setTextAutosizingWindowSizeOverride(m_originalTextAutosizingWindowSizeOverride);
    settings->setAccessibilityFontScaleFactor(m_originalAccessibilityFontScaleFactor);
    settings->setMediaTypeOverride(m_originalMediaTypeOverride);
    settings->setMockScrollbarsEnabled(m_originalMockScrollbarsEnabled);
    RuntimeEnabledFeatures::setLangAttributeAwareFormControlUIEnabled(m_langAttributeAwareFormControlUIEnabled);
    settings->setImagesEnabled(m_imagesEnabled);
    settings->setShouldDisplaySubtitles(m_shouldDisplaySubtitles);
    settings->setShouldDisplayCaptions(m_shouldDisplayCaptions);
    settings->setShouldDisplayTextDescriptions(m_shouldDisplayTextDescriptions);
    settings->setDefaultVideoPosterURL(m_defaultVideoPosterURL);
    settings->setCompositorDrivenAcceleratedScrollingEnabled(m_originalCompositorDrivenAcceleratedScrollEnabled);
    settings->setLayerSquashingEnabled(m_originalLayerSquashingEnabled);
    settings->setPasswordGenerationDecorationEnabled(m_originalPasswordGenerationDecorationEnabled);
    settings->genericFontFamilySettings().reset();
}

// We can't use RefCountedSupplement because that would try to make InternalSettings RefCounted
// and InternalSettings is already RefCounted via its base class, InternalSettingsGenerated.
// Instead, we manually make InternalSettings supplement Page.
class InternalSettingsWrapper : public Supplement<Page> {
public:
    explicit InternalSettingsWrapper(Page* page)
        : m_internalSettings(InternalSettings::create(page)) { }
    virtual ~InternalSettingsWrapper() { m_internalSettings->hostDestroyed(); }
#if !ASSERT_DISABLED
    virtual bool isRefCountedWrapper() const OVERRIDE { return true; }
#endif
    InternalSettings* internalSettings() const { return m_internalSettings.get(); }

private:
    RefPtr<InternalSettings> m_internalSettings;
};

const char* InternalSettings::supplementName()
{
    return "InternalSettings";
}

InternalSettings* InternalSettings::from(Page* page)
{
    if (!Supplement<Page>::from(page, supplementName()))
        Supplement<Page>::provideTo(page, supplementName(), adoptPtr(new InternalSettingsWrapper(page)));
    return static_cast<InternalSettingsWrapper*>(Supplement<Page>::from(page, supplementName()))->internalSettings();
}

InternalSettings::~InternalSettings()
{
}

InternalSettings::InternalSettings(Page* page)
    : InternalSettingsGenerated(page)
    , m_page(page)
    , m_backup(&page->settings())
{
}

void InternalSettings::resetToConsistentState()
{
    page()->setPageScaleFactor(1, IntPoint(0, 0));

    m_backup.restoreTo(settings());
    m_backup = Backup(settings());

    InternalSettingsGenerated::resetToConsistentState();
}

Settings* InternalSettings::settings() const
{
    if (!page())
        return 0;
    return &page()->settings();
}

void InternalSettings::setMockScrollbarsEnabled(bool enabled, ExceptionState& exceptionState)
{
    InternalSettingsGuardForSettings();
    settings()->setMockScrollbarsEnabled(enabled);
}

void InternalSettings::setAuthorShadowDOMForAnyElementEnabled(bool isEnabled)
{
    RuntimeEnabledFeatures::setAuthorShadowDOMForAnyElementEnabled(isEnabled);
}

void InternalSettings::setExperimentalWebSocketEnabled(bool isEnabled)
{
    settings()->setExperimentalWebSocketEnabled(isEnabled);
}

void InternalSettings::setStyleScopedEnabled(bool enabled)
{
    RuntimeEnabledFeatures::setStyleScopedEnabled(enabled);
}

void InternalSettings::setExperimentalContentSecurityPolicyFeaturesEnabled(bool enabled)
{
    RuntimeEnabledFeatures::setExperimentalContentSecurityPolicyFeaturesEnabled(enabled);
}

void InternalSettings::setOverlayScrollbarsEnabled(bool enabled)
{
    RuntimeEnabledFeatures::setOverlayScrollbarsEnabled(enabled);
}

void InternalSettings::setTouchEventEmulationEnabled(bool enabled, ExceptionState& exceptionState)
{
    InternalSettingsGuardForSettings();
    settings()->setTouchEventEmulationEnabled(enabled);
}

void InternalSettings::setViewportEnabled(bool enabled, ExceptionState& exceptionState)
{
    InternalSettingsGuardForSettings();
    settings()->setViewportEnabled(enabled);
}

// FIXME: This is a temporary flag and should be removed once accelerated
// overflow scroll is ready (crbug.com/254111).
void InternalSettings::setCompositorDrivenAcceleratedScrollingEnabled(bool enabled, ExceptionState& exceptionState)
{
    InternalSettingsGuardForSettings();
    settings()->setCompositorDrivenAcceleratedScrollingEnabled(enabled);
}

// FIXME: This is a temporary flag and should be removed once squashing is
// ready (crbug.com/261605).
void InternalSettings::setLayerSquashingEnabled(bool enabled, ExceptionState& exceptionState)
{
    InternalSettingsGuardForSettings();
    settings()->setLayerSquashingEnabled(enabled);
}

void InternalSettings::setStandardFontFamily(const AtomicString& family, const String& script, ExceptionState& exceptionState)
{
    InternalSettingsGuardForSettings();
    UScriptCode code = scriptNameToCode(script);
    if (code == USCRIPT_INVALID_CODE)
        return;
    settings()->genericFontFamilySettings().setStandard(family, code);
    m_page->setNeedsRecalcStyleInAllFrames();
}

void InternalSettings::setSerifFontFamily(const AtomicString& family, const String& script, ExceptionState& exceptionState)
{
    InternalSettingsGuardForSettings();
    UScriptCode code = scriptNameToCode(script);
    if (code == USCRIPT_INVALID_CODE)
        return;
    settings()->genericFontFamilySettings().setSerif(family, code);
    m_page->setNeedsRecalcStyleInAllFrames();
}

void InternalSettings::setSansSerifFontFamily(const AtomicString& family, const String& script, ExceptionState& exceptionState)
{
    InternalSettingsGuardForSettings();
    UScriptCode code = scriptNameToCode(script);
    if (code == USCRIPT_INVALID_CODE)
        return;
    settings()->genericFontFamilySettings().setSansSerif(family, code);
    m_page->setNeedsRecalcStyleInAllFrames();
}

void InternalSettings::setFixedFontFamily(const AtomicString& family, const String& script, ExceptionState& exceptionState)
{
    InternalSettingsGuardForSettings();
    UScriptCode code = scriptNameToCode(script);
    if (code == USCRIPT_INVALID_CODE)
        return;
    settings()->genericFontFamilySettings().setFixed(family, code);
    m_page->setNeedsRecalcStyleInAllFrames();
}

void InternalSettings::setCursiveFontFamily(const AtomicString& family, const String& script, ExceptionState& exceptionState)
{
    InternalSettingsGuardForSettings();
    UScriptCode code = scriptNameToCode(script);
    if (code == USCRIPT_INVALID_CODE)
        return;
    settings()->genericFontFamilySettings().setCursive(family, code);
    m_page->setNeedsRecalcStyleInAllFrames();
}

void InternalSettings::setFantasyFontFamily(const AtomicString& family, const String& script, ExceptionState& exceptionState)
{
    InternalSettingsGuardForSettings();
    UScriptCode code = scriptNameToCode(script);
    if (code == USCRIPT_INVALID_CODE)
        return;
    settings()->genericFontFamilySettings().setFantasy(family, code);
    m_page->setNeedsRecalcStyleInAllFrames();
}

void InternalSettings::setPictographFontFamily(const AtomicString& family, const String& script, ExceptionState& exceptionState)
{
    InternalSettingsGuardForSettings();
    UScriptCode code = scriptNameToCode(script);
    if (code == USCRIPT_INVALID_CODE)
        return;
    settings()->genericFontFamilySettings().setPictograph(family, code);
    m_page->setNeedsRecalcStyleInAllFrames();
}

void InternalSettings::setTextAutosizingEnabled(bool enabled, ExceptionState& exceptionState)
{
    InternalSettingsGuardForSettings();
    settings()->setTextAutosizingEnabled(enabled);
}

void InternalSettings::setTextAutosizingWindowSizeOverride(int width, int height, ExceptionState& exceptionState)
{
    InternalSettingsGuardForSettings();
    settings()->setTextAutosizingWindowSizeOverride(IntSize(width, height));
}

void InternalSettings::setMediaTypeOverride(const String& mediaType, ExceptionState& exceptionState)
{
    InternalSettingsGuardForSettings();
    settings()->setMediaTypeOverride(mediaType);
}

void InternalSettings::setAccessibilityFontScaleFactor(float fontScaleFactor, ExceptionState& exceptionState)
{
    InternalSettingsGuardForSettings();
    settings()->setAccessibilityFontScaleFactor(fontScaleFactor);
}

void InternalSettings::setCSSExclusionsEnabled(bool enabled)
{
    RuntimeEnabledFeatures::setCSSExclusionsEnabled(enabled);
}

void InternalSettings::setEditingBehavior(const String& editingBehavior, ExceptionState& exceptionState)
{
    InternalSettingsGuardForSettings();
    if (equalIgnoringCase(editingBehavior, "win"))
        settings()->setEditingBehaviorType(EditingWindowsBehavior);
    else if (equalIgnoringCase(editingBehavior, "mac"))
        settings()->setEditingBehaviorType(EditingMacBehavior);
    else if (equalIgnoringCase(editingBehavior, "unix"))
        settings()->setEditingBehaviorType(EditingUnixBehavior);
    else if (equalIgnoringCase(editingBehavior, "android"))
        settings()->setEditingBehaviorType(EditingAndroidBehavior);
    else
        exceptionState.throwUninformativeAndGenericDOMException(SyntaxError);
}

void InternalSettings::setLangAttributeAwareFormControlUIEnabled(bool enabled)
{
    RuntimeEnabledFeatures::setLangAttributeAwareFormControlUIEnabled(enabled);
}

void InternalSettings::setImagesEnabled(bool enabled, ExceptionState& exceptionState)
{
    InternalSettingsGuardForSettings();
    settings()->setImagesEnabled(enabled);
}

void InternalSettings::setDefaultVideoPosterURL(const String& url, ExceptionState& exceptionState)
{
    InternalSettingsGuardForSettings();
    settings()->setDefaultVideoPosterURL(url);
}

void InternalSettings::setPasswordGenerationDecorationEnabled(bool enabled, ExceptionState& exceptionState)
{
    InternalSettingsGuardForSettings();
    settings()->setPasswordGenerationDecorationEnabled(enabled);
}

}
<commit_msg>Improve core/testing/InternalSettings exception messages.<commit_after>/*
 * Copyright (C) 2012 Google Inc. All rights reserved.
 * Copyright (C) 2013 Apple Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1.  Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 * 2.  Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"
#include "InternalSettings.h"

#include "RuntimeEnabledFeatures.h"
#include "bindings/v8/ExceptionState.h"
#include "core/dom/ExceptionCode.h"
#include "core/page/Page.h"
#include "core/frame/Settings.h"
#include "platform/ColorChooser.h"
#include "platform/Supplementable.h"
#include "platform/text/LocaleToScriptMapping.h"

#define InternalSettingsGuardForSettingsReturn(returnValue) \
    if (!settings()) { \
        exceptionState.throwDOMException(InvalidAccessError, "The settings object cannot be obtained."); \
        return returnValue; \
    }

#define InternalSettingsGuardForSettings()  \
    if (!settings()) { \
        exceptionState.throwDOMException(InvalidAccessError, "The settings object cannot be obtained."); \
        return; \
    }

#define InternalSettingsGuardForPage() \
    if (!page()) { \
        exceptionState.throwDOMException(InvalidAccessError, "The page object cannot be obtained."); \
        return; \
    }

namespace WebCore {

InternalSettings::Backup::Backup(Settings* settings)
    : m_originalCSSExclusionsEnabled(RuntimeEnabledFeatures::cssExclusionsEnabled())
    , m_originalAuthorShadowDOMForAnyElementEnabled(RuntimeEnabledFeatures::authorShadowDOMForAnyElementEnabled())
    , m_originalExperimentalWebSocketEnabled(settings->experimentalWebSocketEnabled())
    , m_originalStyleScoped(RuntimeEnabledFeatures::styleScopedEnabled())
    , m_originalCSP(RuntimeEnabledFeatures::experimentalContentSecurityPolicyFeaturesEnabled())
    , m_originalOverlayScrollbarsEnabled(RuntimeEnabledFeatures::overlayScrollbarsEnabled())
    , m_originalEditingBehavior(settings->editingBehaviorType())
    , m_originalTextAutosizingEnabled(settings->textAutosizingEnabled())
    , m_originalTextAutosizingWindowSizeOverride(settings->textAutosizingWindowSizeOverride())
    , m_originalAccessibilityFontScaleFactor(settings->accessibilityFontScaleFactor())
    , m_originalMediaTypeOverride(settings->mediaTypeOverride())
    , m_originalMockScrollbarsEnabled(settings->mockScrollbarsEnabled())
    , m_langAttributeAwareFormControlUIEnabled(RuntimeEnabledFeatures::langAttributeAwareFormControlUIEnabled())
    , m_imagesEnabled(settings->imagesEnabled())
    , m_shouldDisplaySubtitles(settings->shouldDisplaySubtitles())
    , m_shouldDisplayCaptions(settings->shouldDisplayCaptions())
    , m_shouldDisplayTextDescriptions(settings->shouldDisplayTextDescriptions())
    , m_defaultVideoPosterURL(settings->defaultVideoPosterURL())
    , m_originalCompositorDrivenAcceleratedScrollEnabled(settings->compositorDrivenAcceleratedScrollingEnabled())
    , m_originalLayerSquashingEnabled(settings->layerSquashingEnabled())
    , m_originalPasswordGenerationDecorationEnabled(settings->passwordGenerationDecorationEnabled())
{
}

void InternalSettings::Backup::restoreTo(Settings* settings)
{
    RuntimeEnabledFeatures::setCSSExclusionsEnabled(m_originalCSSExclusionsEnabled);
    RuntimeEnabledFeatures::setAuthorShadowDOMForAnyElementEnabled(m_originalAuthorShadowDOMForAnyElementEnabled);
    settings->setExperimentalWebSocketEnabled(m_originalExperimentalWebSocketEnabled);
    RuntimeEnabledFeatures::setStyleScopedEnabled(m_originalStyleScoped);
    RuntimeEnabledFeatures::setExperimentalContentSecurityPolicyFeaturesEnabled(m_originalCSP);
    RuntimeEnabledFeatures::setOverlayScrollbarsEnabled(m_originalOverlayScrollbarsEnabled);
    settings->setEditingBehaviorType(m_originalEditingBehavior);
    settings->setTextAutosizingEnabled(m_originalTextAutosizingEnabled);
    settings->setTextAutosizingWindowSizeOverride(m_originalTextAutosizingWindowSizeOverride);
    settings->setAccessibilityFontScaleFactor(m_originalAccessibilityFontScaleFactor);
    settings->setMediaTypeOverride(m_originalMediaTypeOverride);
    settings->setMockScrollbarsEnabled(m_originalMockScrollbarsEnabled);
    RuntimeEnabledFeatures::setLangAttributeAwareFormControlUIEnabled(m_langAttributeAwareFormControlUIEnabled);
    settings->setImagesEnabled(m_imagesEnabled);
    settings->setShouldDisplaySubtitles(m_shouldDisplaySubtitles);
    settings->setShouldDisplayCaptions(m_shouldDisplayCaptions);
    settings->setShouldDisplayTextDescriptions(m_shouldDisplayTextDescriptions);
    settings->setDefaultVideoPosterURL(m_defaultVideoPosterURL);
    settings->setCompositorDrivenAcceleratedScrollingEnabled(m_originalCompositorDrivenAcceleratedScrollEnabled);
    settings->setLayerSquashingEnabled(m_originalLayerSquashingEnabled);
    settings->setPasswordGenerationDecorationEnabled(m_originalPasswordGenerationDecorationEnabled);
    settings->genericFontFamilySettings().reset();
}

// We can't use RefCountedSupplement because that would try to make InternalSettings RefCounted
// and InternalSettings is already RefCounted via its base class, InternalSettingsGenerated.
// Instead, we manually make InternalSettings supplement Page.
class InternalSettingsWrapper : public Supplement<Page> {
public:
    explicit InternalSettingsWrapper(Page* page)
        : m_internalSettings(InternalSettings::create(page)) { }
    virtual ~InternalSettingsWrapper() { m_internalSettings->hostDestroyed(); }
#if !ASSERT_DISABLED
    virtual bool isRefCountedWrapper() const OVERRIDE { return true; }
#endif
    InternalSettings* internalSettings() const { return m_internalSettings.get(); }

private:
    RefPtr<InternalSettings> m_internalSettings;
};

const char* InternalSettings::supplementName()
{
    return "InternalSettings";
}

InternalSettings* InternalSettings::from(Page* page)
{
    if (!Supplement<Page>::from(page, supplementName()))
        Supplement<Page>::provideTo(page, supplementName(), adoptPtr(new InternalSettingsWrapper(page)));
    return static_cast<InternalSettingsWrapper*>(Supplement<Page>::from(page, supplementName()))->internalSettings();
}

InternalSettings::~InternalSettings()
{
}

InternalSettings::InternalSettings(Page* page)
    : InternalSettingsGenerated(page)
    , m_page(page)
    , m_backup(&page->settings())
{
}

void InternalSettings::resetToConsistentState()
{
    page()->setPageScaleFactor(1, IntPoint(0, 0));

    m_backup.restoreTo(settings());
    m_backup = Backup(settings());

    InternalSettingsGenerated::resetToConsistentState();
}

Settings* InternalSettings::settings() const
{
    if (!page())
        return 0;
    return &page()->settings();
}

void InternalSettings::setMockScrollbarsEnabled(bool enabled, ExceptionState& exceptionState)
{
    InternalSettingsGuardForSettings();
    settings()->setMockScrollbarsEnabled(enabled);
}

void InternalSettings::setAuthorShadowDOMForAnyElementEnabled(bool isEnabled)
{
    RuntimeEnabledFeatures::setAuthorShadowDOMForAnyElementEnabled(isEnabled);
}

void InternalSettings::setExperimentalWebSocketEnabled(bool isEnabled)
{
    settings()->setExperimentalWebSocketEnabled(isEnabled);
}

void InternalSettings::setStyleScopedEnabled(bool enabled)
{
    RuntimeEnabledFeatures::setStyleScopedEnabled(enabled);
}

void InternalSettings::setExperimentalContentSecurityPolicyFeaturesEnabled(bool enabled)
{
    RuntimeEnabledFeatures::setExperimentalContentSecurityPolicyFeaturesEnabled(enabled);
}

void InternalSettings::setOverlayScrollbarsEnabled(bool enabled)
{
    RuntimeEnabledFeatures::setOverlayScrollbarsEnabled(enabled);
}

void InternalSettings::setTouchEventEmulationEnabled(bool enabled, ExceptionState& exceptionState)
{
    InternalSettingsGuardForSettings();
    settings()->setTouchEventEmulationEnabled(enabled);
}

void InternalSettings::setViewportEnabled(bool enabled, ExceptionState& exceptionState)
{
    InternalSettingsGuardForSettings();
    settings()->setViewportEnabled(enabled);
}

// FIXME: This is a temporary flag and should be removed once accelerated
// overflow scroll is ready (crbug.com/254111).
void InternalSettings::setCompositorDrivenAcceleratedScrollingEnabled(bool enabled, ExceptionState& exceptionState)
{
    InternalSettingsGuardForSettings();
    settings()->setCompositorDrivenAcceleratedScrollingEnabled(enabled);
}

// FIXME: This is a temporary flag and should be removed once squashing is
// ready (crbug.com/261605).
void InternalSettings::setLayerSquashingEnabled(bool enabled, ExceptionState& exceptionState)
{
    InternalSettingsGuardForSettings();
    settings()->setLayerSquashingEnabled(enabled);
}

void InternalSettings::setStandardFontFamily(const AtomicString& family, const String& script, ExceptionState& exceptionState)
{
    InternalSettingsGuardForSettings();
    UScriptCode code = scriptNameToCode(script);
    if (code == USCRIPT_INVALID_CODE)
        return;
    settings()->genericFontFamilySettings().setStandard(family, code);
    m_page->setNeedsRecalcStyleInAllFrames();
}

void InternalSettings::setSerifFontFamily(const AtomicString& family, const String& script, ExceptionState& exceptionState)
{
    InternalSettingsGuardForSettings();
    UScriptCode code = scriptNameToCode(script);
    if (code == USCRIPT_INVALID_CODE)
        return;
    settings()->genericFontFamilySettings().setSerif(family, code);
    m_page->setNeedsRecalcStyleInAllFrames();
}

void InternalSettings::setSansSerifFontFamily(const AtomicString& family, const String& script, ExceptionState& exceptionState)
{
    InternalSettingsGuardForSettings();
    UScriptCode code = scriptNameToCode(script);
    if (code == USCRIPT_INVALID_CODE)
        return;
    settings()->genericFontFamilySettings().setSansSerif(family, code);
    m_page->setNeedsRecalcStyleInAllFrames();
}

void InternalSettings::setFixedFontFamily(const AtomicString& family, const String& script, ExceptionState& exceptionState)
{
    InternalSettingsGuardForSettings();
    UScriptCode code = scriptNameToCode(script);
    if (code == USCRIPT_INVALID_CODE)
        return;
    settings()->genericFontFamilySettings().setFixed(family, code);
    m_page->setNeedsRecalcStyleInAllFrames();
}

void InternalSettings::setCursiveFontFamily(const AtomicString& family, const String& script, ExceptionState& exceptionState)
{
    InternalSettingsGuardForSettings();
    UScriptCode code = scriptNameToCode(script);
    if (code == USCRIPT_INVALID_CODE)
        return;
    settings()->genericFontFamilySettings().setCursive(family, code);
    m_page->setNeedsRecalcStyleInAllFrames();
}

void InternalSettings::setFantasyFontFamily(const AtomicString& family, const String& script, ExceptionState& exceptionState)
{
    InternalSettingsGuardForSettings();
    UScriptCode code = scriptNameToCode(script);
    if (code == USCRIPT_INVALID_CODE)
        return;
    settings()->genericFontFamilySettings().setFantasy(family, code);
    m_page->setNeedsRecalcStyleInAllFrames();
}

void InternalSettings::setPictographFontFamily(const AtomicString& family, const String& script, ExceptionState& exceptionState)
{
    InternalSettingsGuardForSettings();
    UScriptCode code = scriptNameToCode(script);
    if (code == USCRIPT_INVALID_CODE)
        return;
    settings()->genericFontFamilySettings().setPictograph(family, code);
    m_page->setNeedsRecalcStyleInAllFrames();
}

void InternalSettings::setTextAutosizingEnabled(bool enabled, ExceptionState& exceptionState)
{
    InternalSettingsGuardForSettings();
    settings()->setTextAutosizingEnabled(enabled);
}

void InternalSettings::setTextAutosizingWindowSizeOverride(int width, int height, ExceptionState& exceptionState)
{
    InternalSettingsGuardForSettings();
    settings()->setTextAutosizingWindowSizeOverride(IntSize(width, height));
}

void InternalSettings::setMediaTypeOverride(const String& mediaType, ExceptionState& exceptionState)
{
    InternalSettingsGuardForSettings();
    settings()->setMediaTypeOverride(mediaType);
}

void InternalSettings::setAccessibilityFontScaleFactor(float fontScaleFactor, ExceptionState& exceptionState)
{
    InternalSettingsGuardForSettings();
    settings()->setAccessibilityFontScaleFactor(fontScaleFactor);
}

void InternalSettings::setCSSExclusionsEnabled(bool enabled)
{
    RuntimeEnabledFeatures::setCSSExclusionsEnabled(enabled);
}

void InternalSettings::setEditingBehavior(const String& editingBehavior, ExceptionState& exceptionState)
{
    InternalSettingsGuardForSettings();
    if (equalIgnoringCase(editingBehavior, "win"))
        settings()->setEditingBehaviorType(EditingWindowsBehavior);
    else if (equalIgnoringCase(editingBehavior, "mac"))
        settings()->setEditingBehaviorType(EditingMacBehavior);
    else if (equalIgnoringCase(editingBehavior, "unix"))
        settings()->setEditingBehaviorType(EditingUnixBehavior);
    else if (equalIgnoringCase(editingBehavior, "android"))
        settings()->setEditingBehaviorType(EditingAndroidBehavior);
    else
        exceptionState.throwDOMException(SyntaxError, "The editing behavior type provided ('" + editingBehavior + "') is invalid.");
}

void InternalSettings::setLangAttributeAwareFormControlUIEnabled(bool enabled)
{
    RuntimeEnabledFeatures::setLangAttributeAwareFormControlUIEnabled(enabled);
}

void InternalSettings::setImagesEnabled(bool enabled, ExceptionState& exceptionState)
{
    InternalSettingsGuardForSettings();
    settings()->setImagesEnabled(enabled);
}

void InternalSettings::setDefaultVideoPosterURL(const String& url, ExceptionState& exceptionState)
{
    InternalSettingsGuardForSettings();
    settings()->setDefaultVideoPosterURL(url);
}

void InternalSettings::setPasswordGenerationDecorationEnabled(bool enabled, ExceptionState& exceptionState)
{
    InternalSettingsGuardForSettings();
    settings()->setPasswordGenerationDecorationEnabled(enabled);
}

}
<|endoftext|>


<commit_before>#define BOOST_TEST_MODULE ext2tests
// svn test

#include <boost/test/unit_test.hpp>
#include "host_node.hpp"
#include "../ext2/structs.hpp"
#include "../ext2/block_device.hpp"
#include <fstream>
#include <iostream>

BOOST_AUTO_TEST_CASE(boost_test_test) { BOOST_REQUIRE_EQUAL(true, true); }

BOOST_AUTO_TEST_CASE(host_node_test) {
	std::remove("host_node_test_file");
	{
		std::fstream file("host_node_test_file", std::ios_base::binary | std::ios_base::in | std::ios_base::trunc | std::ios_base::out);
		BOOST_REQUIRE_EQUAL(file.is_open(), true);
		file << "Hello ext2!";
	}
	{
		host_node node("host_node_test_file", 11);
		BOOST_REQUIRE_EQUAL(node.length(), 11);
		char buffer[1024];
		BOOST_REQUIRE_EQUAL(node.read(6, buffer, 1024), 5);
		BOOST_CHECK(std::string(buffer, 5) == "ext2!");
		const char *test = "ASDFGH";
		BOOST_REQUIRE_EQUAL(node.write(3, test, 4), 4);
		BOOST_REQUIRE_EQUAL(node.read(0, buffer, 1024), 11);
		BOOST_CHECK(std::string(buffer, 11) == "HelASDFxt2!");
	}
	{
		std::fstream file("host_node_test_file", std::ios_base::binary | std::ios_base::in);
		BOOST_REQUIRE_EQUAL(file.is_open(), true);
		std::string s;
		file >> s;
		BOOST_CHECK(s == "HelASDFxt2!");
	}
}

BOOST_AUTO_TEST_CASE(superblock_test) {
	ext2::detail::superblock firstblock;
	BOOST_REQUIRE_EQUAL(sizeof(firstblock), 236);
}

struct test_device {

	char data[4096];

	test_device() {
		std::memset(data, 0, sizeof(data));
	}

	void write(uint64_t offset, const char* buffer, uint64_t size) {
		std::memcpy(data + offset, buffer, size);
	}

	void read(uint64_t offset, char* buffer, uint64_t size) {
		std::memcpy(buffer, data + offset, size);
	}

};

BOOST_AUTO_TEST_CASE(block_device_test) {

	ext2::block_device<test_device> d(5); // block have size of 5 bytes
	std::string test = "This is a test message.";
	d.write(0, test.c_str(), test.size());
	BOOST_CHECK(std::string(d.data) == test);
	char buffer[1024];
	d.read(0, buffer, test.size());
	BOOST_CHECK(std::string(buffer) == test);

	d.write(67, test.c_str(), test.size());
	BOOST_CHECK(std::string(&d.data[67]) == test);
	std::memset(buffer, 0, sizeof(buffer));
	d.read(67, buffer, test.size());
	BOOST_CHECK(std::string(buffer) == test);

	test = "asd";
	d.write(201, test.c_str(), test.size());
	BOOST_CHECK(std::string(&d.data[201]) == test);
	std::memset(buffer, 0, sizeof(buffer));
	d.read(201, buffer, test.size());
	BOOST_CHECK(std::string(buffer) == test);
}

BOOST_AUTO_TEST_CASE(read_superblock_test) {

	host_node image("image.img", 1024*1024*10);
	ext2::block_device<host_node> image2(128, "image.img", 1024*1024*10); // block have size of 128 bytes
	auto superblock = ext2::read_superblock(image);
	auto superblock2 = ext2::read_superblock(image2);
	BOOST_CHECK(superblock.data == superblock2.data);

	BOOST_REQUIRE_EQUAL(superblock.data.inodes_count, 2560);
	BOOST_REQUIRE_EQUAL(superblock.data.blocks_count, 10240);
	BOOST_REQUIRE_EQUAL(superblock.data.reserved_blocks_count, 512);
	BOOST_REQUIRE_EQUAL(superblock.data.free_block_count, 9770);
	BOOST_REQUIRE_EQUAL(superblock.data.free_inodes_count, 2540);
	BOOST_REQUIRE_EQUAL(superblock.data.super_block_number, 1);
	BOOST_REQUIRE_EQUAL(superblock.data.block_size_log, 0);
	BOOST_REQUIRE_EQUAL(superblock.data.fragment_size_log, 0);
	BOOST_REQUIRE_EQUAL(superblock.data.blocks_per_group, 8192);
	BOOST_REQUIRE_EQUAL(superblock.data.fragments_per_group, 8192);
	BOOST_REQUIRE_EQUAL(superblock.data.inodes_per_group, 1280);
	BOOST_REQUIRE_EQUAL(superblock.data.mount_count, 0);
	BOOST_REQUIRE_EQUAL(superblock.data.mount_count_max, 65535);
	BOOST_REQUIRE_EQUAL(superblock.data.ext2_magic_number, 61267);
	BOOST_REQUIRE_EQUAL(superblock.data.file_system_state, 1);
	BOOST_REQUIRE_EQUAL(superblock.data.error_behaviour, 1);
	BOOST_REQUIRE_EQUAL(superblock.data.rev_level_minor, 0);
	BOOST_REQUIRE_EQUAL(superblock.data.check_interval, 0);
	BOOST_REQUIRE_EQUAL(superblock.data.os_id, 0);
	BOOST_REQUIRE_EQUAL(superblock.data.rev_level_major, 1);
	BOOST_REQUIRE_EQUAL(superblock.data.user_id_res_blocks, 0);
	BOOST_REQUIRE_EQUAL(superblock.data.group_id_res_blocks, 0);
	BOOST_REQUIRE_EQUAL(superblock.data.first_unreserved_inode, 11);
	BOOST_REQUIRE_EQUAL(superblock.data.inode_size, 128);
	BOOST_REQUIRE_EQUAL(superblock.data.this_partof_group, 0);
	BOOST_REQUIRE_EQUAL(superblock.data.features_opt, 56);
	BOOST_REQUIRE_EQUAL(superblock.data.features_req, 2);
	BOOST_REQUIRE_EQUAL(superblock.data.features_readonly, 1);
	BOOST_CHECK(superblock.data.volume_name() == "");
	BOOST_CHECK(superblock.data.mount_path_last() == "/home/pi/test");
	BOOST_REQUIRE_EQUAL(superblock.data.compression_algorithm, 0);
	BOOST_REQUIRE_EQUAL(superblock.data.journal_inode, 0);
	BOOST_REQUIRE_EQUAL(superblock.data.journal_device, 0);
	BOOST_REQUIRE_EQUAL(superblock.data.orphan_list_head, 0);

}

<commit_msg>Added more tests<commit_after>#define BOOST_TEST_MODULE ext2tests
// svn test

#include <boost/test/unit_test.hpp>
#include "host_node.hpp"
#include "../ext2/structs.hpp"
#include "../ext2/block_device.hpp"
#include <fstream>
#include <iostream>

BOOST_AUTO_TEST_CASE(boost_test_test) { BOOST_REQUIRE_EQUAL(true, true); }

BOOST_AUTO_TEST_CASE(host_node_test) {
	std::remove("host_node_test_file");
	{
		std::fstream file("host_node_test_file", std::ios_base::binary | std::ios_base::in | std::ios_base::trunc | std::ios_base::out);
		BOOST_REQUIRE_EQUAL(file.is_open(), true);
		file << "Hello ext2!";
	}
	{
		host_node node("host_node_test_file", 11);
		BOOST_REQUIRE_EQUAL(node.length(), 11);
		char buffer[1024];
		BOOST_REQUIRE_EQUAL(node.read(6, buffer, 1024), 5);
		BOOST_CHECK(std::string(buffer, 5) == "ext2!");
		const char *test = "ASDFGH";
		BOOST_REQUIRE_EQUAL(node.write(3, test, 4), 4);
		BOOST_REQUIRE_EQUAL(node.read(0, buffer, 1024), 11);
		BOOST_CHECK(std::string(buffer, 11) == "HelASDFxt2!");
	}
	{
		std::fstream file("host_node_test_file", std::ios_base::binary | std::ios_base::in);
		BOOST_REQUIRE_EQUAL(file.is_open(), true);
		std::string s;
		file >> s;
		BOOST_CHECK(s == "HelASDFxt2!");
	}
}

BOOST_AUTO_TEST_CASE(superblock_test) {
	ext2::detail::superblock firstblock;
	BOOST_REQUIRE_EQUAL(sizeof(firstblock), 236);
	BOOST_REQUIRE_EQUAL(sizeof(firstblock), sizeof(ext2::detail::superblock));
}

BOOST_AUTO_TEST_CASE(group_descriptor_test) {
	ext2::detail::group_descriptor x;
	BOOST_REQUIRE_EQUAL(sizeof(x), 32);
}

BOOST_AUTO_TEST_CASE(inode_test) {
	ext2::detail::inode x;
	BOOST_REQUIRE_EQUAL(sizeof(x), 128);
}
BOOST_AUTO_TEST_CASE(os_spec_test) {
	using namespace ext2::detail;

	os::specific_value_1 x;
	BOOST_REQUIRE_EQUAL(sizeof(x), 4);
	os::linux::specific_value_2 l;
	os::hurd::specific_value_2 h;
	os::masix::specific_value_2 m;
	BOOST_REQUIRE_EQUAL(sizeof(l), sizeof(h));
	BOOST_REQUIRE_EQUAL(sizeof(h), sizeof(m));
	BOOST_REQUIRE_EQUAL(sizeof(h), 12);

}
struct test_device {

	char data[4096];

	test_device() {
		std::memset(data, 0, sizeof(data));
	}

	void write(uint64_t offset, const char* buffer, uint64_t size) {
		std::memcpy(data + offset, buffer, size);
	}

	void read(uint64_t offset, char* buffer, uint64_t size) {
		std::memcpy(buffer, data + offset, size);
	}

};

BOOST_AUTO_TEST_CASE(block_device_test) {

	ext2::block_device<test_device> d(5); // block have size of 5 bytes
	std::string test = "This is a test message.";
	d.write(0, test.c_str(), test.size());
	BOOST_CHECK(std::string(d.data) == test);
	char buffer[1024];
	d.read(0, buffer, test.size());
	BOOST_CHECK(std::string(buffer) == test);

	d.write(67, test.c_str(), test.size());
	BOOST_CHECK(std::string(&d.data[67]) == test);
	std::memset(buffer, 0, sizeof(buffer));
	d.read(67, buffer, test.size());
	BOOST_CHECK(std::string(buffer) == test);

	test = "asd";
	d.write(201, test.c_str(), test.size());
	BOOST_CHECK(std::string(&d.data[201]) == test);
	std::memset(buffer, 0, sizeof(buffer));
	d.read(201, buffer, test.size());
	BOOST_CHECK(std::string(buffer) == test);
}

BOOST_AUTO_TEST_CASE(read_superblock_test) {

	host_node image("image.img", 1024*1024*10);
	ext2::block_device<host_node> image2(128, "image.img", 1024*1024*10); // block have size of 128 bytes
	auto superblock = ext2::read_superblock(image);
	auto superblock2 = ext2::read_superblock(image2);
	BOOST_CHECK(superblock.data == superblock2.data);

	BOOST_REQUIRE_EQUAL(superblock.data.inode_count, 2560);
	BOOST_REQUIRE_EQUAL(superblock.data.block_count, 10240);
	BOOST_REQUIRE_EQUAL(superblock.data.reserved_blocks_count, 512);
	BOOST_REQUIRE_EQUAL(superblock.data.free_block_count, 9770);
	BOOST_REQUIRE_EQUAL(superblock.data.free_inodes_count, 2540);
	BOOST_REQUIRE_EQUAL(superblock.data.super_block_number, 1);
	BOOST_REQUIRE_EQUAL(superblock.data.block_size_log, 0);
	BOOST_REQUIRE_EQUAL(superblock.data.fragment_size_log, 0);
	BOOST_REQUIRE_EQUAL(superblock.data.blocks_per_group, 8192);
	BOOST_REQUIRE_EQUAL(superblock.data.fragments_per_group, 8192);
	BOOST_REQUIRE_EQUAL(superblock.data.inodes_per_group, 1280);
	BOOST_REQUIRE_EQUAL(superblock.data.mount_count, 0);
	BOOST_REQUIRE_EQUAL(superblock.data.mount_count_max, 65535);
	BOOST_REQUIRE_EQUAL(superblock.data.ext2_magic_number, 61267);
	BOOST_REQUIRE_EQUAL(superblock.data.file_system_state, 1);
	BOOST_REQUIRE_EQUAL(superblock.data.error_behaviour, 1);
	BOOST_REQUIRE_EQUAL(superblock.data.rev_level_minor, 0);
	BOOST_REQUIRE_EQUAL(superblock.data.check_interval, 0);
	BOOST_REQUIRE_EQUAL(superblock.data.os_id, 0);
	BOOST_REQUIRE_EQUAL(superblock.data.rev_level_major, 1);
	BOOST_REQUIRE_EQUAL(superblock.data.user_id_res_blocks, 0);
	BOOST_REQUIRE_EQUAL(superblock.data.group_id_res_blocks, 0);
	BOOST_REQUIRE_EQUAL(superblock.data.first_unreserved_inode, 11);
	BOOST_REQUIRE_EQUAL(superblock.data.inode_size, 128);
	BOOST_REQUIRE_EQUAL(superblock.data.this_partof_group, 0);
	BOOST_REQUIRE_EQUAL(superblock.data.features_opt, 56);
	BOOST_REQUIRE_EQUAL(superblock.data.features_req, 2);
	BOOST_REQUIRE_EQUAL(superblock.data.features_readonly, 1);
	BOOST_CHECK(superblock.data.volume_name() == "");
	BOOST_CHECK(superblock.data.mount_path_last() == "/home/pi/test");
	BOOST_REQUIRE_EQUAL(superblock.data.compression_algorithm, 0);
	BOOST_REQUIRE_EQUAL(superblock.data.journal_inode, 0);
	BOOST_REQUIRE_EQUAL(superblock.data.journal_device, 0);
	BOOST_REQUIRE_EQUAL(superblock.data.orphan_list_head, 0);
	BOOST_REQUIRE_EQUAL(superblock.data.block_group_count(), std::ceil((float)superblock.data.inode_count/superblock.data.inodes_per_group));
	BOOST_REQUIRE_EQUAL(superblock.data.block_group_count(), 2);
	BOOST_REQUIRE_EQUAL(superblock.data.block_size(), 1024);
	BOOST_REQUIRE_EQUAL(superblock.data.fragment_size(), 1024);
}

BOOST_AUTO_TEST_CASE(write_read_vector_test) {
	using block = ext2::block_data<test_device, char>;
	test_device d;
	std::string msg = "qwertzuiopasdfghjklyxcvbnm";
	d.write(0, msg.c_str(), msg.size());
	BOOST_CHECK(d.data == msg);

	auto vec = ext2::read_vector<block>(d, 0, msg.size());
	BOOST_REQUIRE_EQUAL(vec.size(), msg.size());
	for(int i = 0; i < msg.size(); i++) {
		BOOST_REQUIRE_EQUAL(vec[i].data, msg[i]);
	}

	for(auto& item : vec) {
		item.data = 'a';
	}
	ext2::write_vector(vec);
	for(int i = 0; i < msg.size(); i++) {
		BOOST_REQUIRE_EQUAL(d.data[i], 'a');
	}

}

BOOST_AUTO_TEST_CASE(read_group_des_table_test) {
	host_node image("image.img", 1024*1024*10);
	auto superblock = ext2::read_superblock(image);
	auto gd_table = ext2::read_group_descriptor_table(superblock);
	BOOST_REQUIRE_EQUAL(gd_table.size(), 2);

	auto& gd1 =  gd_table[0];
	BOOST_REQUIRE_EQUAL(gd1.data.address_block_bitmap, 42);
	BOOST_REQUIRE_EQUAL(gd1.data.address_inode_bitmap, 43);
	BOOST_REQUIRE_EQUAL(gd1.data.address_inode_table, 44);
	BOOST_REQUIRE_EQUAL(gd1.data.free_blocks, 7928);
	BOOST_REQUIRE_EQUAL(gd1.data.free_inodes, 1262);
	BOOST_REQUIRE_EQUAL(gd1.data.count_directories, 4);

	auto& gd2 =  gd_table[1];
	BOOST_REQUIRE_EQUAL(gd2.data.address_block_bitmap, 8234);
	BOOST_REQUIRE_EQUAL(gd2.data.address_inode_bitmap, 8235);
	BOOST_REQUIRE_EQUAL(gd2.data.address_inode_table, 8236);
	BOOST_REQUIRE_EQUAL(gd2.data.free_blocks, 1842);
	BOOST_REQUIRE_EQUAL(gd2.data.free_inodes, 1278);
	BOOST_REQUIRE_EQUAL(gd2.data.count_directories, 2);

}

<|endoftext|>


<commit_before>#pragma once

#include <cstring>
#include <string>
#include <cassert>

namespace iod
{

  struct stringview
  {
    stringview() : str(0), len(0) {}
    stringview(const std::string& _str) : str(&_str[0]), len(_str.size()) {}
    stringview(const char* _str, std::size_t _len) : str(_str), len(_len) {}
    stringview(const char* _begin, const char* _end) : str(_begin), len(_end - _begin) { assert(_end >= _begin); }
    stringview(const char* _str) : str(_str), len(strlen(_str)) {}

    bool operator==(const stringview& o) const { return len == o.len and !strncmp(o.str, str, len); }
    bool operator==(const std::string& o) const { return len == o.size() and !strncmp(&o[0], str, len); }
    bool operator==(const char* o) const { return len == strlen(o) and !strncmp(o, str, len); }

    bool operator<(const stringview& o) const { return strncmp(o.str, str, std::min(len, o.len)); }
    explicit operator std::string() const { return std::string(str, len); }

    auto& operator[](int p) { return str[p]; }
    const auto& operator[](int p) const { return str[p]; }

    int size() const { return len; }
    const char* data() const { return str; }
    auto to_std_string() const { return std::string(str, len); }

    const char* str;
    std::size_t len;
  };

}
<commit_msg>stringview::substr.<commit_after>#pragma once

#include <cstring>
#include <string>
#include <cassert>

namespace iod
{

  struct stringview
  {
    stringview() : str(0), len(0) {}
    stringview(const std::string& _str) : str(&_str[0]), len(_str.size()) {}
    stringview(const char* _str, std::size_t _len) : str(_str), len(_len) {}
    stringview(const char* _begin, const char* _end) : str(_begin), len(_end - _begin) { assert(_end >= _begin); }
    stringview(const char* _str) : str(_str), len(strlen(_str)) {}

    bool operator==(const stringview& o) const { return len == o.len and !strncmp(o.str, str, len); }
    bool operator==(const std::string& o) const { return len == o.size() and !strncmp(&o[0], str, len); }
    bool operator==(const char* o) const { return len == strlen(o) and !strncmp(o, str, len); }

    bool operator<(const stringview& o) const { return strncmp(o.str, str, std::min(len, o.len)); }
    explicit operator std::string() const { return std::string(str, len); }

    auto& operator[](int p) { return str[p]; }
    const auto& operator[](int p) const { return str[p]; }

    int size() const { return len; }
    const char* data() const { return str; }
    auto to_std_string() const { return std::string(str, len); }

    auto substr(int start, int new_len) { return stringview(str + start, new_len); }

    const char* str;
    std::size_t len;
  };

}
<|endoftext|>


<commit_before>/////////////////////////////////////////////////////////////////////////
// $Id: gameport.cc,v 1.4 2003/12/26 13:53:40 vruppert Exp $
/////////////////////////////////////////////////////////////////////////
//
//  Copyright (C) 2003  MandrakeSoft S.A.
//
//    MandrakeSoft S.A.
//    43, rue d'Aboukir
//    75002 Paris - France
//    http://www.linux-mandrake.com/
//    http://www.mandrakesoft.com/
//
//  This library is free software; you can 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 of the License, or (at your option) any later version.
//
//  This library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA

//
// Standard PC gameport
//

// Define BX_PLUGGABLE in files that can be compiled into plugins.  For
// platforms that require a special tag on exported symbols, BX_PLUGGABLE
// is used to know when we are exporting symbols and when we are importing.
#define BX_PLUGGABLE

#include "bochs.h"

#ifdef __linux__

#include <linux/joystick.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>

#elif defined(WIN32)

#define JOY_BUTTON1 1
#define JOY_BUTTON2 2
#define JOYSTICKID1 0

UINT STDCALL joyGetPos(UINT, LPJOYINFO);

#endif

#define LOG_THIS theGameport->

bx_gameport_c *theGameport = NULL;

  int
libgameport_LTX_plugin_init(plugin_t *plugin, plugintype_t type, int argc, char *argv[])
{
  theGameport = new bx_gameport_c ();
  bx_devices.pluginGameport = theGameport;
  BX_REGISTER_DEVICE_DEVMODEL(plugin, type, theGameport, BX_PLUGIN_GAMEPORT);
  return(0); // Success
}

  void
libgameport_LTX_plugin_fini(void)
{
}

bx_gameport_c::bx_gameport_c(void)
{
  put("GAME");
  settype(EXTFPUIRQLOG);
}

bx_gameport_c::~bx_gameport_c(void)
{
  if (joyfd >= 0) close(joyfd);
  BX_DEBUG(("Exit."));
}

  void
bx_gameport_c::init(void)
{
  // Allocate the gameport IO address range 0x200..0x207
  for (unsigned addr=0x200; addr<0x208; addr++) {
    DEV_register_ioread_handler(this, read_handler, addr, "Gameport", 1);
    DEV_register_iowrite_handler(this, write_handler, addr, "Gameport", 1);
  }

  BX_GAMEPORT_THIS port = 0xf0;
  BX_GAMEPORT_THIS write_usec = 0;
  BX_GAMEPORT_THIS timer_x = 0;
  BX_GAMEPORT_THIS timer_y = 0;

#ifdef __linux__
  BX_GAMEPORT_THIS joyfd = open("/dev/input/js0", O_RDONLY);
  if (BX_GAMEPORT_THIS joyfd >= 0) {
    for (unsigned i=0; i<4; i++) poll_joydev();
  }
#elif defined(WIN32)
  JOYINFO joypos;
  if (joyGetPos(JOYSTICKID1, &joypos) == JOYERR_NOERROR) {
    BX_GAMEPORT_THIS joyfd = 1;
  } else {
    BX_GAMEPORT_THIS joyfd = -1;
  }
#else
  BX_GAMEPORT_THIS joyfd = -1;
#endif
}

  void
bx_gameport_c::reset(unsigned type)
{
  // nothing for now
}

  void
bx_gameport_c::poll_joydev(void)
{
#ifdef __linux__
  struct js_event e;
  fd_set joyfds;
  struct timeval tv;

  memset(&tv, 0, sizeof(tv));
  FD_ZERO(&joyfds);
  FD_SET(BX_GAMEPORT_THIS joyfd, &joyfds);
  e.type = 0;
  if (select(BX_GAMEPORT_THIS joyfd+1, &joyfds, NULL, NULL, &tv)) {
    read(BX_GAMEPORT_THIS joyfd, &e, sizeof(struct js_event));
    if (e.type & JS_EVENT_BUTTON) {
      if (e.value == 1) {
        BX_GAMEPORT_THIS port &= ~(0x10 << e.number);
      } else {
        BX_GAMEPORT_THIS port |= (0x10 << e.number);
      }
    }
    if (e.type & JS_EVENT_AXIS) {
      if (e.number == 0) {
        BX_GAMEPORT_THIS delay_x = 25 + ((e.value + 0x8000) / 60);
      }
      if (e.number == 1) {
        BX_GAMEPORT_THIS delay_y = 25 + ((e.value + 0x8000) / 62);
      }
    }
  }
#elif defined(WIN32)
  JOYINFO joypos;
  if (joyGetPos(JOYSTICKID1, &joypos) == JOYERR_NOERROR) {
    if (joypos.wButtons & JOY_BUTTON1) {
      BX_GAMEPORT_THIS port &= ~0x10;
    } else {
      BX_GAMEPORT_THIS port |= 0x10;
    }
    if (joypos.wButtons & JOY_BUTTON2) {
      BX_GAMEPORT_THIS port &= ~0x20;
    } else {
      BX_GAMEPORT_THIS port |= 0x20;
    }
    BX_GAMEPORT_THIS delay_x = 25 + (joypos.wXpos / 60);
    BX_GAMEPORT_THIS delay_y = 25 + (joypos.wYpos / 60);
  }
#endif
}

  // static IO port read callback handler
  // redirects to non-static class handler to avoid virtual functions

  Bit32u
bx_gameport_c::read_handler(void *this_ptr, Bit32u address, unsigned io_len)
{
#if !BX_USE_GAME_SMF
  bx_gameport_c *class_ptr = (bx_gameport_c *) this_ptr;

  return( class_ptr->read(address, io_len) );
}

  Bit32u
bx_gameport_c::read(Bit32u address, unsigned io_len)
{
#else
  UNUSED(this_ptr);
#endif // !BX_USE_GAME_SMF
  Bit64u usec;

  if (BX_GAMEPORT_THIS joyfd >= 0) {
    poll_joydev();
    usec = bx_pc_system.time_usec();
    if (BX_GAMEPORT_THIS timer_x) {
      if ((usec - BX_GAMEPORT_THIS write_usec) >= BX_GAMEPORT_THIS delay_x) {
        BX_GAMEPORT_THIS port &= 0xfe;
        BX_GAMEPORT_THIS timer_x = 0;
      }
    }
    if (BX_GAMEPORT_THIS timer_y) {
      if ((usec - BX_GAMEPORT_THIS write_usec) >= BX_GAMEPORT_THIS delay_y) {
        BX_GAMEPORT_THIS port &= 0xfd;
        BX_GAMEPORT_THIS timer_y = 0;
      }
    }
  } else {
    BX_DEBUG(("read: joystick not present"));
  }
  return BX_GAMEPORT_THIS port;
}

  // static IO port write callback handler
  // redirects to non-static class handler to avoid virtual functions

  void
bx_gameport_c::write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len)
{
#if !BX_USE_GAME_SMF
  bx_gameport_c *class_ptr = (bx_gameport_c *) this_ptr;

  class_ptr->write(address, value, io_len);
}

  void
bx_gameport_c::write(Bit32u address, Bit32u value, unsigned io_len)
{
#else
  UNUSED(this_ptr);
#endif // !BX_USE_GAME_SMF

  BX_GAMEPORT_THIS write_usec = bx_pc_system.time_usec();
  BX_GAMEPORT_THIS timer_x = 1;
  BX_GAMEPORT_THIS timer_y = 1;
  BX_GAMEPORT_THIS port |= 0x0f;
}
<commit_msg>- add temporary hack for compiling with visual c++<commit_after>/////////////////////////////////////////////////////////////////////////
// $Id: gameport.cc,v 1.5 2003/12/29 21:48:56 cbothamy Exp $
/////////////////////////////////////////////////////////////////////////
//
//  Copyright (C) 2003  MandrakeSoft S.A.
//
//    MandrakeSoft S.A.
//    43, rue d'Aboukir
//    75002 Paris - France
//    http://www.linux-mandrake.com/
//    http://www.mandrakesoft.com/
//
//  This library is free software; you can 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 of the License, or (at your option) any later version.
//
//  This library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA

//
// Standard PC gameport
//

// Define BX_PLUGGABLE in files that can be compiled into plugins.  For
// platforms that require a special tag on exported symbols, BX_PLUGGABLE
// is used to know when we are exporting symbols and when we are importing.
#define BX_PLUGGABLE

#include "bochs.h"

#ifdef __linux__

#include <linux/joystick.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>

#elif defined(WIN32)

#ifndef JOY_BUTTON1
#define JOY_BUTTON1 1
#define JOY_BUTTON2 2
UINT STDCALL joyGetPos(UINT, LPJOYINFO);
#endif

#define JOYSTICKID1 0

#endif

#define LOG_THIS theGameport->

bx_gameport_c *theGameport = NULL;

  int
libgameport_LTX_plugin_init(plugin_t *plugin, plugintype_t type, int argc, char *argv[])
{
  theGameport = new bx_gameport_c ();
  bx_devices.pluginGameport = theGameport;
  BX_REGISTER_DEVICE_DEVMODEL(plugin, type, theGameport, BX_PLUGIN_GAMEPORT);
  return(0); // Success
}

  void
libgameport_LTX_plugin_fini(void)
{
}

bx_gameport_c::bx_gameport_c(void)
{
  put("GAME");
  settype(EXTFPUIRQLOG);
}

bx_gameport_c::~bx_gameport_c(void)
{
  if (joyfd >= 0) close(joyfd);
  BX_DEBUG(("Exit."));
}

  void
bx_gameport_c::init(void)
{
  // Allocate the gameport IO address range 0x200..0x207
  for (unsigned addr=0x200; addr<0x208; addr++) {
    DEV_register_ioread_handler(this, read_handler, addr, "Gameport", 1);
    DEV_register_iowrite_handler(this, write_handler, addr, "Gameport", 1);
  }

  BX_GAMEPORT_THIS port = 0xf0;
  BX_GAMEPORT_THIS write_usec = 0;
  BX_GAMEPORT_THIS timer_x = 0;
  BX_GAMEPORT_THIS timer_y = 0;

#ifdef __linux__
  BX_GAMEPORT_THIS joyfd = open("/dev/input/js0", O_RDONLY);
  if (BX_GAMEPORT_THIS joyfd >= 0) {
    for (unsigned i=0; i<4; i++) poll_joydev();
  }
#elif defined(WIN32)
  JOYINFO joypos;
  if (joyGetPos(JOYSTICKID1, &joypos) == JOYERR_NOERROR) {
    BX_GAMEPORT_THIS joyfd = 1;
  } else {
    BX_GAMEPORT_THIS joyfd = -1;
  }
#else
  BX_GAMEPORT_THIS joyfd = -1;
#endif
}

  void
bx_gameport_c::reset(unsigned type)
{
  // nothing for now
}

  void
bx_gameport_c::poll_joydev(void)
{
#ifdef __linux__
  struct js_event e;
  fd_set joyfds;
  struct timeval tv;

  memset(&tv, 0, sizeof(tv));
  FD_ZERO(&joyfds);
  FD_SET(BX_GAMEPORT_THIS joyfd, &joyfds);
  e.type = 0;
  if (select(BX_GAMEPORT_THIS joyfd+1, &joyfds, NULL, NULL, &tv)) {
    read(BX_GAMEPORT_THIS joyfd, &e, sizeof(struct js_event));
    if (e.type & JS_EVENT_BUTTON) {
      if (e.value == 1) {
        BX_GAMEPORT_THIS port &= ~(0x10 << e.number);
      } else {
        BX_GAMEPORT_THIS port |= (0x10 << e.number);
      }
    }
    if (e.type & JS_EVENT_AXIS) {
      if (e.number == 0) {
        BX_GAMEPORT_THIS delay_x = 25 + ((e.value + 0x8000) / 60);
      }
      if (e.number == 1) {
        BX_GAMEPORT_THIS delay_y = 25 + ((e.value + 0x8000) / 62);
      }
    }
  }
#elif defined(WIN32)
  JOYINFO joypos;
  if (joyGetPos(JOYSTICKID1, &joypos) == JOYERR_NOERROR) {
    if (joypos.wButtons & JOY_BUTTON1) {
      BX_GAMEPORT_THIS port &= ~0x10;
    } else {
      BX_GAMEPORT_THIS port |= 0x10;
    }
    if (joypos.wButtons & JOY_BUTTON2) {
      BX_GAMEPORT_THIS port &= ~0x20;
    } else {
      BX_GAMEPORT_THIS port |= 0x20;
    }
    BX_GAMEPORT_THIS delay_x = 25 + (joypos.wXpos / 60);
    BX_GAMEPORT_THIS delay_y = 25 + (joypos.wYpos / 60);
  }
#endif
}

  // static IO port read callback handler
  // redirects to non-static class handler to avoid virtual functions

  Bit32u
bx_gameport_c::read_handler(void *this_ptr, Bit32u address, unsigned io_len)
{
#if !BX_USE_GAME_SMF
  bx_gameport_c *class_ptr = (bx_gameport_c *) this_ptr;

  return( class_ptr->read(address, io_len) );
}

  Bit32u
bx_gameport_c::read(Bit32u address, unsigned io_len)
{
#else
  UNUSED(this_ptr);
#endif // !BX_USE_GAME_SMF
  Bit64u usec;

  if (BX_GAMEPORT_THIS joyfd >= 0) {
    poll_joydev();
    usec = bx_pc_system.time_usec();
    if (BX_GAMEPORT_THIS timer_x) {
      if ((usec - BX_GAMEPORT_THIS write_usec) >= BX_GAMEPORT_THIS delay_x) {
        BX_GAMEPORT_THIS port &= 0xfe;
        BX_GAMEPORT_THIS timer_x = 0;
      }
    }
    if (BX_GAMEPORT_THIS timer_y) {
      if ((usec - BX_GAMEPORT_THIS write_usec) >= BX_GAMEPORT_THIS delay_y) {
        BX_GAMEPORT_THIS port &= 0xfd;
        BX_GAMEPORT_THIS timer_y = 0;
      }
    }
  } else {
    BX_DEBUG(("read: joystick not present"));
  }
  return BX_GAMEPORT_THIS port;
}

  // static IO port write callback handler
  // redirects to non-static class handler to avoid virtual functions

  void
bx_gameport_c::write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len)
{
#if !BX_USE_GAME_SMF
  bx_gameport_c *class_ptr = (bx_gameport_c *) this_ptr;

  class_ptr->write(address, value, io_len);
}

  void
bx_gameport_c::write(Bit32u address, Bit32u value, unsigned io_len)
{
#else
  UNUSED(this_ptr);
#endif // !BX_USE_GAME_SMF

  BX_GAMEPORT_THIS write_usec = bx_pc_system.time_usec();
  BX_GAMEPORT_THIS timer_x = 1;
  BX_GAMEPORT_THIS timer_y = 1;
  BX_GAMEPORT_THIS port |= 0x0f;
}
<|endoftext|>


<commit_before>/*
 * <one line to give the library's name and an idea of what it does.>
 * Copyright (C) 2013  <copyright holder> <email>
 *
 * This library is free software; you can 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.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 */

#include "xdgcachedmenu.h"
#include <QAction>
#include <QIcon>
#include <QCursor>
#include <QToolTip>
#include <QList>
#include <QUrl>
#include <QDrag>
#include <QMouseEvent>
#include <QApplication>
#include <qtxdg/XdgDesktopFile>
#include <qtxdg/XdgIcon>
#include <QHelpEvent>
#include <QDebug>

XdgCachedMenuAction::XdgCachedMenuAction(MenuCacheItem* item, QObject* parent):
    QAction(parent),
    item_(menu_cache_item_ref(item))
{
    QString title = QString::fromUtf8(menu_cache_item_get_name(item));
    setText(title);
    // Only set tooltips for app items
    if(menu_cache_item_get_type(item) == MENU_CACHE_TYPE_APP)
    {
        QString comment = QString::fromUtf8(menu_cache_item_get_comment(item));
        setToolTip(comment);
    }
}

XdgCachedMenuAction::~XdgCachedMenuAction()
{
  if(item_)
    menu_cache_item_unref(item_);
}

void XdgCachedMenuAction::updateIcon()
{
    if(icon().isNull())
    {
        QIcon icon = XdgIcon::fromTheme(menu_cache_item_get_icon(item_));
        setIcon(icon);
    }
}

XdgCachedMenu::XdgCachedMenu(QWidget* parent): QMenu(parent)
{
    connect(this, SIGNAL(aboutToShow()), SLOT(onAboutToShow()));
}

XdgCachedMenu::XdgCachedMenu(MenuCache* menuCache, QWidget* parent): QMenu(parent)
{
    // qDebug() << "CREATE MENU FROM CACHE" << menuCache;
    MenuCacheDir* dir = menu_cache_get_root_dir(menuCache);
    addMenuItems(this, dir);
    connect(this, SIGNAL(aboutToShow()), SLOT(onAboutToShow()));
}

XdgCachedMenu::~XdgCachedMenu()
{
}

void XdgCachedMenu::addMenuItems(QMenu* menu, MenuCacheDir* dir)
{
  for(GSList* l = menu_cache_dir_get_children(dir); l; l = l->next)
  {
    MenuCacheItem* item = (MenuCacheItem*)l->data;
    MenuCacheType type = menu_cache_item_get_type(item);

    if(type == MENU_CACHE_TYPE_SEP)
    {
      menu->addSeparator();
      continue;
    }
    else
    {
      XdgCachedMenuAction* action = new XdgCachedMenuAction(item, menu);
      menu->addAction(action);
      if(type == MENU_CACHE_TYPE_APP)
        connect(action, SIGNAL(triggered(bool)), SLOT(onItemTrigerred()));
      else if(type == MENU_CACHE_TYPE_DIR)
      {
        XdgCachedMenu* submenu = new XdgCachedMenu(menu);
        action->setMenu(submenu);
        addMenuItems(submenu, (MenuCacheDir*)item);
      }
    }
  }
}

void XdgCachedMenu::onItemTrigerred()
{
    XdgCachedMenuAction* action = static_cast<XdgCachedMenuAction*>(sender());
    XdgDesktopFile df;
    char* desktop_file = menu_cache_item_get_file_path(action->item());
    df.load(desktop_file);
    g_free(desktop_file);
    df.startDetached();
}

// taken from libqtxdg: XdgMenuWidget
bool XdgCachedMenu::event(QEvent* event)
{
    if (event->type() == QEvent::MouseButtonPress)
    {
        QMouseEvent *e = static_cast<QMouseEvent*>(event);
        if (e->button() == Qt::LeftButton)
            mDragStartPosition = e->pos();
    }

    else if (event->type() == QEvent::MouseMove)
    {
        QMouseEvent *e = static_cast<QMouseEvent*>(event);
        handleMouseMoveEvent(e);
    }

    else if(event->type() == QEvent::ToolTip)
    {
        QHelpEvent* helpEvent = static_cast<QHelpEvent*>(event);
        QAction* action = actionAt(helpEvent->pos());
        if(action && action->menu() == NULL)
            QToolTip::showText(helpEvent->globalPos(), action->toolTip(), this);
    }

    return QMenu::event(event);
}

// taken from libqtxdg: XdgMenuWidget
void XdgCachedMenu::handleMouseMoveEvent(QMouseEvent *event)
{
    if (!(event->buttons() & Qt::LeftButton))
        return;

    if ((event->pos() - mDragStartPosition).manhattanLength() < QApplication::startDragDistance())
        return;

    XdgCachedMenuAction *a = qobject_cast<XdgCachedMenuAction*>(actionAt(event->pos()));
    if (!a)
        return;

    QList<QUrl> urls;
    char* desktop_file = menu_cache_item_get_file_path(a->item());
    urls << QUrl(desktop_file);
    g_free(desktop_file);

    QMimeData *mimeData = new QMimeData();
    mimeData->setUrls(urls);

    QDrag *drag = new QDrag(this);
    drag->setMimeData(mimeData);
    drag->exec(Qt::CopyAction | Qt::LinkAction);
}

void XdgCachedMenu::onAboutToShow()
{
    Q_FOREACH(QAction* action, actions())
    {
        if(action->inherits("XdgCachedMenuAction"))
        {
            static_cast<XdgCachedMenuAction*>(action)->updateIcon();

            // this seems to cause some incorrect menu behaviour.
            // qApp->processEvents();
        }
    }
}
<commit_msg>Avoid mnemonics in the main application menu caused by & symbol in the name of the desktop apps.<commit_after>/*
 * <one line to give the library's name and an idea of what it does.>
 * Copyright (C) 2013  <copyright holder> <email>
 *
 * This library is free software; you can 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.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 */

#include "xdgcachedmenu.h"
#include <QAction>
#include <QIcon>
#include <QCursor>
#include <QToolTip>
#include <QList>
#include <QUrl>
#include <QDrag>
#include <QMouseEvent>
#include <QApplication>
#include <qtxdg/XdgDesktopFile>
#include <qtxdg/XdgIcon>
#include <QHelpEvent>
#include <QDebug>

XdgCachedMenuAction::XdgCachedMenuAction(MenuCacheItem* item, QObject* parent):
    QAction(parent),
    item_(menu_cache_item_ref(item))
{
    QString title = QString::fromUtf8(menu_cache_item_get_name(item));
    title = title.replace('&', QLatin1String("&&")); // & is reserved for mnemonics
    setText(title);
    // Only set tooltips for app items
    if(menu_cache_item_get_type(item) == MENU_CACHE_TYPE_APP)
    {
        QString comment = QString::fromUtf8(menu_cache_item_get_comment(item));
        setToolTip(comment);
    }
}

XdgCachedMenuAction::~XdgCachedMenuAction()
{
  if(item_)
    menu_cache_item_unref(item_);
}

void XdgCachedMenuAction::updateIcon()
{
    if(icon().isNull())
    {
        QIcon icon = XdgIcon::fromTheme(menu_cache_item_get_icon(item_));
        setIcon(icon);
    }
}

XdgCachedMenu::XdgCachedMenu(QWidget* parent): QMenu(parent)
{
    connect(this, SIGNAL(aboutToShow()), SLOT(onAboutToShow()));
}

XdgCachedMenu::XdgCachedMenu(MenuCache* menuCache, QWidget* parent): QMenu(parent)
{
    // qDebug() << "CREATE MENU FROM CACHE" << menuCache;
    MenuCacheDir* dir = menu_cache_get_root_dir(menuCache);
    addMenuItems(this, dir);
    connect(this, SIGNAL(aboutToShow()), SLOT(onAboutToShow()));
}

XdgCachedMenu::~XdgCachedMenu()
{
}

void XdgCachedMenu::addMenuItems(QMenu* menu, MenuCacheDir* dir)
{
  for(GSList* l = menu_cache_dir_get_children(dir); l; l = l->next)
  {
    MenuCacheItem* item = (MenuCacheItem*)l->data;
    MenuCacheType type = menu_cache_item_get_type(item);

    if(type == MENU_CACHE_TYPE_SEP)
    {
      menu->addSeparator();
      continue;
    }
    else
    {
      XdgCachedMenuAction* action = new XdgCachedMenuAction(item, menu);
      menu->addAction(action);
      if(type == MENU_CACHE_TYPE_APP)
        connect(action, SIGNAL(triggered(bool)), SLOT(onItemTrigerred()));
      else if(type == MENU_CACHE_TYPE_DIR)
      {
        XdgCachedMenu* submenu = new XdgCachedMenu(menu);
        action->setMenu(submenu);
        addMenuItems(submenu, (MenuCacheDir*)item);
      }
    }
  }
}

void XdgCachedMenu::onItemTrigerred()
{
    XdgCachedMenuAction* action = static_cast<XdgCachedMenuAction*>(sender());
    XdgDesktopFile df;
    char* desktop_file = menu_cache_item_get_file_path(action->item());
    df.load(desktop_file);
    g_free(desktop_file);
    df.startDetached();
}

// taken from libqtxdg: XdgMenuWidget
bool XdgCachedMenu::event(QEvent* event)
{
    if (event->type() == QEvent::MouseButtonPress)
    {
        QMouseEvent *e = static_cast<QMouseEvent*>(event);
        if (e->button() == Qt::LeftButton)
            mDragStartPosition = e->pos();
    }

    else if (event->type() == QEvent::MouseMove)
    {
        QMouseEvent *e = static_cast<QMouseEvent*>(event);
        handleMouseMoveEvent(e);
    }

    else if(event->type() == QEvent::ToolTip)
    {
        QHelpEvent* helpEvent = static_cast<QHelpEvent*>(event);
        QAction* action = actionAt(helpEvent->pos());
        if(action && action->menu() == NULL)
            QToolTip::showText(helpEvent->globalPos(), action->toolTip(), this);
    }

    return QMenu::event(event);
}

// taken from libqtxdg: XdgMenuWidget
void XdgCachedMenu::handleMouseMoveEvent(QMouseEvent *event)
{
    if (!(event->buttons() & Qt::LeftButton))
        return;

    if ((event->pos() - mDragStartPosition).manhattanLength() < QApplication::startDragDistance())
        return;

    XdgCachedMenuAction *a = qobject_cast<XdgCachedMenuAction*>(actionAt(event->pos()));
    if (!a)
        return;

    QList<QUrl> urls;
    char* desktop_file = menu_cache_item_get_file_path(a->item());
    urls << QUrl(desktop_file);
    g_free(desktop_file);

    QMimeData *mimeData = new QMimeData();
    mimeData->setUrls(urls);

    QDrag *drag = new QDrag(this);
    drag->setMimeData(mimeData);
    drag->exec(Qt::CopyAction | Qt::LinkAction);
}

void XdgCachedMenu::onAboutToShow()
{
    Q_FOREACH(QAction* action, actions())
    {
        if(action->inherits("XdgCachedMenuAction"))
        {
            static_cast<XdgCachedMenuAction*>(action)->updateIcon();

            // this seems to cause some incorrect menu behaviour.
            // qApp->processEvents();
        }
    }
}
<|endoftext|>


<commit_before>/*
* Copyright (C) 2008-2011 J-P Nurmi <jpnurmi@gmail.com>
*
* This library is free software; you can 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 of the License, or (at your
* option) any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
* License for more details.
*/

#include <QtDeclarative>
#include <IrcSession>
#include <IrcMessage>
#include <IrcUtil>
#include <Irc>

QML_DECLARE_TYPE(IrcSession)
QML_DECLARE_TYPE(IrcMessage)
QML_DECLARE_TYPE(IrcInviteMessage)
QML_DECLARE_TYPE(IrcJoinMessage)
QML_DECLARE_TYPE(IrcKickMessage)
QML_DECLARE_TYPE(IrcModeMessage)
QML_DECLARE_TYPE(IrcNickMessage)
QML_DECLARE_TYPE(IrcNoticeMessage)
QML_DECLARE_TYPE(IrcNumericMessage)
QML_DECLARE_TYPE(IrcPartMessage)
QML_DECLARE_TYPE(IrcPrivateMessage)
QML_DECLARE_TYPE(IrcQuitMessage)
QML_DECLARE_TYPE(IrcTopicMessage)

class DeclarativeIrc : public Irc
{
    Q_OBJECT

public:
    explicit DeclarativeIrc(QObject* parent = 0) : Irc(parent) { }

    Q_INVOKABLE IrcMessage* createMessage(const QString& command, QObject* parent = 0)
    {
        return IrcMessage::create(command, parent);
    }

    Q_INVOKABLE QString nickFromPrefix(const QString& prefix)
    {
        return IrcUtil::nickFromTarget(prefix);
    }
};

QML_DECLARE_TYPE(DeclarativeIrc)

class IrcPlugin : public QDeclarativeExtensionPlugin
{
    Q_OBJECT

public:
    virtual void initializeEngine(QDeclarativeEngine* engine, const char* uri)
    {
        QDeclarativeExtensionPlugin::initializeEngine(engine, uri);
        QDeclarativeContext *context = engine->rootContext();
        DeclarativeIrc* irc = new DeclarativeIrc(context);
        context->setContextProperty("Irc", irc);
    }

    void registerTypes(const char *uri)
    {
        qmlRegisterType<IrcSession>(uri, 1, 0, "IrcSession");
        qmlRegisterType<IrcMessage>(uri, 1, 0, "IrcMessage");
        qmlRegisterType<IrcJoinMessage>(uri, 1, 0, "IrcJoinMessage");
    }
};

#include "ircplugin.moc"

Q_EXPORT_PLUGIN2(ircplugin, IrcPlugin);
<commit_msg>Working on the declarative plugin...<commit_after>/*
* Copyright (C) 2008-2011 J-P Nurmi <jpnurmi@gmail.com>
*
* This library is free software; you can 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 of the License, or (at your
* option) any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
* License for more details.
*/

#include <QtDeclarative>
#include <IrcSession>
#include <IrcMessage>
#include <IrcPrefix>
#include <IrcUtil>
#include <Irc>

QML_DECLARE_TYPE(IrcSession)
QML_DECLARE_TYPE(IrcMessage)
QML_DECLARE_TYPE(IrcInviteMessage)
QML_DECLARE_TYPE(IrcJoinMessage)
QML_DECLARE_TYPE(IrcKickMessage)
QML_DECLARE_TYPE(IrcModeMessage)
QML_DECLARE_TYPE(IrcNickMessage)
QML_DECLARE_TYPE(IrcNoticeMessage)
QML_DECLARE_TYPE(IrcNumericMessage)
QML_DECLARE_TYPE(IrcPartMessage)
QML_DECLARE_TYPE(IrcPrivateMessage)
QML_DECLARE_TYPE(IrcQuitMessage)
QML_DECLARE_TYPE(IrcTopicMessage)

class DeclarativeIrc : public Irc
{
    Q_OBJECT

public:
    explicit DeclarativeIrc(QObject* parent = 0) : Irc(parent) { }

    Q_INVOKABLE IrcMessage* createMessage(const QString& command, QObject* parent = 0)
    {
        return IrcMessage::create(command, parent);
    }

    Q_INVOKABLE QString nick(const QString& prefix)
    {
        return IrcPrefix(prefix).nick();
    }

    Q_INVOKABLE QString user(const QString& prefix)
    {
        return IrcPrefix(prefix).user();
    }

    Q_INVOKABLE QString host(const QString& prefix)
    {
        return IrcPrefix(prefix).host();
    }
};

QML_DECLARE_TYPE(DeclarativeIrc)

class IrcPlugin : public QDeclarativeExtensionPlugin
{
    Q_OBJECT

public:
    virtual void initializeEngine(QDeclarativeEngine* engine, const char* uri)
    {
        QDeclarativeExtensionPlugin::initializeEngine(engine, uri);
        QDeclarativeContext *context = engine->rootContext();
        DeclarativeIrc* irc = new DeclarativeIrc(context);
        context->setContextProperty("Irc", irc);
    }

    void registerTypes(const char *uri)
    {
        qmlRegisterType<IrcSession>(uri, 1, 0, "IrcSession");
        qmlRegisterType<IrcMessage>(uri, 1, 0, "IrcMessage");
        qmlRegisterType<IrcInviteMessage>(uri, 1, 0, "IrcInviteMessage");
        qmlRegisterType<IrcJoinMessage>(uri, 1, 0, "IrcJoinMessage");
        qmlRegisterType<IrcKickMessage>(uri, 1, 0, "IrcKickMessage");
        qmlRegisterType<IrcModeMessage>(uri, 1, 0, "IrcModeMessage");
        qmlRegisterType<IrcNickMessage>(uri, 1, 0, "IrcNickMessage");
        qmlRegisterType<IrcNoticeMessage>(uri, 1, 0, "IrcNoticeMessage");
        qmlRegisterType<IrcNumericMessage>(uri, 1, 0, "IrcNumericMessage");
        qmlRegisterType<IrcPartMessage>(uri, 1, 0, "IrcPartMessage");
        qmlRegisterType<IrcPrivateMessage>(uri, 1, 0, "IrcPrivateMessage");
        qmlRegisterType<IrcQuitMessage>(uri, 1, 0, "IrcQuitMessage");
        qmlRegisterType<IrcTopicMessage>(uri, 1, 0, "IrcTopicMessage");
    }
};

#include "ircplugin.moc"

Q_EXPORT_PLUGIN2(ircplugin, IrcPlugin);
<|endoftext|>


<commit_before>/*
    Copyright (C) 2001 by Martin Geisse <mgeisse@gmx.net>

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

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public
    License along with this library; if not, write to the Free
    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include "cssysdef.h"
#include "iutil/eventh.h"
#include "iutil/comp.h"
#include "iutil/objreg.h"
#include "imesh/mdlconv.h"
#include "cstool/mdldata.h"
#include "csutil/datastrm.h"
#include "csutil/csendian.h"
#include "csutil/csstring.h"
#include "csutil/nobjvec.h"
#include "csutil/parray.h"
#include "csutil/util.h"
#include <ctype.h>

// upper bound onsize of biggest data element (vertex, polygon) in an MD2 file
static int const MAX_DATAELEMENT_SIZE = 8192;

// size of various MD2 elements
static int const SIZEOF_MD2SHORT = 2;
static int const SIZEOF_MD2LONG = 4;
static int const SIZEOF_MD2FLOAT = 4;
static int const SIZEOF_MD2SKINNAME = 64;
static int const SIZEOF_MD2FRAMENAME = 16;
static int const SIZEOF_MD2HEADER = 15*SIZEOF_MD2LONG;

static const float SCALE_FACTOR = 0.025f;
static const float FRAME_DELAY = 0.1f;

typedef csPDelArray<csString> csStringVector;

struct csMD2Header
{
  // width and height of skin texture in pixels
  long SkinWidth, SkinHeight;
  // size of each frame int the sprite, in pixels
  long FrameSize;
  // number of skins, vertices, texels, triangles, glcmds(?), frames
  long SkinCount, VertexCount, TexelCount, TriangleCount, glcmds, FrameCount;
  // offset of the skin information in the file
  long SkinOffset;
  // offset of the texel information in the file
  long TexelOffset;
  // offset of the triangle information in the file
  long TriangleOffset;
  // offset of the frame information in the file
  long FramesOffset;
  // offset of the GL commands information in the file
  long GLCommandsOffset;
  // total file size
  long FileSize;
};

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

class csModelConverterMD2 : public iModelConverter
{
private:
  csModelConverterFormat FormatInfo;

public:
  SCF_DECLARE_IBASE;

  /// constructor
  csModelConverterMD2 (iBase *pBase);

  /// destructor
  virtual ~csModelConverterMD2 ();

  bool Initialize (iObjectRegistry *object_reg);
  virtual size_t GetFormatCount();
  virtual const csModelConverterFormat *GetFormat( size_t idx );
  virtual csPtr<iModelData> Load( uint8* Buffer, size_t size );
  virtual csPtr<iDataBuffer> Save( iModelData*, const char *format );

  struct Component : public iComponent
  {
    SCF_DECLARE_EMBEDDED_IBASE (csModelConverterMD2);
    virtual bool Initialize (iObjectRegistry *object_reg)
    {
      return scfParent->Initialize (object_reg);
    }
  } scfiComponent;
};

SCF_IMPLEMENT_IBASE (csModelConverterMD2)
  SCF_IMPLEMENTS_INTERFACE (iModelConverter)
  SCF_IMPLEMENTS_EMBEDDED_INTERFACE (iComponent)
SCF_IMPLEMENT_IBASE_END

SCF_IMPLEMENT_EMBEDDED_IBASE (csModelConverterMD2::Component)
  SCF_IMPLEMENTS_INTERFACE (iComponent)
SCF_IMPLEMENT_IBASE_END

SCF_IMPLEMENT_FACTORY (csModelConverterMD2)

CS_IMPLEMENT_PLUGIN

csModelConverterMD2::csModelConverterMD2 (iBase *pBase)
{
  SCF_CONSTRUCT_IBASE (pBase);
  SCF_CONSTRUCT_EMBEDDED_IBASE (scfiComponent);

  FormatInfo.Name = "md2";
  FormatInfo.CanLoad = true;
  FormatInfo.CanSave = false;
}

csModelConverterMD2::~csModelConverterMD2 ()
{
  SCF_DESTRUCT_EMBEDDED_IBASE (scfiComponent);
  SCF_DESTRUCT_IBASE ();
}

bool csModelConverterMD2::Initialize (iObjectRegistry *)
{
  return true;
}

size_t csModelConverterMD2::GetFormatCount ()
{
  return 1;
}

const csModelConverterFormat *csModelConverterMD2::GetFormat (size_t idx)
{
  return (idx == 0) ? &FormatInfo : 0;
}

/*
  Purpose:

    csModelConverterMD2::Load() reads a Quake2 MD2 model file.

  Examples:

  Modified:

    13 July 1999 Gary Haussmann

  Author:

    John Burkardt

  Modified by Martin Geisse to work with the new converter system.
*/

static bool CheckMD2Version (csDataStream &in)
{
  // Read in header and check for a correct file.  The
  // header consists of two longs, containing
  // the magic identifiter 'IDP2' as the first long,
  // followed by a version number (8)
  uint32 FileID, FileVersion;
  in.ReadUInt32 (FileID);
  in.ReadUInt32 (FileVersion);
  FileID = csLittleEndianLong (FileID);
  FileVersion = csLittleEndianLong (FileVersion);

  if (FileID != ( ('2'<<24)+('P'<<16)+('D'<<8)+'I' ) )
    return false;

  if (FileVersion != 8)
    return false;

  return true;
}

#define CS_MD2_READ(num,name)						\
  hdr->name = csGetLittleEndianLong (buf + num * SIZEOF_MD2LONG);

static void ReadMD2Header (csMD2Header *hdr, csDataStream *in)
{
  char buf [SIZEOF_MD2HEADER];
  in->Read (buf, SIZEOF_MD2HEADER);

  CS_MD2_READ (0, SkinWidth);
  CS_MD2_READ (1, SkinHeight);
  CS_MD2_READ (2, FrameSize);
  CS_MD2_READ (3, SkinCount);
  CS_MD2_READ (4, VertexCount);
  CS_MD2_READ (5, TexelCount);
  CS_MD2_READ (6, TriangleCount);
  CS_MD2_READ (7, glcmds);
  CS_MD2_READ (8, FrameCount);
  CS_MD2_READ (9, SkinOffset);
  CS_MD2_READ (10, TexelOffset);
  CS_MD2_READ (11, TriangleOffset);
  CS_MD2_READ (12, FramesOffset);
  CS_MD2_READ (13, GLCommandsOffset);
  CS_MD2_READ (14, FileSize);
}

#undef CS_MD2_READ

static void extractActionName (const char * str, char * act)
{
  for (size_t i = 0; str[i] != '\0' && !isdigit(str[i]); i++)
    act[i] = str[i];
  act[i] = 0;
}

csPtr<iModelData> csModelConverterMD2::Load (uint8 *Buffer, size_t Size)
{
  // prepare input buffer
  csDataStream in (Buffer, Size, false);
  uint8 readbuffer[MAX_DATAELEMENT_SIZE];
  int i,j;

  // check for the correct version
  if (!CheckMD2Version (in))
    return 0;

  // build the object framework
  iModelData *Scene = new csModelData ();
  iModelDataObject *Object = new csModelDataObject ();
  Scene->QueryObject ()->ObjAdd (Object->QueryObject ());

  // read MD2 header
  csMD2Header Header;
  ReadMD2Header (&Header, &in);

  // read in texmap (skin) names - skin names are 64 bytes long
  // Unused
  csStringVector SkinNames;
  in.SetPosition (Header.SkinOffset);
  for (i = 0; i < Header.SkinCount; i++)
  {
    char name[SIZEOF_MD2SKINNAME];
    in.Read (name, SIZEOF_MD2SKINNAME);
    csString *s = new csString (name);
    SkinNames.Push (s);
  }

  // read in skin data. This contains texture map coordinates for each
  // vertex; the spatial location of each vertex varies with each
  // frame, and is stored elsewhere, in the frame data section.
  // The only data we read here
  // are the static texture map (uv) locations for each vertex!
  csVector2 *Texels = new csVector2 [Header.TexelCount];
  in.SetPosition (Header.TexelOffset);
  for (i = 0; i < Header.TexelCount; i++)
  {
    in.Read (readbuffer, SIZEOF_MD2SHORT*2);
    Texels [i].Set (csGetLittleEndianShort(readbuffer)/(float)Header.SkinWidth,
                    csGetLittleEndianShort(readbuffer+2)/(float)Header.SkinHeight);
  }

  // next we read in the triangle connectivity data.  This data describes
  // each triangle as three indices, referring to three numbered vertices.
  // This data is, like the skin texture coords, independent of frame number.
  // There are actually two set of indices in the original quake file;
  // one indexes into the xyz coordinate table, the other indexes into
  // the uv texture coordinate table.
  in.SetPosition (Header.TriangleOffset);
  for (i = 0; i < Header.TriangleCount; i++)
  {
    iModelDataPolygon *Polygon = new csModelDataPolygon ();
    Object->QueryObject ()->ObjAdd (Polygon->QueryObject ());

    in.Read (readbuffer, SIZEOF_MD2SHORT*6);
    for (j = 0; j < 3; j++)
    {
      short xyzindex = csGetLittleEndianShort (readbuffer + j * SIZEOF_MD2SHORT);
      short texindex = csGetLittleEndianShort (readbuffer + (j+3) * SIZEOF_MD2SHORT);
      Polygon->AddVertex (xyzindex, 0, 0, texindex);
    }

    Polygon->DecRef ();
  }

  // now we read in the frames.  The number of frames is stored in 'num_object'

  iModelDataVertices *DefaultFrame = 0;

  char currAction [256];
  memset (currAction, 0, 256);
  csRef<iModelDataAction> action;
  float time = 0;

  for (i = 0; i < Header.FrameCount; i++, time += FRAME_DELAY)
  {
    csVector3 scale, translate;
    // read in scale and translate info
    in.Read (&scale, SIZEOF_MD2FLOAT*3);
    in.Read (&translate, SIZEOF_MD2FLOAT*3);
    for (j = 0; j < 3; j++)
    {
      scale[j] = csConvertEndian (scale[j]);
      translate[j] = csConvertEndian (translate[j]);
    }
    scale *= SCALE_FACTOR;
    translate *= SCALE_FACTOR;

    // name of this frame
    char FrameName [SIZEOF_MD2FRAMENAME+1];
    char ActionName [SIZEOF_MD2FRAMENAME+1];
    in.Read (FrameName, SIZEOF_MD2FRAMENAME);
    FrameName [SIZEOF_MD2FRAMENAME] = 0;
    extractActionName (FrameName, ActionName);
    if (strcmp (ActionName, currAction))
    {
      memcpy (currAction, ActionName, strlen (ActionName)+1);
      action = csPtr<iModelDataAction> (new csModelDataAction ());
      action->QueryObject ()->SetName (currAction);
      Object->QueryObject ()->ObjAdd (action->QueryObject ());
      time = FRAME_DELAY;
    }

    // read in vertex coordinate data for the frame
    in.Read (readbuffer, 4*Header.VertexCount);

    iModelDataVertices *VertexFrame = new csModelDataVertices ();
    action->AddFrame (time, VertexFrame->QueryObject ());
    VertexFrame->QueryObject ()->SetName (FrameName);
    if (!DefaultFrame)
       DefaultFrame = VertexFrame;

    for (j = 0; j < Header.TexelCount; j++)
    {
      VertexFrame->AddTexel (Texels [j]);
    }

    for (j = 0; j < Header.VertexCount; j++)
    {
      const uint8 * buf = readbuffer + j*4;
      csVector3 v (buf [0], buf [1], buf [2]);
      for (int k = 0; k < 3; k++)
        v[k] = v[k] * scale[k] + translate[k];
      // swap y and z
      float t = v.y;
      v.y = v.z;
      v.z = t;

      VertexFrame->AddVertex (v);
    }
    VertexFrame->AddColor (csColor (1, 1, 1));
    VertexFrame->AddNormal (csVector3 (1, 0, 0));
    VertexFrame->DecRef ();
  }
  Object->SetDefaultVertices (DefaultFrame);
  Object->DecRef ();
  delete Texels;
  return csPtr<iModelData> (Scene);
}

csPtr<iDataBuffer> csModelConverterMD2::Save (iModelData *, const char *Format)
{
  if (strcasecmp (Format, "md2"))
    return 0;

  return 0;
}
<commit_msg>Fix compilation error.<commit_after>/*
    Copyright (C) 2001 by Martin Geisse <mgeisse@gmx.net>

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

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public
    License along with this library; if not, write to the Free
    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include "cssysdef.h"
#include "iutil/eventh.h"
#include "iutil/comp.h"
#include "iutil/objreg.h"
#include "imesh/mdlconv.h"
#include "cstool/mdldata.h"
#include "csutil/datastrm.h"
#include "csutil/csendian.h"
#include "csutil/csstring.h"
#include "csutil/nobjvec.h"
#include "csutil/parray.h"
#include "csutil/util.h"
#include <ctype.h>

// upper bound onsize of biggest data element (vertex, polygon) in an MD2 file
static int const MAX_DATAELEMENT_SIZE = 8192;

// size of various MD2 elements
static int const SIZEOF_MD2SHORT = 2;
static int const SIZEOF_MD2LONG = 4;
static int const SIZEOF_MD2FLOAT = 4;
static int const SIZEOF_MD2SKINNAME = 64;
static int const SIZEOF_MD2FRAMENAME = 16;
static int const SIZEOF_MD2HEADER = 15*SIZEOF_MD2LONG;

static const float SCALE_FACTOR = 0.025f;
static const float FRAME_DELAY = 0.1f;

typedef csPDelArray<csString> csStringVector;

struct csMD2Header
{
  // width and height of skin texture in pixels
  long SkinWidth, SkinHeight;
  // size of each frame int the sprite, in pixels
  long FrameSize;
  // number of skins, vertices, texels, triangles, glcmds(?), frames
  long SkinCount, VertexCount, TexelCount, TriangleCount, glcmds, FrameCount;
  // offset of the skin information in the file
  long SkinOffset;
  // offset of the texel information in the file
  long TexelOffset;
  // offset of the triangle information in the file
  long TriangleOffset;
  // offset of the frame information in the file
  long FramesOffset;
  // offset of the GL commands information in the file
  long GLCommandsOffset;
  // total file size
  long FileSize;
};

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

class csModelConverterMD2 : public iModelConverter
{
private:
  csModelConverterFormat FormatInfo;

public:
  SCF_DECLARE_IBASE;

  /// constructor
  csModelConverterMD2 (iBase *pBase);

  /// destructor
  virtual ~csModelConverterMD2 ();

  bool Initialize (iObjectRegistry *object_reg);
  virtual size_t GetFormatCount();
  virtual const csModelConverterFormat *GetFormat( size_t idx );
  virtual csPtr<iModelData> Load( uint8* Buffer, size_t size );
  virtual csPtr<iDataBuffer> Save( iModelData*, const char *format );

  struct Component : public iComponent
  {
    SCF_DECLARE_EMBEDDED_IBASE (csModelConverterMD2);
    virtual bool Initialize (iObjectRegistry *object_reg)
    {
      return scfParent->Initialize (object_reg);
    }
  } scfiComponent;
};

SCF_IMPLEMENT_IBASE (csModelConverterMD2)
  SCF_IMPLEMENTS_INTERFACE (iModelConverter)
  SCF_IMPLEMENTS_EMBEDDED_INTERFACE (iComponent)
SCF_IMPLEMENT_IBASE_END

SCF_IMPLEMENT_EMBEDDED_IBASE (csModelConverterMD2::Component)
  SCF_IMPLEMENTS_INTERFACE (iComponent)
SCF_IMPLEMENT_IBASE_END

SCF_IMPLEMENT_FACTORY (csModelConverterMD2)

CS_IMPLEMENT_PLUGIN

csModelConverterMD2::csModelConverterMD2 (iBase *pBase)
{
  SCF_CONSTRUCT_IBASE (pBase);
  SCF_CONSTRUCT_EMBEDDED_IBASE (scfiComponent);

  FormatInfo.Name = "md2";
  FormatInfo.CanLoad = true;
  FormatInfo.CanSave = false;
}

csModelConverterMD2::~csModelConverterMD2 ()
{
  SCF_DESTRUCT_EMBEDDED_IBASE (scfiComponent);
  SCF_DESTRUCT_IBASE ();
}

bool csModelConverterMD2::Initialize (iObjectRegistry *)
{
  return true;
}

size_t csModelConverterMD2::GetFormatCount ()
{
  return 1;
}

const csModelConverterFormat *csModelConverterMD2::GetFormat (size_t idx)
{
  return (idx == 0) ? &FormatInfo : 0;
}

/*
  Purpose:

    csModelConverterMD2::Load() reads a Quake2 MD2 model file.

  Examples:

  Modified:

    13 July 1999 Gary Haussmann

  Author:

    John Burkardt

  Modified by Martin Geisse to work with the new converter system.
*/

static bool CheckMD2Version (csDataStream &in)
{
  // Read in header and check for a correct file.  The
  // header consists of two longs, containing
  // the magic identifiter 'IDP2' as the first long,
  // followed by a version number (8)
  uint32 FileID, FileVersion;
  in.ReadUInt32 (FileID);
  in.ReadUInt32 (FileVersion);
  FileID = csLittleEndianLong (FileID);
  FileVersion = csLittleEndianLong (FileVersion);

  if (FileID != ( ('2'<<24)+('P'<<16)+('D'<<8)+'I' ) )
    return false;

  if (FileVersion != 8)
    return false;

  return true;
}

#define CS_MD2_READ(num,name)						\
  hdr->name = csGetLittleEndianLong (buf + num * SIZEOF_MD2LONG);

static void ReadMD2Header (csMD2Header *hdr, csDataStream *in)
{
  char buf [SIZEOF_MD2HEADER];
  in->Read (buf, SIZEOF_MD2HEADER);

  CS_MD2_READ (0, SkinWidth);
  CS_MD2_READ (1, SkinHeight);
  CS_MD2_READ (2, FrameSize);
  CS_MD2_READ (3, SkinCount);
  CS_MD2_READ (4, VertexCount);
  CS_MD2_READ (5, TexelCount);
  CS_MD2_READ (6, TriangleCount);
  CS_MD2_READ (7, glcmds);
  CS_MD2_READ (8, FrameCount);
  CS_MD2_READ (9, SkinOffset);
  CS_MD2_READ (10, TexelOffset);
  CS_MD2_READ (11, TriangleOffset);
  CS_MD2_READ (12, FramesOffset);
  CS_MD2_READ (13, GLCommandsOffset);
  CS_MD2_READ (14, FileSize);
}

#undef CS_MD2_READ

static void extractActionName (const char * str, char * act)
{
  size_t i;
  for (i = 0; str[i] != '\0' && !isdigit(str[i]); i++)
    act[i] = str[i];
  act[i] = 0;
}

csPtr<iModelData> csModelConverterMD2::Load (uint8 *Buffer, size_t Size)
{
  // prepare input buffer
  csDataStream in (Buffer, Size, false);
  uint8 readbuffer[MAX_DATAELEMENT_SIZE];
  int i,j;

  // check for the correct version
  if (!CheckMD2Version (in))
    return 0;

  // build the object framework
  iModelData *Scene = new csModelData ();
  iModelDataObject *Object = new csModelDataObject ();
  Scene->QueryObject ()->ObjAdd (Object->QueryObject ());

  // read MD2 header
  csMD2Header Header;
  ReadMD2Header (&Header, &in);

  // read in texmap (skin) names - skin names are 64 bytes long
  // Unused
  csStringVector SkinNames;
  in.SetPosition (Header.SkinOffset);
  for (i = 0; i < Header.SkinCount; i++)
  {
    char name[SIZEOF_MD2SKINNAME];
    in.Read (name, SIZEOF_MD2SKINNAME);
    csString *s = new csString (name);
    SkinNames.Push (s);
  }

  // read in skin data. This contains texture map coordinates for each
  // vertex; the spatial location of each vertex varies with each
  // frame, and is stored elsewhere, in the frame data section.
  // The only data we read here
  // are the static texture map (uv) locations for each vertex!
  csVector2 *Texels = new csVector2 [Header.TexelCount];
  in.SetPosition (Header.TexelOffset);
  for (i = 0; i < Header.TexelCount; i++)
  {
    in.Read (readbuffer, SIZEOF_MD2SHORT*2);
    Texels [i].Set (csGetLittleEndianShort(readbuffer)/(float)Header.SkinWidth,
                    csGetLittleEndianShort(readbuffer+2)/(float)Header.SkinHeight);
  }

  // next we read in the triangle connectivity data.  This data describes
  // each triangle as three indices, referring to three numbered vertices.
  // This data is, like the skin texture coords, independent of frame number.
  // There are actually two set of indices in the original quake file;
  // one indexes into the xyz coordinate table, the other indexes into
  // the uv texture coordinate table.
  in.SetPosition (Header.TriangleOffset);
  for (i = 0; i < Header.TriangleCount; i++)
  {
    iModelDataPolygon *Polygon = new csModelDataPolygon ();
    Object->QueryObject ()->ObjAdd (Polygon->QueryObject ());

    in.Read (readbuffer, SIZEOF_MD2SHORT*6);
    for (j = 0; j < 3; j++)
    {
      short xyzindex = csGetLittleEndianShort (readbuffer + j * SIZEOF_MD2SHORT);
      short texindex = csGetLittleEndianShort (readbuffer + (j+3) * SIZEOF_MD2SHORT);
      Polygon->AddVertex (xyzindex, 0, 0, texindex);
    }

    Polygon->DecRef ();
  }

  // now we read in the frames.  The number of frames is stored in 'num_object'

  iModelDataVertices *DefaultFrame = 0;

  char currAction [256];
  memset (currAction, 0, 256);
  csRef<iModelDataAction> action;
  float time = 0;

  for (i = 0; i < Header.FrameCount; i++, time += FRAME_DELAY)
  {
    csVector3 scale, translate;
    // read in scale and translate info
    in.Read (&scale, SIZEOF_MD2FLOAT*3);
    in.Read (&translate, SIZEOF_MD2FLOAT*3);
    for (j = 0; j < 3; j++)
    {
      scale[j] = csConvertEndian (scale[j]);
      translate[j] = csConvertEndian (translate[j]);
    }
    scale *= SCALE_FACTOR;
    translate *= SCALE_FACTOR;

    // name of this frame
    char FrameName [SIZEOF_MD2FRAMENAME+1];
    char ActionName [SIZEOF_MD2FRAMENAME+1];
    in.Read (FrameName, SIZEOF_MD2FRAMENAME);
    FrameName [SIZEOF_MD2FRAMENAME] = 0;
    extractActionName (FrameName, ActionName);
    if (strcmp (ActionName, currAction))
    {
      memcpy (currAction, ActionName, strlen (ActionName)+1);
      action = csPtr<iModelDataAction> (new csModelDataAction ());
      action->QueryObject ()->SetName (currAction);
      Object->QueryObject ()->ObjAdd (action->QueryObject ());
      time = FRAME_DELAY;
    }

    // read in vertex coordinate data for the frame
    in.Read (readbuffer, 4*Header.VertexCount);

    iModelDataVertices *VertexFrame = new csModelDataVertices ();
    action->AddFrame (time, VertexFrame->QueryObject ());
    VertexFrame->QueryObject ()->SetName (FrameName);
    if (!DefaultFrame)
       DefaultFrame = VertexFrame;

    for (j = 0; j < Header.TexelCount; j++)
    {
      VertexFrame->AddTexel (Texels [j]);
    }

    for (j = 0; j < Header.VertexCount; j++)
    {
      const uint8 * buf = readbuffer + j*4;
      csVector3 v (buf [0], buf [1], buf [2]);
      for (int k = 0; k < 3; k++)
        v[k] = v[k] * scale[k] + translate[k];
      // swap y and z
      float t = v.y;
      v.y = v.z;
      v.z = t;

      VertexFrame->AddVertex (v);
    }
    VertexFrame->AddColor (csColor (1, 1, 1));
    VertexFrame->AddNormal (csVector3 (1, 0, 0));
    VertexFrame->DecRef ();
  }
  Object->SetDefaultVertices (DefaultFrame);
  Object->DecRef ();
  delete Texels;
  return csPtr<iModelData> (Scene);
}

csPtr<iDataBuffer> csModelConverterMD2::Save (iModelData *, const char *Format)
{
  if (strcasecmp (Format, "md2"))
    return 0;

  return 0;
}
<|endoftext|>