<commit_before>#include "parser.h"
#include "myexception.h"
#include <QRegularExpression>

static const QRegularExpression moduleNamePattern("^([A-Z]|_|[0-9])+$");

Parser::Parser(const QVector<Token> &tokens) : tokens(tokens), it(tokens.begin()), end(tokens.end()), log(&_log)
{
    parse();
}

bool Parser::accept(Token::Type t) {
    if (it->type == t) {
        lastAccepted = it++;
        return true;
    }
    return false;
}

void Parser::expect(Token::Type t, QString err) {
    if (it->type == t) {
        lastAccepted = it++;
        return;
    }

    throw MyException(QString("Unexpected token type. Received %1. Expected type %2. Error : %3").arg(it->toString()).arg(Token::typeToString(t)).arg(err));
}

void Parser::parse() {
    // Step 1) get module name
    expect(Token::MODULE, "File must start with a Module declaration");
    expect(Token::IDENTIFIER, "'module' keyword must be followed by an identifier that will be the module name, in uppercase");
    const QString moduleName = lastAccepted->lexeme;
    if (!moduleNamePattern.match(moduleName).hasMatch())
        throw MyException(QString("Module name must contain only uppercase letters, digits and underscores. Thus, name %1 is incorrect").arg(moduleName));

    setModuleName(moduleName);
    log << "Module name found : " << moduleName << endl;

    // Step 2) get all the exported declarations (functions and types inside the module)
    expect(Token::LEFT_BRACKET, "Module declaration must start with a left bracket '{'");

    while (!accept(Token::RIGHT_BRACKET)) {
        auto newestSymbol = this->parseExportedSymbol();
        if (newestSymbol->isFunction)
            addExportedFunction(newestSymbol->name, newestSymbol->returnType, newestSymbol->argTypes);
        else
            addExportedType(newestSymbol->name);
        accept(Token::COMMA); //Facultative
    }

    // Step 3) Now that module has ended, we expect a semicolong and then parse every other statement
    expect(Token::SEMICOLON, "Module declaration : missing semicolon");

    while (!atEnd()) { //TODO
        parseDeclarationAndAddIt();
    }

}

QSharedPointer<Parser::ExportedSymbol> Parser::parseExportedSymbol() {
    expect(Token::IDENTIFIER, "All declarations in a module must start with an identifier");
    QString first = lastAccepted->value.toString();
    if (accept(Token::COMMA))
    {
        log << "Parsed an exported type whose name is " << first;
        return QSharedPointer<ExportedSymbol>(ExportedSymbol::type(first));
    }

    /*It's a function.
    Two forms are allowed :
    -ReturnType func(argType, argType1,...) ->
    -func(argType, argType2,...) -> ReturnType
    */
    if (accept(Token::IDENTIFIER)) {
        QString returnType = first;
        QString funcName = lastAccepted->value.toString();
        QStringList argTypes;
        expect(Token::LEFT_PAREN, "Function signature must contain parenthesis");
        while (!accept(Token::RIGHT_PAREN)) {
            expect(Token::IDENTIFIER, "Expected typename"); //TODO : allow compound type names (qualifiers etc)
            argTypes << lastAccepted->value.toString();
            accept(Token::COMMA); // At the moment, compound type names will be seen as two types and so 2 args. TODO : fix this
        }

        log << "Parsed a function declaration (exproted in module) with C-style syntax. Name : " << funcName << ". Return type : " << returnType << ". Args types : ";
        for (auto& t : argTypes)
            log << t <<';';
        log << endl;

        return QSharedPointer<ExportedSymbol>(ExportedSymbol::func(funcName, returnType, argTypes));
    }

    else if (accept(Token::LEFT_PAREN)) {
        QString& funcName = first;
        QStringList argTypes;
        while (!accept(Token::RIGHT_PAREN)) {
            expect(Token::IDENTIFIER, "Expected typename"); //TODO : allow compound type names (qualifiers etc)
            argTypes << lastAccepted->value.toString();
            accept(Token::COMMA); // At the moment, compound type names will be seen as two types and so 2 args. TODO : fix this
        }
        expect(Token::ARROW, "Function declarations that do not start with return type must be followed by an arrow.");
        expect(Token::IDENTIFIER, "Arrow must be followed by a type name");
        QString returnType = lastAccepted->value.toString();
        log << "Parsed a function declaration (exproted in module) with C-style syntax. Name : " << funcName << ". Return type : " << returnType << ". Args types : ";
                for (auto& t : argTypes)
                    log << t <<';';
        log << endl;
        return QSharedPointer<ExportedSymbol>(ExportedSymbol::func(funcName, returnType, argTypes));

    }

    //Else it's a type declaration
    log << "Parsed a type to export : " << first << endl;
    return QSharedPointer<ExportedSymbol>(ExportedSymbol::type(first));
}

void Parser::parseDeclarationAndAddIt() {
    if (accept(Token::STRUCT)) {
        parseStruct();
    }
    else {
        throw MyException("Unimplemented method called : Parser::parseDeclarationAndAddIt");
    }
}

void Parser::parseStruct() {
    expect(Token::IDENTIFIER, "Struct must have a single-word name");
    const QString name = lastAccepted->value.toString();
    log << "Parsing struct called " << name << endl;
    expect(Token::LEFT_BRACKET, "Expected bracket after a struct declaration");
    while (!accept(Token::RIGHT_BRACKET)) {
        parseVariableDeclaration();
    }
    expect(Token::SEMICOLON, "Struct definition must end with a ;");
}

void Parser::parseVariableDeclaration() {
    throw MyException("Unimplemented method called : Parser::parseVariableDeclaration");
}
<commit_msg>Added variable declaration parsing<commit_after>#include "parser.h"
#include "myexception.h"
#include <QRegularExpression>

static const QRegularExpression moduleNamePattern("^([A-Z]|_|[0-9])+$");

Parser::Parser(const QVector<Token> &tokens) : tokens(tokens), it(tokens.begin()), end(tokens.end()), log(&_log)
{
    parse();
}

bool Parser::accept(Token::Type t) {
    if (it->type == t) {
        lastAccepted = it++;
        return true;
    }
    return false;
}

void Parser::expect(Token::Type t, QString err) {
    if (it->type == t) {
        lastAccepted = it++;
        return;
    }

    throw MyException(QString("Unexpected token type. Received %1. Expected type %2. Error : %3").arg(it->toString()).arg(Token::typeToString(t)).arg(err));
}

void Parser::parse() {
    // Step 1) get module name
    expect(Token::MODULE, "File must start with a Module declaration");
    expect(Token::IDENTIFIER, "'module' keyword must be followed by an identifier that will be the module name, in uppercase");
    const QString moduleName = lastAccepted->lexeme;
    if (!moduleNamePattern.match(moduleName).hasMatch())
        throw MyException(QString("Module name must contain only uppercase letters, digits and underscores. Thus, name %1 is incorrect").arg(moduleName));

    setModuleName(moduleName);
    log << "Module name found : " << moduleName << endl;

    // Step 2) get all the exported declarations (functions and types inside the module)
    expect(Token::LEFT_BRACKET, "Module declaration must start with a left bracket '{'");

    while (!accept(Token::RIGHT_BRACKET)) {
        auto newestSymbol = this->parseExportedSymbol();
        if (newestSymbol->isFunction)
            addExportedFunction(newestSymbol->name, newestSymbol->returnType, newestSymbol->argTypes);
        else
            addExportedType(newestSymbol->name);
        accept(Token::COMMA); //Facultative
    }

    // Step 3) Now that module has ended, we expect a semicolong and then parse every other statement
    expect(Token::SEMICOLON, "Module declaration : missing semicolon");

    while (!atEnd()) { //TODO
        parseDeclarationAndAddIt();
    }

}

QSharedPointer<Parser::ExportedSymbol> Parser::parseExportedSymbol() {
    expect(Token::IDENTIFIER, "All declarations in a module must start with an identifier");
    QString first = lastAccepted->value.toString();
    if (accept(Token::COMMA))
    {
        log << "Parsed an exported type whose name is " << first;
        return QSharedPointer<ExportedSymbol>(ExportedSymbol::type(first));
    }

    /*It's a function.
    Two forms are allowed :
    -ReturnType func(argType, argType1,...) ->
    -func(argType, argType2,...) -> ReturnType
    */
    if (accept(Token::IDENTIFIER)) {
        QString returnType = first;
        QString funcName = lastAccepted->value.toString();
        QStringList argTypes;
        expect(Token::LEFT_PAREN, "Function signature must contain parenthesis");
        while (!accept(Token::RIGHT_PAREN)) {
            expect(Token::IDENTIFIER, "Expected typename"); //TODO : allow compound type names (qualifiers etc)
            argTypes << lastAccepted->value.toString();
            accept(Token::COMMA); // At the moment, compound type names will be seen as two types and so 2 args. TODO : fix this
        }

        log << "Parsed a function declaration (exproted in module) with C-style syntax. Name : " << funcName << ". Return type : " << returnType << ". Args types : ";
        for (auto& t : argTypes)
            log << t <<';';
        log << endl;

        return QSharedPointer<ExportedSymbol>(ExportedSymbol::func(funcName, returnType, argTypes));
    }

    else if (accept(Token::LEFT_PAREN)) {
        QString& funcName = first;
        QStringList argTypes;
        while (!accept(Token::RIGHT_PAREN)) {
            expect(Token::IDENTIFIER, "Expected typename"); //TODO : allow compound type names (qualifiers etc)
            argTypes << lastAccepted->value.toString();
            accept(Token::COMMA); // At the moment, compound type names will be seen as two types and so 2 args. TODO : fix this
        }
        expect(Token::ARROW, "Function declarations that do not start with return type must be followed by an arrow.");
        expect(Token::IDENTIFIER, "Arrow must be followed by a type name");
        QString returnType = lastAccepted->value.toString();
        log << "Parsed a function declaration (exproted in module) with C-style syntax. Name : " << funcName << ". Return type : " << returnType << ". Args types : ";
                for (auto& t : argTypes)
                    log << t <<';';
        log << endl;
        return QSharedPointer<ExportedSymbol>(ExportedSymbol::func(funcName, returnType, argTypes));

    }

    //Else it's a type declaration
    log << "Parsed a type to export : " << first << endl;
    return QSharedPointer<ExportedSymbol>(ExportedSymbol::type(first));
}

void Parser::parseDeclarationAndAddIt() {
    if (accept(Token::STRUCT)) {
        parseStruct();
    }
    else {
        //throw MyException("Unimplemented method called : Parser::parseDeclarationAndAddIt");
        lastAccepted = it++; //TEMPORARY : pass
        return;
    }
}

void Parser::parseStruct() {
    expect(Token::IDENTIFIER, "Struct must have a single-word name");
    const QString name = lastAccepted->value.toString();
    log << "Parsing struct called " << name << endl;
    expect(Token::LEFT_BRACKET, "Expected bracket after a struct declaration");
    while (!accept(Token::RIGHT_BRACKET)) {
        parseVariableDeclaration();
    }
    expect(Token::SEMICOLON, "Struct definition must end with a ;");
}

void Parser::parseVariableDeclaration() {
    expect(Token::IDENTIFIER, "Variable declaration must start with a typename !");
    const QString type = lastAccepted->value.toString();
    expect(Token::IDENTIFIER, "Variable declaration must contain an identifer as varibale's name !");
    const QString name = lastAccepted->value.toString();
    expect(Token::SEMICOLON, "Missing semicolon");
    log << QString("Parsed a variable declaration. Type is %0, name is %1.").arg(type).arg(name);
}
<|endoftext|>


<commit_before>
#include <display/VRTrackedLookAtNode.h>

namespace MinVR {

