<commit_before>/* * This file is part of Maliit framework *
 *
 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
 * All rights reserved.
 *
 * Contact: maliit-discuss@lists.maliit.org
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License version 2.1 as published by the Free Software Foundation
 * and appearing in the file LICENSE.LGPL included in the packaging
 * of this file.
 */

#include "minputcontextconnection.h"

#include <QKeyEvent>

namespace {
    // attribute names for updateWidgetInformation() map
    const char * const FocusStateAttribute = "focusState";
    const char * const ContentTypeAttribute = "contentType";
    const char * const CorrectionAttribute = "correctionEnabled";
    const char * const PredictionAttribute = "predictionEnabled";
    const char * const AutoCapitalizationAttribute = "autocapitalizationEnabled";
    const char * const SurroundingTextAttribute = "surroundingText";
    const char * const AnchorPositionAttribute = "anchorPosition";
    const char * const CursorPositionAttribute = "cursorPosition";
    const char * const HasSelectionAttribute = "hasSelection";
    const char * const InputMethodModeAttribute = "inputMethodMode";
    const char * const WinId = "winId";
    const char * const CursorRectAttribute = "cursorRectangle";
    const char * const HiddenTextAttribute = "hiddenText";
    const char * const PreeditClickPosAttribute = "preeditClickPos";
}

class MInputContextConnectionPrivate
{
public:
    MInputContextConnectionPrivate();
    ~MInputContextConnectionPrivate();
};

MInputContextConnectionPrivate::MInputContextConnectionPrivate()
{
    // nothing
}

MInputContextConnectionPrivate::~MInputContextConnectionPrivate()
{
    // nothing
}

////////////////////////
// actual class

MInputContextConnection::MInputContextConnection(QObject *parent)
    : activeConnection(0)
    , d(new MInputContextConnectionPrivate)
    , lastOrientation(0)
    , mGlobalCorrectionEnabled(false)
    , mRedirectionEnabled(false)
    , mDetectableAutoRepeat(false)
{
    Q_UNUSED(parent);
}

MInputContextConnection::~MInputContextConnection()
{
    delete d;
}

/* Accessors to widgetState */
bool MInputContextConnection::focusState(bool &valid)
{
    QVariant focusStateVariant = mWidgetState[FocusStateAttribute];
    valid = focusStateVariant.isValid();
    return focusStateVariant.toBool();
}

int MInputContextConnection::contentType(bool &valid)
{
    QVariant contentTypeVariant = mWidgetState[ContentTypeAttribute];
    return contentTypeVariant.toInt(&valid);
}

bool MInputContextConnection::correctionEnabled(bool &valid)
{
    QVariant correctionVariant = mWidgetState[CorrectionAttribute];
    valid = correctionVariant.isValid();
    return correctionVariant.toBool();
}

bool MInputContextConnection::predictionEnabled(bool &valid)
{
    QVariant predictionVariant = mWidgetState[PredictionAttribute];
    valid = predictionVariant.isValid();
    return predictionVariant.toBool();
}

bool MInputContextConnection::autoCapitalizationEnabled(bool &valid)
{
    QVariant capitalizationVariant = mWidgetState[AutoCapitalizationAttribute];
    valid = capitalizationVariant.isValid();
    return capitalizationVariant.toBool();
}

QRect MInputContextConnection::cursorRectangle(bool &valid)
{
    QVariant cursorRectVariant = mWidgetState[CursorRectAttribute];
    valid = cursorRectVariant.isValid();
    return cursorRectVariant.toRect();
}

bool MInputContextConnection::hiddenText(bool &valid)
{
    QVariant hiddenTextVariant = mWidgetState[HiddenTextAttribute];
    valid = hiddenTextVariant.isValid();
    return hiddenTextVariant.toBool();
}

bool MInputContextConnection::surroundingText(QString &text, int &cursorPosition)
{
    QVariant textVariant = mWidgetState[SurroundingTextAttribute];
    QVariant posVariant = mWidgetState[CursorPositionAttribute];

    if (textVariant.isValid() && posVariant.isValid()) {
        text = textVariant.toString();
        cursorPosition = posVariant.toInt();
        return true;
    }

    return false;
}

bool MInputContextConnection::hasSelection(bool &valid)
{
    QVariant selectionVariant = mWidgetState[HasSelectionAttribute];
    valid = selectionVariant.isValid();
    return selectionVariant.toBool();
}

int MInputContextConnection::inputMethodMode(bool &valid)
{
    QVariant modeVariant = mWidgetState[InputMethodModeAttribute];
    return modeVariant.toInt(&valid);
}

QRect MInputContextConnection::preeditRectangle(bool &valid)
{
    valid = false;
    return QRect();
}

WId MInputContextConnection::winId()
{
#ifdef Q_WS_WIN
    WId result = 0;
    return result;
#else
    QVariant winIdVariant = mWidgetState[WinId];
    // after transfer by dbus type can change
    switch (winIdVariant.type()) {
    case QVariant::UInt:
        if (sizeof(uint) >= sizeof(WId))
            return winIdVariant.toUInt();
        break;
    case QVariant::ULongLong:
        if (sizeof(qulonglong) >= sizeof(WId))
            return winIdVariant.toULongLong();
        break;
    default:
        if (winIdVariant.canConvert<WId>())
            return winIdVariant.value<WId>();
    }
    return 0;
#endif
}

int MInputContextConnection::anchorPosition(bool &valid)
{
    QVariant posVariant = mWidgetState[AnchorPositionAttribute];
    valid = posVariant.isValid();
    return posVariant.toInt();
}

int MInputContextConnection::preeditClickPos(bool &valid) const
{
    QVariant selectionVariant = mWidgetState[PreeditClickPosAttribute];
    valid = selectionVariant.isValid();
    return selectionVariant.toInt();
}

/* End accessors to widget state */

/* Handlers for inbound communication */
void MInputContextConnection::showInputMethod(unsigned int connectionId)
{
    if (activeConnection != connectionId)
        return;

    Q_EMIT showInputMethodRequest();
}

void MInputContextConnection::hideInputMethod(unsigned int connectionId)
{
    // Only allow this call for current active connection.
    if (activeConnection != connectionId)
        return;

    Q_EMIT hideInputMethodRequest();
}

void MInputContextConnection::mouseClickedOnPreedit(unsigned int connectionId,
                                                            const QPoint &pos, const QRect &preeditRect)
{
    if (activeConnection != connectionId)
        return;

    Q_EMIT mouseClickedOnPreedit(pos, preeditRect);
}

void MInputContextConnection::setPreedit(unsigned int connectionId,
                                                 const QString &text, int cursorPos)
{
    if (activeConnection != connectionId)
        return;

    preedit = text;

    Q_EMIT preeditChanged(text, cursorPos);
}

void MInputContextConnection::reset(unsigned int connectionId)
{
    if (activeConnection != connectionId)
        return;

    preedit.clear();

    Q_EMIT resetInputMethodRequest();

    if (!preedit.isEmpty()) {
        qWarning("Preedit set from InputMethod::reset()!");
        preedit.clear();
    }
}

void
MInputContextConnection::updateWidgetInformation(
    unsigned int connectionId, const QMap<QString, QVariant> &stateInfo,
    bool handleFocusChange)
{
    QMap<QString, QVariant> oldState = mWidgetState;

    mWidgetState = stateInfo;

#ifndef Q_WS_WIN
    if (handleFocusChange) {
        Q_EMIT focusChanged(winId());
    }
#endif

    Q_EMIT widgetStateChanged(connectionId, mWidgetState, oldState, handleFocusChange);
}

void
MInputContextConnection::receivedAppOrientationAboutToChange(unsigned int connectionId,
                                                                     int angle)
{
    if (activeConnection != connectionId)
        return;

    // Needs to be passed to the MImRotationAnimation listening
    // to this signal first before the plugins. This ensures
    // that the rotation animation can be painted sufficiently early.
    Q_EMIT contentOrientationAboutToChange(angle);

    Q_EMIT contentOrientationAboutToChangeCompleted(angle);
}

void MInputContextConnection::receivedAppOrientationChanged(unsigned int connectionId,
                                                                    int angle)
{
    if (activeConnection != connectionId)
        return;

    // Handle orientation changes through MImRotationAnimation with priority.
    // That's needed for getting the correct rotated pixmap buffers.
    Q_EMIT contentOrientationChanged(angle);

    Q_EMIT contentOrientationChangeCompleted(angle);
}

void MInputContextConnection::setCopyPasteState(unsigned int connectionId,
                                                        bool copyAvailable, bool pasteAvailable)
{
    if (activeConnection != connectionId)
        return;

    Q_EMIT copyPasteStateChanged(copyAvailable, pasteAvailable);
}

void MInputContextConnection::processKeyEvent(
    unsigned int connectionId, QEvent::Type keyType, Qt::Key keyCode,
    Qt::KeyboardModifiers modifiers, const QString &text, bool autoRepeat, int count,
    quint32 nativeScanCode, quint32 nativeModifiers, unsigned long time)
{
    if (activeConnection != connectionId)
        return;

    Q_EMIT receivedKeyEvent(keyType, keyCode,
                            modifiers, text, autoRepeat, count,
                            nativeScanCode, nativeModifiers, time);
}

void MInputContextConnection::registerAttributeExtension(unsigned int connectionId, int id,
                                                         const QString &attributeExtension)
{
    Q_EMIT attributeExtensionRegistered(connectionId, id, attributeExtension);
}

void MInputContextConnection::unregisterAttributeExtension(unsigned int connectionId, int id)
{
    Q_EMIT attributeExtensionUnregistered(connectionId, id);
}

void MInputContextConnection::setExtendedAttribute(
    unsigned int connectionId, int id, const QString &target, const QString &targetName,
    const QString &attribute, const QVariant &value)
{
    Q_EMIT extendedAttributeChanged(connectionId, id, target, targetName, attribute, value);
}

void MInputContextConnection::loadPluginSettings(int connectionId, const QString &descriptionLanguage)
{
    Q_EMIT pluginSettingsRequested(connectionId, descriptionLanguage);
}
/* End handlers for inbound communication */

bool MInputContextConnection::detectableAutoRepeat()
{
    return mDetectableAutoRepeat;
}

void MInputContextConnection::setDetectableAutoRepeat(bool enabled)
{
    mDetectableAutoRepeat = enabled;
}

void MInputContextConnection::setGlobalCorrectionEnabled(bool enabled)
{
    mGlobalCorrectionEnabled = enabled;
}

bool MInputContextConnection::globalCorrectionEnabled()
{
    return mGlobalCorrectionEnabled;
}

void MInputContextConnection::setRedirectKeys(bool enabled)
{
    mRedirectionEnabled = enabled;
}

bool MInputContextConnection::redirectKeysEnabled()
{
    return mRedirectionEnabled;
}

/* */
void MInputContextConnection::sendCommitString(const QString &string, int replaceStart,
                                          int replaceLength, int cursorPos) {

    const int cursorPosition(mWidgetState[CursorPositionAttribute].toInt());
    bool validAnchor(false);

    preedit.clear();

    if (replaceLength == 0  // we don't support replacement
        // we don't support selections
        && anchorPosition(validAnchor) == cursorPosition
        && validAnchor) {
        const int insertPosition(cursorPosition + replaceStart);
        if (insertPosition >= 0) {
            mWidgetState[SurroundingTextAttribute]
                = mWidgetState[SurroundingTextAttribute].toString().insert(insertPosition, string);
            mWidgetState[CursorPositionAttribute] = cursorPos < 0 ? (insertPosition + string.length()) : cursorPos;
            mWidgetState[AnchorPositionAttribute] = mWidgetState[CursorPositionAttribute];
        }
    }
}