	VRTrackedLookAtNode::VRTrackedLookAtNode(const std::string &name, const std::string &headTrackingEventName, VRMatrix4 initiallookAtMatrix) :
		VRDisplayNode(name), _lookAtMatrix(initiallookAtMatrix), _trackingEvent(headTrackingEventName)
{
  _valuesAdded.push_back("/LookAtMatrix");
}

VRTrackedLookAtNode::~VRTrackedLookAtNode()
{
}

void
VRTrackedLookAtNode::render(VRDataIndex *renderState, VRRenderHandler *renderHandler)
{
	renderState->pushState();

	renderState->addData("/LookAtMatrix", _lookAtMatrix);

	VRDisplayNode::render(renderState, renderHandler);

	renderState->popState();
}

void
VRTrackedLookAtNode::onVREvent(const VREvent &e)
{
	if (e.getName() == "/" + _trackingEvent) {
		VRMatrix4 head_frame(e.getDataAsFloatArray("Transform"));
		_lookAtMatrix = head_frame.inverse();
	}
}

VRDisplayNode* VRTrackedLookAtNode::create(VRMainInterface *vrMain, VRDataIndex *config, const std::string &nameSpace) {

	std::string trackingEvent = config->getValue("HeadTrackingEvent", nameSpace);
	VRMatrix4 lookAtMatrix;

	if (config->exists("LookAtMatrix", nameSpace)){
		lookAtMatrix = config->getValue("LookAtMatrix", nameSpace);
	}
	else if (config->exists("LookAtUp", nameSpace) && config->exists("LookAtEye", nameSpace) && config->exists("LookAtCenter", nameSpace))
	{
		VRVector3 up = config->getValue("LookAtUp", nameSpace);
		VRVector3 eye = config->getValue("LookAtEye", nameSpace);
		VRVector3 center = config->getValue("LookAtCenter", nameSpace);

		VRVector3 z = center - eye;
		z.normalize();
		VRVector3 x = up.cross(z);
		x.normalize();
		VRVector3 y = z.cross(x);

        VRMatrix4 M1 = VRMatrix4::fromRowMajorElements(x[0], y[0], z[0], 0,
                                                       x[1], y[1], z[1], 0,
                                                       x[2], y[2], z[2], 0,
                                                       0, 0, 0, 1);

        VRMatrix4 M2 = VRMatrix4::fromRowMajorElements(1, 0, 0, -eye[0],
                                                       0, 1, 0, -eye[1],
                                                       0, 0, 1, -eye[2],
                                                       0, 0, 0, 1);

		lookAtMatrix = M1 * M2;
	}
	else
	{
		std::cerr << "Warning : no LookAtMatrix defined for " << nameSpace << std::endl;
		std::cerr << "Either Define  LookAtMatrix or LookAtUp,LookAEye and LookAtCenter" << std::endl;
		std::cerr << "Using IdentityMatrix as default 1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1 " << std::endl;
	}

	VRTrackedLookAtNode *node = new VRTrackedLookAtNode(nameSpace, trackingEvent, lookAtMatrix);

	vrMain->addEventHandler(node);

	return node;
}

} // end namespace

<commit_msg>Fixed a bug in the TrackedLookAtNode which was introduced due to the new VREvents<commit_after>
#include <display/VRTrackedLookAtNode.h>

namespace MinVR {

	VRTrackedLookAtNode::VRTrackedLookAtNode(const std::string &name, const std::string &headTrackingEventName, VRMatrix4 initiallookAtMatrix) :
		VRDisplayNode(name), _lookAtMatrix(initiallookAtMatrix), _trackingEvent(headTrackingEventName)
{
  _valuesAdded.push_back("/LookAtMatrix");
}

VRTrackedLookAtNode::~VRTrackedLookAtNode()
{
}

void
VRTrackedLookAtNode::render(VRDataIndex *renderState, VRRenderHandler *renderHandler)
{
	renderState->pushState();

	renderState->addData("/LookAtMatrix", _lookAtMatrix);

	VRDisplayNode::render(renderState, renderHandler);

	renderState->popState();
}

void
VRTrackedLookAtNode::onVREvent(const VREvent &e)
{
	if (e.getName() == _trackingEvent) {
		VRMatrix4 head_frame(e.getDataAsFloatArray("Transform"));
		_lookAtMatrix = head_frame.inverse();
	}
}

VRDisplayNode* VRTrackedLookAtNode::create(VRMainInterface *vrMain, VRDataIndex *config, const std::string &nameSpace) {

	std::string trackingEvent = config->getValue("HeadTrackingEvent", nameSpace);
	VRMatrix4 lookAtMatrix;

	if (config->exists("LookAtMatrix", nameSpace)){
		lookAtMatrix = config->getValue("LookAtMatrix", nameSpace);
	}
	else if (config->exists("LookAtUp", nameSpace) && config->exists("LookAtEye", nameSpace) && config->exists("LookAtCenter", nameSpace))
	{
		VRVector3 up = config->getValue("LookAtUp", nameSpace);
		VRVector3 eye = config->getValue("LookAtEye", nameSpace);
		VRVector3 center = config->getValue("LookAtCenter", nameSpace);

		VRVector3 z = center - eye;
		z.normalize();
		VRVector3 x = up.cross(z);
		x.normalize();
		VRVector3 y = z.cross(x);

        VRMatrix4 M1 = VRMatrix4::fromRowMajorElements(x[0], y[0], z[0], 0,
                                                       x[1], y[1], z[1], 0,
                                                       x[2], y[2], z[2], 0,
                                                       0, 0, 0, 1);

        VRMatrix4 M2 = VRMatrix4::fromRowMajorElements(1, 0, 0, -eye[0],
                                                       0, 1, 0, -eye[1],
                                                       0, 0, 1, -eye[2],
                                                       0, 0, 0, 1);

		lookAtMatrix = M1 * M2;
	}
	else
	{
		std::cerr << "Warning : no LookAtMatrix defined for " << nameSpace << std::endl;
		std::cerr << "Either Define  LookAtMatrix or LookAtUp,LookAEye and LookAtCenter" << std::endl;
		std::cerr << "Using IdentityMatrix as default 1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1 " << std::endl;
	}

	VRTrackedLookAtNode *node = new VRTrackedLookAtNode(nameSpace, trackingEvent, lookAtMatrix);

	vrMain->addEventHandler(node);

	return node;
}

} // end namespace

<|endoftext|>


<commit_before><commit_msg>added simple camera viewer<commit_after><|endoftext|>


<commit_before>/*
  arrayops.c: array operators

  Copyright (C) 2017 Victor Lazzarini
  This file is part of Csound.

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

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

  You should have received a copy of the GNU Lesser General Public
  License along with Csound; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
  02111-1307 USA
*/
#include <algorithm>
#include <cmath>
#include <plugin.h>

extern inline MYFLT frac(MYFLT f) { return std::modf(f, &f); }

/** i-time, k-rate operator
    kout[] op kin[]
 */
template <MYFLT (*op)(MYFLT)> struct ArrayOp : csnd::Plugin<1, 1> {
  int process(csnd::myfltvec &out, csnd::myfltvec &in) {
    std::transform(in.begin(), in.end(), out.begin(),
                   [](MYFLT f) { return op(f); });
    return OK;
  }

  int init() {
    csnd::myfltvec &out = outargs.myfltvec_data(0);
    csnd::myfltvec &in = inargs.myfltvec_data(0);
    out.init(csound, in.len());
    return process(out, in);
  }

  int kperf() {
    return process(outargs.myfltvec_data(0), inargs.myfltvec_data(0));
    ;
  }
};

/** i-time, k-rate binary operator
    kout[] op kin1[], kin2[]
 */
template <MYFLT (*bop)(MYFLT, MYFLT)> struct ArrayOp2 : csnd::Plugin<1, 2> {

  int process(csnd::myfltvec &out, csnd::myfltvec &in1, csnd::myfltvec &in2) {
    std::transform(in1.begin(), in1.end(), in2.begin(), out.begin(),
                   [](MYFLT f1, MYFLT f2) { return bop(f1, f2); });
    return OK;
  }

  int init() {
    csnd::myfltvec &out = outargs.myfltvec_data(0);
    csnd::myfltvec &in1 = inargs.myfltvec_data(0);
    csnd::myfltvec &in2 = inargs.myfltvec_data(1);
    if (in2.len() < in1.len())
      return csound->init_error(Str("second input array is too short\n"));
    out.init(csound, in1.len());
    return process(out, in1, in2);
  }

  int kperf() {
    return process(outargs.myfltvec_data(0), inargs.myfltvec_data(0),
                   inargs.myfltvec_data(1));
  }
};

#include <modload.h>
void csnd::on_load(Csound *csound) {
  csnd::plugin<ArrayOp<std::ceil>>(csound, "ceil", "i[]", "i[]",
                                   csnd::thread::i);
  csnd::plugin<ArrayOp<std::ceil>>(csound, "ceil", "k[]", "k[]",
                                   csnd::thread::ik);
  csnd::plugin<ArrayOp<std::floor>>(csound, "floor", "i[]", "i[]",
                                    csnd::thread::i);
  csnd::plugin<ArrayOp<std::floor>>(csound, "floor", "k[]", "k[]",
                                    csnd::thread::ik);
  csnd::plugin<ArrayOp<std::round>>(csound, "round", "i[]", "i[]",
                                    csnd::thread::i);
  csnd::plugin<ArrayOp<std::round>>(csound, "round", "k[]", "k[]",
                                    csnd::thread::ik);
  csnd::plugin<ArrayOp<std::trunc>>(csound, "int", "i[]", "i[]",
                                    csnd::thread::i);
  csnd::plugin<ArrayOp<std::trunc>>(csound, "int", "k[]", "k[]",
                                    csnd::thread::i);
  csnd::plugin<ArrayOp<frac>>(csound, "frac", "i[]", "i[]", csnd::thread::i);
  csnd::plugin<ArrayOp<frac>>(csound, "frac", "k[]", "k[]", csnd::thread::ik);
  csnd::plugin<ArrayOp<std::exp2>>(csound, "powoftwo", "i[]", "i[]",
                                   csnd::thread::i);
  csnd::plugin<ArrayOp<std::exp2>>(csound, "powoftwo", "k[]", "k[]",
                                   csnd::thread::ik);
  csnd::plugin<ArrayOp<std::fabs>>(csound, "abs", "i[]", "i[]",
                                   csnd::thread::i);
  csnd::plugin<ArrayOp<std::fabs>>(csound, "abs", "k[]", "k[]",
                                   csnd::thread::ik);
  csnd::plugin<ArrayOp<std::log10>>(csound, "log2", "i[]", "i[]",
                                    csnd::thread::i);
  csnd::plugin<ArrayOp<std::log10>>(csound, "log2", "k[]", "k[]",
                                    csnd::thread::ik);
  csnd::plugin<ArrayOp<std::log10>>(csound, "log10", "i[]", "i[]",
                                    csnd::thread::i);
  csnd::plugin<ArrayOp<std::log10>>(csound, "log10", "k[]", "k[]",
                                    csnd::thread::ik);
  csnd::plugin<ArrayOp<std::log>>(csound, "log", "i[]", "i[]", csnd::thread::i);
  csnd::plugin<ArrayOp<std::log>>(csound, "log", "k[]", "k[]", csnd::thread::ik);
  csnd::plugin<ArrayOp<std::exp>>(csound, "exp", "i[]", "i[]", csnd::thread::i);
  csnd::plugin<ArrayOp<std::exp>>(csound, "exp", "k[]", "k[]", csnd::thread::ik);
  csnd::plugin<ArrayOp<std::sqrt>>(csound, "sqrt", "i[]", "i[]",
                                   csnd::thread::i);
  csnd::plugin<ArrayOp<std::sqrt>>(csound, "sqrt", "k[]", "k[]",
                                   csnd::thread::ik);
  csnd::plugin<ArrayOp<std::cos>>(csound, "cos", "i[]", "i[]", csnd::thread::i);
  csnd::plugin<ArrayOp<std::cos>>(csound, "cos", "k[]", "k[]",
                                  csnd::thread::ik);
  csnd::plugin<ArrayOp<std::sin>>(csound, "sin", "i[]", "i[]", csnd::thread::i);
  csnd::plugin<ArrayOp<std::sin>>(csound, "sin", "k[]", "k[]",
                                  csnd::thread::ik);
  csnd::plugin<ArrayOp<std::tan>>(csound, "tan", "i[]", "i[]", csnd::thread::i);
  csnd::plugin<ArrayOp<std::tan>>(csound, "tan", "k[]", "k[]",
                                  csnd::thread::ik);
  csnd::plugin<ArrayOp<std::acos>>(csound, "cosinv", "i[]", "i[]",
                                   csnd::thread::i);
  csnd::plugin<ArrayOp<std::acos>>(csound, "cosinv", "k[]", "k[]",
                                   csnd::thread::ik);
  csnd::plugin<ArrayOp<std::asin>>(csound, "sininv", "i[]", "i[]",
                                   csnd::thread::i);
  csnd::plugin<ArrayOp<std::asin>>(csound, "sininv", "k[]", "k[]",
                                   csnd::thread::ik);
  csnd::plugin<ArrayOp<std::atan>>(csound, "taninv", "i[]", "i[]",
                                   csnd::thread::i);
  csnd::plugin<ArrayOp<std::atan>>(csound, "taninv", "k[]", "k[]",
                                   csnd::thread::ik);
  csnd::plugin<ArrayOp<std::cosh>>(csound, "cosh", "i[]", "i[]",
                                   csnd::thread::i);
  csnd::plugin<ArrayOp<std::cosh>>(csound, "cosh", "k[]", "k[]",
                                   csnd::thread::ik);
  csnd::plugin<ArrayOp<std::sinh>>(csound, "sinh", "i[]", "i[]",
                                   csnd::thread::i);
  csnd::plugin<ArrayOp<std::sinh>>(csound, "sinh", "k[]", "k[]",
                                   csnd::thread::ik);
  csnd::plugin<ArrayOp<std::tanh>>(csound, "tanh", "i[]", "i[]",
                                   csnd::thread::i);
  csnd::plugin<ArrayOp<std::tanh>>(csound, "tanh", "k[]", "k[]",
                                   csnd::thread::ik);
  csnd::plugin<ArrayOp<std::cbrt>>(csound, "cbrt", "i[]", "i[]",
                                   csnd::thread::i);
  csnd::plugin<ArrayOp<std::cbrt>>(csound, "cbrt", "k[]", "k[]",
                                   csnd::thread::ik);
  csnd::plugin<ArrayOp2<std::atan2>>(csound, "taninv", "i[]", "i[]i[]",
                                     csnd::thread::i);
  csnd::plugin<ArrayOp2<std::atan2>>(csound, "taninv", "k[]", "k[]k[]",
                                     csnd::thread::ik);
  csnd::plugin<ArrayOp2<std::pow>>(csound, "pow", "i[]", "i[]i[]",
                                   csnd::thread::i);
  csnd::plugin<ArrayOp2<std::pow>>(csound, "pow", "k[]", "k[]k[]",
                                   csnd::thread::ik);
  csnd::plugin<ArrayOp2<std::hypot>>(csound, "hypot", "i[]", "i[]i[]",
                                     csnd::thread::i);
  csnd::plugin<ArrayOp2<std::hypot>>(csound, "hypot", "k[]", "k[]k[]",
                                     csnd::thread::ik);
  csnd::plugin<ArrayOp2<std::fmod>>(csound, "fmod", "i[]", "i[]i[]",
                                    csnd::thread::i);
  csnd::plugin<ArrayOp2<std::fmod>>(csound, "fmod", "k[]", "k[]k[]",
                                    csnd::thread::ik);
  csnd::plugin<ArrayOp2<std::fmax>>(csound, "fmax", "i[]", "i[]i[]",
                                    csnd::thread::i);
  csnd::plugin<ArrayOp2<std::fmax>>(csound, "fmax", "k[]", "k[]k[]",
                                    csnd::thread::ik);
  csnd::plugin<ArrayOp2<std::fmin>>(csound, "fmin", "i[]", "i[]i[]",
                                    csnd::thread::i);
  csnd::plugin<ArrayOp2<std::fmin>>(csound, "fmin", "k[]", "k[]k[]",
                                    csnd::thread::ik);
}
<commit_msg>array sorting<commit_after>/*
  arrayops.c: array operators

  Copyright (C) 2017 Victor Lazzarini
  This file is part of Csound.

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

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

  You should have received a copy of the GNU Lesser General Public
  License along with Csound; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
  02111-1307 USA
*/
#include <algorithm>
#include <cmath>
#include <functional>
#include <plugin.h>