void MInputContextConnection::sendKeyEvent(const QKeyEvent &keyEvent,
                                           Maliit::EventRequestType requestType)
{
    if (requestType != Maliit::EventRequestSignalOnly
        && preedit.isEmpty()
        && keyEvent.key() == Qt::Key_Backspace
        && keyEvent.type() == QEvent::KeyPress) {
        QString surrString(mWidgetState[SurroundingTextAttribute].toString());
        const int cursorPosition(mWidgetState[CursorPositionAttribute].toInt());
        bool validAnchor(false);

        if (!surrString.isEmpty()
            && cursorPosition > 0
            // we don't support selections
            && anchorPosition(validAnchor) == cursorPosition
            && validAnchor) {
            mWidgetState[SurroundingTextAttribute] = surrString.remove(cursorPosition - 1, 1);
            mWidgetState[CursorPositionAttribute] = cursorPosition - 1;
            mWidgetState[AnchorPositionAttribute] = cursorPosition - 1;
        }
    }
}
/* */

/* */
void MInputContextConnection::handleDisconnection(unsigned int connectionId)
{
    Q_EMIT clientDisconnected(connectionId);

    if (activeConnection != connectionId) {
        return;
    }

    activeConnection = 0;

    Q_EMIT activeClientDisconnected();
}

void MInputContextConnection::activateContext(unsigned int connectionId)
{
    if (connectionId == activeConnection) {
        return;
    }

    /* Notify current/previously active context that it is no longer active */
    sendActivationLostEvent();

    activeConnection = connectionId;

    /* Notify new input context about state/settings stored in the IM server */
    if (activeConnection) {
        /* Hack: Circumvent if(newValue == oldValue) return; guards */
        mGlobalCorrectionEnabled = !mGlobalCorrectionEnabled;
        setGlobalCorrectionEnabled(!mGlobalCorrectionEnabled);

        mRedirectionEnabled = !mRedirectionEnabled;
        setRedirectKeys(!mRedirectionEnabled);

        mDetectableAutoRepeat = !mDetectableAutoRepeat;
        setDetectableAutoRepeat(!mDetectableAutoRepeat);
    }

    Q_EMIT clientActivated(connectionId);

}
/* */

void MInputContextConnection::sendPreeditString(const QString &string,
                                                const QList<Maliit::PreeditTextFormat> &preeditFormats,
                                                int replaceStart, int replaceLength,
                                                int cursorPos)
{
    Q_UNUSED(preeditFormats);
    Q_UNUSED(replaceStart);
    Q_UNUSED(replaceLength);
    Q_UNUSED(cursorPos);
    if (activeConnection) {
        preedit = string;
    }
}

/* */
void MInputContextConnection::setSelection(int start, int length)
{
    Q_UNUSED(start);
    Q_UNUSED(length);
}

void MInputContextConnection::notifyImInitiatedHiding()
{}

void MInputContextConnection::invokeAction(const QString &action, const QKeySequence &sequence)
{
    Q_UNUSED(action);
    Q_UNUSED(sequence);
}

QString MInputContextConnection::selection(bool &valid)
{
    valid = false;
    return QString();
}

void MInputContextConnection::setLanguage(const QString &language)
{
    Q_UNUSED(language);
}

void MInputContextConnection::sendActivationLostEvent()
{}

void MInputContextConnection::updateInputMethodArea(const QRegion &region)
{
    Q_UNUSED(region);
}

void MInputContextConnection::notifyExtendedAttributeChanged(int ,
                                                             const QString &,
                                                             const QString &,
                                                             const QString &,
                                                             const QVariant &)
{
    // empty default implementation
}

void MInputContextConnection::notifyExtendedAttributeChanged(const QList<int> &,
                                                             int ,
                                                             const QString &,
                                                             const QString &,
                                                             const QString &,
                                                             const QVariant &)
{
    // empty default implementation
}

void MInputContextConnection::pluginSettingsLoaded(int clientId, const QList<MImPluginSettingsInfo> &info)
{
    Q_UNUSED(clientId);
    Q_UNUSED(info);

    // empty default implementation
}

QVariantMap MInputContextConnection::widgetState() const
{
    return mWidgetState;
}
<commit_msg>Only allow widget state changes from active connection<commit_after>/* * This file is part of Maliit framework *
 *
 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
 * All rights reserved.
 *
 * Contact: maliit-discuss@lists.maliit.org
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License version 2.1 as published by the Free Software Foundation
 * and appearing in the file LICENSE.LGPL included in the packaging
 * of this file.
 */

#include "minputcontextconnection.h"

#include <QKeyEvent>

namespace {
    // attribute names for updateWidgetInformation() map
    const char * const FocusStateAttribute = "focusState";
    const char * const ContentTypeAttribute = "contentType";
    const char * const CorrectionAttribute = "correctionEnabled";
    const char * const PredictionAttribute = "predictionEnabled";
    const char * const AutoCapitalizationAttribute = "autocapitalizationEnabled";
    const char * const SurroundingTextAttribute = "surroundingText";
    const char * const AnchorPositionAttribute = "anchorPosition";
    const char * const CursorPositionAttribute = "cursorPosition";
    const char * const HasSelectionAttribute = "hasSelection";
    const char * const InputMethodModeAttribute = "inputMethodMode";
    const char * const WinId = "winId";
    const char * const CursorRectAttribute = "cursorRectangle";
    const char * const HiddenTextAttribute = "hiddenText";
    const char * const PreeditClickPosAttribute = "preeditClickPos";
}

class MInputContextConnectionPrivate
{
public:
    MInputContextConnectionPrivate();
    ~MInputContextConnectionPrivate();
};

MInputContextConnectionPrivate::MInputContextConnectionPrivate()
{
    // nothing
}

MInputContextConnectionPrivate::~MInputContextConnectionPrivate()
{
    // nothing
}

////////////////////////
// actual class

MInputContextConnection::MInputContextConnection(QObject *parent)
    : activeConnection(0)
    , d(new MInputContextConnectionPrivate)
    , lastOrientation(0)
    , mGlobalCorrectionEnabled(false)
    , mRedirectionEnabled(false)
    , mDetectableAutoRepeat(false)
{
    Q_UNUSED(parent);
}

MInputContextConnection::~MInputContextConnection()
{
    delete d;
}

/* Accessors to widgetState */
bool MInputContextConnection::focusState(bool &valid)
{
    QVariant focusStateVariant = mWidgetState[FocusStateAttribute];
    valid = focusStateVariant.isValid();
    return focusStateVariant.toBool();
}

int MInputContextConnection::contentType(bool &valid)
{
    QVariant contentTypeVariant = mWidgetState[ContentTypeAttribute];
    return contentTypeVariant.toInt(&valid);
}

bool MInputContextConnection::correctionEnabled(bool &valid)
{
    QVariant correctionVariant = mWidgetState[CorrectionAttribute];
    valid = correctionVariant.isValid();
    return correctionVariant.toBool();
}

bool MInputContextConnection::predictionEnabled(bool &valid)
{
    QVariant predictionVariant = mWidgetState[PredictionAttribute];
    valid = predictionVariant.isValid();
    return predictionVariant.toBool();
}

bool MInputContextConnection::autoCapitalizationEnabled(bool &valid)
{
    QVariant capitalizationVariant = mWidgetState[AutoCapitalizationAttribute];
    valid = capitalizationVariant.isValid();
    return capitalizationVariant.toBool();
}

QRect MInputContextConnection::cursorRectangle(bool &valid)
{
    QVariant cursorRectVariant = mWidgetState[CursorRectAttribute];
    valid = cursorRectVariant.isValid();
    return cursorRectVariant.toRect();
}

bool MInputContextConnection::hiddenText(bool &valid)
{
    QVariant hiddenTextVariant = mWidgetState[HiddenTextAttribute];
    valid = hiddenTextVariant.isValid();
    return hiddenTextVariant.toBool();
}

bool MInputContextConnection::surroundingText(QString &text, int &cursorPosition)
{
    QVariant textVariant = mWidgetState[SurroundingTextAttribute];
    QVariant posVariant = mWidgetState[CursorPositionAttribute];

    if (textVariant.isValid() && posVariant.isValid()) {
        text = textVariant.toString();
        cursorPosition = posVariant.toInt();
        return true;
    }

    return false;
}

bool MInputContextConnection::hasSelection(bool &valid)
{
    QVariant selectionVariant = mWidgetState[HasSelectionAttribute];
    valid = selectionVariant.isValid();
    return selectionVariant.toBool();
}

int MInputContextConnection::inputMethodMode(bool &valid)
{
    QVariant modeVariant = mWidgetState[InputMethodModeAttribute];
    return modeVariant.toInt(&valid);
}

QRect MInputContextConnection::preeditRectangle(bool &valid)
{
    valid = false;
    return QRect();
}

WId MInputContextConnection::winId()
{
#ifdef Q_WS_WIN
    WId result = 0;
    return result;
#else
    QVariant winIdVariant = mWidgetState[WinId];
    // after transfer by dbus type can change
    switch (winIdVariant.type()) {
    case QVariant::UInt:
        if (sizeof(uint) >= sizeof(WId))
            return winIdVariant.toUInt();
        break;
    case QVariant::ULongLong:
        if (sizeof(qulonglong) >= sizeof(WId))
            return winIdVariant.toULongLong();
        break;
    default:
        if (winIdVariant.canConvert<WId>())
            return winIdVariant.value<WId>();
    }
    return 0;
#endif
}

int MInputContextConnection::anchorPosition(bool &valid)
{
    QVariant posVariant = mWidgetState[AnchorPositionAttribute];
    valid = posVariant.isValid();
    return posVariant.toInt();
}

int MInputContextConnection::preeditClickPos(bool &valid) const
{
    QVariant selectionVariant = mWidgetState[PreeditClickPosAttribute];
    valid = selectionVariant.isValid();
    return selectionVariant.toInt();
}

/* End accessors to widget state */

/* Handlers for inbound communication */
void MInputContextConnection::showInputMethod(unsigned int connectionId)
{
    if (activeConnection != connectionId)
        return;

    Q_EMIT showInputMethodRequest();
}

void MInputContextConnection::hideInputMethod(unsigned int connectionId)
{
    // Only allow this call for current active connection.
    if (activeConnection != connectionId)
        return;

    Q_EMIT hideInputMethodRequest();
}

void MInputContextConnection::mouseClickedOnPreedit(unsigned int connectionId,
                                                            const QPoint &pos, const QRect &preeditRect)
{
    if (activeConnection != connectionId)
        return;

    Q_EMIT mouseClickedOnPreedit(pos, preeditRect);
}

void MInputContextConnection::setPreedit(unsigned int connectionId,
                                                 const QString &text, int cursorPos)
{
    if (activeConnection != connectionId)
        return;

    preedit = text;

    Q_EMIT preeditChanged(text, cursorPos);
}

void MInputContextConnection::reset(unsigned int connectionId)
{
    if (activeConnection != connectionId)
        return;

    preedit.clear();

    Q_EMIT resetInputMethodRequest();

    if (!preedit.isEmpty()) {
        qWarning("Preedit set from InputMethod::reset()!");
        preedit.clear();
    }
}

void
MInputContextConnection::updateWidgetInformation(
    unsigned int connectionId, const QMap<QString, QVariant> &stateInfo,
    bool handleFocusChange)
{
    if (activeConnection != connectionId)
        return;

    QMap<QString, QVariant> oldState = mWidgetState;

    mWidgetState = stateInfo;

#ifndef Q_WS_WIN
    if (handleFocusChange) {
        Q_EMIT focusChanged(winId());
    }
#endif

    Q_EMIT widgetStateChanged(connectionId, mWidgetState, oldState, handleFocusChange);
}

void
MInputContextConnection::receivedAppOrientationAboutToChange(unsigned int connectionId,
                                                                     int angle)
{
    if (activeConnection != connectionId)
        return;

    // Needs to be passed to the MImRotationAnimation listening
    // to this signal first before the plugins. This ensures
    // that the rotation animation can be painted sufficiently early.
    Q_EMIT contentOrientationAboutToChange(angle);

    Q_EMIT contentOrientationAboutToChangeCompleted(angle);
}

void MInputContextConnection::receivedAppOrientationChanged(unsigned int connectionId,
                                                                    int angle)
{
    if (activeConnection != connectionId)
        return;

    // Handle orientation changes through MImRotationAnimation with priority.
    // That's needed for getting the correct rotated pixmap buffers.
    Q_EMIT contentOrientationChanged(angle);

    Q_EMIT contentOrientationChangeCompleted(angle);
}