extern inline MYFLT frac(MYFLT f) { return std::modf(f, &f); }

/** i-time, k-rate operator
    kout[] op kin[]
 */
template <MYFLT (*op)(MYFLT)> struct ArrayOp : csnd::Plugin<1, 1> {
  int process(csnd::myfltvec &out, csnd::myfltvec &in) {
    std::transform(in.begin(), in.end(), out.begin(),
                   [](MYFLT f) { return op(f); });
    return OK;
  }

  int init() {
    csnd::myfltvec &out = outargs.myfltvec_data(0);
    csnd::myfltvec &in = inargs.myfltvec_data(0);
    out.init(csound, in.len());
    return process(out, in);
  }

  int kperf() {
    return process(outargs.myfltvec_data(0), inargs.myfltvec_data(0));
  }
};

/** i-time, k-rate binary operator
    kout[] op kin1[], kin2[]
 */
template <MYFLT (*bop)(MYFLT, MYFLT)> struct ArrayOp2 : csnd::Plugin<1, 2> {

  int process(csnd::myfltvec &out, csnd::myfltvec &in1, csnd::myfltvec &in2) {
    std::transform(in1.begin(), in1.end(), in2.begin(), out.begin(),
                   [](MYFLT f1, MYFLT f2) { return bop(f1, f2); });
    return OK;
  }

  int init() {
    csnd::myfltvec &out = outargs.myfltvec_data(0);
    csnd::myfltvec &in1 = inargs.myfltvec_data(0);
    csnd::myfltvec &in2 = inargs.myfltvec_data(1);
    if (in2.len() < in1.len())
      return csound->init_error(Str("second input array is too short\n"));
    out.init(csound, in1.len());
    return process(out, in1, in2);
  }

  int kperf() {
    return process(outargs.myfltvec_data(0), inargs.myfltvec_data(0),
                   inargs.myfltvec_data(1));
  }
};

/** i-time, k-rate operator
    kout[] sort[a,d] kin[]
 */
template <typename T>struct ArraySort : csnd::Plugin<1, 1> {
  int process(csnd::myfltvec &out, csnd::myfltvec &in) {
    std::copy(in.begin(), in.end(), out.begin());
    std::sort(out.begin(), out.end(), T());
    return OK;
  }

  int init() {
    csnd::myfltvec &out = outargs.myfltvec_data(0);
    csnd::myfltvec &in = inargs.myfltvec_data(0);
    out.init(csound, in.len());
    return process(out, in);
  }

  int kperf() {
    return process(outargs.myfltvec_data(0), inargs.myfltvec_data(0));
  }
};

#include <modload.h>
void csnd::on_load(Csound *csound) {
  csnd::plugin<ArrayOp<std::ceil>>(csound, "ceil", "i[]", "i[]",
                                   csnd::thread::i);
  csnd::plugin<ArrayOp<std::ceil>>(csound, "ceil", "k[]", "k[]",
                                   csnd::thread::ik);
  csnd::plugin<ArrayOp<std::floor>>(csound, "floor", "i[]", "i[]",
                                    csnd::thread::i);
  csnd::plugin<ArrayOp<std::floor>>(csound, "floor", "k[]", "k[]",
                                    csnd::thread::ik);
  csnd::plugin<ArrayOp<std::round>>(csound, "round", "i[]", "i[]",
                                    csnd::thread::i);
  csnd::plugin<ArrayOp<std::round>>(csound, "round", "k[]", "k[]",
                                    csnd::thread::ik);
  csnd::plugin<ArrayOp<std::trunc>>(csound, "int", "i[]", "i[]",
                                    csnd::thread::i);
  csnd::plugin<ArrayOp<std::trunc>>(csound, "int", "k[]", "k[]",
                                    csnd::thread::i);
  csnd::plugin<ArrayOp<frac>>(csound, "frac", "i[]", "i[]", csnd::thread::i);
  csnd::plugin<ArrayOp<frac>>(csound, "frac", "k[]", "k[]", csnd::thread::ik);
  csnd::plugin<ArrayOp<std::exp2>>(csound, "powoftwo", "i[]", "i[]",
                                   csnd::thread::i);
  csnd::plugin<ArrayOp<std::exp2>>(csound, "powoftwo", "k[]", "k[]",
                                   csnd::thread::ik);
  csnd::plugin<ArrayOp<std::fabs>>(csound, "abs", "i[]", "i[]",
                                   csnd::thread::i);
  csnd::plugin<ArrayOp<std::fabs>>(csound, "abs", "k[]", "k[]",
                                   csnd::thread::ik);
  csnd::plugin<ArrayOp<std::log10>>(csound, "log2", "i[]", "i[]",
                                    csnd::thread::i);
  csnd::plugin<ArrayOp<std::log10>>(csound, "log2", "k[]", "k[]",
                                    csnd::thread::ik);
  csnd::plugin<ArrayOp<std::log10>>(csound, "log10", "i[]", "i[]",
                                    csnd::thread::i);
  csnd::plugin<ArrayOp<std::log10>>(csound, "log10", "k[]", "k[]",
                                    csnd::thread::ik);
  csnd::plugin<ArrayOp<std::log>>(csound, "log", "i[]", "i[]", csnd::thread::i);
  csnd::plugin<ArrayOp<std::log>>(csound, "log", "k[]", "k[]", csnd::thread::ik);
  csnd::plugin<ArrayOp<std::exp>>(csound, "exp", "i[]", "i[]", csnd::thread::i);
  csnd::plugin<ArrayOp<std::exp>>(csound, "exp", "k[]", "k[]", csnd::thread::ik);
  csnd::plugin<ArrayOp<std::sqrt>>(csound, "sqrt", "i[]", "i[]",
                                   csnd::thread::i);
  csnd::plugin<ArrayOp<std::sqrt>>(csound, "sqrt", "k[]", "k[]",
                                   csnd::thread::ik);
  csnd::plugin<ArrayOp<std::cos>>(csound, "cos", "i[]", "i[]", csnd::thread::i);
  csnd::plugin<ArrayOp<std::cos>>(csound, "cos", "k[]", "k[]",
                                  csnd::thread::ik);
  csnd::plugin<ArrayOp<std::sin>>(csound, "sin", "i[]", "i[]", csnd::thread::i);
  csnd::plugin<ArrayOp<std::sin>>(csound, "sin", "k[]", "k[]",
                                  csnd::thread::ik);
  csnd::plugin<ArrayOp<std::tan>>(csound, "tan", "i[]", "i[]", csnd::thread::i);
  csnd::plugin<ArrayOp<std::tan>>(csound, "tan", "k[]", "k[]",
                                  csnd::thread::ik);
  csnd::plugin<ArrayOp<std::acos>>(csound, "cosinv", "i[]", "i[]",
                                   csnd::thread::i);
  csnd::plugin<ArrayOp<std::acos>>(csound, "cosinv", "k[]", "k[]",
                                   csnd::thread::ik);
  csnd::plugin<ArrayOp<std::asin>>(csound, "sininv", "i[]", "i[]",
                                   csnd::thread::i);
  csnd::plugin<ArrayOp<std::asin>>(csound, "sininv", "k[]", "k[]",
                                   csnd::thread::ik);
  csnd::plugin<ArrayOp<std::atan>>(csound, "taninv", "i[]", "i[]",
                                   csnd::thread::i);
  csnd::plugin<ArrayOp<std::atan>>(csound, "taninv", "k[]", "k[]",
                                   csnd::thread::ik);
  csnd::plugin<ArrayOp<std::cosh>>(csound, "cosh", "i[]", "i[]",
                                   csnd::thread::i);
  csnd::plugin<ArrayOp<std::cosh>>(csound, "cosh", "k[]", "k[]",
                                   csnd::thread::ik);
  csnd::plugin<ArrayOp<std::sinh>>(csound, "sinh", "i[]", "i[]",
                                   csnd::thread::i);
  csnd::plugin<ArrayOp<std::sinh>>(csound, "sinh", "k[]", "k[]",
                                   csnd::thread::ik);
  csnd::plugin<ArrayOp<std::tanh>>(csound, "tanh", "i[]", "i[]",
                                   csnd::thread::i);
  csnd::plugin<ArrayOp<std::tanh>>(csound, "tanh", "k[]", "k[]",
                                   csnd::thread::ik);
  csnd::plugin<ArrayOp<std::cbrt>>(csound, "cbrt", "i[]", "i[]",
                                   csnd::thread::i);
  csnd::plugin<ArrayOp<std::cbrt>>(csound, "cbrt", "k[]", "k[]",
                                   csnd::thread::ik);
  csnd::plugin<ArrayOp2<std::atan2>>(csound, "taninv", "i[]", "i[]i[]",
                                     csnd::thread::i);
  csnd::plugin<ArrayOp2<std::atan2>>(csound, "taninv", "k[]", "k[]k[]",
                                     csnd::thread::ik);
  csnd::plugin<ArrayOp2<std::pow>>(csound, "pow", "i[]", "i[]i[]",
                                   csnd::thread::i);
  csnd::plugin<ArrayOp2<std::pow>>(csound, "pow", "k[]", "k[]k[]",
                                   csnd::thread::ik);
  csnd::plugin<ArrayOp2<std::hypot>>(csound, "hypot", "i[]", "i[]i[]",
                                     csnd::thread::i);
  csnd::plugin<ArrayOp2<std::hypot>>(csound, "hypot", "k[]", "k[]k[]",
                                     csnd::thread::ik);
  csnd::plugin<ArrayOp2<std::fmod>>(csound, "fmod", "i[]", "i[]i[]",
                                    csnd::thread::i);
  csnd::plugin<ArrayOp2<std::fmod>>(csound, "fmod", "k[]", "k[]k[]",
                                    csnd::thread::ik);
  csnd::plugin<ArrayOp2<std::fmax>>(csound, "fmax", "i[]", "i[]i[]",
                                    csnd::thread::i);
  csnd::plugin<ArrayOp2<std::fmax>>(csound, "fmax", "k[]", "k[]k[]",
                                    csnd::thread::ik);
  csnd::plugin<ArrayOp2<std::fmin>>(csound, "fmin", "i[]", "i[]i[]",
                                    csnd::thread::i);
  csnd::plugin<ArrayOp2<std::fmin>>(csound, "fmin", "k[]", "k[]k[]",
                                    csnd::thread::ik);
  csnd::plugin<ArraySort<std::less<MYFLT>>>(csound, "sorta", "i[]", "i[]",
                                    csnd::thread::i);
  csnd::plugin<ArraySort<std::greater<MYFLT>>>(csound, "sortd", "i[]", "i[]",
                                    csnd::thread::i);
  csnd::plugin<ArraySort<std::less<MYFLT>>>(csound, "sorta", "k[]", "k[]",
                                    csnd::thread::ik);
  csnd::plugin<ArraySort<std::greater<MYFLT>>>(csound, "sortd", "k[]", "k[]",
                                    csnd::thread::ik);

}
<|endoftext|>


<commit_before>#include "Device.h"
#include "Settings.h"
#include <Wire.h>

int Settings::capability_bitarray = 0;
int Settings::smoothingIncriment = 40; //How aggressive the throttle changes
int Settings::deadZone_min = MIDPOINT;
int Settings::deadZone_max = MIDPOINT;
bool Settings::water_type = 0; //Freshwater

void Settings::device_setup(){
Wire.begin();
}

void Settings::device_loop(Command command){
    if (command.cmp("reportSetting")) {
      Serial.print(F("*settings:"));
      Serial.print(F("smoothingIncriment|"));
      Serial.print(String(Settings::smoothingIncriment) + ",");
      Serial.print(F("deadZone_min|"));
      Serial.print(String(Settings::deadZone_min) + ",");
      Serial.print(F("deadZone_max|"));
      Serial.print(String(Settings::deadZone_max) + ";");
      Serial.print(F("water_type"));
      Serial.println(String(Settings::water_type) + ";");

    }
    else if (command.cmp("rcap")){ //report capabilities
      Serial.print(F("CAPA:"));
      Serial.print(capability_bitarray);
      Serial.print(';');
      scan_i2c();
    }
    else if (command.cmp("updateSetting")) {
      Settings::smoothingIncriment = command.args[1];
      Settings::deadZone_min = command.args[2];
      Settings::deadZone_max = command.args[3];
      Settings::water_type = command.args[4];
    }

}

void Settings::scan_i2c(){
  byte error, address;
  int nDevices;

  Serial.println(F("log:Scanning...;"));

  nDevices = 0;
  for(address = 1; address < 127; address++ )
  {
    // The i2c_scanner uses the return value of
    // the Write.endTransmisstion to see if
    // a device did acknowledge to the address.
    Wire.beginTransmission(address);
    error = Wire.endTransmission();

    if (error == 0)
    {
      Serial.print(F("log:I2C device found at address 0x"));
      if (address<16)
        Serial.print("0");
      Serial.print(address,HEX);
      Serial.println("  !;");

      nDevices++;
    }
    else if (error==4)
    {
      Serial.print(F("log:Unknow error at address 0x"));
      if (address<16)
        Serial.print("0");
      Serial.print(address,HEX);
      Serial.println(";");
    }
  }
  if (nDevices == 0)
    Serial.println(F("log:No I2C devices found\n;"));
  else
    Serial.println(F("log:done\n;"));

  delay(5000);           // wait 5 seconds for next scan

}
<commit_msg>Hardcoded deadzone for thrusters<commit_after>#include "Device.h"
#include "Settings.h"
#include <Wire.h>

int Settings::capability_bitarray = 0;
int Settings::smoothingIncriment = 40; //How aggressive the throttle changes
int Settings::deadZone_min = 25;
int Settings::deadZone_max = 25;
bool Settings::water_type = 0; //Freshwater

void Settings::device_setup(){
Wire.begin();
}

void Settings::device_loop(Command command){
    if (command.cmp("reportSetting")) {
      Serial.print(F("*settings:"));
      Serial.print(F("smoothingIncriment|"));
      Serial.print(String(Settings::smoothingIncriment) + ",");
      Serial.print(F("deadZone_min|"));
      Serial.print(String(Settings::deadZone_min) + ",");
      Serial.print(F("deadZone_max|"));
      Serial.print(String(Settings::deadZone_max) + ";");
      Serial.print(F("water_type"));
      Serial.println(String(Settings::water_type) + ";");

    }
    else if (command.cmp("rcap")){ //report capabilities
      Serial.print(F("CAPA:"));
      Serial.print(capability_bitarray);
      Serial.print(';');
      scan_i2c();
    }
    else if (command.cmp("updateSetting")) {
      //TODO: Need to update the motors with new deadZone setting. Probably move
      //deadzone to the thruster resposibilitiy
      Settings::smoothingIncriment = command.args[1];
      Settings::deadZone_min = command.args[2];
      Settings::deadZone_max = command.args[3];
      Settings::water_type = command.args[4];
    }

}

void Settings::scan_i2c(){
  byte error, address;
  int nDevices;

  Serial.println(F("log:Scanning...;"));

  nDevices = 0;
  for(address = 1; address < 127; address++ )
  {
    // The i2c_scanner uses the return value of
    // the Write.endTransmisstion to see if
    // a device did acknowledge to the address.
    Wire.beginTransmission(address);
    error = Wire.endTransmission();

    if (error == 0)
    {
      Serial.print(F("log:I2C device found at address 0x"));
      if (address<16)
        Serial.print("0");
      Serial.print(address,HEX);
      Serial.println("  !;");

      nDevices++;
    }
    else if (error==4)
    {
      Serial.print(F("log:Unknow error at address 0x"));
      if (address<16)
        Serial.print("0");
      Serial.print(address,HEX);
      Serial.println(";");
    }
  }
  if (nDevices == 0)
    Serial.println(F("log:No I2C devices found\n;"));
  else
    Serial.println(F("log:done\n;"));

  delay(5000);           // wait 5 seconds for next scan

}
<|endoftext|>


<commit_before>/**
 * File    : D.cpp
 * Author  : Kazune Takahashi
 * Created : 2018-7-7 21:58:13
 * Powered by Visual Studio Code
 */

#include <iostream>
#include <iomanip>   // << fixed << setprecision(xxx)
#include <algorithm> // do { } while ( next_permutation(A, A+xxx) ) ;
#include <vector>
#include <string> // to_string(nnn) // substr(m, n) // stoi(nnn)
#include <complex>
#include <tuple>
#include <queue>
#include <stack>
#include <map> // if (M.find(key) != M.end()) { }
#include <set>
#include <functional>
#include <random> // auto rd = bind(uniform_int_distribution<int>(0, 9), mt19937(19920725));
#include <chrono> // std::chrono::system_clock::time_point start_time, end_time;
// start = std::chrono::system_clock::now();
// double elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(end_time-start_time).count();
#include <cctype>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
using namespace std;

#define DEBUG 0 // change 0 -> 1 if we need debug.

typedef long long ll;

// const int dx[4] = {1, 0, -1, 0};
// const int dy[4] = {0, 1, 0, -1};

// const int C = 1e6+10;
// const ll M = 1000000007;

typedef tuple<ll, int> P;

int N, M;
int S[2];
vector<P> V[2][100010];
priority_queue<P, vector<P>, greater<P>> Q[2];
ll dist[2][100010];
ll ans[100010];

int main()
{
  cin >> N >> M >> S[0] >> S[1];
  S[0]--;
  S[1]--;
  for (auto i = 0; i < M; i++)
  {
    int u, v, a, b;
    cin >> u >> v >> a >> b;
    u--;
    v--;
    V[0][u].push_back(P(a, v));
    V[0][v].push_back(P(a, u));
    V[1][v].push_back(P(b, u));
    V[1][u].push_back(P(b, v));
  }
  fill(&dist[0][0], &dist[0][0] + 2 * 100010, -1);
  for (auto k = 0; k < 2; k++)
  {
    Q[k].push(P(0, S[k]));
    while (!Q[k].empty())
    {
      ll d = get<0>(Q[k].top());
      int now = get<1>(Q[k].top());
      cerr << "now = " << now << endl;
      Q[k].pop();
      if (dist[k][now] == -1)
      {
        dist[k][now] = d;
        for (auto x : V[2][now])
        {
          ll new_d = get<0>(x);
          int dst = get<1>(x);
          if (dist[k][dst] == -1)
          {
            Q[k].push(P(d + new_d, dst));
          }
        }
      }
    }
  }
  for (auto i = 0; i < N; i++)
  {
    ans[i] = dist[0][i] + dist[1][i];
    cerr << "dist[0][" << i << "] = " << dist[0][i] << endl;
    cerr << "dist[1][" << i << "] = " << dist[1][i] << endl;
  }
  for (auto i = N - 1; i >= 1; i--)
  {
    ans[i - 1] = min(ans[i - 1], ans[i]);
  }
  ll X = 1000000000000000;
  for (auto i = 0; i < N; i++)
  {
    cout << X - ans[i] << endl;
  }
}<commit_msg>submit D.cpp to 'D - Saving Snuuk' (soundhound2018-summer-qual) [C++14 (GCC 5.4.1)]<commit_after>/**
 * File    : D.cpp
 * Author  : Kazune Takahashi
 * Created : 2018-7-7 21:58:13
 * Powered by Visual Studio Code
 */

#include <iostream>
#include <iomanip>   // << fixed << setprecision(xxx)
#include <algorithm> // do { } while ( next_permutation(A, A+xxx) ) ;
#include <vector>
#include <string> // to_string(nnn) // substr(m, n) // stoi(nnn)
#include <complex>
#include <tuple>
#include <queue>
#include <stack>
#include <map> // if (M.find(key) != M.end()) { }
#include <set>
#include <functional>
#include <random> // auto rd = bind(uniform_int_distribution<int>(0, 9), mt19937(19920725));
#include <chrono> // std::chrono::system_clock::time_point start_time, end_time;
// start = std::chrono::system_clock::now();
// double elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(end_time-start_time).count();
#include <cctype>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstdlib>
using namespace std;

#define DEBUG 0 // change 0 -> 1 if we need debug.

typedef long long ll;

// const int dx[4] = {1, 0, -1, 0};
// const int dy[4] = {0, 1, 0, -1};

// const int C = 1e6+10;
// const ll M = 1000000007;

typedef tuple<ll, int> P;

int N, M;
int S[2];
vector<P> V[2][100010];
priority_queue<P, vector<P>, greater<P>> Q[2];
ll dist[2][100010];
ll ans[100010];

int main()
{
  cin >> N >> M >> S[0] >> S[1];
  S[0]--;
  S[1]--;
  for (auto i = 0; i < M; i++)
  {
    int u, v, a, b;
    cin >> u >> v >> a >> b;
    u--;
    v--;
    V[0][u].push_back(P(a, v));
    V[0][v].push_back(P(a, u));
    V[1][v].push_back(P(b, u));
    V[1][u].push_back(P(b, v));
  }
  fill(&dist[0][0], &dist[0][0] + 2 * 100010, -1);
  for (auto k = 0; k < 2; k++)
  {
    Q[k].push(P(0, S[k]));
    while (!Q[k].empty())
    {
      ll d = get<0>(Q[k].top());
      int now = get<1>(Q[k].top());
      Q[k].pop();
      if (dist[k][now] == -1)
      {
        dist[k][now] = d;
        for (auto x : V[k][now])
        {
          ll new_d = get<0>(x);
          int dst = get<1>(x);
          if (dist[k][dst] == -1)
          {
            Q[k].push(P(d + new_d, dst));
          }
        }
      }
    }
  }
  for (auto i = 0; i < N; i++)
  {
    ans[i] = dist[0][i] + dist[1][i];
    //cerr << "dist[0][" << i << "] = " << dist[0][i] << endl;
    //cerr << "dist[1][" << i << "] = " << dist[1][i] << endl;
  }
  for (auto i = N - 1; i >= 1; i--)
  {
    ans[i - 1] = min(ans[i - 1], ans[i]);
  }
  ll X = 1000000000000000;
  for (auto i = 0; i < N; i++)
  {
    cout << X - ans[i] << endl;
  }
}<|endoftext|>


<commit_before><commit_msg>Fix test<commit_after><|endoftext|>


<commit_before>#include "stdafx.h"

#include "ClientToolsCssV34.h"

#include "addresses.h"
#include "RenderView.h"

#include <cssV34/sdk_src/public/tier1/KeyValues.h>
#include <cssV34/sdk_src/public/tools/bonelist.h>

#include <shared/StringTools.h>

#include <Windows.h>
#include <deps/release/Detours/src/detours.h>

using namespace SOURCESDK::CSSV34;

SOURCESDK::CStudioHdr * g_cssv34_hdr = nullptr;
std::vector<SOURCESDK::matrix3x4_t> g_cssv34_BoneState;