void MInputContextConnection::setCopyPasteState(unsigned int connectionId,
                                                        bool copyAvailable, bool pasteAvailable)
{
    if (activeConnection != connectionId)
        return;

    Q_EMIT copyPasteStateChanged(copyAvailable, pasteAvailable);
}

void MInputContextConnection::processKeyEvent(
    unsigned int connectionId, QEvent::Type keyType, Qt::Key keyCode,
    Qt::KeyboardModifiers modifiers, const QString &text, bool autoRepeat, int count,
    quint32 nativeScanCode, quint32 nativeModifiers, unsigned long time)
{
    if (activeConnection != connectionId)
        return;

    Q_EMIT receivedKeyEvent(keyType, keyCode,
                            modifiers, text, autoRepeat, count,
                            nativeScanCode, nativeModifiers, time);
}

void MInputContextConnection::registerAttributeExtension(unsigned int connectionId, int id,
                                                         const QString &attributeExtension)
{
    Q_EMIT attributeExtensionRegistered(connectionId, id, attributeExtension);
}

void MInputContextConnection::unregisterAttributeExtension(unsigned int connectionId, int id)
{
    Q_EMIT attributeExtensionUnregistered(connectionId, id);
}

void MInputContextConnection::setExtendedAttribute(
    unsigned int connectionId, int id, const QString &target, const QString &targetName,
    const QString &attribute, const QVariant &value)
{
    Q_EMIT extendedAttributeChanged(connectionId, id, target, targetName, attribute, value);
}

void MInputContextConnection::loadPluginSettings(int connectionId, const QString &descriptionLanguage)
{
    Q_EMIT pluginSettingsRequested(connectionId, descriptionLanguage);
}
/* End handlers for inbound communication */

bool MInputContextConnection::detectableAutoRepeat()
{
    return mDetectableAutoRepeat;
}

void MInputContextConnection::setDetectableAutoRepeat(bool enabled)
{
    mDetectableAutoRepeat = enabled;
}

void MInputContextConnection::setGlobalCorrectionEnabled(bool enabled)
{
    mGlobalCorrectionEnabled = enabled;
}

bool MInputContextConnection::globalCorrectionEnabled()
{
    return mGlobalCorrectionEnabled;
}

void MInputContextConnection::setRedirectKeys(bool enabled)
{
    mRedirectionEnabled = enabled;
}

bool MInputContextConnection::redirectKeysEnabled()
{
    return mRedirectionEnabled;
}

/* */
void MInputContextConnection::sendCommitString(const QString &string, int replaceStart,
                                          int replaceLength, int cursorPos) {

    const int cursorPosition(mWidgetState[CursorPositionAttribute].toInt());
    bool validAnchor(false);

    preedit.clear();

    if (replaceLength == 0  // we don't support replacement
        // we don't support selections
        && anchorPosition(validAnchor) == cursorPosition
        && validAnchor) {
        const int insertPosition(cursorPosition + replaceStart);
        if (insertPosition >= 0) {
            mWidgetState[SurroundingTextAttribute]
                = mWidgetState[SurroundingTextAttribute].toString().insert(insertPosition, string);
            mWidgetState[CursorPositionAttribute] = cursorPos < 0 ? (insertPosition + string.length()) : cursorPos;
            mWidgetState[AnchorPositionAttribute] = mWidgetState[CursorPositionAttribute];
        }
    }
}

void MInputContextConnection::sendKeyEvent(const QKeyEvent &keyEvent,
                                           Maliit::EventRequestType requestType)
{
    if (requestType != Maliit::EventRequestSignalOnly
        && preedit.isEmpty()
        && keyEvent.key() == Qt::Key_Backspace
        && keyEvent.type() == QEvent::KeyPress) {
        QString surrString(mWidgetState[SurroundingTextAttribute].toString());
        const int cursorPosition(mWidgetState[CursorPositionAttribute].toInt());
        bool validAnchor(false);

        if (!surrString.isEmpty()
            && cursorPosition > 0
            // we don't support selections
            && anchorPosition(validAnchor) == cursorPosition
            && validAnchor) {
            mWidgetState[SurroundingTextAttribute] = surrString.remove(cursorPosition - 1, 1);
            mWidgetState[CursorPositionAttribute] = cursorPosition - 1;
            mWidgetState[AnchorPositionAttribute] = cursorPosition - 1;
        }
    }
}
/* */

/* */
void MInputContextConnection::handleDisconnection(unsigned int connectionId)
{
    Q_EMIT clientDisconnected(connectionId);

    if (activeConnection != connectionId) {
        return;
    }

    activeConnection = 0;

    Q_EMIT activeClientDisconnected();
}

void MInputContextConnection::activateContext(unsigned int connectionId)
{
    if (connectionId == activeConnection) {
        return;
    }

    /* Notify current/previously active context that it is no longer active */
    sendActivationLostEvent();

    activeConnection = connectionId;

    /* Notify new input context about state/settings stored in the IM server */
    if (activeConnection) {
        /* Hack: Circumvent if(newValue == oldValue) return; guards */
        mGlobalCorrectionEnabled = !mGlobalCorrectionEnabled;
        setGlobalCorrectionEnabled(!mGlobalCorrectionEnabled);

        mRedirectionEnabled = !mRedirectionEnabled;
        setRedirectKeys(!mRedirectionEnabled);

        mDetectableAutoRepeat = !mDetectableAutoRepeat;
        setDetectableAutoRepeat(!mDetectableAutoRepeat);
    }

    Q_EMIT clientActivated(connectionId);

}
/* */

void MInputContextConnection::sendPreeditString(const QString &string,
                                                const QList<Maliit::PreeditTextFormat> &preeditFormats,
                                                int replaceStart, int replaceLength,
                                                int cursorPos)
{
    Q_UNUSED(preeditFormats);
    Q_UNUSED(replaceStart);
    Q_UNUSED(replaceLength);
    Q_UNUSED(cursorPos);
    if (activeConnection) {
        preedit = string;
    }
}

/* */
void MInputContextConnection::setSelection(int start, int length)
{
    Q_UNUSED(start);
    Q_UNUSED(length);
}

void MInputContextConnection::notifyImInitiatedHiding()
{}

void MInputContextConnection::invokeAction(const QString &action, const QKeySequence &sequence)
{
    Q_UNUSED(action);
    Q_UNUSED(sequence);
}

QString MInputContextConnection::selection(bool &valid)
{
    valid = false;
    return QString();
}

void MInputContextConnection::setLanguage(const QString &language)
{
    Q_UNUSED(language);
}

void MInputContextConnection::sendActivationLostEvent()
{}

void MInputContextConnection::updateInputMethodArea(const QRegion &region)
{
    Q_UNUSED(region);
}

void MInputContextConnection::notifyExtendedAttributeChanged(int ,
                                                             const QString &,
                                                             const QString &,
                                                             const QString &,
                                                             const QVariant &)
{
    // empty default implementation
}

void MInputContextConnection::notifyExtendedAttributeChanged(const QList<int> &,
                                                             int ,
                                                             const QString &,
                                                             const QString &,
                                                             const QString &,
                                                             const QVariant &)
{
    // empty default implementation
}

void MInputContextConnection::pluginSettingsLoaded(int clientId, const QList<MImPluginSettingsInfo> &info)
{
    Q_UNUSED(clientId);
    Q_UNUSED(info);

    // empty default implementation
}

QVariantMap MInputContextConnection::widgetState() const
{
    return mWidgetState;
}
<|endoftext|>


<commit_before>#include <algorithm>
#include <queue>
#include <string>
#include <utility>
#include <vector>

// Algorithm to be tested

static std::pair<int,int> find_cell(std::vector<std::string> const& map, char cell_type)
{
  for (std::size_t idx {} ; idx != map.size() ; ++idx)
  {
    auto found = std::find(map[idx].begin(), map[idx].end(), cell_type);
    if (found != map[idx].end())
    {
      return std::make_pair(std::distance(map[idx].begin(), found), idx);
    }
  }
  return std::make_pair(-1, -1);
}

struct IterItem
{
  int num_roads;
  std::pair<int, int> position;

  IterItem(int num_roads, std::pair<int,int> const& position) : num_roads(num_roads), position(position) {}
  bool operator<(IterItem const& other) const { return num_roads > other.num_roads; }
};

static char& cell_at(std::vector<std::string>& map, std::pair<int,int> const& pt)
{
  return map[pt.second][pt.first];
}
static bool is_road(std::vector<std::string>& map, std::pair<int,int> const& pt)
{
  char cell = cell_at(map, pt);
  return cell == '|' || cell == '-' || cell == '!' || cell == '~';
}
static bool is_ok(std::vector<std::string>& map, std::pair<int,int> const& pt)
{
  char cell = cell_at(map, pt);
  return cell == '|' || cell == '-' || cell == '.' || cell == 'H';
}
static void nok(std::vector<std::string>& map, std::pair<int,int> const& pt)
{
  char& cell = cell_at(map, pt);
  switch (cell)
  {
    case '|': cell = '!'; break;
    case '-': cell = '~'; break;
    case 'H': break;
    default: cell = '?'; break;
  };
}

static void push_first_time(std::vector<std::string>& map,  std::priority_queue<IterItem>& nexts, int num_roads, std::pair<int,int> const& pt, std::pair<int,int> const& prev, char forbidden)
{
  if (pt.first < 0 || (std::size_t)pt.first >= map[0].size()) { return; }
  if (pt.second < 0 || (std::size_t)pt.second >= map.size()) { return; }
  if (is_ok(map, pt) && cell_at(map, pt) != forbidden)
  {
    if (! is_road(map, pt) && cell_at(map, prev) == (forbidden == '-' ? '~' : '!'))
    {
      return;
    }

    if (is_road(map, pt) && ! is_road(map, prev))
    {
      ++num_roads;
    }
    nok(map, pt);
    nexts.emplace(num_roads, pt);
  }
}

int fewest_crossings(std::vector<std::string> const& map_)
{
  auto map = map_;
  auto start_pt = find_cell(map, 'S');
  nok(map, start_pt);

  std::priority_queue<IterItem> nexts;
  nexts.emplace(0, start_pt);

  while (! nexts.empty())
  {
    auto item = nexts.top();
    auto num_roads = item.num_roads;
    auto const& pt = item.position;
    nexts.pop();

    if (cell_at(map, pt) == 'H') { return num_roads; }

    push_first_time(map, nexts, num_roads, std::make_pair(pt.first +1, pt.second), pt, '-');
    push_first_time(map, nexts, num_roads, std::make_pair(pt.first -1, pt.second), pt, '-');
    push_first_time(map, nexts, num_roads, std::make_pair(pt.first, pt.second +1), pt, '|');
    push_first_time(map, nexts, num_roads, std::make_pair(pt.first, pt.second -1), pt, '|');
  }
  return -1;
}

<commit_msg>[topcoder-walkinghome] Fixes #8<commit_after>#include <algorithm>
#include <queue>
#include <string>
#include <utility>
#include <vector>

// Algorithm to be tested

static std::pair<int,int> find_cell(std::vector<std::string> const& map, char cell_type)
{
  for (std::size_t idx {} ; idx != map.size() ; ++idx)
  {
    auto found = std::find(map[idx].begin(), map[idx].end(), cell_type);
    if (found != map[idx].end())
    {
      return std::make_pair(std::distance(map[idx].begin(), found), idx);
    }
  }
  return std::make_pair(-1, -1);
}

struct IterItem
{
  int num_roads;
  std::pair<int, int> position;

  IterItem(int num_roads, std::pair<int,int> const& position) : num_roads(num_roads), position(position) {}
  bool operator<(IterItem const& other) const { return num_roads > other.num_roads; }
};

static char& cell_at(std::vector<std::string>& map, std::pair<int,int> const& pt)
{
  return map[pt.second][pt.first];
}
static bool is_road(std::vector<std::string>& map, std::pair<int,int> const& pt)
{
  char cell = cell_at(map, pt);
  return cell == '|' || cell == '-' || cell == '!' || cell == '~';
}
static bool is_ok(std::vector<std::string>& map, std::pair<int,int> const& pt)
{
  char cell = cell_at(map, pt);
  return cell == '|' || cell == '-' || cell == '.' || cell == 'H';
}
static void nok(std::vector<std::string>& map, std::pair<int,int> const& pt)
{
  char& cell = cell_at(map, pt);
  switch (cell)
  {
    case '|': cell = '!'; break;
    case '-': cell = '~'; break;
    case 'H': break;
    default: cell = '?'; break;
  };
}