typedef void *  (__fastcall * cssv34_C_BaseAnimating_RecordBones_t)(void * This, void* Edx, SOURCESDK::CStudioHdr *hdr, SOURCESDK::matrix3x4_t *pBoneState );
cssv34_C_BaseAnimating_RecordBones_t True_cssv34_C_BaseAnimating_RecordBones = nullptr;
void * __fastcall My_cssv34_C_BaseAnimating_RecordBones(void * This, void* Edx, SOURCESDK::CStudioHdr *hdr, SOURCESDK::matrix3x4_t *pBoneState ) {
	void * result = True_cssv34_C_BaseAnimating_RecordBones(This, Edx, hdr, pBoneState);
	g_cssv34_hdr =  hdr;
	if(g_cssv34_BoneState.size() < hdr->numbones()) g_cssv34_BoneState.resize(hdr->numbones());
	memcpy(&(g_cssv34_BoneState[0]),pBoneState,sizeof(SOURCESDK::matrix3x4_t) * hdr->numbones());
	return result;
}

bool cssv34_C_BaseAnimating_RecordBones_Install(void)
{
	static bool firstResult = false;
	static bool firstRun = true;
	if (!firstRun) return firstResult;
	firstRun = false;

	if (AFXADDR_GET(cssv34_client_C_BaseAnimating_RecordBones))
	{
		LONG error = NO_ERROR;

		True_cssv34_C_BaseAnimating_RecordBones = (cssv34_C_BaseAnimating_RecordBones_t)AFXADDR_GET(cssv34_client_C_BaseAnimating_RecordBones);

		DetourTransactionBegin();
		DetourUpdateThread(GetCurrentThread());
		DetourAttach(&(PVOID&)True_cssv34_C_BaseAnimating_RecordBones, My_cssv34_C_BaseAnimating_RecordBones);
		error = DetourTransactionCommit();

		firstResult = NO_ERROR == error;
	}

	return firstResult;
}

CClientToolsCssV34 * CClientToolsCssV34::m_Instance = 0;

CClientToolsCssV34::CClientToolsCssV34(SOURCESDK::CSSV34::IClientTools * clientTools)
	: CClientTools()
	, m_ClientTools(clientTools)
{
	m_Instance = this;
}

CClientToolsCssV34::~CClientToolsCssV34()
{
	m_Instance = 0;
}

void CClientToolsCssV34::OnPostToolMessage(void * hEntity, void * msg)
{
	CClientTools::OnPostToolMessage(hEntity, msg);

	OnPostToolMessageCssV34(reinterpret_cast<SOURCESDK::CSSV34::HTOOLHANDLE>(hEntity), reinterpret_cast<SOURCESDK::CSSV34::KeyValues *>(msg));
}

void CClientToolsCssV34::OnPostToolMessageCssV34(SOURCESDK::CSSV34::HTOOLHANDLE hEntity, SOURCESDK::CSSV34::KeyValues * msg)
{
	if (!(hEntity != SOURCESDK::CSSV34::HTOOLHANDLE_INVALID && msg))
		return;

	char const * msgName = msg->GetName();

	if (!strcmp("entity_state", msgName))
	{
		if (GetRecording())
		{
			char const * className = m_ClientTools->GetClassname(hEntity);
			if (!className) className = "[NULL]";

			if (0 != Debug_get())
			{
				if (2 <= Debug_get())
				{
					Tier0_Msg("-- %s (%i) --\n", className, hEntity);
					for (SOURCESDK::CSSV34::KeyValues * subKey = msg->GetFirstSubKey(); 0 != subKey; subKey = subKey->GetNextKey())
						Tier0_Msg("%s,\n", subKey->GetName());
					Tier0_Msg("----\n");
				}

				if (SOURCESDK::CSSV34::BaseEntityRecordingState_t * pBaseEntityRs = (SOURCESDK::CSSV34::BaseEntityRecordingState_t *)(msg->GetPtr("baseentity")))
				{
					Tier0_Msg("%i: %s: %s\n", hEntity, className, pBaseEntityRs->m_pModelName);
				}
			}

			bool isPlayer =
				false
				|| className && (
					!strcmp(className, "class C_CSPlayer")
					|| !strcmp(className, "class C_CSRagdoll")
					)
				;

			bool isWeapon =
				false
				|| className && (
					StringBeginsWith(className, "weapon_")
					|| !strcmp(className, "class C_BreakableProp")
					)
				;

			bool isProjectile =
				className && !strcmp(className, "grenade")
				;

			bool isViewModel =
				className && (
					!strcmp(className, "viewmodel")
					)
				;

			if (false
				|| RecordPlayers_get() && isPlayer
				|| RecordWeapons_get() && isWeapon
				|| RecordProjectiles_get() && isProjectile
				|| RecordViewModels_get() && isViewModel
				)
			{
				SOURCESDK::CSSV34::BaseEntityRecordingState_t * pBaseEntityRs = (SOURCESDK::CSSV34::BaseEntityRecordingState_t *)(msg->GetPtr("baseentity"));

				if (!RecordInvisible_get() && !(pBaseEntityRs && pBaseEntityRs->m_bVisible))
				{
					// Entity not visible, avoid trash data:

					std::map<SOURCESDK::CSSV34::HTOOLHANDLE, bool>::iterator it = m_TrackedHandles.find(hEntity);
					if (it != m_TrackedHandles.end() && it->second)
					{
						MarkHidden((int)(it->first));

						it->second = false;
					}

					return;
				}

				bool wasVisible = false;
				bool hasParentTransform = false;
				SOURCESDK::matrix3x4_t parentTransform;

				WriteDictionary("entity_state");
				Write((int)hEntity);
				{
					SOURCESDK::CSSV34::BaseEntityRecordingState_t * pBaseEntityRs = (SOURCESDK::CSSV34::BaseEntityRecordingState_t *)(msg->GetPtr("baseentity"));
					if (pBaseEntityRs)
					{
						WriteDictionary("baseentity");
						//Write((float)pBaseEntityRs->m_flTime);
						WriteDictionary(pBaseEntityRs->m_pModelName);
						Write((bool)wasVisible);

						hasParentTransform = true;
						SOURCESDK::AngleMatrix(pBaseEntityRs->m_vecRenderAngles, pBaseEntityRs->m_vecRenderOrigin, parentTransform);
						WriteMatrix3x4(parentTransform);
					}
				}

				m_TrackedHandles[hEntity] = wasVisible;

				{
					SOURCESDK::CSSV34::BaseAnimatingRecordingState_t * pBaseAnimatingRs = (SOURCESDK::CSSV34::BaseAnimatingRecordingState_t *)(msg->GetPtr("baseanimating"));
					if (pBaseAnimatingRs && hasParentTransform)
					{
						WriteDictionary("baseanimating");
						//Write((int)pBaseAnimatingRs->m_nSkin);
						//Write((int)pBaseAnimatingRs->m_nBody);
						//Write((int)pBaseAnimatingRs->m_nSequence);
						WriteBones(g_cssv34_hdr, &(g_cssv34_BoneState[0]), parentTransform);
					}
				}

				WriteDictionary("/");

				bool viewModel = 0 != msg->GetInt("viewmodel");

				Write((bool)viewModel);
			}
		}
	}
	else if (!strcmp("deleted", msgName))
	{
		std::map<SOURCESDK::CSSV34::HTOOLHANDLE, bool>::iterator it = m_TrackedHandles.find(hEntity);
		if (it != m_TrackedHandles.end())
		{
			if (GetRecording())
			{
				WriteDictionary("deleted");
				Write((int)(it->first));
			}

			m_TrackedHandles.erase(it);
		}
	}
	else if (!strcmp("created", msgName))
	{
		if (0 != Debug_get() && hEntity != SOURCESDK::CSGO::HTOOLHANDLE_INVALID)
		{
			const char * className = m_ClientTools->GetClassname(hEntity);
			if (!className) className = "[NULL]";

			Tier0_Msg("%i n/a: %s\n", hEntity, className);
		}

		if (hEntity != SOURCESDK::CSGO::HTOOLHANDLE_INVALID)// && m_ClientTools->ShouldRecord(hEntity))
		{
			m_TrackedHandles[hEntity] = false;
			if(GetRecording()) m_ClientTools->SetRecording(hEntity, true);
		}
	}
}

void CClientToolsCssV34::OnBeforeFrameRenderStart(void)
{
	CClientTools::OnBeforeFrameRenderStart();

}

void CClientToolsCssV34::OnAfterFrameRenderEnd(void)
{

	CClientTools::OnAfterFrameRenderEnd();
}

void CClientToolsCssV34::EnableRecordingMode_set(bool value) {
	m_ClientTools->EnableRecordingMode(value);
}

bool CClientToolsCssV34::EnableRecordingMode_get() {
	return m_ClientTools->IsInRecordingMode();
}

void CClientToolsCssV34::StartRecording(wchar_t const * fileName)
{
	CClientTools::StartRecording(fileName);

	if (GetRecording())
	{
		if(!cssv34_C_BaseAnimating_RecordBones_Install())
		{
			Tier0_Warning("AFX: Failed to install IClientRenderable::SetupBones hook.\n");
		}

		for (std::map<SOURCESDK::CSSV34::HTOOLHANDLE, bool>::iterator it = m_TrackedHandles.begin(); it != m_TrackedHandles.end(); ++it)
		{
			m_ClientTools->SetRecording(it->first, true);
		}
	}
}

void CClientToolsCssV34::EndRecording()
{
	if (GetRecording())
	{
		for (std::map<SOURCESDK::CSSV34::HTOOLHANDLE, bool>::iterator it = m_TrackedHandles.begin(); it != m_TrackedHandles.end(); ++it)
		{
			m_ClientTools->SetRecording(it->first, false);
		}
	}

	CClientTools::EndRecording();
}

void CClientToolsCssV34::Write(SOURCESDK::CSSV34::CBoneList const * value)
{
	Write((int)value->m_nBones);

	for (int i = 0; i < value->m_nBones; ++i)
	{
		Write(value->m_vecPos[i]);
		Write(value->m_quatRot[i]);
	}
}
<commit_msg>Fix CSSV34 AGRv6 RecordBones hook<commit_after>#include "stdafx.h"

#include "ClientToolsCssV34.h"

#include "addresses.h"
#include "RenderView.h"

#include <cssV34/sdk_src/public/tier1/KeyValues.h>
#include <cssV34/sdk_src/public/tools/bonelist.h>

#include <shared/StringTools.h>

#include <Windows.h>
#include <deps/release/Detours/src/detours.h>

using namespace SOURCESDK::CSSV34;

SOURCESDK::CStudioHdr * g_cssv34_hdr = nullptr;
std::vector<SOURCESDK::matrix3x4_t> g_cssv34_BoneState;

typedef void *  (__fastcall * cssv34_C_BaseAnimating_RecordBones_t)(SOURCESDK::CStudioHdr *hdr, void* Edx, SOURCESDK::matrix3x4_t *pBoneState );
cssv34_C_BaseAnimating_RecordBones_t True_cssv34_C_BaseAnimating_RecordBones = nullptr;
void * __fastcall My_cssv34_C_BaseAnimating_RecordBones(SOURCESDK::CStudioHdr *hdr, void* Edx, SOURCESDK::matrix3x4_t *pBoneState ) {
	void * result = True_cssv34_C_BaseAnimating_RecordBones(hdr, Edx, pBoneState);
	g_cssv34_hdr =  hdr;
	if(g_cssv34_BoneState.size() < hdr->numbones()) g_cssv34_BoneState.resize(hdr->numbones());
	memcpy(&(g_cssv34_BoneState[0]),pBoneState,sizeof(SOURCESDK::matrix3x4_t) * hdr->numbones());
	return result;
}

bool cssv34_C_BaseAnimating_RecordBones_Install(void)
{
	static bool firstResult = false;
	static bool firstRun = true;
	if (!firstRun) return firstResult;
	firstRun = false;

	if (AFXADDR_GET(cssv34_client_C_BaseAnimating_RecordBones))
	{
		LONG error = NO_ERROR;

		True_cssv34_C_BaseAnimating_RecordBones = (cssv34_C_BaseAnimating_RecordBones_t)AFXADDR_GET(cssv34_client_C_BaseAnimating_RecordBones);

		DetourTransactionBegin();
		DetourUpdateThread(GetCurrentThread());
		DetourAttach(&(PVOID&)True_cssv34_C_BaseAnimating_RecordBones, My_cssv34_C_BaseAnimating_RecordBones);
		error = DetourTransactionCommit();

		firstResult = NO_ERROR == error;
	}

	return firstResult;
}

CClientToolsCssV34 * CClientToolsCssV34::m_Instance = 0;

CClientToolsCssV34::CClientToolsCssV34(SOURCESDK::CSSV34::IClientTools * clientTools)
	: CClientTools()
	, m_ClientTools(clientTools)
{
	m_Instance = this;
}

CClientToolsCssV34::~CClientToolsCssV34()
{
	m_Instance = 0;
}

void CClientToolsCssV34::OnPostToolMessage(void * hEntity, void * msg)
{
	CClientTools::OnPostToolMessage(hEntity, msg);

	OnPostToolMessageCssV34(reinterpret_cast<SOURCESDK::CSSV34::HTOOLHANDLE>(hEntity), reinterpret_cast<SOURCESDK::CSSV34::KeyValues *>(msg));
}

void CClientToolsCssV34::OnPostToolMessageCssV34(SOURCESDK::CSSV34::HTOOLHANDLE hEntity, SOURCESDK::CSSV34::KeyValues * msg)
{
	if (!(hEntity != SOURCESDK::CSSV34::HTOOLHANDLE_INVALID && msg))
		return;

	char const * msgName = msg->GetName();

	if (!strcmp("entity_state", msgName))
	{
		if (GetRecording())
		{
			char const * className = m_ClientTools->GetClassname(hEntity);
			if (!className) className = "[NULL]";

			if (0 != Debug_get())
			{
				if (2 <= Debug_get())
				{
					Tier0_Msg("-- %s (%i) --\n", className, hEntity);
					for (SOURCESDK::CSSV34::KeyValues * subKey = msg->GetFirstSubKey(); 0 != subKey; subKey = subKey->GetNextKey())
						Tier0_Msg("%s,\n", subKey->GetName());
					Tier0_Msg("----\n");
				}

				if (SOURCESDK::CSSV34::BaseEntityRecordingState_t * pBaseEntityRs = (SOURCESDK::CSSV34::BaseEntityRecordingState_t *)(msg->GetPtr("baseentity")))
				{
					Tier0_Msg("%i: %s: %s\n", hEntity, className, pBaseEntityRs->m_pModelName);
				}
			}

			bool isPlayer =
				false
				|| className && (
					!strcmp(className, "class C_CSPlayer")
					|| !strcmp(className, "class C_CSRagdoll")
					)
				;

			bool isWeapon =
				false
				|| className && (
					StringBeginsWith(className, "weapon_")
					|| !strcmp(className, "class C_BreakableProp")
					)
				;

			bool isProjectile =
				className && !strcmp(className, "grenade")
				;

			bool isViewModel =
				className && (
					!strcmp(className, "viewmodel")
					)
				;

			if (false
				|| RecordPlayers_get() && isPlayer
				|| RecordWeapons_get() && isWeapon
				|| RecordProjectiles_get() && isProjectile
				|| RecordViewModels_get() && isViewModel
				)
			{
				SOURCESDK::CSSV34::BaseEntityRecordingState_t * pBaseEntityRs = (SOURCESDK::CSSV34::BaseEntityRecordingState_t *)(msg->GetPtr("baseentity"));

				if (!RecordInvisible_get() && !(pBaseEntityRs && pBaseEntityRs->m_bVisible))
				{
					// Entity not visible, avoid trash data:

					std::map<SOURCESDK::CSSV34::HTOOLHANDLE, bool>::iterator it = m_TrackedHandles.find(hEntity);
					if (it != m_TrackedHandles.end() && it->second)
					{
						MarkHidden((int)(it->first));

						it->second = false;
					}

					return;
				}

				bool wasVisible = false;
				bool hasParentTransform = false;
				SOURCESDK::matrix3x4_t parentTransform;

				WriteDictionary("entity_state");
				Write((int)hEntity);
				{
					SOURCESDK::CSSV34::BaseEntityRecordingState_t * pBaseEntityRs = (SOURCESDK::CSSV34::BaseEntityRecordingState_t *)(msg->GetPtr("baseentity"));
					if (pBaseEntityRs)
					{
						WriteDictionary("baseentity");
						//Write((float)pBaseEntityRs->m_flTime);
						WriteDictionary(pBaseEntityRs->m_pModelName);
						Write((bool)wasVisible);

						hasParentTransform = true;
						SOURCESDK::AngleMatrix(pBaseEntityRs->m_vecRenderAngles, pBaseEntityRs->m_vecRenderOrigin, parentTransform);
						WriteMatrix3x4(parentTransform);
					}
				}

				m_TrackedHandles[hEntity] = wasVisible;

				{
					SOURCESDK::CSSV34::BaseAnimatingRecordingState_t * pBaseAnimatingRs = (SOURCESDK::CSSV34::BaseAnimatingRecordingState_t *)(msg->GetPtr("baseanimating"));
					if (pBaseAnimatingRs && hasParentTransform)
					{
						WriteDictionary("baseanimating");
						//Write((int)pBaseAnimatingRs->m_nSkin);
						//Write((int)pBaseAnimatingRs->m_nBody);
						//Write((int)pBaseAnimatingRs->m_nSequence);
						WriteBones(g_cssv34_hdr, &(g_cssv34_BoneState[0]), parentTransform);
					}
				}

				WriteDictionary("/");

				bool viewModel = 0 != msg->GetInt("viewmodel");

				Write((bool)viewModel);
			}
		}
	}
	else if (!strcmp("deleted", msgName))
	{
		std::map<SOURCESDK::CSSV34::HTOOLHANDLE, bool>::iterator it = m_TrackedHandles.find(hEntity);
		if (it != m_TrackedHandles.end())
		{
			if (GetRecording())
			{
				WriteDictionary("deleted");
				Write((int)(it->first));
			}

			m_TrackedHandles.erase(it);
		}
	}
	else if (!strcmp("created", msgName))
	{
		if (0 != Debug_get() && hEntity != SOURCESDK::CSGO::HTOOLHANDLE_INVALID)
		{
			const char * className = m_ClientTools->GetClassname(hEntity);
			if (!className) className = "[NULL]";

			Tier0_Msg("%i n/a: %s\n", hEntity, className);
		}

		if (hEntity != SOURCESDK::CSGO::HTOOLHANDLE_INVALID)// && m_ClientTools->ShouldRecord(hEntity))
		{
			m_TrackedHandles[hEntity] = false;
			if(GetRecording()) m_ClientTools->SetRecording(hEntity, true);
		}
	}
}

void CClientToolsCssV34::OnBeforeFrameRenderStart(void)
{
	CClientTools::OnBeforeFrameRenderStart();

}

void CClientToolsCssV34::OnAfterFrameRenderEnd(void)
{

	CClientTools::OnAfterFrameRenderEnd();
}

void CClientToolsCssV34::EnableRecordingMode_set(bool value) {
	m_ClientTools->EnableRecordingMode(value);
}

bool CClientToolsCssV34::EnableRecordingMode_get() {
	return m_ClientTools->IsInRecordingMode();
}

void CClientToolsCssV34::StartRecording(wchar_t const * fileName)
{
	CClientTools::StartRecording(fileName);

	if (GetRecording())
	{
		if(!cssv34_C_BaseAnimating_RecordBones_Install())
		{
			Tier0_Warning("AFX: Failed to install IClientRenderable::SetupBones hook.\n");
		}

		for (std::map<SOURCESDK::CSSV34::HTOOLHANDLE, bool>::iterator it = m_TrackedHandles.begin(); it != m_TrackedHandles.end(); ++it)
		{
			m_ClientTools->SetRecording(it->first, true);
		}
	}
}

void CClientToolsCssV34::EndRecording()
{
	if (GetRecording())
	{
		for (std::map<SOURCESDK::CSSV34::HTOOLHANDLE, bool>::iterator it = m_TrackedHandles.begin(); it != m_TrackedHandles.end(); ++it)
		{
			m_ClientTools->SetRecording(it->first, false);
		}
	}

	CClientTools::EndRecording();
}

void CClientToolsCssV34::Write(SOURCESDK::CSSV34::CBoneList const * value)
{
	Write((int)value->m_nBones);

	for (int i = 0; i < value->m_nBones; ++i)
	{
		Write(value->m_vecPos[i]);
		Write(value->m_quatRot[i]);
	}
}
<|endoftext|>