static void push_first_time(std::vector<std::string>& map,  std::priority_queue<IterItem>& nexts, int num_roads, std::pair<int,int> const& pt, std::pair<int,int> const& prev, char forbidden)
{
  if (pt.first < 0 || (std::size_t)pt.first >= map[0].size()) { return; }
  if (pt.second < 0 || (std::size_t)pt.second >= map.size()) { return; }
  if (is_ok(map, pt) && cell_at(map, pt) != forbidden)
  {
    if (! is_road(map, pt) && cell_at(map, prev) == (forbidden == '-' ? '~' : '!'))
    {
      return;
    }

    if (is_road(map, pt))
    {
      if (is_road(map, prev))
      {
        char prev_road { cell_at(map, prev) == '~' ? '-' : '|' };
        if (prev_road != cell_at(map, pt)) { return; }
      }
      else
      {
        ++num_roads;
      }
    }
    nok(map, pt);
    nexts.emplace(num_roads, pt);
  }
}

int fewest_crossings(std::vector<std::string> const& map_)
{
  auto map = map_;
  auto start_pt = find_cell(map, 'S');
  nok(map, start_pt);

  std::priority_queue<IterItem> nexts;
  nexts.emplace(0, start_pt);

  while (! nexts.empty())
  {
    auto item = nexts.top();
    auto num_roads = item.num_roads;
    auto const& pt = item.position;
    nexts.pop();

    if (cell_at(map, pt) == 'H') { return num_roads; }

    push_first_time(map, nexts, num_roads, std::make_pair(pt.first +1, pt.second), pt, '-');
    push_first_time(map, nexts, num_roads, std::make_pair(pt.first -1, pt.second), pt, '-');
    push_first_time(map, nexts, num_roads, std::make_pair(pt.first, pt.second +1), pt, '|');
    push_first_time(map, nexts, num_roads, std::make_pair(pt.first, pt.second -1), pt, '|');
  }
  return -1;
}

<|endoftext|>


<commit_before>/*
* Copyright (c) 2003-2011 Rony Shapiro <ronys@users.sourceforge.net>.
* All rights reserved. Use of the code is allowed under the
* Artistic License 2.0 terms, as specified in the LICENSE file
* distributed with this code, or available from
* http://www.opensource.org/licenses/artistic-license-2.0.php
*/

/**
 * \file Linux-specific implementation of utf8conv.h
 */

#include "../typedefs.h"
#include "../utf8conv.h"
#include <cstdlib>
#include <clocale>
#include <cassert>
#include <cstring>
#include <string>

using namespace std;

class Startup {
public:
  Startup() {
    char *sl = setlocale(LC_ALL, "");
    if (sl == NULL)
      throw "Couldn't initialize locale - bailing out";
  }
};

static Startup startup;

size_t pws_os::wcstombs(char *dst, size_t maxdstlen,
                        const wchar_t *src, size_t , bool )
{
  return ::wcstombs(dst, src, maxdstlen) + 1;
}

size_t pws_os::mbstowcs(wchar_t *dst, size_t maxdstlen,
                        const char *src, size_t , bool )
{
  return ::mbstowcs(dst, src, maxdstlen) + 1;
}

wstring pws_os::towc(const char *val)
{
  wstring retval(L"");
  assert(val != NULL);
  int len = strlen(val);
  int wsize;
  const char *p = val;
  wchar_t wvalue;
  while (len > 0) {
    wsize = mbtowc(&wvalue, p, MB_CUR_MAX);
    if (wsize <= 0)
      break;
    retval += wvalue;
    p += wsize;
    len -= wsize;
  };
  return retval;
}

#ifdef UNICODE
std::string pws_os::tomb(const stringT& val)
{
  if (!val.empty()) {
    const size_t N = std::wcstombs(NULL, val.c_str(), 0);
    assert(N > 0);
    char* szstr = new char[N+1];
    szstr[N] = 0;
    std::wcstombs(szstr, val.c_str(), N);
    std::string retval(szstr);
    delete[] szstr;
    return retval;
  } else
    return string();
}
#else
std::string pws_os::tomb(const stringT& val)
{
  return val;
}
#endif

<commit_msg>Linux: Try harder and fail more gracefully if we can't load the environment-specified locale<commit_after>/*
* Copyright (c) 2003-2011 Rony Shapiro <ronys@users.sourceforge.net>.
* All rights reserved. Use of the code is allowed under the
* Artistic License 2.0 terms, as specified in the LICENSE file
* distributed with this code, or available from
* http://www.opensource.org/licenses/artistic-license-2.0.php
*/

/**
 * \file Linux-specific implementation of utf8conv.h
 */

#include "../typedefs.h"
#include "../utf8conv.h"
#include <cstdlib>
#include <clocale>
#include <cassert>
#include <cstring>
#include <string>
#include <unistd.h>

using namespace std;

class Startup {
public:
  Startup() {
    // Sice this can fail before main(), we can't rely on cerr etc.
    // being intialized. At least give the user a clue...
    char *gl = setlocale(LC_ALL, NULL);
    char *sl = setlocale(LC_ALL, "");
    if (sl == NULL) {
      // Couldn't get environment-specified locale, warn user
      // and punt to default "C"
      char wrnmess[] = "Couldn't load locale, falling back to default\n";
      write(STDERR_FILENO, wrnmess, sizeof(wrnmess)/sizeof(*wrnmess)-1);
      sl = setlocale(LC_ALL, gl);
    }
    if (sl == NULL) {
      // If we can't get the default,we're really FUBARed
      char errmess[] = "Couldn't initialize locale - bailing out\n";
      write(STDERR_FILENO, errmess, sizeof(errmess)/sizeof(*errmess)-1);
      _exit(2);
    }
  }
};

static Startup startup;

size_t pws_os::wcstombs(char *dst, size_t maxdstlen,
                        const wchar_t *src, size_t , bool )
{
  return ::wcstombs(dst, src, maxdstlen) + 1;
}

size_t pws_os::mbstowcs(wchar_t *dst, size_t maxdstlen,
                        const char *src, size_t , bool )
{
  return ::mbstowcs(dst, src, maxdstlen) + 1;
}

wstring pws_os::towc(const char *val)
{
  wstring retval(L"");
  assert(val != NULL);
  int len = strlen(val);
  int wsize;
  const char *p = val;
  wchar_t wvalue;
  while (len > 0) {
    wsize = mbtowc(&wvalue, p, MB_CUR_MAX);
    if (wsize <= 0)
      break;
    retval += wvalue;
    p += wsize;
    len -= wsize;
  };
  return retval;
}

#ifdef UNICODE
std::string pws_os::tomb(const stringT& val)
{
  if (!val.empty()) {
    const size_t N = std::wcstombs(NULL, val.c_str(), 0);
    assert(N > 0);
    char* szstr = new char[N+1];
    szstr[N] = 0;
    std::wcstombs(szstr, val.c_str(), N);
    std::string retval(szstr);
    delete[] szstr;
    return retval;
  } else
    return string();
}
#else
std::string pws_os::tomb(const stringT& val)
{
  return val;
}
#endif

<|endoftext|>


<commit_before><commit_msg>Remove dead code<commit_after><|endoftext|>


<commit_before><commit_msg>This shall probably check nId != 0 && ..., not do a bitwise &<commit_after><|endoftext|>


<commit_before>#ifndef MANIFOLDS_FUNCTIONS_INTEGRAL_POLYNOMIAL_SIMPLIFICATIONS_HH
#define MANIFOLDS_FUNCTIONS_INTEGRAL_POLYNOMIAL_SIMPLIFICATIONS_HH

#include "integral_polynomial.hh"
#include "polynomial.hh"
#include "addition.hh"
#include "simplify.hh"
#include "unary_minus.hh"
#include "zero.hh"

namespace manifolds {
template <class T1, class T2, T1... t1s, T2... t2s>
struct Simplification<
    Addition<IntegralPolynomial<std::integer_sequence<T1, t1s...> >,
             IntegralPolynomial<std::integer_sequence<T2, t2s...> > >,
    /*add_ip_ip*/ 0> {
  typedef std::int64_t Tr;

  template <class, class> struct Extended;

  template <class T, T... indices, Tr... padding>
  struct Extended<std::integer_sequence<T, indices...>,
                  std::integer_sequence<Tr, padding...> > {
    typedef std::integer_sequence<Tr, indices..., (padding - padding)...> type;
  };

  static const int padding1 =
      sizeof...(t1s) < sizeof...(t2s) ? sizeof...(t2s) - sizeof...(t1s) : 0;
  typedef typename Extended<std::integer_sequence<T1, t1s...>,
                            std::make_integer_sequence<Tr, padding1> >::type
  padded1;

  static const int padding2 =
      sizeof...(t2s) < sizeof...(t1s) ? sizeof...(t1s) - sizeof...(t2s) : 0;
  typedef typename Extended<std::integer_sequence<T2, t2s...>,
                            std::make_integer_sequence<Tr, padding2> >::type
  padded2;

  template <class, class> struct Add;

  template <Tr... indices1, Tr... indices2>
  struct Add<std::integer_sequence<Tr, indices1...>,
             std::integer_sequence<Tr, indices2...> > {
    typedef std::integer_sequence<Tr, (indices1 + indices2)...> type;
  };

  typedef IntegralPolynomial<typename Add<padded1, padded2>::type> type;

  static type
  Combine(Addition<IntegralPolynomial<std::integer_sequence<T1, t1s...> >,
                   IntegralPolynomial<std::integer_sequence<T2, t2s...> > >) {
    SIMPLIFY_INFO("Simplifying addition of "
                  "integral_polynomials\n");
    return type{};
  }
};

template <class T1, class T2, T1... t1s, T2... t2s>
struct Simplification<
    Multiplication<IntegralPolynomial<std::integer_sequence<T1, t1s...> >,
                   IntegralPolynomial<std::integer_sequence<T2, t2s...> > >,
    /*mult_ip_ip*/ 0> {
  typedef long Tr;

  typedef std::integer_sequence<T1, t1s...> inputs1;
  typedef std::integer_sequence<T2, t2s...> inputs2;

  template <int, class> struct get_value;

  template <int i, class T, T... ts>
  struct get_value<
      i, std::integer_sequence<
             T, ts...> > : nth<i, std::integral_constant<T, ts>...>::type {};

  template <int, Tr, class> struct set_value;

  template <int i, Tr t, class T, T... ts>
  struct set_value<i, t, std::integer_sequence<T, ts...> > {
    typedef std::integer_sequence<T, ts...> values;
    template <class, class> struct apply;

    template <int... lefts, int... rights>
    struct apply<std::integer_sequence<int, lefts...>,
                 std::integer_sequence<int, rights...> > {
      typedef std::integer_sequence<Tr, get_value<lefts, values>::value..., t,
                                    get_value<rights + i + 1, values>::value...>
      type;
    };

    typedef typename apply<
        std::make_integer_sequence<int, i>,
        std::make_integer_sequence<int, sizeof...(ts) - i - 1> >::type type;
  };

  template <int i, int j, class OutSeq,
            bool = (i + j < seq_size<OutSeq>::value)>
  struct Add {
    typedef typename set_value<i + j, get_value<i + j, OutSeq>::value +
                                          (Tr)get_value<i, inputs1>::value *(
                                              Tr)get_value<j, inputs2>::value,
                               OutSeq>::type type;
  };

  template <int i, int j, class T, T... ts>
  struct Add<i, j, std::integer_sequence<T, ts...>, false> {
    static_assert(i + j == sizeof...(ts), "Internal error");
    typedef std::integer_sequence<T, ts..., (Tr)get_value<i, inputs1>::value *(
                                                Tr)get_value<j, inputs2>::value>
    type;
  };

  template <int i, int j, class OutSeq> struct P2Loop {
    typedef typename P2Loop<i, j - 1, typename Add<i, j, OutSeq>::type>::type
    type;
  };

  template <int i, class OutSeq> struct P2Loop<i, -1, OutSeq> {
    typedef OutSeq type;
  };

  template <int i, class OutSeq> struct P1Loop {
    typedef typename P1Loop<
        i - 1, typename P2Loop<i, sizeof...(t2s) - 1, OutSeq>::type>::type type;
  };

  template <class OutSeq> struct P1Loop<-1, OutSeq> {
    typedef OutSeq type;
  };

  template <class> struct InitOutput;

  template <int... indices> struct InitOutput<iseq<indices...> > {
    typedef std::integer_sequence<Tr, ((void)indices, 0)...> type;
  };

  typedef IntegralPolynomial<typename P1Loop<
      sizeof...(t1s) - 1,
      typename InitOutput<
          miseq<sizeof...(t1s) + sizeof...(t2s) - 1> >::type>::type> type;

  static type Combine(
      Multiplication<IntegralPolynomial<std::integer_sequence<T1, t1s...> >,
                     IntegralPolynomial<std::integer_sequence<T2, t2s...> > >) {
    SIMPLIFY_INFO("Simplifying multiplication of "
                  "integral_polynomials\n");
    return type{};
  }
};

template <class T, T... ts>
struct Simplification<IntegralPolynomial<std::integer_sequence<T, ts...> >,
                      /*ip*/ 0> {
  template <T t> using ic = std::integral_constant<T, t>;

  template <T... t2s> struct pop {
    template <class> struct apply;

    template <std::size_t... is>
    struct apply<std::integer_sequence<std::size_t, is...> > {
      typedef std::integer_sequence<T, nth<is, ic<t2s>...>::type::value...>
      type;
    };

    typedef typename apply<std::make_index_sequence<sizeof...(t2s) - 1> >::type
    type;
  };

  template <class, bool> struct pop_if;

  template <class> struct stopping_condition;

  template <T... touts>
  struct stopping_condition<std::integer_sequence<T, touts...> > {
    static const bool value =
        sizeof...(ts) == 1 || last<ic<touts>...>::type::value != 0;
  };

  template <T... touts>
  struct pop_if<std::integer_sequence<T, touts...>, true> {
    typedef std::integer_sequence<T, touts...> type;
  };

  template <T... touts>
  struct pop_if<std::integer_sequence<T, touts...>, false> {
    typedef typename pop<touts...>::type next;
    typedef typename pop_if<next, stopping_condition<next>::value>::type type;
  };

  typedef IntegralPolynomial<typename pop_if<
      std::integer_sequence<T, ts...>,
      stopping_condition<std::integer_sequence<T, ts...> >::value>::type> type;

  static type Combine(IntegralPolynomial<std::integer_sequence<T, ts...> >) {
    SIMPLIFY_INFO("Simplifying of "
                  "integral_polynomial\n");
    return type{};
  }
};

template <template <class...> class Variadic, class T1, class O1, class T2,
          T2... t2s>
struct Simplification<
    Variadic<Polynomial<T1, O1>,
             IntegralPolynomial<std::integer_sequence<T2, t2s...> > >,
    /*var_p_ip*/ 1> {
  typedef Variadic<Polynomial<T1, O1>, Polynomial<T2, int_<sizeof...(t2s)> > >
  type;

  static type
  Combine(Variadic<Polynomial<T1, O1>,
                   IntegralPolynomial<std::integer_sequence<T2, t2s...> > > v) {
    SIMPLIFY_INFO("Simplifying variadic of "
                  "polynomial and integral_polynomial\n");
    return { get<0>(v.GetFunctions()), get<1>(v.GetFunctions()).ToPoly() };
  }
};

template <template <class...> class Variadic, class T1, class O1, class T2,
          T2... t2s>
struct Simplification<
    Variadic<IntegralPolynomial<std::integer_sequence<T2, t2s...> >,
             Polynomial<T1, O1> >,
    /*var_ip_p*/ 0> {
  typedef Variadic<Polynomial<T2, int_<sizeof...(t2s)> >, Polynomial<T1, O1> >
  type;

  static type
  Combine(Variadic<IntegralPolynomial<std::integer_sequence<T2, t2s...> >,
                   Polynomial<T1, O1> > v) {
    SIMPLIFY_INFO("Simplifying variadic of "
                  "integral_polynomial and polynomial\n");
    return { get<0>(v.GetFunctions()).ToPoly(), get<1>(v.GetFunctions()) };
  }
};

template <class T, T... coeffs>
struct Simplification<
    UnaryMinus<IntegralPolynomial<std::integer_sequence<T, coeffs...> > >, 0> {
  typedef typename std::conditional<std::is_unsigned<T>::value,
                                    std::make_signed<T>,
                                    Identity<T> >::type::type CType;

  typedef IntegralPolynomial<std::integer_sequence<CType, (-(CType)coeffs)...> >
  type;

  static type Combine(
      UnaryMinus<IntegralPolynomial<std::integer_sequence<T, coeffs...> > >) {
    SIMPLIFY_INFO("Simplifying negative of integral polynomial");
    return type{};
  }
};

template <class A>
struct Simplification<Addition<A, A>, /*add_f_f*/ 3,
                      typename std::enable_if<is_stateless<A>::value>::type> {
  typedef Composition<IntegralPolynomial<iseq<0, 2> >, A> type;
  static type Combine(Addition<A, A> a) {
    SIMPLIFY_INFO("Simplifying addition of function by itself\n");
    type b = { IntegralPolynomial<iseq<0, 2> >(), A() };
    return b;
  }
};

template <class A>
struct Simplification<Multiplication<A, A>, /*mult_f_f*/ 3,
                      typename std::enable_if<is_stateless<A>::value>::type> {
  typedef Composition<IntegralPolynomial<iseq<0, 0, 1> >, A> type;

  static type Combine(Multiplication<A, A>) {
    SIMPLIFY_INFO("Simplifying multiplication of function "
                  "by itself\n");
    return { IntegralPolynomial<iseq<0, 0, 1> >(), A() };
  }
};

template <class T, class U, U us>
struct Simplification<
    Addition<T, IntegralPolynomial<std::integer_sequence<U, us> > >,
    /*add_f_ip_1*/ 2> {
  typedef Composition<IntegralPolynomial<std::integer_sequence<U, us, (U)1> >,
                      T> type;

  static type
  Combine(Addition<T, IntegralPolynomial<std::integer_sequence<U, us> > > a) {
    SIMPLIFY_INFO("Simplifying addition of constant "
                  "and another function");
    auto t = a.GetFunctions();
    return { IntegralPolynomial<std::integer_sequence<U, us, (U)1> >(),
             get<0>(t) };
  }
};

template <class T, class U>
struct Simplification<
    Multiplication<T, IntegralPolynomial<std::integer_sequence<U, (U)1> > >,
    /*mult_f_ip_1*/ 0> {
  static T Combine(Multiplication<
      T, IntegralPolynomial<std::integer_sequence<U, (U)1> > > m) {
    SIMPLIFY_INFO("Simplifying multiplication of function by 1");
    return get<0>(m.GetFunctions());
  }
};

template <class T>
struct Simplification<IntegralPolynomial<std::integer_sequence<T, (T)0> >,
                      /*ip_0*/ 0> {
  static auto Combine(IntegralPolynomial<std::integer_sequence<T, (T)0> >) {
    return zero;
  }
};
}

#endif
<commit_msg>Simplification conflict has changed the priorities of these simplifications<commit_after>#ifndef MANIFOLDS_FUNCTIONS_INTEGRAL_POLYNOMIAL_SIMPLIFICATIONS_HH
#define MANIFOLDS_FUNCTIONS_INTEGRAL_POLYNOMIAL_SIMPLIFICATIONS_HH

#include "integral_polynomial.hh"
#include "polynomial.hh"
#include "addition.hh"
#include "simplify.hh"
#include "unary_minus.hh"
#include "zero.hh"