<commit_before>/* * This file is part of meego-im-framework *
 *
 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
 * All rights reserved.
 * Contact: Nokia Corporation (directui@nokia.com)
 *
 * If you have questions regarding the use of this file, please contact
 * Nokia at directui@nokia.com.
 *
 * 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 "mattributeextensionmanager.h"
#include "mattributeextension.h"
#include "mtoolbardata.h"
#include "mtoolbarlayout.h"
#include "mkeyoverridedata.h"
#include "mkeyoverride.h"

#include <QVariant>
#include <QFileInfo>
#include <QFile>
#include <QDebug>

namespace {
    const QString DefaultConfigurationPath = QString::fromLatin1(MALIIT_EXTENSIONS_DIR);
    const char * const PreferredDomainSettingName(MALIIT_CONFIG_ROOT"preferred_domain");
    const char * const DomainItemName("_domain");
    const char * const KeysExtensionString("/keys");
    const char * const ToolbarExtensionString("/toolbar");

    const char * const ToolbarIdAttribute = "toolbarId";
    const char * const ToolbarAttribute = "toolbar";
    const char * const FocusStateAttribute = "focusState";
}

MAttributeExtensionManager::MAttributeExtensionManager()
    : copyPasteStatus(MInputMethod::InputMethodNoCopyPaste),
      preferredDomainSetting(PreferredDomainSettingName)
{
    createStandardObjects();
    connect(&preferredDomainSetting, SIGNAL(valueChanged()), this, SLOT(handlePreferredDomainUpdate()));
}

MAttributeExtensionManager::~MAttributeExtensionManager()
{
}

QList<MAttributeExtensionId> MAttributeExtensionManager::attributeExtensionIdList() const
{
    return attributeExtensions.keys();
}

QSharedPointer<MAttributeExtension> MAttributeExtensionManager::attributeExtension(const MAttributeExtensionId &id) const
{
    AttributeExtensionContainer::iterator iterator(attributeExtensions.find(id));

    if (iterator != attributeExtensions.end())
        return iterator.value();
    return QSharedPointer<MAttributeExtension>();
}

QSharedPointer<MToolbarData> MAttributeExtensionManager::toolbarData(const MAttributeExtensionId &id) const
{
    AttributeExtensionContainer::iterator iterator(attributeExtensions.find(id));

    if (iterator != attributeExtensions.end())
        return iterator.value()->toolbarData();
    return QSharedPointer<MToolbarData>();
}

bool  MAttributeExtensionManager::contains(const MAttributeExtensionId &id) const
{
    return attributeExtensions.contains(id);
}

void MAttributeExtensionManager::setCopyPasteState(bool copyAvailable, bool pasteAvailable)
{
    if (!copyPaste) {
        return;
    }

    MInputMethod::CopyPasteState newStatus = MInputMethod::InputMethodNoCopyPaste;
    MInputMethod::ActionType actionType = MInputMethod::ActionUndefined;

    if (copyAvailable) {
        newStatus = MInputMethod::InputMethodCopy;
    } else if (pasteAvailable) {
        newStatus = MInputMethod::InputMethodPaste;
    }

    if (copyPasteStatus == newStatus)
        return;

    bool enabled = false;
    QString textId("qtn_comm_copy");

    copyPasteStatus = newStatus;
    switch (newStatus) {
    case MInputMethod::InputMethodNoCopyPaste:
        break;
    case MInputMethod::InputMethodCopy:
        enabled = true;
        actionType = MInputMethod::ActionCopy;
        break;
    case MInputMethod::InputMethodPaste:
        enabled = true;
        textId = "qtn_comm_paste";
        actionType = MInputMethod::ActionPaste;
        break;
    }
    copyPaste->setTextId(textId);
    copyPaste->setEnabled(enabled);
    if (!copyPaste->actions().isEmpty()) {
        copyPaste->actions().first()->setType(actionType);
    }
}

void MAttributeExtensionManager::createStandardObjects()
{
    // TODO: standard buttons are not used anymore and should be removed
    // This code assumes that StandardToolbar provides exactly two buttons: copy/paste and close.
    // That file is controlled by us, so we can rely on this assertion.
    standardAttributeExtension = QSharedPointer<MAttributeExtension>(new MAttributeExtension(MAttributeExtensionId::standardAttributeExtensionId(),
                                                                                QString()));

    if (standardAttributeExtension && standardAttributeExtension->toolbarData()) {
        attributeExtensions.insert(MAttributeExtensionId::standardAttributeExtensionId(), standardAttributeExtension);

        Q_FOREACH (QSharedPointer<MToolbarItem> item, standardAttributeExtension->toolbarData()->items()) {
            item->setCustom(false);
            QList<QSharedPointer<MToolbarItemAction> > actions = item->actions();
            if (actions.isEmpty()) {
                continue; // should never happen
            }

            switch (actions.at(0)->type()) {
            case MInputMethod::ActionClose:
                close = item;
                break;
            case MInputMethod::ActionCopyPaste:
                copyPaste = item;
                // set initial state
                copyPaste->setVisible(true);
                copyPaste->setEnabled(false);
                copyPaste->setTextId("qtn_comm_copy");
                copyPaste->actions().first()->setType(MInputMethod::ActionUndefined);
                break;
            default:
                break;
            }
        }
    }
}

void MAttributeExtensionManager::addStandardButtons(const QSharedPointer<MToolbarData> &toolbarData)
{
    if (!toolbarData || !standardAttributeExtension || !standardAttributeExtension->toolbarData()) {
        return;
    }

    QSharedPointer<MToolbarLayout> landscape = toolbarData->layout(MInputMethod::Landscape).constCast<MToolbarLayout>();
    QSharedPointer<MToolbarLayout> portrait = toolbarData->layout(MInputMethod::Portrait).constCast<MToolbarLayout>();

    if (landscape) {
        addStandardButtons(landscape, toolbarData);
    }

    if (portrait && portrait != landscape) {
        addStandardButtons(portrait, toolbarData);
    }
}

void MAttributeExtensionManager::addStandardButtons(const QSharedPointer<MToolbarLayout> &layout,
                                         const QSharedPointer<MToolbarData> &toolbarData)
{
    Q_FOREACH (const QSharedPointer<MToolbarItem> &item, standardAttributeExtension->toolbarData()->items()) {
        if (!toolbarData->refusedNames().contains(item->name())) {
            toolbarData->append(layout, item);
        }
    }
}

void MAttributeExtensionManager::handlePreferredDomainUpdate()
{
    Q_FOREACH (QSharedPointer<MAttributeExtension> attributeExtension, attributeExtensions.values()) {
        QSharedPointer<MToolbarData> toolbar = attributeExtension->toolbarData();
        updateDomain(toolbar);
    }
}

void MAttributeExtensionManager::updateDomain(QSharedPointer<MToolbarData> &toolbar)
{
    const QString domain(preferredDomainSetting.value().toString());
    if (domain.isEmpty()) {
        return;
    }

    QSharedPointer<MToolbarItem> item(toolbar->item(DomainItemName));
    if (!item) {
        return;
    }

    QList<QSharedPointer<MToolbarItemAction> > actions(item->actions());
    if (actions.length() != 1 || actions[0]->type() != MInputMethod::ActionSendString) {
        return;
    }

    actions[0]->setText(domain);
    item->setText(domain);
}

void MAttributeExtensionManager::registerAttributeExtension(const MAttributeExtensionId &id, const QString &fileName)
{
    if (!id.isValid() || attributeExtensions.contains(id))
        return;

    // Only register default extension in the case of empty string.
    // Don't register extension if user makes a typo in the file name.
    if (!fileName.isEmpty()) {
        QString absoluteFileName = fileName;
        QFileInfo info(absoluteFileName);
        if (info.isRelative())
            absoluteFileName = DefaultConfigurationPath + info.fileName();
        if (!QFile::exists(absoluteFileName))
            return;
    }

    QSharedPointer<MAttributeExtension> attributeExtension(new MAttributeExtension(id, fileName));
    if (attributeExtension) {
        addStandardButtons(attributeExtension->toolbarData());
        QSharedPointer<MToolbarData> toolbar = attributeExtension->toolbarData();
        updateDomain(toolbar);
        attributeExtensions.insert(id, attributeExtension);
    }
}

void MAttributeExtensionManager::unregisterAttributeExtension(const MAttributeExtensionId &id)
{
    if (!attributeExtensions.contains(id))
        return;

    attributeExtensions.remove(id);
}

void MAttributeExtensionManager::setToolbarItemAttribute(const MAttributeExtensionId &id,
                                              const QString &itemName,
                                              const QString &attribute,
                                              const QVariant &value)
{
    setExtendedAttribute(id, ToolbarExtensionString, itemName,
                         attribute, value);
}

QMap<QString, QSharedPointer<MKeyOverride> > MAttributeExtensionManager::keyOverrides(
        const MAttributeExtensionId &id) const
{
    QList<QSharedPointer<MKeyOverride> > overrides;
    QSharedPointer<MAttributeExtension> extension = attributeExtension(id);
    if (extension) {
        overrides = extension->keyOverrideData()->keyOverrides();
    }
    QMap<QString, QSharedPointer<MKeyOverride> > overridesMap;
    Q_FOREACH (const QSharedPointer<MKeyOverride> &override, overrides) {
        overridesMap.insert(override->keyId(), override);
    }
    return overridesMap;
}

void MAttributeExtensionManager::setExtendedAttribute(const MAttributeExtensionId &id,
                                                      const QString &target,
                                                      const QString &targetItem,
                                                      const QString &attribute,
                                                      const QVariant &value)
{
    if (!id.isValid() || attribute.isEmpty() || targetItem.isEmpty() || !value.isValid())
        return;

    QSharedPointer<MAttributeExtension> extension = attributeExtension(id);

    if (!extension) {
        return;
    }

    if (target == KeysExtensionString) {
        // create key override if not exist.
        bool newKeyOverrideCreated = extension->keyOverrideData()->createKeyOverride(targetItem);
        QSharedPointer<MKeyOverride> keyOverride = extension->keyOverrideData()->keyOverride(targetItem);

        Q_ASSERT(keyOverride);
        const QByteArray byteArray = attribute.toLatin1();
        const char * const c_str = byteArray.data();

        // Ignore l10n lengthvariants in QStrings for labels, always pick longest variant (first)
        if (attribute == "label") {
            QString label = value.toString();
            label = label.split(QChar(0x9c)).first();
            const QVariant newValue(label);
            keyOverride->setProperty(c_str, newValue);
        } else {
            keyOverride->setProperty(c_str, value);
        }

        // Q_EMIT signal to notify the new key override is created.
        if (newKeyOverrideCreated) {
            Q_EMIT keyOverrideCreated();
        }
    } else if (target == ToolbarExtensionString) {
        QSharedPointer<MToolbarData> toolbar = extension->toolbarData();
        if (!toolbar) {
            qWarning() << "Can not find toolbar data!";
            return;
        }
        QSharedPointer<MToolbarItem> item = toolbar->item(targetItem);
        if (!item) {
            return;
        }
        const QByteArray byteArray = attribute.toLatin1();
        const char * const c_str = byteArray.data();
        item->setProperty(c_str, value);
    } else {
        qWarning() << "Invalid or incompatible attribute extension target:" << target;
    }
}

void MAttributeExtensionManager::handleClientDisconnect(unsigned int clientId)
{
    // unregister toolbars registered by the lost connection
    const QString service(QString::number(clientId));
    QSet<MAttributeExtensionId>::iterator i(attributeExtensionIds.begin());
    while (i != attributeExtensionIds.end()) {
        if ((*i).service() == service) {
            unregisterAttributeExtension(*i);
            i = attributeExtensionIds.erase(i);
        } else {
            ++i;
        }
    }
}

void MAttributeExtensionManager::handleExtendedAttributeUpdate(unsigned int clientId, int id,
                                   const QString &target, const QString &targetName,
                                   const QString &attribute, const QVariant &value)
{
    MAttributeExtensionId globalId(id, QString::number(clientId));
    if (globalId.isValid() && attributeExtensionIds.contains(globalId)) {
        setExtendedAttribute(globalId, target, targetName, attribute, value);
    }
}

void MAttributeExtensionManager::handleAttributeExtensionRegistered(unsigned int clientId,
                                                                  int id, const QString &attributeExtension)
{
    MAttributeExtensionId globalId(id, QString::number(clientId));
    if (globalId.isValid() && !attributeExtensionIds.contains(globalId)) {
        registerAttributeExtension(globalId, attributeExtension);
        attributeExtensionIds.insert(globalId);
    }
}

void MAttributeExtensionManager::handleAttributeExtensionUnregistered(unsigned int clientId, int id)
{
    MAttributeExtensionId globalId(id, QString::number(clientId));
    if (globalId.isValid() && attributeExtensionIds.contains(globalId)) {
        unregisterAttributeExtension(globalId);
        attributeExtensionIds.remove(globalId);
    }
}

void MAttributeExtensionManager::handleWidgetStateChanged(unsigned int clientId,
                                                          const QMap<QString, QVariant> &newState,
                                                          const QMap<QString, QVariant> &oldState,
                                                          bool focusChanged)

{
    Q_UNUSED(oldState);
    // toolbar change
    MAttributeExtensionId oldAttributeExtensionId;
    MAttributeExtensionId newAttributeExtensionId;
    oldAttributeExtensionId = attributeExtensionId;

    QVariant variant = newState[ToolbarIdAttribute];
    if (variant.isValid()) {
        // map toolbar id from local to global
        newAttributeExtensionId = MAttributeExtensionId(variant.toInt(), QString::number(clientId));
    }
    if (!newAttributeExtensionId.isValid()) {
        newAttributeExtensionId = MAttributeExtensionId::standardAttributeExtensionId();
    }

    variant = newState[FocusStateAttribute];
    if (not variant.isValid()) {
        qCritical() << __PRETTY_FUNCTION__ << "Invalid focus state";
    }
    bool widgetFocusState = variant.toBool();

    // compare the toolbar id (global)
    if (oldAttributeExtensionId != newAttributeExtensionId) {
        QString toolbarFile = newState[ToolbarAttribute].toString();
        if (!contains(newAttributeExtensionId) && !toolbarFile.isEmpty()) {
            // register toolbar if toolbar manager does not contain it but
            // toolbar file is not empty. This can reload the toolbar data
            // if im-uiserver crashes.
            // XXX: should not happen, the input context is reponsible for registering
            // and resending the toolbar information on server reconnect
            qWarning() << "Unregistered toolbar found in widget information";

            variant = newState[ToolbarIdAttribute];
            if (variant.isValid()) {
                const int toolbarLocalId = variant.toInt();
                // FIXME: brittle to call the signal handler directly like this
                handleAttributeExtensionRegistered(clientId, toolbarLocalId, toolbarFile);
            }
        }
        Q_EMIT attributeExtensionIdChanged(newAttributeExtensionId);
        // store the new used toolbar id(global).
        attributeExtensionId = newAttributeExtensionId;
    }
    // this happens when we focus on a text widget with no attribute extensions.
    else if (focusChanged && widgetFocusState)
    {
        Q_EMIT attributeExtensionIdChanged(newAttributeExtensionId);
    }
}
<commit_msg>Use ::const_iterator when required<commit_after>/* * This file is part of meego-im-framework *
 *
 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
 * All rights reserved.
 * Contact: Nokia Corporation (directui@nokia.com)
 *
 * If you have questions regarding the use of this file, please contact
 * Nokia at directui@nokia.com.
 *
 * 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 "mattributeextensionmanager.h"
#include "mattributeextension.h"
#include "mtoolbardata.h"
#include "mtoolbarlayout.h"
#include "mkeyoverridedata.h"
#include "mkeyoverride.h"

#include <QVariant>
#include <QFileInfo>
#include <QFile>
#include <QDebug>

namespace {
    const QString DefaultConfigurationPath = QString::fromLatin1(MALIIT_EXTENSIONS_DIR);
    const char * const PreferredDomainSettingName(MALIIT_CONFIG_ROOT"preferred_domain");
    const char * const DomainItemName("_domain");
    const char * const KeysExtensionString("/keys");
    const char * const ToolbarExtensionString("/toolbar");

    const char * const ToolbarIdAttribute = "toolbarId";
    const char * const ToolbarAttribute = "toolbar";
    const char * const FocusStateAttribute = "focusState";
}

MAttributeExtensionManager::MAttributeExtensionManager()
    : copyPasteStatus(MInputMethod::InputMethodNoCopyPaste),
      preferredDomainSetting(PreferredDomainSettingName)
{
    createStandardObjects();
    connect(&preferredDomainSetting, SIGNAL(valueChanged()), this, SLOT(handlePreferredDomainUpdate()));
}

MAttributeExtensionManager::~MAttributeExtensionManager()
{
}

QList<MAttributeExtensionId> MAttributeExtensionManager::attributeExtensionIdList() const
{
    return attributeExtensions.keys();
}

QSharedPointer<MAttributeExtension> MAttributeExtensionManager::attributeExtension(const MAttributeExtensionId &id) const
{
    AttributeExtensionContainer::const_iterator iterator(attributeExtensions.find(id));

    if (iterator != attributeExtensions.end())
        return iterator.value();
    return QSharedPointer<MAttributeExtension>();
}

QSharedPointer<MToolbarData> MAttributeExtensionManager::toolbarData(const MAttributeExtensionId &id) const
{
    AttributeExtensionContainer::const_iterator iterator(attributeExtensions.find(id));

    if (iterator != attributeExtensions.end())
        return iterator.value()->toolbarData();
    return QSharedPointer<MToolbarData>();
}

bool  MAttributeExtensionManager::contains(const MAttributeExtensionId &id) const
{
    return attributeExtensions.contains(id);
}

void MAttributeExtensionManager::setCopyPasteState(bool copyAvailable, bool pasteAvailable)
{
    if (!copyPaste) {
        return;
    }

    MInputMethod::CopyPasteState newStatus = MInputMethod::InputMethodNoCopyPaste;
    MInputMethod::ActionType actionType = MInputMethod::ActionUndefined;

    if (copyAvailable) {
        newStatus = MInputMethod::InputMethodCopy;
    } else if (pasteAvailable) {
        newStatus = MInputMethod::InputMethodPaste;
    }

    if (copyPasteStatus == newStatus)
        return;

    bool enabled = false;
    QString textId("qtn_comm_copy");

    copyPasteStatus = newStatus;
    switch (newStatus) {
    case MInputMethod::InputMethodNoCopyPaste:
        break;
    case MInputMethod::InputMethodCopy:
        enabled = true;
        actionType = MInputMethod::ActionCopy;
        break;
    case MInputMethod::InputMethodPaste:
        enabled = true;
        textId = "qtn_comm_paste";
        actionType = MInputMethod::ActionPaste;
        break;
    }
    copyPaste->setTextId(textId);
    copyPaste->setEnabled(enabled);
    if (!copyPaste->actions().isEmpty()) {
        copyPaste->actions().first()->setType(actionType);
    }
}

void MAttributeExtensionManager::createStandardObjects()
{
    // TODO: standard buttons are not used anymore and should be removed
    // This code assumes that StandardToolbar provides exactly two buttons: copy/paste and close.
    // That file is controlled by us, so we can rely on this assertion.
    standardAttributeExtension = QSharedPointer<MAttributeExtension>(new MAttributeExtension(MAttributeExtensionId::standardAttributeExtensionId(),
                                                                                QString()));

    if (standardAttributeExtension && standardAttributeExtension->toolbarData()) {
        attributeExtensions.insert(MAttributeExtensionId::standardAttributeExtensionId(), standardAttributeExtension);

        Q_FOREACH (QSharedPointer<MToolbarItem> item, standardAttributeExtension->toolbarData()->items()) {
            item->setCustom(false);
            QList<QSharedPointer<MToolbarItemAction> > actions = item->actions();
            if (actions.isEmpty()) {
                continue; // should never happen
            }

            switch (actions.at(0)->type()) {
            case MInputMethod::ActionClose:
                close = item;
                break;
            case MInputMethod::ActionCopyPaste:
                copyPaste = item;
                // set initial state
                copyPaste->setVisible(true);
                copyPaste->setEnabled(false);
                copyPaste->setTextId("qtn_comm_copy");
                copyPaste->actions().first()->setType(MInputMethod::ActionUndefined);
                break;
            default:
                break;
            }
        }
    }
}

void MAttributeExtensionManager::addStandardButtons(const QSharedPointer<MToolbarData> &toolbarData)
{
    if (!toolbarData || !standardAttributeExtension || !standardAttributeExtension->toolbarData()) {
        return;
    }

    QSharedPointer<MToolbarLayout> landscape = toolbarData->layout(MInputMethod::Landscape).constCast<MToolbarLayout>();
    QSharedPointer<MToolbarLayout> portrait = toolbarData->layout(MInputMethod::Portrait).constCast<MToolbarLayout>();

    if (landscape) {
        addStandardButtons(landscape, toolbarData);
    }

    if (portrait && portrait != landscape) {
        addStandardButtons(portrait, toolbarData);
    }
}

void MAttributeExtensionManager::addStandardButtons(const QSharedPointer<MToolbarLayout> &layout,
                                         const QSharedPointer<MToolbarData> &toolbarData)
{
    Q_FOREACH (const QSharedPointer<MToolbarItem> &item, standardAttributeExtension->toolbarData()->items()) {
        if (!toolbarData->refusedNames().contains(item->name())) {
            toolbarData->append(layout, item);
        }
    }
}

void MAttributeExtensionManager::handlePreferredDomainUpdate()
{
    Q_FOREACH (QSharedPointer<MAttributeExtension> attributeExtension, attributeExtensions.values()) {
        QSharedPointer<MToolbarData> toolbar = attributeExtension->toolbarData();
        updateDomain(toolbar);
    }
}

void MAttributeExtensionManager::updateDomain(QSharedPointer<MToolbarData> &toolbar)
{
    const QString domain(preferredDomainSetting.value().toString());
    if (domain.isEmpty()) {
        return;
    }

    QSharedPointer<MToolbarItem> item(toolbar->item(DomainItemName));
    if (!item) {
        return;
    }

    QList<QSharedPointer<MToolbarItemAction> > actions(item->actions());
    if (actions.length() != 1 || actions[0]->type() != MInputMethod::ActionSendString) {
        return;
    }

    actions[0]->setText(domain);
    item->setText(domain);
}

void MAttributeExtensionManager::registerAttributeExtension(const MAttributeExtensionId &id, const QString &fileName)
{
    if (!id.isValid() || attributeExtensions.contains(id))
        return;

    // Only register default extension in the case of empty string.
    // Don't register extension if user makes a typo in the file name.
    if (!fileName.isEmpty()) {
        QString absoluteFileName = fileName;
        QFileInfo info(absoluteFileName);
        if (info.isRelative())
            absoluteFileName = DefaultConfigurationPath + info.fileName();
        if (!QFile::exists(absoluteFileName))
            return;
    }

    QSharedPointer<MAttributeExtension> attributeExtension(new MAttributeExtension(id, fileName));
    if (attributeExtension) {
        addStandardButtons(attributeExtension->toolbarData());
        QSharedPointer<MToolbarData> toolbar = attributeExtension->toolbarData();
        updateDomain(toolbar);
        attributeExtensions.insert(id, attributeExtension);
    }
}

void MAttributeExtensionManager::unregisterAttributeExtension(const MAttributeExtensionId &id)
{
    if (!attributeExtensions.contains(id))
        return;

    attributeExtensions.remove(id);
}

void MAttributeExtensionManager::setToolbarItemAttribute(const MAttributeExtensionId &id,
                                              const QString &itemName,
                                              const QString &attribute,
                                              const QVariant &value)
{
    setExtendedAttribute(id, ToolbarExtensionString, itemName,
                         attribute, value);
}

QMap<QString, QSharedPointer<MKeyOverride> > MAttributeExtensionManager::keyOverrides(
        const MAttributeExtensionId &id) const
{
    QList<QSharedPointer<MKeyOverride> > overrides;
    QSharedPointer<MAttributeExtension> extension = attributeExtension(id);
    if (extension) {
        overrides = extension->keyOverrideData()->keyOverrides();
    }
    QMap<QString, QSharedPointer<MKeyOverride> > overridesMap;
    Q_FOREACH (const QSharedPointer<MKeyOverride> &override, overrides) {
        overridesMap.insert(override->keyId(), override);
    }
    return overridesMap;
}

void MAttributeExtensionManager::setExtendedAttribute(const MAttributeExtensionId &id,
                                                      const QString &target,
                                                      const QString &targetItem,
                                                      const QString &attribute,
                                                      const QVariant &value)
{
    if (!id.isValid() || attribute.isEmpty() || targetItem.isEmpty() || !value.isValid())
        return;

    QSharedPointer<MAttributeExtension> extension = attributeExtension(id);

    if (!extension) {
        return;
    }

    if (target == KeysExtensionString) {
        // create key override if not exist.
        bool newKeyOverrideCreated = extension->keyOverrideData()->createKeyOverride(targetItem);
        QSharedPointer<MKeyOverride> keyOverride = extension->keyOverrideData()->keyOverride(targetItem);

        Q_ASSERT(keyOverride);
        const QByteArray byteArray = attribute.toLatin1();
        const char * const c_str = byteArray.data();

        // Ignore l10n lengthvariants in QStrings for labels, always pick longest variant (first)
        if (attribute == "label") {
            QString label = value.toString();
            label = label.split(QChar(0x9c)).first();
            const QVariant newValue(label);
            keyOverride->setProperty(c_str, newValue);
        } else {
            keyOverride->setProperty(c_str, value);
        }

        // Q_EMIT signal to notify the new key override is created.
        if (newKeyOverrideCreated) {
            Q_EMIT keyOverrideCreated();
        }
    } else if (target == ToolbarExtensionString) {
        QSharedPointer<MToolbarData> toolbar = extension->toolbarData();
        if (!toolbar) {
            qWarning() << "Can not find toolbar data!";
            return;
        }
        QSharedPointer<MToolbarItem> item = toolbar->item(targetItem);
        if (!item) {
            return;
        }
        const QByteArray byteArray = attribute.toLatin1();
        const char * const c_str = byteArray.data();
        item->setProperty(c_str, value);
    } else {
        qWarning() << "Invalid or incompatible attribute extension target:" << target;
    }
}

void MAttributeExtensionManager::handleClientDisconnect(unsigned int clientId)
{
    // unregister toolbars registered by the lost connection
    const QString service(QString::number(clientId));
    QSet<MAttributeExtensionId>::iterator i(attributeExtensionIds.begin());
    while (i != attributeExtensionIds.end()) {
        if ((*i).service() == service) {
            unregisterAttributeExtension(*i);
            i = attributeExtensionIds.erase(i);
        } else {
            ++i;
        }
    }
}

void MAttributeExtensionManager::handleExtendedAttributeUpdate(unsigned int clientId, int id,
                                   const QString &target, const QString &targetName,
                                   const QString &attribute, const QVariant &value)
{
    MAttributeExtensionId globalId(id, QString::number(clientId));
    if (globalId.isValid() && attributeExtensionIds.contains(globalId)) {
        setExtendedAttribute(globalId, target, targetName, attribute, value);
    }
}

void MAttributeExtensionManager::handleAttributeExtensionRegistered(unsigned int clientId,
                                                                  int id, const QString &attributeExtension)
{
    MAttributeExtensionId globalId(id, QString::number(clientId));
    if (globalId.isValid() && !attributeExtensionIds.contains(globalId)) {
        registerAttributeExtension(globalId, attributeExtension);
        attributeExtensionIds.insert(globalId);
    }
}

void MAttributeExtensionManager::handleAttributeExtensionUnregistered(unsigned int clientId, int id)
{
    MAttributeExtensionId globalId(id, QString::number(clientId));
    if (globalId.isValid() && attributeExtensionIds.contains(globalId)) {
        unregisterAttributeExtension(globalId);
        attributeExtensionIds.remove(globalId);
    }
}

void MAttributeExtensionManager::handleWidgetStateChanged(unsigned int clientId,
                                                          const QMap<QString, QVariant> &newState,
                                                          const QMap<QString, QVariant> &oldState,
                                                          bool focusChanged)

{
    Q_UNUSED(oldState);
    // toolbar change
    MAttributeExtensionId oldAttributeExtensionId;
    MAttributeExtensionId newAttributeExtensionId;
    oldAttributeExtensionId = attributeExtensionId;

    QVariant variant = newState[ToolbarIdAttribute];
    if (variant.isValid()) {
        // map toolbar id from local to global
        newAttributeExtensionId = MAttributeExtensionId(variant.toInt(), QString::number(clientId));
    }
    if (!newAttributeExtensionId.isValid()) {
        newAttributeExtensionId = MAttributeExtensionId::standardAttributeExtensionId();
    }

    variant = newState[FocusStateAttribute];
    if (not variant.isValid()) {
        qCritical() << __PRETTY_FUNCTION__ << "Invalid focus state";
    }
    bool widgetFocusState = variant.toBool();

    // compare the toolbar id (global)
    if (oldAttributeExtensionId != newAttributeExtensionId) {
        QString toolbarFile = newState[ToolbarAttribute].toString();
        if (!contains(newAttributeExtensionId) && !toolbarFile.isEmpty()) {
            // register toolbar if toolbar manager does not contain it but
            // toolbar file is not empty. This can reload the toolbar data
            // if im-uiserver crashes.
            // XXX: should not happen, the input context is reponsible for registering
            // and resending the toolbar information on server reconnect
            qWarning() << "Unregistered toolbar found in widget information";

            variant = newState[ToolbarIdAttribute];
            if (variant.isValid()) {
                const int toolbarLocalId = variant.toInt();
                // FIXME: brittle to call the signal handler directly like this
                handleAttributeExtensionRegistered(clientId, toolbarLocalId, toolbarFile);
            }
        }
        Q_EMIT attributeExtensionIdChanged(newAttributeExtensionId);
        // store the new used toolbar id(global).
        attributeExtensionId = newAttributeExtensionId;
    }
    // this happens when we focus on a text widget with no attribute extensions.
    else if (focusChanged && widgetFocusState)
    {
        Q_EMIT attributeExtensionIdChanged(newAttributeExtensionId);
    }
}
<|endoftext|>


<commit_before><commit_msg>Remove the C wrapper calls from stacktraces<commit_after><|endoftext|>