namespace manifolds {
template <class T1, class T2, T1... t1s, T2... t2s>
struct Simplification<
    Addition<IntegralPolynomial<std::integer_sequence<T1, t1s...> >,
             IntegralPolynomial<std::integer_sequence<T2, t2s...> > >,
    /*add_ip_ip*/ 0> {
  typedef std::int64_t Tr;

  template <class, class> struct Extended;

  template <class T, T... indices, Tr... padding>
  struct Extended<std::integer_sequence<T, indices...>,
                  std::integer_sequence<Tr, padding...> > {
    typedef std::integer_sequence<Tr, indices..., (padding - padding)...> type;
  };

  static const int padding1 =
      sizeof...(t1s) < sizeof...(t2s) ? sizeof...(t2s) - sizeof...(t1s) : 0;
  typedef typename Extended<std::integer_sequence<T1, t1s...>,
                            std::make_integer_sequence<Tr, padding1> >::type
  padded1;

  static const int padding2 =
      sizeof...(t2s) < sizeof...(t1s) ? sizeof...(t1s) - sizeof...(t2s) : 0;
  typedef typename Extended<std::integer_sequence<T2, t2s...>,
                            std::make_integer_sequence<Tr, padding2> >::type
  padded2;

  template <class, class> struct Add;

  template <Tr... indices1, Tr... indices2>
  struct Add<std::integer_sequence<Tr, indices1...>,
             std::integer_sequence<Tr, indices2...> > {
    typedef std::integer_sequence<Tr, (indices1 + indices2)...> type;
  };

  typedef IntegralPolynomial<typename Add<padded1, padded2>::type> type;

  static type
  Combine(Addition<IntegralPolynomial<std::integer_sequence<T1, t1s...> >,
                   IntegralPolynomial<std::integer_sequence<T2, t2s...> > >) {
    SIMPLIFY_INFO("Simplifying addition of "
                  "integral_polynomials\n");
    return type{};
  }
};

template <class T1, class T2, T1... t1s, T2... t2s>
struct Simplification<
    Multiplication<IntegralPolynomial<std::integer_sequence<T1, t1s...> >,
                   IntegralPolynomial<std::integer_sequence<T2, t2s...> > >,
    /*mult_ip_ip*/ 0> {
  typedef long Tr;

  typedef std::integer_sequence<T1, t1s...> inputs1;
  typedef std::integer_sequence<T2, t2s...> inputs2;

  template <int, class> struct get_value;

  template <int i, class T, T... ts>
  struct get_value<
      i, std::integer_sequence<
             T, ts...> > : nth<i, std::integral_constant<T, ts>...>::type {};

  template <int, Tr, class> struct set_value;

  template <int i, Tr t, class T, T... ts>
  struct set_value<i, t, std::integer_sequence<T, ts...> > {
    typedef std::integer_sequence<T, ts...> values;
    template <class, class> struct apply;

    template <int... lefts, int... rights>
    struct apply<std::integer_sequence<int, lefts...>,
                 std::integer_sequence<int, rights...> > {
      typedef std::integer_sequence<Tr, get_value<lefts, values>::value..., t,
                                    get_value<rights + i + 1, values>::value...>
      type;
    };

    typedef typename apply<
        std::make_integer_sequence<int, i>,
        std::make_integer_sequence<int, sizeof...(ts) - i - 1> >::type type;
  };

  template <int i, int j, class OutSeq,
            bool = (i + j < seq_size<OutSeq>::value)>
  struct Add {
    typedef typename set_value<i + j, get_value<i + j, OutSeq>::value +
                                          (Tr)get_value<i, inputs1>::value *(
                                              Tr)get_value<j, inputs2>::value,
                               OutSeq>::type type;
  };

  template <int i, int j, class T, T... ts>
  struct Add<i, j, std::integer_sequence<T, ts...>, false> {
    static_assert(i + j == sizeof...(ts), "Internal error");
    typedef std::integer_sequence<T, ts..., (Tr)get_value<i, inputs1>::value *(
                                                Tr)get_value<j, inputs2>::value>
    type;
  };

  template <int i, int j, class OutSeq> struct P2Loop {
    typedef typename P2Loop<i, j - 1, typename Add<i, j, OutSeq>::type>::type
    type;
  };

  template <int i, class OutSeq> struct P2Loop<i, -1, OutSeq> {
    typedef OutSeq type;
  };

  template <int i, class OutSeq> struct P1Loop {
    typedef typename P1Loop<
        i - 1, typename P2Loop<i, sizeof...(t2s) - 1, OutSeq>::type>::type type;
  };

  template <class OutSeq> struct P1Loop<-1, OutSeq> {
    typedef OutSeq type;
  };

  template <class> struct InitOutput;

  template <int... indices> struct InitOutput<iseq<indices...> > {
    typedef std::integer_sequence<Tr, ((void)indices, 0)...> type;
  };

  typedef IntegralPolynomial<typename P1Loop<
      sizeof...(t1s) - 1,
      typename InitOutput<
          miseq<sizeof...(t1s) + sizeof...(t2s) - 1> >::type>::type> type;

  static type Combine(
      Multiplication<IntegralPolynomial<std::integer_sequence<T1, t1s...> >,
                     IntegralPolynomial<std::integer_sequence<T2, t2s...> > >) {
    SIMPLIFY_INFO("Simplifying multiplication of "
                  "integral_polynomials\n");
    return type{};
  }
};

template <class T, T... ts>
struct Simplification<IntegralPolynomial<std::integer_sequence<T, ts...> >,
                      /*ip*/ 0> {
  template <T t> using ic = std::integral_constant<T, t>;

  template <T... t2s> struct pop {
    template <class> struct apply;

    template <std::size_t... is>
    struct apply<std::integer_sequence<std::size_t, is...> > {
      typedef std::integer_sequence<T, nth<is, ic<t2s>...>::type::value...>
      type;
    };

    typedef typename apply<std::make_index_sequence<sizeof...(t2s) - 1> >::type
    type;
  };

  template <class, bool> struct pop_if;

  template <class> struct stopping_condition;

  template <T... touts>
  struct stopping_condition<std::integer_sequence<T, touts...> > {
    static const bool value =
        sizeof...(ts) == 1 || last<ic<touts>...>::type::value != 0;
  };

  template <T... touts>
  struct pop_if<std::integer_sequence<T, touts...>, true> {
    typedef std::integer_sequence<T, touts...> type;
  };

  template <T... touts>
  struct pop_if<std::integer_sequence<T, touts...>, false> {
    typedef typename pop<touts...>::type next;
    typedef typename pop_if<next, stopping_condition<next>::value>::type type;
  };

  typedef IntegralPolynomial<typename pop_if<
      std::integer_sequence<T, ts...>,
      stopping_condition<std::integer_sequence<T, ts...> >::value>::type> type;

  static type Combine(IntegralPolynomial<std::integer_sequence<T, ts...> >) {
    SIMPLIFY_INFO("Simplifying of "
                  "integral_polynomial\n");
    return type{};
  }
};

template <template <class...> class Variadic, class T1, class O1, class T2,
          T2... t2s>
struct Simplification<
    Variadic<Polynomial<T1, O1>,
             IntegralPolynomial<std::integer_sequence<T2, t2s...> > >,
    /*var_p_ip*/2> {
  typedef Variadic<Polynomial<T1, O1>, Polynomial<T2, int_<sizeof...(t2s)> > >
  type;

  static type
  Combine(Variadic<Polynomial<T1, O1>,
                   IntegralPolynomial<std::integer_sequence<T2, t2s...> > > v) {
    SIMPLIFY_INFO("Simplifying variadic of "
                  "polynomial and integral_polynomial\n");
    return { get<0>(v.GetFunctions()), get<1>(v.GetFunctions()).ToPoly() };
  }
};

template <template <class...> class Variadic, class T1, class O1, class T2,
          T2... t2s>
struct Simplification<
    Variadic<IntegralPolynomial<std::integer_sequence<T2, t2s...> >,
             Polynomial<T1, O1> >,
    /*var_ip_p*/ 0> {
  typedef Variadic<Polynomial<T2, int_<sizeof...(t2s)> >, Polynomial<T1, O1> >
  type;

  static type
  Combine(Variadic<IntegralPolynomial<std::integer_sequence<T2, t2s...> >,
                   Polynomial<T1, O1> > v) {
    SIMPLIFY_INFO("Simplifying variadic of "
                  "integral_polynomial and polynomial\n");
    return { get<0>(v.GetFunctions()).ToPoly(), get<1>(v.GetFunctions()) };
  }
};

template <class T, T... coeffs>
struct Simplification<
    UnaryMinus<IntegralPolynomial<std::integer_sequence<T, coeffs...> > >, 0> {
  typedef typename std::conditional<std::is_unsigned<T>::value,
                                    std::make_signed<T>,
                                    Identity<T> >::type::type CType;

  typedef IntegralPolynomial<std::integer_sequence<CType, (-(CType)coeffs)...> >
  type;

  static type Combine(
      UnaryMinus<IntegralPolynomial<std::integer_sequence<T, coeffs...> > >) {
    SIMPLIFY_INFO("Simplifying negative of integral polynomial");
    return type{};
  }
};

template <class A>
struct Simplification<Addition<A, A>, /*add_f_f*/ 3,
                      typename std::enable_if<is_stateless<A>::value>::type> {
  typedef Composition<IntegralPolynomial<iseq<0, 2> >, A> type;
  static type Combine(Addition<A, A> a) {
    SIMPLIFY_INFO("Simplifying addition of function by itself\n");
    type b = { IntegralPolynomial<iseq<0, 2> >(), A() };
    return b;
  }
};

template <class A>
struct Simplification<Multiplication<A, A>, /*mult_f_f*/ 3,
                      typename std::enable_if<is_stateless<A>::value>::type> {
  typedef Composition<IntegralPolynomial<iseq<0, 0, 1> >, A> type;

  static type Combine(Multiplication<A, A>) {
    SIMPLIFY_INFO("Simplifying multiplication of function "
                  "by itself\n");
    return { IntegralPolynomial<iseq<0, 0, 1> >(), A() };
  }
};

template <class T, class U, U us>
struct Simplification<
    Addition<T, IntegralPolynomial<std::integer_sequence<U, us> > >,
    /*add_f_ip_1*/3> {
  typedef Composition<IntegralPolynomial<std::integer_sequence<U, us, (U)1> >,
                      T> type;

  static type
  Combine(Addition<T, IntegralPolynomial<std::integer_sequence<U, us> > > a) {
    SIMPLIFY_INFO("Simplifying addition of constant "
                  "and another function");
    auto t = a.GetFunctions();
    return { IntegralPolynomial<std::integer_sequence<U, us, (U)1> >(),
             get<0>(t) };
  }
};

template <class T, class U>
struct Simplification<
    Multiplication<T, IntegralPolynomial<std::integer_sequence<U, (U)1> > >,
    /*mult_f_ip_1*/1> {
  static T Combine(Multiplication<
      T, IntegralPolynomial<std::integer_sequence<U, (U)1> > > m) {
    SIMPLIFY_INFO("Simplifying multiplication of function by 1");
    return get<0>(m.GetFunctions());
  }
};

template <class T>
struct Simplification<IntegralPolynomial<std::integer_sequence<T, (T)0> >,
                      /*ip_0*/ 0> {
  static auto Combine(IntegralPolynomial<std::integer_sequence<T, (T)0> >) {
    return zero;
  }
};
}

#endif
<|endoftext|>


<commit_before>void display (const char *filename="galice.root",Int_t nevent=0) {
// Dynamically link some shared libs
   if (gClassTable->GetID("AliRun") < 0) {
      gROOT->LoadMacro("loadlibs.C");
      loadlibs();
   } else {
      delete gAlice;
      gAlice = 0;
   }

// Connect the Root Galice file containing Geometry, Kine and Hits

   TFile *file = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
   if(file){
     cout<<"galice.root is already open \n";
   }
   else {
     if(!file)file=TFile::Open(filename);
   }

// Get AliRun object from file or create it if not on file
   if (!gAlice) {
      gAlice = (AliRun*)file->Get("gAlice");
      if (gAlice) printf("AliRun object found on file\n");
      if (!gAlice) gAlice = new AliRun("gAlice","Alice test program");
   }

// Create Event Display object
   AliDisplay *edisplay = new AliDisplay(750);

// Display the requested event
   gAlice->GetEvent(nevent);
   edisplay->ShowNextEvent(0);

// Define the buttons to switch on/off the existing modules
   Float_t nodet=0.;
   TObjArray *moduli = gAlice->Modules();
   Int_t nomod=moduli->GetEntriesFast();
   AliModule *modu;
   for (Int_t j=0; j<nomod; j++){
     modu=(AliModule*)moduli->At(j);
     char *avoid=strstr("BODY MAG ABSO DIPO HALL FRAME SHIL PIPE",modu->GetName());
     if(avoid)continue;
     nodet++;
   }
   TDialogCanvas *dialog = new TDialogCanvas("Modules"," ",150,30*nodet);
   Float_t yval1=1./nodet*0.9*0.05;
   Float_t yval2=1./nodet*0.9*0.95;
   char action[50];
   char title[30];
   char bname[30];
   TButton *butto1;
   for (Int_t j=0; j<nomod; j++){
     modu=(AliModule*)moduli->At(j);
     char *avoid=strstr(" BODY MAG ABSO DIPO HALL FRAME SHIL PIPE",modu->GetName());
     if(avoid)continue;
     sprintf(action,"swioff(\"%s\")",modu->GetName());
     sprintf(title,"%s is on",modu->GetName());
     sprintf(bname,"but%s",modu->GetName());
     butto1 = new TButton(title,action,.05,yval1,.95,yval2);
     butto1->SetName(bname);
     butto1->SetFillColor(3);
     butto1->Draw();
     yval1+=1./nodet;
     yval2+=1./nodet;
   }
}

void swioff(const char *dete){
  gAlice->Display()->DisableDetector(dete);
  gAlice->Display()->Pad()->Modified();
  gAlice->Display()->Pad()->Update();
  char bname[30];
  char action[50];
  char title[30];
  sprintf(bname,"but%s",dete);
  TDialogCanvas *dia = (TDialogCanvas *)gROOT->FindObject("Modules");
  TButton *bt = (TButton *)dia->FindObject(bname);
  bt->SetFillColor(2);
  sprintf(action,"swion(\"%s\")",dete);
  bt->SetMethod(action);
  sprintf(title,"%s is off",dete);
  bt->SetTitle(title);
  dia->Draw();
}

void swion(const char *dete){
  gAlice->Display()->EnableDetector(dete);
  gAlice->Display()->Pad()->Modified();
  gAlice->Display()->Pad()->Update();
  TDialogCanvas *dia = (TDialogCanvas *)gROOT->FindObject("Modules");
  char bname[30];
  char action[50];
  char title[30];
  sprintf(bname,"but%s",dete);
  TButton *bt = (TButton *)dia->FindObject(bname);
  bt->SetFillColor(3);
  sprintf(action,"swioff(\"%s\")",dete);
  bt->SetMethod(action);
  sprintf(title,"%s is on",dete);
  bt->SetTitle(title);
  dia->Draw();
}

<commit_msg>Updated display.C. Possibility to select tracks. (M.Ivanov)<commit_after>// This macro displays the hits belonging to a track for selected detectors
// Input: in the tracks contains the interesting tracks
//        ntracks is the number of interesing tracks
//        The default values correspond to "Show everything"
// Note: For the moment it works only with HIJING events, the PYTHIA is
//       still not supported
void display (const char *filename="galice.root",Int_t nevent=0, Int_t * tracks=0, Int_t ntracks=0) {
// Dynamically link some shared libs
   if (gClassTable->GetID("AliRun") < 0) {
      gROOT->LoadMacro("loadlibs.C");
      loadlibs();
   } else {
      delete gAlice;
      gAlice = 0;
   }

// Connect the Root Galice file containing Geometry, Kine and Hits

   TFile *file = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
   if(file){
     cout<<"galice.root is already open \n";
   }
   else {
     if(!file)file=TFile::Open(filename);
   }

// Get AliRun object from file or create it if not on file
   if (!gAlice) {
      gAlice = (AliRun*)file->Get("gAlice");
      if (gAlice) printf("AliRun object found on file\n");
      if (!gAlice) gAlice = new AliRun("gAlice","Alice test program");
   }

// Create Event Display object
   AliDisplay *edisplay = new AliDisplay(750);
   if (ntracks>0) edisplay->SetTracksToDisplay(tracks, ntracks);

// Display the requested event
   gAlice->GetEvent(nevent);
   edisplay->ShowNextEvent(0);

// Define the buttons to switch on/off the existing modules
   Float_t nodet=0.;
   TObjArray *moduli = gAlice->Modules();
   Int_t nomod=moduli->GetEntriesFast();
   AliModule *modu;
   for (Int_t j=0; j<nomod; j++){
     modu=(AliModule*)moduli->At(j);
     char *avoid=strstr("BODY MAG ABSO DIPO HALL FRAME SHIL PIPE",modu->GetName());
     if(avoid)continue;
     nodet++;
   }
   TDialogCanvas *dialog = new TDialogCanvas("Modules"," ",150,30*nodet);
   Float_t yval1=1./nodet*0.9*0.05;
   Float_t yval2=1./nodet*0.9*0.95;
   char action[50];
   char title[30];
   char bname[30];
   TButton *butto1;
   for (Int_t j=0; j<nomod; j++){
     modu=(AliModule*)moduli->At(j);
     char *avoid=strstr(" BODY MAG ABSO DIPO HALL FRAME SHIL PIPE",modu->GetName());
     if(avoid)continue;
     sprintf(action,"swioff(\"%s\")",modu->GetName());
     sprintf(title,"%s is on",modu->GetName());
     sprintf(bname,"but%s",modu->GetName());
     butto1 = new TButton(title,action,.05,yval1,.95,yval2);
     butto1->SetName(bname);
     butto1->SetFillColor(3);
     butto1->Draw();
     yval1+=1./nodet;
     yval2+=1./nodet;
   }
}

void swioff(const char *dete){
  gAlice->Display()->DisableDetector(dete);
  gAlice->Display()->Pad()->Modified();
  gAlice->Display()->Pad()->Update();
  char bname[30];
  char action[50];
  char title[30];
  sprintf(bname,"but%s",dete);
  TDialogCanvas *dia = (TDialogCanvas *)gROOT->FindObject("Modules");
  TButton *bt = (TButton *)dia->FindObject(bname);
  bt->SetFillColor(2);
  sprintf(action,"swion(\"%s\")",dete);
  bt->SetMethod(action);
  sprintf(title,"%s is off",dete);
  bt->SetTitle(title);
  dia->Draw();
}

void swion(const char *dete){
  gAlice->Display()->EnableDetector(dete);
  gAlice->Display()->Pad()->Modified();
  gAlice->Display()->Pad()->Update();
  TDialogCanvas *dia = (TDialogCanvas *)gROOT->FindObject("Modules");
  char bname[30];
  char action[50];
  char title[30];
  sprintf(bname,"but%s",dete);
  TButton *bt = (TButton *)dia->FindObject(bname);
  bt->SetFillColor(3);
  sprintf(action,"swioff(\"%s\")",dete);
  bt->SetMethod(action);
  sprintf(title,"%s is on",dete);
  bt->SetTitle(title);
  dia->Draw();
}

<|endoftext|>


<commit_before>/*
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Library General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 *
 * Universe.cpp
 * Represents a universe of DMX data
 * Copyright (C) 2005-2008 Simon Newton
 *
 */

#include <llad/Universe.h>
#include <llad/logger.h>
#include <llad/Port.h>
#include "UniverseStore.h"
#include "Client.h"

#include <arpa/inet.h>
#include <iterator>
#include <string.h>
#include <stdio.h>

namespace lla {

const string Universe::K_UNIVERSE_NAME_VAR = "universe_name";
const string Universe::K_UNIVERSE_MODE_VAR = "universe_mode";
const string Universe::K_UNIVERSE_PORT_VAR = "universe_ports";
const string Universe::K_UNIVERSE_CLIENTS_VAR = "universe_clients";
const string Universe::K_MERGE_HTP_STR = "htp";
const string Universe::K_MERGE_LTP_STR = "ltp";

/*
 * Create a new universe
 *
 * @param uid  the universe id of this universe
 */
Universe::Universe(int universe_id, UniverseStore *store, ExportMap *export_map):
  m_universe_name(""),
  m_universe_id(universe_id),
  m_merge_mode(Universe::MERGE_LTP),
  m_universe_store(store),
  m_length(DMX_UNIVERSE_SIZE),
  m_export_map(export_map) {

  memset(m_data, 0x00, DMX_UNIVERSE_SIZE);

  stringstream universe_id_str;
  universe_id_str << universe_id;
  m_universe_id_str = universe_id_str.str();

  UpdateName();
  UpdateMode();

  if (m_export_map) {
    m_export_map->GetIntMapVar(K_UNIVERSE_PORT_VAR)->Set(m_universe_id_str, 0);
    m_export_map->GetIntMapVar(K_UNIVERSE_CLIENTS_VAR)->Set(m_universe_id_str, 0);
  }
}

/*
 * Delete this universe
 */
Universe::~Universe() {
  if (m_export_map) {
    m_export_map->GetStringMapVar(K_UNIVERSE_NAME_VAR)->Remove(m_universe_id_str);
    m_export_map->GetStringMapVar(K_UNIVERSE_MODE_VAR)->Remove(m_universe_id_str);
    m_export_map->GetIntMapVar(K_UNIVERSE_PORT_VAR)->Remove(m_universe_id_str);
    m_export_map->GetIntMapVar(K_UNIVERSE_CLIENTS_VAR)->Remove(m_universe_id_str);
  }
}

/*
 * Set the universe name
 */
void Universe::SetName(const string &name) {
  m_universe_name = name;
  UpdateName();
}

/*
 * Set the universe merge mode
 */
void Universe::SetMergeMode(merge_mode merge_mode) {
  m_merge_mode = merge_mode;
  UpdateMode();
}

/*
 * Add a port to this universe
 *
 * @param port the port to add
 */
int Universe::AddPort(AbstractPort *port) {
  vector<AbstractPort*>::iterator iter;
  Universe *universe = port->GetUniverse();

  if (universe == this)
    return 0;

  // unpatch if required
  if (universe != NULL) {
    Logger::instance()->log(Logger::DEBUG,
                            "Port %d is bound to universe %d",
                            port->PortId(),
                            universe->UniverseId());
    universe->RemovePort(port);

    m_universe_store->DeleteUniverseIfInactive(universe);
  }

  // patch to this universe
  Logger::instance()->log(Logger::INFO,
                          "Patched %d to universe %d",
                          port->PortId() ,
                          m_universe_id);
  m_ports.push_back(port);
  port->SetUniverse(this);
  if (m_export_map) {
    IntMap *map = m_export_map->GetIntMapVar(K_UNIVERSE_PORT_VAR);
    map->Set(m_universe_id_str, map->Get(m_universe_id_str) + 1);
  }
  return 0;
}

/*
 * Remove a port from this universe. After calling this method you need to
 * check if this universe is still in use, and if not delete it
 *
 * @param prt the port to remove
 */
int Universe::RemovePort(AbstractPort *port) {
  vector<AbstractPort*>::iterator iter;

  iter = find(m_ports.begin(), m_ports.end(), port);

  if (iter != m_ports.end()) {
    m_ports.erase(iter);
    port->SetUniverse(NULL);
    if (m_export_map) {
      IntMap *map = m_export_map->GetIntMapVar(K_UNIVERSE_PORT_VAR);
      map->Set(m_universe_id_str, map->Get(m_universe_id_str) - 1);
    }
    Logger::instance()->log(Logger::DEBUG,
                            "Port %p has been removed from uni %d",
                            port,
                            m_universe_id);

  } else {
    Logger::instance()->log(Logger::DEBUG, "Could not find port in universe");
    return -1;
  }
  return 0;
}

/*
 * Add this client to this universe
 *
 * @param client the client to add
 */
int Universe::AddClient(Client *client) {
  vector<Client*>::iterator iter = find(m_clients.begin(),
                                        m_clients.end(),
                                        client);

  if (iter != m_clients.end())
    return 0;

  Logger::instance()->log(Logger::INFO,
                          "Added client %p to universe %d",
                          client,
                          m_universe_id);
  m_clients.push_back(client);
  if (m_export_map) {
    IntMap *map = m_export_map->GetIntMapVar(K_UNIVERSE_CLIENTS_VAR);
    map->Set(m_universe_id_str, map->Get(m_universe_id_str) + 1);
  }
  return 0;
}

/*
 * Remove this client from the universe. After calling this method you need to
 * check if this universe is still in use, and if not delete it
 *
 * @param client  the client to remove
 */
int Universe::RemoveClient(Client *client) {
  vector<Client*>::iterator iter = find(m_clients.begin(),
                                        m_clients.end(),
                                        client);

  if (iter != m_clients.end()) {
    m_clients.erase(iter);
    if (m_export_map) {
      IntMap *map = m_export_map->GetIntMapVar(K_UNIVERSE_CLIENTS_VAR);
      map->Set(m_universe_id_str, map->Get(m_universe_id_str) - 1);
    }
    Logger::instance()->log(Logger::INFO,
                            "Client %p has been removed from uni %d",
                            client,
                            m_universe_id);
  }
  return 0;
}

/*
 * Set the dmx data for this universe
 *
 * @param  dmx  pointer to the dmx data
 * @param  len  the length of the dmx buffer
 */
int Universe::SetDMX(uint8_t *dmx, unsigned int length) {
  if (m_merge_mode == Universe::MERGE_LTP) {
    m_length = length < DMX_UNIVERSE_SIZE ? length : DMX_UNIVERSE_SIZE;
    memcpy(m_data, dmx, m_length);
  } else {
    // HTP, this is more difficult, we'll need a buffer per client
    // for now just set it
    //TODO: implement proper HTP merging from clients
    m_length = length < DMX_UNIVERSE_SIZE ? length : DMX_UNIVERSE_SIZE;
    memcpy(m_data, dmx, m_length);
  }
  return this->UpdateDependants();
}

/*
 * Get the dmx data for this universe
 *
 * @param dmx    the buffer to copy data into
 * @param length  the length of the buffer
 */
int Universe::GetDMX(uint8_t *dmx, unsigned int length) const {
  int len = length < m_length ? length : m_length;
  memcpy(dmx, m_data, len);
  return len;
}

/*
 * Get the dmx data for this universe
 *
 * @param length  the length of the buffer
 * @returns a pointer to the DMX data
 */
const uint8_t *Universe::GetDMX(int &length) const {
  length = m_length;
  return m_data;
}

/*
 * Call this when the dmx in a port that is part of this universe changes
 *
 * @param prt   the port that has changed
 */
int Universe::PortDataChanged(AbstractPort *port) {
  unsigned int i, len;

  if (m_merge_mode == Universe::MERGE_LTP) {
    // LTP merge mode
    // this is simple, find the port and copy the data
    for (i =0; i < m_ports.size(); i++) {
      if (m_ports[i] == port && port->CanRead()) {
        // read the new data and update our dependants
        m_length = port->ReadDMX(m_data, DMX_UNIVERSE_SIZE);
        UpdateDependants();
        break;
      }
    }
  } else {
    // htp merge mode
    // iterate over ports which we can read and take the highest value
    // of each channel
    bool first = true;
    for (i =0; i < m_ports.size(); i++) {
      if (port->CanRead()) {
        if (first) {
          m_length = port->ReadDMX(m_data, DMX_UNIVERSE_SIZE);
          first = false;
        } else {
          len = port->ReadDMX(m_merge, DMX_UNIVERSE_SIZE);
          Merge();
        }
      }
    }
    UpdateDependants();
  }

  return 0;
}

/*
 * Return true if this universe is in use
 */
bool Universe::IsActive() const {
  return m_ports.size() > 0 || m_clients.size() > 0;
}

// Private Methods
//-----------------------------------------------------------------------------

/*
 * Called when the dmx data for this universe changes,
 * updates everyone who needs to know (patched ports and network clients)
 *
 */
int Universe::UpdateDependants() {
  unsigned int i;

  // write to all ports assigned to this unviverse
  for (i=0; i < m_ports.size(); i++) {
    m_ports[i]->WriteDMX(m_data, m_length);
  }

  // write to all clients
  for (i=0; i < m_clients.size(); i++) {
    Logger::instance()->log(Logger::DEBUG, "Sending dmx data msg to client");
    m_clients[i]->SendDMX(m_universe_id, m_data, m_length);
  }
  return 0;
}

/*
 * Update the name in the export map.
 */
void Universe::UpdateName() {
  if (!m_export_map)
    return;
  StringMap *name_map = m_export_map->GetStringMapVar(K_UNIVERSE_NAME_VAR);
  name_map->Set(m_universe_id_str, m_universe_name);
}

/*
 * Update the mode in the export map.
 */
void Universe::UpdateMode() {
  if (!m_export_map)
    return;
  StringMap *mode_map = m_export_map->GetStringMapVar(K_UNIVERSE_MODE_VAR);
  mode_map->Set(m_universe_id_str,
                m_merge_mode == Universe::MERGE_LTP ?
                K_MERGE_LTP_STR : K_MERGE_HTP_STR);
}

/*
 * HTP merge the merge buffer into the data buffer
 */
void Universe::Merge() {
  int i, l;

  // l is the length we merge over
  l = m_mlength < m_length ? m_mlength : m_length;

  for (i=0; i < l; i++) {
    m_data[i] = m_data[i] > m_merge[i] ? m_data[i] : m_merge[i];
  }

  if (m_mlength > m_length) {
    // copy the remaining over
    memcpy(&m_data[l], &m_merge[l], m_mlength - m_length);
    m_length = m_mlength;
  }
}

} //lla
<commit_msg> * add the missing include so that find() works<commit_after>/*
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Library General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 *
 * Universe.cpp
 * Represents a universe of DMX data
 * Copyright (C) 2005-2008 Simon Newton
 *
 */

#include <llad/Universe.h>
#include <llad/logger.h>
#include <llad/Port.h>
#include "UniverseStore.h"
#include "Client.h"

#include <arpa/inet.h>
#include <iterator>
#include <algorithm>
#include <string.h>
#include <stdio.h>

namespace lla {

const string Universe::K_UNIVERSE_NAME_VAR = "universe_name";
const string Universe::K_UNIVERSE_MODE_VAR = "universe_mode";
const string Universe::K_UNIVERSE_PORT_VAR = "universe_ports";
const string Universe::K_UNIVERSE_CLIENTS_VAR = "universe_clients";
const string Universe::K_MERGE_HTP_STR = "htp";
const string Universe::K_MERGE_LTP_STR = "ltp";

/*
 * Create a new universe
 *
 * @param uid  the universe id of this universe
 */
Universe::Universe(int universe_id, UniverseStore *store, ExportMap *export_map):
  m_universe_name(""),
  m_universe_id(universe_id),
  m_merge_mode(Universe::MERGE_LTP),
  m_universe_store(store),
  m_length(DMX_UNIVERSE_SIZE),
  m_export_map(export_map) {

  memset(m_data, 0x00, DMX_UNIVERSE_SIZE);

  stringstream universe_id_str;
  universe_id_str << universe_id;
  m_universe_id_str = universe_id_str.str();

  UpdateName();
  UpdateMode();

  if (m_export_map) {
    m_export_map->GetIntMapVar(K_UNIVERSE_PORT_VAR)->Set(m_universe_id_str, 0);
    m_export_map->GetIntMapVar(K_UNIVERSE_CLIENTS_VAR)->Set(m_universe_id_str, 0);
  }
}

/*
 * Delete this universe
 */
Universe::~Universe() {
  if (m_export_map) {
    m_export_map->GetStringMapVar(K_UNIVERSE_NAME_VAR)->Remove(m_universe_id_str);
    m_export_map->GetStringMapVar(K_UNIVERSE_MODE_VAR)->Remove(m_universe_id_str);
    m_export_map->GetIntMapVar(K_UNIVERSE_PORT_VAR)->Remove(m_universe_id_str);
    m_export_map->GetIntMapVar(K_UNIVERSE_CLIENTS_VAR)->Remove(m_universe_id_str);
  }
}

/*
 * Set the universe name
 */
void Universe::SetName(const string &name) {
  m_universe_name = name;
  UpdateName();
}

/*
 * Set the universe merge mode
 */
void Universe::SetMergeMode(merge_mode merge_mode) {
  m_merge_mode = merge_mode;
  UpdateMode();
}

/*
 * Add a port to this universe
 *
 * @param port the port to add
 */
int Universe::AddPort(AbstractPort *port) {
  vector<AbstractPort*>::iterator iter;
  Universe *universe = port->GetUniverse();

  if (universe == this)
    return 0;

  // unpatch if required
  if (universe != NULL) {
    Logger::instance()->log(Logger::DEBUG,
                            "Port %d is bound to universe %d",
                            port->PortId(),
                            universe->UniverseId());
    universe->RemovePort(port);

    m_universe_store->DeleteUniverseIfInactive(universe);
  }

  // patch to this universe
  Logger::instance()->log(Logger::INFO,
                          "Patched %d to universe %d",
                          port->PortId() ,
                          m_universe_id);
  m_ports.push_back(port);
  port->SetUniverse(this);
  if (m_export_map) {
    IntMap *map = m_export_map->GetIntMapVar(K_UNIVERSE_PORT_VAR);
    map->Set(m_universe_id_str, map->Get(m_universe_id_str) + 1);
  }
  return 0;
}

/*
 * Remove a port from this universe. After calling this method you need to
 * check if this universe is still in use, and if not delete it
 *
 * @param prt the port to remove
 */
int Universe::RemovePort(AbstractPort *port) {
  vector<AbstractPort*>::iterator iter;

  iter = find(m_ports.begin(), m_ports.end(), port);

  if (iter != m_ports.end()) {
    m_ports.erase(iter);
    port->SetUniverse(NULL);
    if (m_export_map) {
      IntMap *map = m_export_map->GetIntMapVar(K_UNIVERSE_PORT_VAR);
      map->Set(m_universe_id_str, map->Get(m_universe_id_str) - 1);
    }
    Logger::instance()->log(Logger::DEBUG,
                            "Port %p has been removed from uni %d",
                            port,
                            m_universe_id);

  } else {
    Logger::instance()->log(Logger::DEBUG, "Could not find port in universe");
    return -1;
  }
  return 0;
}

/*
 * Add this client to this universe
 *
 * @param client the client to add
 */
int Universe::AddClient(Client *client) {
  vector<Client*>::iterator iter = find(m_clients.begin(),
                                        m_clients.end(),
                                        client);

  if (iter != m_clients.end())
    return 0;

  Logger::instance()->log(Logger::INFO,
                          "Added client %p to universe %d",
                          client,
                          m_universe_id);
  m_clients.push_back(client);
  if (m_export_map) {
    IntMap *map = m_export_map->GetIntMapVar(K_UNIVERSE_CLIENTS_VAR);
    map->Set(m_universe_id_str, map->Get(m_universe_id_str) + 1);
  }
  return 0;
}

/*
 * Remove this client from the universe. After calling this method you need to
 * check if this universe is still in use, and if not delete it
 *
 * @param client  the client to remove
 */
int Universe::RemoveClient(Client *client) {
  vector<Client*>::iterator iter = find(m_clients.begin(),
                                        m_clients.end(),
                                        client);

  if (iter != m_clients.end()) {
    m_clients.erase(iter);
    if (m_export_map) {
      IntMap *map = m_export_map->GetIntMapVar(K_UNIVERSE_CLIENTS_VAR);
      map->Set(m_universe_id_str, map->Get(m_universe_id_str) - 1);
    }
    Logger::instance()->log(Logger::INFO,
                            "Client %p has been removed from uni %d",
                            client,
                            m_universe_id);
  }
  return 0;
}

/*
 * Set the dmx data for this universe
 *
 * @param  dmx  pointer to the dmx data
 * @param  len  the length of the dmx buffer
 */
int Universe::SetDMX(uint8_t *dmx, unsigned int length) {
  if (m_merge_mode == Universe::MERGE_LTP) {
    m_length = length < DMX_UNIVERSE_SIZE ? length : DMX_UNIVERSE_SIZE;
    memcpy(m_data, dmx, m_length);
  } else {
    // HTP, this is more difficult, we'll need a buffer per client
    // for now just set it
    //TODO: implement proper HTP merging from clients
    m_length = length < DMX_UNIVERSE_SIZE ? length : DMX_UNIVERSE_SIZE;
    memcpy(m_data, dmx, m_length);
  }
  return this->UpdateDependants();
}

/*
 * Get the dmx data for this universe
 *
 * @param dmx    the buffer to copy data into
 * @param length  the length of the buffer
 */
int Universe::GetDMX(uint8_t *dmx, unsigned int length) const {
  int len = length < m_length ? length : m_length;
  memcpy(dmx, m_data, len);
  return len;
}

/*
 * Get the dmx data for this universe
 *
 * @param length  the length of the buffer
 * @returns a pointer to the DMX data
 */
const uint8_t *Universe::GetDMX(int &length) const {
  length = m_length;
  return m_data;
}

/*
 * Call this when the dmx in a port that is part of this universe changes
 *
 * @param prt   the port that has changed
 */
int Universe::PortDataChanged(AbstractPort *port) {
  unsigned int i, len;

  if (m_merge_mode == Universe::MERGE_LTP) {
    // LTP merge mode
    // this is simple, find the port and copy the data
    for (i =0; i < m_ports.size(); i++) {
      if (m_ports[i] == port && port->CanRead()) {
        // read the new data and update our dependants
        m_length = port->ReadDMX(m_data, DMX_UNIVERSE_SIZE);
        UpdateDependants();
        break;
      }
    }
  } else {
    // htp merge mode
    // iterate over ports which we can read and take the highest value
    // of each channel
    bool first = true;
    for (i =0; i < m_ports.size(); i++) {
      if (port->CanRead()) {
        if (first) {
          m_length = port->ReadDMX(m_data, DMX_UNIVERSE_SIZE);
          first = false;
        } else {
          len = port->ReadDMX(m_merge, DMX_UNIVERSE_SIZE);
          Merge();
        }
      }
    }
    UpdateDependants();
  }

  return 0;
}

/*
 * Return true if this universe is in use
 */
bool Universe::IsActive() const {
  return m_ports.size() > 0 || m_clients.size() > 0;
}

// Private Methods
//-----------------------------------------------------------------------------

/*
 * Called when the dmx data for this universe changes,
 * updates everyone who needs to know (patched ports and network clients)
 *
 */
int Universe::UpdateDependants() {
  unsigned int i;

  // write to all ports assigned to this unviverse
  for (i=0; i < m_ports.size(); i++) {
    m_ports[i]->WriteDMX(m_data, m_length);
  }

  // write to all clients
  for (i=0; i < m_clients.size(); i++) {
    Logger::instance()->log(Logger::DEBUG, "Sending dmx data msg to client");
    m_clients[i]->SendDMX(m_universe_id, m_data, m_length);
  }
  return 0;
}

/*
 * Update the name in the export map.
 */
void Universe::UpdateName() {
  if (!m_export_map)
    return;
  StringMap *name_map = m_export_map->GetStringMapVar(K_UNIVERSE_NAME_VAR);
  name_map->Set(m_universe_id_str, m_universe_name);
}

/*
 * Update the mode in the export map.
 */
void Universe::UpdateMode() {
  if (!m_export_map)
    return;
  StringMap *mode_map = m_export_map->GetStringMapVar(K_UNIVERSE_MODE_VAR);
  mode_map->Set(m_universe_id_str,
                m_merge_mode == Universe::MERGE_LTP ?
                K_MERGE_LTP_STR : K_MERGE_HTP_STR);
}

/*
 * HTP merge the merge buffer into the data buffer
 */
void Universe::Merge() {
  int i, l;

  // l is the length we merge over
  l = m_mlength < m_length ? m_mlength : m_length;

  for (i=0; i < l; i++) {
    m_data[i] = m_data[i] > m_merge[i] ? m_data[i] : m_merge[i];
  }

  if (m_mlength > m_length) {
    // copy the remaining over
    memcpy(&m_data[l], &m_merge[l], m_mlength - m_length);
    m_length = m_mlength;
  }
}

} //lla
<|endoftext|>