<commit_before>// Copyright (c) 2014 Dano Pernis
// See LICENSE for details

#include <map>
#include <string>
#include "ssa.h"

namespace hcc { namespace ssa {

void subroutine::copy_propagation()
{
    struct replacer_algorithm {
        void insert(const argument& from, const argument& to)
        {
            // replace[to] = from;
            // find if there's a chain
            auto it = replace.find(from);
            if (it != replace.end()) {
                replace.emplace(to, it->second).first->second = it->second;
            } else {
                replace.emplace(to, from).first->second = from;
            }
        }

        void operator()(argument& a) const
        {
            auto it = replace.find(a);
            if (it != replace.end())
                a = it->second;
        }

        std::map<argument, argument> replace;
    } replacer;

    // pass 1: find MOVs and make replacement list
    for_each_bb([&] (basic_block& bb) {
    for (auto& instruction : bb.instructions) {
        if (instruction.type == instruction_type::MOV) {
            const auto& src = instruction.arguments[1];
            const auto& dst = instruction.arguments[0];
            replacer.insert(src, dst);
        }
    }
    });

    // pass 2: apply the replacement
    for_each_bb([&] (basic_block& bb) {
    for (auto& instruction : bb.instructions) {
        instruction.use_apply(replacer);
    }
    });
}

}} // namespace hcc::ssa
<commit_msg>Refactored SSA copy propagation<commit_after>// Copyright (c) 2014 Dano Pernis
// See LICENSE for details

#include <map>
#include <string>
#include "ssa.h"

namespace hcc { namespace ssa {

void subroutine::copy_propagation()
{
    std::map<argument, argument> replace;
    auto replacer = [&] (argument& a) {
        auto it = replace.find(a);
        if (it != replace.end()) {
            a = it->second;
        }
    };

    // pass 1: find MOVs and make replacement list
    for_each_bb([&] (basic_block& bb) {
    for (auto& instruction : bb.instructions) {
        if (instruction.type == instruction_type::MOV) {
            const auto& src = instruction.arguments[1];
            const auto& dst = instruction.arguments[0];
            // replace[dst] = src;
            // find if there's a chain
            auto it = replace.find(src);
            if (it != replace.end()) {
                replace.emplace(dst, it->second).first->second = it->second;
            } else {
                replace.emplace(dst, src).first->second = src;
            }
        }
    }
    });

    // pass 2: apply the replacement
    for_each_bb([&] (basic_block& bb) {
    for (auto& instruction : bb.instructions) {
        instruction.use_apply(replacer);
    }
    });
}

}} // namespace hcc::ssa
<|endoftext|>


<commit_before>
#include "gtest/gtest.h"

TEST(ThatWeFailQUickly, TautologiesAreTrue) {
	EXPECT_TRUE(false);
}

int main(int argc, char** argv)
{
	// run all tests
	::testing::InitGoogleTest(&argc, argv);

	return RUN_ALL_TESTS();
}
<commit_msg>Make simple test pass<commit_after>
#include "gtest/gtest.h"

TEST(ThatWeFailQUickly, TautologiesAreTrue) {
	EXPECT_TRUE(true);
}

int main(int argc, char** argv)
{
	// run all tests
	::testing::InitGoogleTest(&argc, argv);

	return RUN_ALL_TESTS();
}
<|endoftext|>


<commit_before>/*
 * This file is part of OpenModelica.
 *
 * Copyright (c) 1998-CurrentYear, Linköping University,
 * Department of Computer and Information Science,
 * SE-58183 Linköping, Sweden.
 *
 * All rights reserved.
 *
 * THIS PROGRAM IS PROVIDED UNDER THE TERMS OF GPL VERSION 3
 * AND THIS OSMC PUBLIC LICENSE (OSMC-PL).
 * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES RECIPIENT'S
 * ACCEPTANCE OF THE OSMC PUBLIC LICENSE.
 *
 * The OpenModelica software and the Open Source Modelica
 * Consortium (OSMC) Public License (OSMC-PL) are obtained
 * from Linköping University, either from the above address,
 * from the URLs: http://www.ida.liu.se/projects/OpenModelica or
 * http://www.openmodelica.org, and in the OpenModelica distribution.
 * GNU version 3 is obtained from: http://www.gnu.org/copyleft/gpl.html.
 *
 * This program is distributed WITHOUT ANY WARRANTY; without
 * even the implied warranty of  MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH
 * IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS
 * OF OSMC-PL.
 *
 * See the full OSMC Public License conditions for more details.
 *
 */

/*
 * HopsanGUI
 * Fluid and Mechatronic Systems, Department of Management and Engineering, Linköping University
 * Main Authors 2009-2010:  Robert Braun, Björn Eriksson, Peter Nordin
 * Contributors 2009-2010:  Mikael Axin, Alessandro Dell'Amico, Karl Pettersson, Ingo Staack
 */

//!
//! @file   SystemParametersWidget.cpp
//! @author Robert Braun <robert.braun@liu.se>
//! @date   2010-10-04
//!
//! @brief Contains a System parameter widget class
//!
//$Id$

#include <QtGui>

#include "../MainWindow.h"
#include "SystemParametersWidget.h"

#include <QWidget>
#include <QDialog>

#include "ProjectTabWidget.h"
#include "../GUIObjects/GUISystem.h"

#include "../common.h"

//! Construtor for System Parameters widget, where the user can see and change the System parameters in the model.
//! @param parent Pointer to the main window
SystemParametersWidget::SystemParametersWidget(MainWindow *parent)
    : QWidget(parent)
{
    //mpParentMainWindow = parent;
    //Set the name and size of the main window
    this->setObjectName("SystemParameterWidget");
    this->resize(400,500);
    this->setWindowTitle("System Parameters");

    mpSystemParametersTable = new SystemParameterTableWidget(0,1,this);

    mpAddButton = new QPushButton(tr("&Set"), this);
    mpAddButton->setFixedHeight(30);
    mpAddButton->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
    mpAddButton->setAutoDefault(false);
    QFont tempFont = mpAddButton->font();
    tempFont.setBold(true);
    mpAddButton->setFont(tempFont);
    mpAddButton->setEnabled(false);

    mpRemoveButton = new QPushButton(tr("&Unset"), this);
    mpRemoveButton->setFixedHeight(30);
    mpRemoveButton->setAutoDefault(false);
    mpRemoveButton->setFont(tempFont);
    mpRemoveButton->setEnabled(false);

    mpGridLayout = new QGridLayout(this);
    mpGridLayout->addWidget(mpSystemParametersTable, 0, 0);
    mpGridLayout->addWidget(mpAddButton, 1, 0);
    mpGridLayout->addWidget(mpRemoveButton, 2, 0);

    update();

    connect(mpAddButton, SIGNAL(clicked()), mpSystemParametersTable, SLOT(openComponentPropertiesDialog()));
    connect(mpRemoveButton, SIGNAL(clicked()), mpSystemParametersTable, SLOT(removeSelectedParameters()));
    connect(gpMainWindow->mpProjectTabs, SIGNAL(currentChanged(int)), this, SLOT(update()));//Strössel!
    connect(gpMainWindow->mpProjectTabs, SIGNAL(newTabAdded()), this, SLOT(update()));//Strössel!
}

void SystemParametersWidget::update()
{
    if(gpMainWindow->mpProjectTabs->count()>0)
    {
        mpAddButton->setEnabled(true);
        mpRemoveButton->setEnabled(true);
    }
    else
    {
        mpAddButton->setEnabled(false);
        mpRemoveButton->setEnabled(false);
    }

    mpSystemParametersTable->update();
}

SystemParameterTableWidget::SystemParameterTableWidget(int rows, int columns, QWidget *parent)
    : QTableWidget(rows, columns, parent)
{
    setFocusPolicy(Qt::StrongFocus);
    setSelectionMode(QAbstractItemView::SingleSelection);

    setBaseSize(400, 500);
    horizontalHeader()->setStretchLastSection(true);
    horizontalHeader()->hide();

    update();

    connect(this, SIGNAL(itemChanged(QTableWidgetItem*)), this, SLOT(changeParameter(QTableWidgetItem*)));
}

void SystemParameterTableWidget::keyPressEvent(QKeyEvent *event)
{
    QTableWidget::keyPressEvent(event);
    if(event->key() == Qt::Key_Delete)
    {
        std::cout << "Delete current System Parameter Widget Items" << std::endl;
        removeSelectedParameters();
    }
}

//! @brief Used for parameter changes done directly in the label
void SystemParameterTableWidget::changeParameter(QTableWidgetItem *item)
{
    //Filter out value labels
    if(item->column() == 1)
    {
        QTableWidgetItem *neighborItem = itemAt(item->row(), item->column()-1);
        QString parName = neighborItem->text();
        QString parValue = item->text();

        //Do not do update, then crash due to the rebuild of the QTableWidgetItems
        setParameter(parName, parValue, false);
    }
}

double SystemParameterTableWidget::getParameter(QString name)
{
    return gpMainWindow->mpProjectTabs->getCurrentTopLevelSystem()->getCoreSystemAccessPtr()->getSystemParameter(name);
}

bool SystemParameterTableWidget::hasParameter(QString name)
{
    return gpMainWindow->mpProjectTabs->getCurrentTopLevelSystem()->getCoreSystemAccessPtr()->hasSystemParameter(name);
}

//! Slot that adds a System parameter value
//! @param name Lookup name for the System parameter
//! @param value Value of the System parameter
void SystemParameterTableWidget::setParameter(QString name, double value, bool doUpdate)
{
    //Error check
    if(!(gpMainWindow->mpProjectTabs->getCurrentTopLevelSystem()->getCoreSystemAccessPtr()->setSystemParameter(name, value)))
    {
        QMessageBox::critical(0, "Hopsan GUI",
                              QString("'%1' is an invalid name for a system parameter.")
                              .arg(name));
        return;
    }
    if(doUpdate)
    {
        update();
    }

    gpMainWindow->mpProjectTabs->getCurrentTab()->hasChanged();
    emit modifiedSystemParameter();
}

//! Slot that adds a System parameter value
//! @param name Lookup name for the System parameter
//! @param value Value of the System parameter
void SystemParameterTableWidget::setParameter(QString name, QString valueTxt, bool doUpdate)
{
    //Error check
    bool isDbl;
    double value = valueTxt.toDouble((&isDbl));
    if(!(isDbl))
    {
        QMessageBox::critical(0, "Hopsan GUI",
                              QString("'%1' is not a valid number.")
                              .arg(valueTxt));
        QString oldValue = QString::number(gpMainWindow->mpProjectTabs->getCurrentTopLevelSystem()->getCoreSystemAccessPtr()->getSystemParameter(name));
        QList<QTableWidgetItem *> items = selectedItems();
        //Error if size() > 1, but it should not be! :)
        for(int i = 0; i<items.size(); ++i)
        {
            items[i]->setText(oldValue);
        }
    }
    else
    {
        setParameter(name, value, doUpdate);
    }
}

void SystemParameterTableWidget::setParameters()
{
    //    if(gpMainWindow->mpProjectTabs->getCurrentTopLevelSystem()->getCoreSystemAccessPtr()->getNumberOfSystemParameters() > 0)
    //    {
    for(int i=0; i<rowCount(); ++i)
    {
        QString name = item(i, 0)->text();
        double value = item(i, 1)->text().toDouble();
        setParameter(name, value);
    }
    //    }
}

//! Slot that removes all selected System parameters in parameter table
//! @todo This shall remove the actual System parameters when they have been implemented, wherever they are stored.
void SystemParameterTableWidget::removeSelectedParameters()
{
    if(gpMainWindow->mpProjectTabs->count()>0)
    {
        QList<QTableWidgetItem *> pSelectedItems = selectedItems();
        QStringList parametersToRemove;
        QString tempName;

        for(int i=0; i<pSelectedItems.size(); ++i)
        {
            tempName = item(pSelectedItems[i]->row(),0)->text();
            if(!parametersToRemove.contains(tempName))
            {
                parametersToRemove.append(tempName);
            }
            removeCellWidget(pSelectedItems[i]->row(), pSelectedItems[i]->column());
            delete pSelectedItems[i];
        }

        for(int j=0; j<parametersToRemove.size(); ++j)
        {
            std::cout << "Removing: " << parametersToRemove[j].toStdString() << std::endl;
            gpMainWindow->mpProjectTabs->getCurrentTopLevelSystem()->getCoreSystemAccessPtr()->removeSystemParameter(parametersToRemove.at(j));
        }
    }

    update();
}

//! Slot that opens "Add Parameter" dialog, where the user can add new System parameters
void SystemParameterTableWidget::openComponentPropertiesDialog()
{
    QDialog *pAddComponentPropertiesDialog = new QDialog(this);
    pAddComponentPropertiesDialog->setWindowTitle("Set System Parameter");

    mpNameLabel = new QLabel("Name: ", this);
    mpNameBox = new QLineEdit(this);
    mpValueLabel = new QLabel("Value: ", this);
    mpValueBox = new QLineEdit(this);
    mpValueBox->setValidator(new QDoubleValidator(this));
    mpAddInDialogButton = new QPushButton("Set", this);
    mpDoneInDialogButton = new QPushButton("Done", this);
    QDialogButtonBox *pButtonBox = new QDialogButtonBox(Qt::Horizontal);
    pButtonBox->addButton(mpAddInDialogButton, QDialogButtonBox::ActionRole);
    pButtonBox->addButton(mpDoneInDialogButton, QDialogButtonBox::ActionRole);

    QGridLayout *pDialogLayout = new QGridLayout(this);
    pDialogLayout->addWidget(mpNameLabel,0,0);
    pDialogLayout->addWidget(mpNameBox,0,1);
    pDialogLayout->addWidget(mpValueLabel,1,0);
    pDialogLayout->addWidget(mpValueBox,1,1);
    pDialogLayout->addWidget(pButtonBox,2,0,1,2);
    pAddComponentPropertiesDialog->setLayout(pDialogLayout);
    pAddComponentPropertiesDialog->show();

    connect(mpDoneInDialogButton,SIGNAL(clicked()),pAddComponentPropertiesDialog,SLOT(close()));
    connect(mpAddInDialogButton,SIGNAL(clicked()),this,SLOT(addParameter()));
}

//! @Private help slot that adds a parameter from the selected name and value in "Add Parameter" dialog
void SystemParameterTableWidget::addParameter()
{
    bool ok;
    setParameter(mpNameBox->text(), mpValueBox->text().toDouble(&ok));
}

//! Updates the parameter table from the contents list
void SystemParameterTableWidget::update()
{
    QMap<std::string, double>::iterator it;
    QMap<std::string, double> tempMap;
    tempMap.clear();
    clear();
    if(gpMainWindow->mpProjectTabs->count()>0)
    {
        tempMap = gpMainWindow->mpProjectTabs->getCurrentTopLevelSystem()->getCoreSystemAccessPtr()->getSystemParametersMap();
    }
    if(tempMap.isEmpty())
    {
        setColumnCount(1);
        setRowCount(1);
        verticalHeader()->hide();

        QTableWidgetItem *item = new QTableWidgetItem();
        item->setText("No System parameters set.");
        item->setBackgroundColor(QColor("white"));
        item->setTextAlignment(Qt::AlignCenter);
        item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);
        setItem(0,0,item);
    }
    else
    {
        setRowCount(0);
        setColumnCount(2);
        setColumnWidth(0, 120);
        verticalHeader()->show();

        for(it=tempMap.begin(); it!=tempMap.end(); ++it)
        {
            QString valueString;
            valueString.setNum(it.value());
            insertRow(rowCount());
            QTableWidgetItem *nameItem = new QTableWidgetItem(QString(it.key().c_str()));
            QTableWidgetItem *valueItem = new QTableWidgetItem(valueString);
            nameItem->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);
            valueItem->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable);
            setItem(rowCount()-1, 0, nameItem);
            setItem(rowCount()-1, 1, valueItem);
        }
    }
}
<commit_msg>minor change<commit_after>/*
 * This file is part of OpenModelica.
 *
 * Copyright (c) 1998-CurrentYear, Linköping University,
 * Department of Computer and Information Science,
 * SE-58183 Linköping, Sweden.
 *
 * All rights reserved.
 *
 * THIS PROGRAM IS PROVIDED UNDER THE TERMS OF GPL VERSION 3
 * AND THIS OSMC PUBLIC LICENSE (OSMC-PL).
 * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES RECIPIENT'S
 * ACCEPTANCE OF THE OSMC PUBLIC LICENSE.
 *
 * The OpenModelica software and the Open Source Modelica
 * Consortium (OSMC) Public License (OSMC-PL) are obtained
 * from Linköping University, either from the above address,
 * from the URLs: http://www.ida.liu.se/projects/OpenModelica or
 * http://www.openmodelica.org, and in the OpenModelica distribution.
 * GNU version 3 is obtained from: http://www.gnu.org/copyleft/gpl.html.
 *
 * This program is distributed WITHOUT ANY WARRANTY; without
 * even the implied warranty of  MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH
 * IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS
 * OF OSMC-PL.
 *
 * See the full OSMC Public License conditions for more details.
 *
 */

/*
 * HopsanGUI
 * Fluid and Mechatronic Systems, Department of Management and Engineering, Linköping University
 * Main Authors 2009-2010:  Robert Braun, Björn Eriksson, Peter Nordin
 * Contributors 2009-2010:  Mikael Axin, Alessandro Dell'Amico, Karl Pettersson, Ingo Staack
 */

//!
//! @file   SystemParametersWidget.cpp
//! @author Robert Braun <robert.braun@liu.se>
//! @date   2010-10-04
//!
//! @brief Contains a System parameter widget class
//!
//$Id$

#include <QtGui>

#include "../MainWindow.h"
#include "SystemParametersWidget.h"

#include <QWidget>
#include <QDialog>

#include "ProjectTabWidget.h"
#include "../GUIObjects/GUISystem.h"

#include "../common.h"

//! Construtor for System Parameters widget, where the user can see and change the System parameters in the model.
//! @param parent Pointer to the main window
SystemParametersWidget::SystemParametersWidget(MainWindow *parent)
    : QWidget(parent)
{
    //mpParentMainWindow = parent;
    //Set the name and size of the main window
    this->setObjectName("SystemParameterWidget");
    this->resize(400,500);
    this->setWindowTitle("System Parameters");

    mpSystemParametersTable = new SystemParameterTableWidget(0,1,this);

    mpAddButton = new QPushButton(tr("&Set"), this);
    mpAddButton->setFixedHeight(30);
    mpAddButton->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
    mpAddButton->setAutoDefault(false);
    QFont tempFont = mpAddButton->font();
    tempFont.setBold(true);
    mpAddButton->setFont(tempFont);
    mpAddButton->setEnabled(false);

    mpRemoveButton = new QPushButton(tr("&Unset"), this);
    mpRemoveButton->setFixedHeight(30);
    mpRemoveButton->setAutoDefault(false);
    mpRemoveButton->setFont(tempFont);
    mpRemoveButton->setEnabled(false);

    mpGridLayout = new QGridLayout(this);
    mpGridLayout->addWidget(mpSystemParametersTable, 0, 0);
    mpGridLayout->addWidget(mpAddButton, 1, 0);
    mpGridLayout->addWidget(mpRemoveButton, 2, 0);

    update();

    connect(mpAddButton, SIGNAL(clicked()), mpSystemParametersTable, SLOT(openComponentPropertiesDialog()));
    connect(mpRemoveButton, SIGNAL(clicked()), mpSystemParametersTable, SLOT(removeSelectedParameters()));
    connect(gpMainWindow->mpProjectTabs, SIGNAL(currentChanged(int)), this, SLOT(update()));//Strössel!
    connect(gpMainWindow->mpProjectTabs, SIGNAL(newTabAdded()), this, SLOT(update()));//Strössel!
}

void SystemParametersWidget::update()
{
    if(gpMainWindow->mpProjectTabs->count()>0)
    {
        mpAddButton->setEnabled(true);
        mpRemoveButton->setEnabled(true);
    }
    else
    {
        mpAddButton->setEnabled(false);
        mpRemoveButton->setEnabled(false);
    }

    mpSystemParametersTable->update();
}

SystemParameterTableWidget::SystemParameterTableWidget(int rows, int columns, QWidget *parent)
    : QTableWidget(rows, columns, parent)
{
    setFocusPolicy(Qt::StrongFocus);
    setSelectionMode(QAbstractItemView::SingleSelection);

    setBaseSize(400, 500);
    horizontalHeader()->setStretchLastSection(true);
    horizontalHeader()->hide();

    update();

    connect(this, SIGNAL(itemChanged(QTableWidgetItem*)), this, SLOT(changeParameter(QTableWidgetItem*)));
}

void SystemParameterTableWidget::keyPressEvent(QKeyEvent *event)
{
    QTableWidget::keyPressEvent(event);
    if(event->key() == Qt::Key_Delete)
    {
        std::cout << "Delete current System Parameter Widget Items" << std::endl;
        removeSelectedParameters();
    }
}

//! @brief Used for parameter changes done directly in the label
void SystemParameterTableWidget::changeParameter(QTableWidgetItem *item)
{
    //Filter out value labels
    if(item->column() == 1)
    {
        QTableWidgetItem *neighborItem = itemAt(item->row(), item->column()-1);
        QString parName = neighborItem->text();
        QString parValue = item->text();

        //Do not do update, then crash due to the rebuild of the QTableWidgetItems
        setParameter(parName, parValue, false);
    }
}

double SystemParameterTableWidget::getParameter(QString name)
{
    return gpMainWindow->mpProjectTabs->getCurrentTopLevelSystem()->getCoreSystemAccessPtr()->getSystemParameter(name);
}

bool SystemParameterTableWidget::hasParameter(QString name)
{
    return gpMainWindow->mpProjectTabs->getCurrentTopLevelSystem()->getCoreSystemAccessPtr()->hasSystemParameter(name);
}

//! Slot that adds a System parameter value
//! @param name Lookup name for the System parameter
//! @param value Value of the System parameter
void SystemParameterTableWidget::setParameter(QString name, double value, bool doUpdate)
{
    //Error check
    if(!(gpMainWindow->mpProjectTabs->getCurrentTopLevelSystem()->getCoreSystemAccessPtr()->setSystemParameter(name, value)))
    {
        QMessageBox::critical(0, "Hopsan GUI",
                              QString("'%1' is an invalid name for a system parameter.")
                              .arg(name));
        return;
    }
    if(doUpdate)
    {
        update();
    }
    emit modifiedSystemParameter();
}

//! Slot that adds a System parameter value
//! @param name Lookup name for the System parameter
//! @param value Value of the System parameter
void SystemParameterTableWidget::setParameter(QString name, QString valueTxt, bool doUpdate)
{
    //Error check
    bool isDbl;
    double value = valueTxt.toDouble((&isDbl));
    if(!(isDbl))
    {
        QMessageBox::critical(0, "Hopsan GUI",
                              QString("'%1' is not a valid number.")
                              .arg(valueTxt));
        QString oldValue = QString::number(gpMainWindow->mpProjectTabs->getCurrentTopLevelSystem()->getCoreSystemAccessPtr()->getSystemParameter(name));
        QList<QTableWidgetItem *> items = selectedItems();
        //Error if size() > 1, but it should not be! :)
        for(int i = 0; i<items.size(); ++i)
        {
            items[i]->setText(oldValue);
        }
    }
    else
    {
        setParameter(name, value, doUpdate);
    }
}

void SystemParameterTableWidget::setParameters()
{
    //    if(gpMainWindow->mpProjectTabs->getCurrentTopLevelSystem()->getCoreSystemAccessPtr()->getNumberOfSystemParameters() > 0)
    //    {
    for(int i=0; i<rowCount(); ++i)
    {
        QString name = item(i, 0)->text();
        double value = item(i, 1)->text().toDouble();
        setParameter(name, value);
    }
    //    }
}

//! Slot that removes all selected System parameters in parameter table
//! @todo This shall remove the actual System parameters when they have been implemented, wherever they are stored.
void SystemParameterTableWidget::removeSelectedParameters()
{
    if(gpMainWindow->mpProjectTabs->count()>0)
    {
        QList<QTableWidgetItem *> pSelectedItems = selectedItems();
        QStringList parametersToRemove;
        QString tempName;

        for(int i=0; i<pSelectedItems.size(); ++i)
        {
            tempName = item(pSelectedItems[i]->row(),0)->text();
            if(!parametersToRemove.contains(tempName))
            {
                parametersToRemove.append(tempName);
                gpMainWindow->mpProjectTabs->getCurrentTab()->hasChanged();
            }
            removeCellWidget(pSelectedItems[i]->row(), pSelectedItems[i]->column());
            delete pSelectedItems[i];
        }

        for(int j=0; j<parametersToRemove.size(); ++j)
        {
            std::cout << "Removing: " << parametersToRemove[j].toStdString() << std::endl;
            gpMainWindow->mpProjectTabs->getCurrentTopLevelSystem()->getCoreSystemAccessPtr()->removeSystemParameter(parametersToRemove.at(j));
        }
    }
    update();
}

//! Slot that opens "Add Parameter" dialog, where the user can add new System parameters
void SystemParameterTableWidget::openComponentPropertiesDialog()
{
    QDialog *pAddComponentPropertiesDialog = new QDialog(this);
    pAddComponentPropertiesDialog->setWindowTitle("Set System Parameter");

    mpNameLabel = new QLabel("Name: ", this);
    mpNameBox = new QLineEdit(this);
    mpValueLabel = new QLabel("Value: ", this);
    mpValueBox = new QLineEdit(this);
    mpValueBox->setValidator(new QDoubleValidator(this));
    mpAddInDialogButton = new QPushButton("Set", this);
    mpDoneInDialogButton = new QPushButton("Done", this);
    QDialogButtonBox *pButtonBox = new QDialogButtonBox(Qt::Horizontal);
    pButtonBox->addButton(mpAddInDialogButton, QDialogButtonBox::ActionRole);
    pButtonBox->addButton(mpDoneInDialogButton, QDialogButtonBox::ActionRole);

    QGridLayout *pDialogLayout = new QGridLayout(this);
    pDialogLayout->addWidget(mpNameLabel,0,0);
    pDialogLayout->addWidget(mpNameBox,0,1);
    pDialogLayout->addWidget(mpValueLabel,1,0);
    pDialogLayout->addWidget(mpValueBox,1,1);
    pDialogLayout->addWidget(pButtonBox,2,0,1,2);
    pAddComponentPropertiesDialog->setLayout(pDialogLayout);
    pAddComponentPropertiesDialog->show();

    connect(mpDoneInDialogButton,SIGNAL(clicked()),pAddComponentPropertiesDialog,SLOT(close()));
    connect(mpAddInDialogButton,SIGNAL(clicked()),this,SLOT(addParameter()));
}

//! @Private help slot that adds a parameter from the selected name and value in "Add Parameter" dialog
void SystemParameterTableWidget::addParameter()
{
    bool ok;
    setParameter(mpNameBox->text(), mpValueBox->text().toDouble(&ok));
    gpMainWindow->mpProjectTabs->getCurrentTab()->hasChanged();
}

//! Updates the parameter table from the contents list
void SystemParameterTableWidget::update()
{
    QMap<std::string, double>::iterator it;
    QMap<std::string, double> tempMap;
    tempMap.clear();
    clear();
    if(gpMainWindow->mpProjectTabs->count()>0)
    {
        tempMap = gpMainWindow->mpProjectTabs->getCurrentTopLevelSystem()->getCoreSystemAccessPtr()->getSystemParametersMap();
    }
    if(tempMap.isEmpty())
    {
        setColumnCount(1);
        setRowCount(1);
        verticalHeader()->hide();

        QTableWidgetItem *item = new QTableWidgetItem();
        item->setText("No System parameters set.");
        item->setBackgroundColor(QColor("white"));
        item->setTextAlignment(Qt::AlignCenter);
        item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);
        setItem(0,0,item);
    }
    else
    {
        setRowCount(0);
        setColumnCount(2);
        setColumnWidth(0, 120);
        verticalHeader()->show();

        for(it=tempMap.begin(); it!=tempMap.end(); ++it)
        {
            QString valueString;
            valueString.setNum(it.value());
            insertRow(rowCount());
            QTableWidgetItem *nameItem = new QTableWidgetItem(QString(it.key().c_str()));
            QTableWidgetItem *valueItem = new QTableWidgetItem(valueString);
            nameItem->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);
            valueItem->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable);
            setItem(rowCount()-1, 0, nameItem);
            setItem(rowCount()-1, 1, valueItem);
        }
    }
}
<|endoftext|>


<commit_before>#include "adskShader.h"

struct KSHairParameters {
	ADSK_BASE_SHADER_PARAMETERS
	miColor     ambience;
	miColor     ambient;
	miColor     diffuse;
	miColor     specular;
	miScalar    exponent;
	miInteger   mode;
};

const unsigned int KSHAIR_VERSION = 1;
typedef ShaderHelper<KSHairParameters> BaseShaderHelperType;

class KSHairClass : public Material<KSHairParameters, BaseShaderHelperType, KSHAIR_VERSION> {
public:

	// Per-render init.
	static void init(miState *state, KSHairParameters *params) {}
	static void exit(miState *state, KSHairParameters *params) {}

	// Per-instance init.
	KSHairClass(miState *state, KSHairParameters *params) :
		Material<KSHairParameters, BaseShaderHelperType, KSHAIR_VERSION>(state, params)
		{}
	~KSHairClass() {}

	miBoolean operator()(miColor *result, miState *state, KSHairParameters *params);

private:

	typedef Material<KSHairParameters, BaseShaderHelperType, KSHAIR_VERSION> MaterialBase;

};

static float smoothstep(float min, float max, float x) {

	float p, term, term2;

	/* first clamp the parameter to [min,max]. */
	if (x < min) {
		p = min;
	} else if (x > max) {
		p = max;
	} else {
		p = x;
	}

	/* now calculate smoothstep value:
	   -2term^3 + 3term^2, where term = (p-min)/(max-min) */
	term  = (p - min) / (max - min);
	term2 = term * term;
	return -2 * term * term2 + 3 * term2;

}

struct ksColor : public miColor {
public:

	ksColor() {}

	ksColor(miColor const &other) {
		r = other.r; g = other.g; b = other.b; a = other.a;
	}

	ksColor(miScalar r_, miScalar g_, miScalar b_, miScalar a_) {
		r = r_; g = g_; b = b_; a = a_;
	}

	ksColor operator*(miScalar v) {
		return ksColor(r * v, g * v, b * v, a * v);
	}

	void operator+=(ksColor const &other) {
		r += other.r; g += other.g; b += other.b; a += other.a;
	}

	ksColor operator+(ksColor const &other) {
		ksColor res(*this);
		res += other;
		return res;
	}

	void operator*=(ksColor const &other) {
		r *= other.r; g *= other.g; b *= other.b; a *= other.a;
	}

	ksColor operator*(ksColor const &other) {
		ksColor res(*this);
		res *= other;
		return res;
	}

};

miBoolean KSHairClass::operator()(miColor *result, miState *state, KSHairParameters *paras) {

	/* shader parameters */
	miColor		*ambient;
	miColor		*diffuse;
	miColor		*specular;
	miScalar	 exponent;
	miInteger	 mode;
	miInteger	 n_light;
	miTag*		 light;
	miScalar	 mult;			/* diffuse multiplier       */
	miColor		 diffcol;		/* for diffuse modification */
	miInteger	 samples;		/* for light sampling       */
	miScalar	 dot_nl;		/* for diffuse colour       */
	miScalar	 dot_th;		/* for specular colour      */
	miScalar	 spec;			/* specular factor          */
	miColor Cl;
	miVector L, H;

	miVector	 cross, hair_n, shading_n;  /* shading normal       */
	miColor		 sum;			/* light contribution       */
	miScalar	 blend;			/* shading normal blend     */
	miVector	 norm = state->normal;	/* for nulling/restoring    */

    // We can't displace.
    if(state->type == miRAY_DISPLACE)
        return miFALSE;

	// Shortcut if we are a shadow shader.
	diffuse = mi_eval_color(&paras->diffuse);
	if (state->type == miRAY_SHADOW) {
		result->r *= diffuse->r;
		result->g *= diffuse->g;
		result->b *= diffuse->b;
		return miTRUE;
	}

    // For mental images macros.
    // XXX: Do we really need this?!
	MBS_SETUP(state)

	// Dealing with render passes.
    PassTypeInfo* passTypeInfo;
    FrameBufferInfo* frameBufferInfo;
    unsigned int numberOfFrameBuffers = getFrameBufferInfo(state, passTypeInfo, frameBufferInfo);

	// Shader parameters.
	*result    = *mi_eval_color(&paras->ambience);
	ambient    =  mi_eval_color(&paras->ambient);
	specular   =  mi_eval_color(&paras->specular);
	exponent   = *mi_eval_scalar(&paras->exponent);
	mode       = *mi_eval_integer(&paras->mode);

    // Hair parameters.
	miScalar	 p = state->bary[1];   // 0 to 1 along hair.
	miVector	 T = state->derivs[0]; // Tangent to hair.
	miVector	 V = state->dir;	   // Eye ray.
	mi_vector_normalize(&T);
	mi_vector_neg(&V);

	// Darker colours near the root.
	mult = 0.5f + smoothstep(0.4f, 0.8f, p) * 0.5f;
	diffcol.r = diffuse->r * mult;
	diffcol.g = diffuse->g * mult;
	diffcol.b = diffuse->b * mult;

	// Base opacity (0.5 at root, 1.0 at tip).
	result->r *= ambient->r;
	result->g *= ambient->g;
	result->b *= ambient->b;
	result->a = 1.0f - smoothstep(0.3f, 1.0f, p);

	/* get shading normal */
	mi_vector_prod(&cross, &state->normal_geom, &T);
	mi_vector_prod(&hair_n, &T, &cross);
	blend = mi_vector_dot(&state->normal_geom, &T);
	shading_n.x = (1.0f-blend)*hair_n.x + blend*state->normal_geom.x;
	shading_n.y = (1.0f-blend)*hair_n.y + blend*state->normal_geom.y;
	shading_n.z = (1.0f-blend)*hair_n.z + blend*state->normal_geom.z;
	mi_vector_normalize(&shading_n);

	/* null state->normal for now, for sampling lights       */
	/* we leave state->pri to avoid losing self-intersection */
	/* handling.                                             */
	state->normal.x = state->normal.y = state->normal.z = 0.0f;

	// Get the light list.
	mi_instance_lightlist(&n_light, &light, state);
    for (; n_light--; light++)
	{

		samples = 0;
		sum.r = sum.g = sum.b = 0;

		// Function that initialize light sample accumulators which need to be called before the sample loop.
		sampleLightBegin(numberOfFrameBuffers, frameBufferInfo);

		while (mi_sample_light(
                &Cl, &L, &dot_nl,
                state, *light, &samples)) {

			// Call to enable renderpass contributions for light shaders that were not developped using the AdskShaderSDK.
			handleNonAdskLights(numberOfFrameBuffers, frameBufferInfo, Cl, *light, state);

			// Do it ourselves.
			dot_nl = mi_vector_dot(&shading_n, &L);
			if (dot_nl < 0.0f)
				dot_nl = 0.0f;
			else if (dot_nl > 1.0f)
				dot_nl = 1.0f;

			sum.r += dot_nl * diffcol.r * Cl.r;
			sum.g += dot_nl * diffcol.g * Cl.g;
			sum.b += dot_nl * diffcol.b * Cl.b;

			/* find the halfway vector h */
			mi_vector_add(&H, &V, &L);
			mi_vector_normalize(&H);

			/* specular coefficient from auk paper */
			dot_th = mi_vector_dot(&T, &H);
			spec = pow(1.0 - dot_th*dot_th, 0.5*exponent);

			/* specular colour */
			if (spec > 0.0) {
				sum.r += spec * specular->r * Cl.r;
				sum.g += spec * specular->g * Cl.g;
				sum.b += spec * specular->b * Cl.b;
			}
		}

		// Function that take care of combining sample values into the material frame buffer values,
		//    called after light sampling loop.
		sampleLightEnd(state,
			   numberOfFrameBuffers,
			   frameBufferInfo,
			   samples,
			   MaterialBase::mFrameBufferWriteOperation,
			   MaterialBase::mFrameBufferWriteFlags,
			   MaterialBase::mFrameBufferWriteFactor);

		if (samples) {
			result->r += sum.r / samples;
			result->g += sum.g / samples;
			result->b += sum.b / samples;
		}
	}

	/* restore state->normal */
	state->normal = norm;

	/* if we are translucent, trace more rays */
	if (result->a < 0.9999) {
		miScalar alphafactor;
		miColor col = {0.0, 0.0, 0.0, 0.0};
		mi_trace_transparent(&col, state);
		alphafactor = 1.0f - result->a;
		result->r   = alphafactor * col.r + result->a * result->r;
		result->g   = alphafactor * col.g + result->a * result->g;
		result->b   = alphafactor * col.b + result->a * result->b;
		result->a  += alphafactor * col.a;
	}

	return miTRUE;
}

EXPOSE(KSHair, miColor, );

<commit_msg>Quickly add (bad) frame buffers<commit_after>#include "adskShader.h"

struct KSHairParameters {
	ADSK_BASE_SHADER_PARAMETERS
	miColor     ambience;
	miColor     ambient;
	miColor     diffuse;
	miColor     specular;
	miScalar    exponent;
	miInteger   mode;
};

const unsigned int KSHAIR_VERSION = 1;
typedef ShaderHelper<KSHairParameters> BaseShaderHelperType;

class KSHairClass : public Material<KSHairParameters, BaseShaderHelperType, KSHAIR_VERSION> {
public:

	// Per-render init.
	static void init(miState *state, KSHairParameters *params) {}
	static void exit(miState *state, KSHairParameters *params) {}

	// Per-instance init.
	KSHairClass(miState *state, KSHairParameters *params) :
		Material<KSHairParameters, BaseShaderHelperType, KSHAIR_VERSION>(state, params)
		{}
	~KSHairClass() {}

	miBoolean operator()(miColor *result, miState *state, KSHairParameters *params);

private:

	typedef Material<KSHairParameters, BaseShaderHelperType, KSHAIR_VERSION> MaterialBase;

};

static float smoothstep(float min, float max, float x) {

	float p, term, term2;

	/* first clamp the parameter to [min,max]. */
	if (x < min) {
		p = min;
	} else if (x > max) {
		p = max;
	} else {
		p = x;
	}

	/* now calculate smoothstep value:
	   -2term^3 + 3term^2, where term = (p-min)/(max-min) */
	term  = (p - min) / (max - min);
	term2 = term * term;
	return -2 * term * term2 + 3 * term2;

}

struct ksColor : public miColor {
public:

	ksColor() {}

	ksColor(miColor const &other) {
		r = other.r; g = other.g; b = other.b; a = other.a;
	}

	ksColor(miScalar r_, miScalar g_, miScalar b_, miScalar a_) {
		r = r_; g = g_; b = b_; a = a_;
	}

	ksColor operator*(miScalar v) {
		return ksColor(r * v, g * v, b * v, a * v);
	}

	void operator+=(ksColor const &other) {
		r += other.r; g += other.g; b += other.b; a += other.a;
	}

	ksColor operator+(ksColor const &other) {
		ksColor res(*this);
		res += other;
		return res;
	}

	void operator*=(ksColor const &other) {
		r *= other.r; g *= other.g; b *= other.b; a *= other.a;
	}

	ksColor operator*(ksColor const &other) {
		ksColor res(*this);
		res *= other;
		return res;
	}

};

miBoolean KSHairClass::operator()(miColor *result, miState *state, KSHairParameters *paras) {

	/* shader parameters */
	miColor		*ambient;
	miColor		*diffuse;
	miColor		*specular;
	miScalar	 exponent;
	miInteger	 mode;
	miInteger	 n_light;
	miTag*		 light;
	miScalar	 mult;			/* diffuse multiplier       */
	miColor		 diffcol;		/* for diffuse modification */
	miInteger	 samples;		/* for light sampling       */
	miScalar	 dot_nl;		/* for diffuse colour       */
	miScalar	 dot_th;		/* for specular colour      */
	miScalar	 spec;			/* specular factor          */
	miColor Cl;
	miVector L, H;

	miVector	 cross, hair_n, shading_n;  /* shading normal       */
	miColor		 sum;			/* light contribution       */
	miScalar	 blend;			/* shading normal blend     */
	miVector	 norm = state->normal;	/* for nulling/restoring    */

    // We can't displace.
    if(state->type == miRAY_DISPLACE)
        return miFALSE;

	// Shortcut if we are a shadow shader.
	diffuse = mi_eval_color(&paras->diffuse);
	if (state->type == miRAY_SHADOW) {
		result->r *= diffuse->r;
		result->g *= diffuse->g;
		result->b *= diffuse->b;
		return miTRUE;
	}

    // For mental images macros.
    // XXX: Do we really need this?!
	MBS_SETUP(state)

	// Dealing with render passes.
    PassTypeInfo* passTypeInfo;
    FrameBufferInfo* frameBufferInfo;
    unsigned int numberOfFrameBuffers = getFrameBufferInfo(state, passTypeInfo, frameBufferInfo);

	// Shader parameters.
	*result    = *mi_eval_color(&paras->ambience);
	ambient    =  mi_eval_color(&paras->ambient);
	specular   =  mi_eval_color(&paras->specular);
	exponent   = *mi_eval_scalar(&paras->exponent);
	mode       = *mi_eval_integer(&paras->mode);

    // Hair parameters.
	miScalar	 p = state->bary[1];   // 0 to 1 along hair.
	miVector	 T = state->derivs[0]; // Tangent to hair.
	miVector	 V = state->dir;	   // Eye ray.
	mi_vector_normalize(&T);
	mi_vector_neg(&V);

	// Darker colours near the root.
	mult = 0.5f + smoothstep(0.4f, 0.8f, p) * 0.5f;
	diffcol.r = diffuse->r * mult;
	diffcol.g = diffuse->g * mult;
	diffcol.b = diffuse->b * mult;

	// Base opacity (0.5 at root, 1.0 at tip).
	result->r *= ambient->r;
	result->g *= ambient->g;
	result->b *= ambient->b;
	result->a = 1.0f - smoothstep(0.3f, 1.0f, p);

	/* get shading normal */
	mi_vector_prod(&cross, &state->normal_geom, &T);
	mi_vector_prod(&hair_n, &T, &cross);
	blend = mi_vector_dot(&state->normal_geom, &T);
	shading_n.x = (1.0f-blend)*hair_n.x + blend*state->normal_geom.x;
	shading_n.y = (1.0f-blend)*hair_n.y + blend*state->normal_geom.y;
	shading_n.z = (1.0f-blend)*hair_n.z + blend*state->normal_geom.z;
	mi_vector_normalize(&shading_n);

	/* null state->normal for now, for sampling lights       */
	/* we leave state->pri to avoid losing self-intersection */
	/* handling.                                             */
	state->normal.x = state->normal.y = state->normal.z = 0.0f;

	miColor diff_sum, spec_sum;

	// Get the light list.
	mi_instance_lightlist(&n_light, &light, state);
    for (; n_light--; light++)
	{

		samples = 0;
		sum.r = sum.g = sum.b = 0;
		diff_sum.r = diff_sum.g = diff_sum.b = 0;
		spec_sum.r = spec_sum.g = spec_sum.b = 0;

		// Function that initialize light sample accumulators which need to be called before the sample loop.
		sampleLightBegin(numberOfFrameBuffers, frameBufferInfo);

		while (mi_sample_light(
                &Cl, &L, &dot_nl,
                state, *light, &samples)) {

			// Call to enable renderpass contributions for light shaders that were not developped using the AdskShaderSDK.
			handleNonAdskLights(numberOfFrameBuffers, frameBufferInfo, Cl, *light, state);

			// Do it ourselves.
			dot_nl = mi_vector_dot(&shading_n, &L);
			if (dot_nl < 0.0f)
				dot_nl = 0.0f;
			else if (dot_nl > 1.0f)
				dot_nl = 1.0f;

			miColor s_diff = diffcol * Cl * dot_nl;
			if (numberOfFrameBuffers && MaterialBase::mFrameBufferWriteOperation)
			{
				MaterialBase::writeToFrameBuffers(state, frameBufferInfo, passTypeInfo, s_diff, DIFFUSE, true);
			}

			diff_sum.r += dot_nl * diffcol.r * Cl.r;
			diff_sum.g += dot_nl * diffcol.g * Cl.g;
			diff_sum.b += dot_nl * diffcol.b * Cl.b;

			/* find the halfway vector h */
			mi_vector_add(&H, &V, &L);
			mi_vector_normalize(&H);

			/* specular coefficient from auk paper */
			dot_th = mi_vector_dot(&T, &H);
			spec = pow(1.0 - dot_th*dot_th, 0.5*exponent);

			/* specular colour */
			if (spec > 0.0) {
				spec_sum.r += spec * specular->r * Cl.r;
				spec_sum.g += spec * specular->g * Cl.g;
				spec_sum.b += spec * specular->b * Cl.b;

				miColor s_spec = *specular * Cl * spec;
				if (numberOfFrameBuffers && MaterialBase::mFrameBufferWriteOperation)
				{
					MaterialBase::writeToFrameBuffers(state, frameBufferInfo, passTypeInfo, s_spec, SPECULAR, true);
				}
			}
		}

		// Function that take care of combining sample values into the material frame buffer values,
		//    called after light sampling loop.
		sampleLightEnd(state,
			   numberOfFrameBuffers,
			   frameBufferInfo,
			   samples,
			   MaterialBase::mFrameBufferWriteOperation,
			   MaterialBase::mFrameBufferWriteFlags,
			   MaterialBase::mFrameBufferWriteFactor);

		if (samples) {
			result->r += (diff_sum.r + spec_sum.r) / samples;
			result->g += (diff_sum.g + spec_sum.g) / samples;
			result->b += (diff_sum.b + spec_sum.b) / samples;
		}
	}

	/* restore state->normal */
	state->normal = norm;

	/* if we are translucent, trace more rays */
	if (result->a < 0.9999) {
		miScalar alphafactor;
		miColor col = {0.0, 0.0, 0.0, 0.0};
		mi_trace_transparent(&col, state);
		alphafactor = 1.0f - result->a;
		result->r   = alphafactor * col.r + result->a * result->r;
		result->g   = alphafactor * col.g + result->a * result->g;
		result->b   = alphafactor * col.b + result->a * result->b;
		result->a  += alphafactor * col.a;
	}

	return miTRUE;
}

EXPOSE(KSHair, miColor, );

<|endoftext|>


<commit_before>
#include <libclientserver.h>

Notify::Notify()
{

}

Notify::~Notify()
{
	if (m_map.size() != 0)
		abort(); //Some things still reference us. This is a bug in the callers code
}

void Notify::Add(INotify *p)
{
	ScopedLock lock(&m_mutex);
	m_map.insert(std::make_pair<INotify *, INotify *>(p, p));
}

void Notify::Remove(INotify *p)
{
	ScopedLock lock(&m_mutex);
	std::map<INotify *, INotify *>::iterator it = m_map.find(p);
	if (it == m_map.end())
		abort(); //Request to delete an item that does not exist
	m_map.erase(it);
}

void Notify::Call(void *d)
{
	ScopedLock lock(&m_mutex);
	for(std::map<INotify *, INotify *>::iterator it = m_map.begin(); it != m_map.end(); it++)
	{
		it->first->Notify(d);
	}
}

<commit_msg>Fix Notify Compile error on ubuntu<commit_after>
#include <libclientserver.h>

Notify::Notify()
{

}

Notify::~Notify()
{
#ifdef DEBUG
	if (m_map.size() != 0)
		abort(); //Some things still reference us. This is a bug in the callers code
#endif
}

void Notify::Add(INotify *p)
{
	ScopedLock lock(&m_mutex);
#ifdef DEBUG
	std::map<INotify *, INotify *>::iterator it = m_map.find(p);
	if (it != m_map.end())
		abort();
#endif
	m_map[p] = p;
}

void Notify::Remove(INotify *p)
{
	ScopedLock lock(&m_mutex);
	std::map<INotify *, INotify *>::iterator it = m_map.find(p);
	if (it == m_map.end())
		abort(); //Request to delete an item that does not exist
	m_map.erase(it);
}

void Notify::Call(void *d)
{
	ScopedLock lock(&m_mutex);
	for(std::map<INotify *, INotify *>::iterator it = m_map.begin(); it != m_map.end(); it++)
	{
		it->first->Notify(d);
	}
}

<|endoftext|>


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

  Program:   Visualization Toolkit
  Module:    TestRenderWindow.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) 1993-2002 Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
#include "vtkRenderer.h"
#include "vtkRenderWindow.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkSphereSource.h"
#include "vtkPolyDataMapper.h"
#include "vtkActor.h"
#include "vtkUnsignedCharArray.h"
#include "vtkFloatArray.h"
#include "vtkProperty.h"

#include "vtkRegressionTestImage.h"

int main( int argc, char *argv[] )
{
  // Create the renderers, render window, and interactor
  vtkRenderWindow *renWin = vtkRenderWindow::New();
  vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New();
  iren->SetRenderWindow(renWin);
  vtkRenderer *ren = vtkRenderer::New();
  renWin->AddRenderer(ren);

  renWin->SetSize( 200, 200 );

  vtkSphereSource *sphereSource = vtkSphereSource::New();
  sphereSource->SetThetaResolution(30.0);
  sphereSource->SetPhiResolution(30.0);
  vtkPolyDataMapper *mapper = vtkPolyDataMapper::New();
  mapper->SetInput( sphereSource->GetOutput() );

  vtkActor *actor = vtkActor::New();
  actor->SetMapper(mapper);
  actor->GetProperty()->SetColor(1.0, 0.0, 0.0);

  ren->AddProp( actor );
  renWin->Render();

  actor->AddPosition( 0.3, 0.3, 0.0 );
  renWin->Render();
  vtkUnsignedCharArray *ucCharArray = vtkUnsignedCharArray::New();
  renWin->GetPixelData( 0, 0, 199, 199, 1, ucCharArray );

  float *fdata = renWin->GetZbufferData( 10, 10, 10, 10 );
  delete [] fdata;

  vtkFloatArray *floatArray = vtkFloatArray::New();
  renWin->GetZbufferData( 30, 30, 199, 199, floatArray );

  ren->RemoveProp( actor );
  renWin->Render();
  renWin->Render();
  renWin->EraseOff();

  renWin->SetZbufferData(  0, 0,  169, 169, floatArray );

  ren->AddProp( actor );
  actor->GetProperty()->SetColor(1,0,1);
  renWin->Render();

  actor->GetProperty()->SetColor(0,1,0);
  actor->AddPosition( -0.1, -0.1, 0.0 );
  renWin->Render();
  renWin->GetRGBAPixelData( 120, 120, 174, 174, 1, floatArray );

  renWin->EraseOn();
  renWin->Render();

  ren->RemoveProp( actor );
  renWin->Render();

  renWin->SetPixelData( 0, 0, 199, 199, ucCharArray, 1 );

  unsigned char *checks = new unsigned char [200*200*3];

  int i, j;

  for ( i = 0; i < 200; i++ )
    for ( j = 0; j < 200; j++ )
      {
      checks[i*200*3 + j*3] = 0;
      checks[i*200*3 + j*3 + 1] = i;
      checks[i*200*3 + j*3 + 2] = j;
      }

  renWin->SetPixelData( 0, 0, 199, 199, checks, 1 );

  renWin->SetRGBAPixelData(  0,  0,  54,  54, floatArray, 1, 0 );

  renWin->SetRGBAPixelData( 20, 20,  74,  74, floatArray, 1, 0 );

  renWin->SetRGBAPixelData( 40, 40,  94,  94, floatArray, 1, 0 );

  renWin->SetRGBAPixelData( 60, 60, 114, 114, floatArray, 1, 0 );

  fdata = renWin->GetRGBAPixelData( 0, 0, 99, 99, 1 );
  renWin->SetRGBAPixelData( 100, 100, 199, 199, fdata, 1, 0 );
  renWin->ReleaseRGBAPixelData( fdata );

  renWin->SwapBuffersOff();

  int retVal = vtkRegressionTestImage( renWin );

  // Interact with the data at 3 frames per second
  iren->SetDesiredUpdateRate(3.0);
  iren->SetStillUpdateRate(0.001);

  if ( retVal == vtkRegressionTester::DO_INTERACTOR)
    {
    iren->Start();
    }

  sphereSource->Delete();
  actor->Delete();
  mapper->Delete();
  ren->Delete();
  renWin->Delete();
  iren->Delete();

  return !retVal;
}

<commit_msg>improve coverage<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    TestRenderWindow.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) 1993-2002 Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
#include "vtkRenderer.h"
#include "vtkRenderWindow.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkSphereSource.h"
#include "vtkPolyDataMapper.h"
#include "vtkActor.h"
#include "vtkUnsignedCharArray.h"
#include "vtkFloatArray.h"
#include "vtkProperty.h"

#include "vtkRegressionTestImage.h"

int main( int argc, char *argv[] )
{
  // Create the renderers, render window, and interactor
  vtkRenderWindow *renWin = vtkRenderWindow::New();
  vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New();
  iren->SetRenderWindow(renWin);
  vtkRenderer *ren = vtkRenderer::New();
  renWin->AddRenderer(ren);

  renWin->SetSize( 200, 200 );

  vtkSphereSource *sphereSource = vtkSphereSource::New();
  sphereSource->SetThetaResolution(30.0);
  sphereSource->SetPhiResolution(30.0);
  vtkPolyDataMapper *mapper = vtkPolyDataMapper::New();
  mapper->SetInput( sphereSource->GetOutput() );

  vtkActor *actor = vtkActor::New();
  actor->SetMapper(mapper);
  actor->GetProperty()->SetColor(1.0, 0.0, 0.0);

  ren->AddProp( actor );
  renWin->Render();

  actor->AddPosition( 0.3, 0.3, 0.0 );
  renWin->Render();
  vtkUnsignedCharArray *ucCharArray = vtkUnsignedCharArray::New();
  renWin->GetPixelData( 0, 0, 199, 199, 1, ucCharArray );

  float *fdata = renWin->GetZbufferData( 10, 10, 10, 10 );
  delete [] fdata;

  vtkFloatArray *floatArray = vtkFloatArray::New();
  renWin->GetZbufferData( 30, 30, 199, 199, floatArray );

  ren->RemoveProp( actor );
  renWin->Render();
  renWin->Render();
  renWin->EraseOff();

  renWin->SetZbufferData(  0, 0,  169, 169, floatArray );

  ren->AddProp( actor );
  actor->GetProperty()->SetColor(1,0,1);
  renWin->Render();

  actor->GetProperty()->SetColor(0,1,0);
  actor->AddPosition( -0.1, -0.1, 0.0 );
  renWin->Render();
  renWin->GetRGBAPixelData( 120, 120, 174, 174, 1, floatArray );

  renWin->EraseOn();
  renWin->Render();

  ren->RemoveProp( actor );
  renWin->Render();

  renWin->SetPixelData( 0, 0, 199, 199, ucCharArray, 1 );

  unsigned char *checks = new unsigned char [200*200*3];

  int i, j;

  for ( i = 0; i < 200; i++ )
    for ( j = 0; j < 200; j++ )
      {
      checks[i*200*3 + j*3] = 0;
      checks[i*200*3 + j*3 + 1] = i;
      checks[i*200*3 + j*3 + 2] = j;
      }

  renWin->SetPixelData( 0, 0, 199, 199, checks, 1 );

  renWin->SetRGBAPixelData(  0,  0,  54,  54, floatArray, 1, 0 );

  renWin->SetRGBAPixelData( 20, 20,  74,  74, floatArray, 1, 0 );

  renWin->SetRGBAPixelData( 40, 40,  94,  94, floatArray, 1, 0 );

  renWin->SetRGBAPixelData( 60, 60, 114, 114, floatArray, 1, 0 );

  fdata = renWin->GetRGBAPixelData( 0, 0, 99, 99, 1 );
  renWin->SetRGBAPixelData( 100, 100, 199, 199, fdata, 1, 0 );
  renWin->ReleaseRGBAPixelData( fdata );

  vtkUnsignedCharArray *ucArray = vtkUnsignedCharArray::New();
  renWin->GetRGBACharPixelData( 20, 150, 40, 170, 1, ucArray );
  renWin->SetRGBACharPixelData( 160, 31, 180, 51, ucArray, 1, 0 );

  renWin->SwapBuffersOff();

  int retVal = vtkRegressionTestImage( renWin );

  // Interact with the data at 3 frames per second
  iren->SetDesiredUpdateRate(3.0);
  iren->SetStillUpdateRate(0.001);

  if ( retVal == vtkRegressionTester::DO_INTERACTOR)
    {
    iren->Start();
    }

  floatArray->Delete();
  ucArray->Delete();
  sphereSource->Delete();
  actor->Delete();
  mapper->Delete();
  ren->Delete();
  renWin->Delete();
  iren->Delete();

  return !retVal;
}

<|endoftext|>


<commit_before>#include <gtest/gtest.h>

#include "../compress-stream.hh"

namespace mimosa
{
  namespace stream
  {
    namespace
    {
      TEST(CompressStream, Compress)
      {
      }

      TEST(CompressStream, Decompress)
      {
      }
    }
  }
}
<commit_msg>fix include<commit_after>#include <gtest/gtest.h>

#include "../compress.hh"

namespace mimosa
{
  namespace stream
  {
    namespace
    {
      TEST(CompressStream, Compress)
      {
      }

      TEST(CompressStream, Decompress)
      {
      }
    }
  }
}
<|endoftext|>


<commit_before>// InteractiveNotifications.cpp : Defines the exported functions for the DLL application.
//

#include "stdafx.h"
#include "InteractiveNotifications.h"
#include <NotificationActivationCallback.h>

#include <Shellapi.h>
#include <string>
#include <iostream>
#include <SDKDDKVer.h>
#include <Windows.h>
#include <Psapi.h>
#include <strsafe.h>
#include <ShObjIdl.h>
#include <Shlobj.h>
#include <Pathcch.h>
#include <propvarutil.h>
#include <propkey.h>
#include <wchar.h>
#include <wrl.h>
#include <wrl\wrappers\corewrappers.h>
#include <windows.ui.notifications.h>

// Correct flow
// RegisterAppForNotificationSupport()
// RegisterActivator()

//  Name:     System.AppUserModel.ToastActivatorCLSID -- PKEY_AppUserModel_ToastActivatorCLSID
//  Type:     Guid -- VT_CLSID
//  FormatID: {9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3}, 26
//
//  Used to CoCreate an INotificationActivationCallback interface to notify about toast activations.
EXTERN_C const PROPERTYKEY DECLSPEC_SELECTANY PKEY_AppUserModel_ToastActivatorCLSID = { { 0x9F4C2855, 0x9F79, 0x4B39,{ 0xA8, 0xD0, 0xE1, 0xD4, 0x2D, 0xE1, 0xD5, 0xF3 } }, 26 };

using namespace ABI::Windows::Data::Xml::Dom;
using namespace ABI::Windows::UI::Notifications;
using namespace Microsoft::WRL;
using namespace Microsoft::WRL::Wrappers;

struct CoTaskMemStringTraits
{
	typedef PWSTR Type;

	inline static bool Close(_In_ Type h) throw() { ::CoTaskMemFree(h); return true; }

	inline static Type GetInvalidValue() throw() { return nullptr; }
};
typedef HandleT<CoTaskMemStringTraits> CoTaskMemString;

const wchar_t Shortcut[] = LR"(Microsoft\Windows\Start Menu\Slack.lnk)";

#define __CSID "B23D2B18-8DD7-403A-B9B7-152B40A1478C"

// For the app to be activated from Action Center, it needs to provide a COM server to be called
// when the notification is activated.  The CLSID of the object needs to be registered with the
// OS via its shortcut so that it knows who to call later.
class DECLSPEC_UUID(__CSID) NotificationActivator WrlSealed WrlFinal
: public RuntimeClass < RuntimeClassFlags<ClassicCom>,
	INotificationActivationCallback >
{
public:
	virtual HRESULT STDMETHODCALLTYPE Activate(
		_In_ LPCWSTR appUserModelId,
		_In_ LPCWSTR invokedArgs,
		_In_reads_(dataCount) const NOTIFICATION_USER_INPUT_DATA* data,
		ULONG dataCount) override
	{
		std::string args;

		for (int i = 0; i < dataCount; i++) {
			LPCWSTR lvalue = data[i].Value;
			LPCWSTR lkey = data[i].Key;

			std::wstring wvalue(lvalue);
			std::wstring wkey(lkey);

			std::string value(wvalue.begin(), wvalue.end());
			std::string key(wkey.begin(), wkey.end());

			args = args + "\"key\":\"" + key + "\"";
			args = args + ",\"value\":\"" + value + "\"";
		}

		std::wstring wToastArgs(invokedArgs);
		std::string toastArgs(wToastArgs.begin(), wToastArgs.end());

		// If you ever want to use system() or similar calls,
		// you'll need to escape stuff. We're using ShellExecute,
		// so we don't have to.

		// std::string escapedArgs = "";
		// for (char ch : args) {
		// 	switch (ch) {
		// 	case ' ': escapedArgs += "%20"; break;
		// 	case '&': escapedArgs += "^&"; break;
		// 	case '\\': escapedArgs += "^\\"; break;
		// 	case '<': escapedArgs += "^<"; break;
		// 	case '>': escapedArgs += "^>"; break;
		// 	case '|': escapedArgs += "^|"; break;
		// 	case '^': escapedArgs += "^^"; break;
		// 	case '"': escapedArgs += "^%22"; break;
		// 	default: escapedArgs += ch; break;
		// 	}
		// }
		//
		// std::string escapedToastArgs = "";
		// for (char ch : toastArgs) {
		// 	switch (ch) {
		// 	case ' ': escapedToastArgs += "%20"; break;
		// 	case '&': escapedToastArgs += "^&"; break;
		// 	case '\\': escapedToastArgs += "^\\"; break;
		// 	case '<': escapedToastArgs += "^<"; break;
		// 	case '>': escapedToastArgs += "^>"; break;
		// 	case '|': escapedToastArgs += "^|"; break;
		// 	case '^': escapedToastArgs += "^^"; break;
		// 	case '"': escapedToastArgs += "%22"; break;
		// 	default: escapedToastArgs += ch; break;
		// 	}
		// }

		// std::string systemCmd = "myapp://" + escapedToastArgs + "^&userData=[{" + escapedArgs + "}]";

		std::string cmd = "myapp://" + toastArgs + "&userData=[{" + args + "}]";
		std::wstring wCmd = InteractiveNotifications::s2ws(cmd);

		ShellExecute(NULL,
			TEXT("open"),
			wCmd.c_str(),
			NULL,
			NULL,
			SW_SHOWNORMAL);

		return HRESULT();
	}
};
CoCreatableClass(NotificationActivator);

namespace InteractiveNotifications
{
	INTERACTIVENOTIFICATIONS_API HRESULT RegisterAppForNotificationSupport(PCWSTR shortcut, PCWSTR appId)
	{
		CoTaskMemString appData;
		auto hr = ::SHGetKnownFolderPath(FOLDERID_RoamingAppData, 0, nullptr, appData.GetAddressOf());

		if (SUCCEEDED(hr))
		{
			wchar_t shortcutPath[MAX_PATH];
			// Todo: Don't hardcode the path
			hr = ::PathCchCombine(shortcutPath, ARRAYSIZE(shortcutPath), appData.Get(), shortcut);

			if (SUCCEEDED(hr))
			{
				DWORD attributes = ::GetFileAttributes(shortcutPath);
				bool fileExists = attributes < 0xFFFFFFF;

				if (!fileExists)
				{
					// Todo: This is probably the wrong path bc Squirrel
					wchar_t exePath[MAX_PATH];
					DWORD charWritten = ::GetModuleFileName(nullptr, exePath, ARRAYSIZE(exePath));
					hr = charWritten > 0 ? S_OK : HRESULT_FROM_WIN32(::GetLastError());

					if (SUCCEEDED(hr))
					{
						hr = InstallShortcut(shortcutPath, exePath, appId);
						if (SUCCEEDED(hr))
						{
							hr = RegisterComServer(exePath);
						}
					}
				}
			}
		}
		return hr;
	}

	_Use_decl_annotations_
	INTERACTIVENOTIFICATIONS_API HRESULT InstallShortcut(PCWSTR shortcutPath, PCWSTR exePath, PCWSTR appId)
	{
		ComPtr<IShellLink> shellLink;
		HRESULT hr = CoCreateInstance(CLSID_ShellLink, nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&shellLink));

		if (!SUCCEEDED(hr)) return hr;
		hr = shellLink->SetPath(exePath);

		if (!SUCCEEDED(hr)) return hr;
		ComPtr<IPropertyStore> propertyStore;
		hr = shellLink.As(&propertyStore);

		if (!SUCCEEDED(hr)) return hr;
		PROPVARIANT propVar;
		propVar.vt = VT_LPWSTR;
		propVar.pwszVal = const_cast<PWSTR>(appId); // for _In_ scenarios, we don't need a copy
		hr = propertyStore->SetValue(PKEY_AppUserModel_ID, propVar);

		if (!SUCCEEDED(hr)) return hr;
		propVar.vt = VT_CLSID;
		propVar.puuid = const_cast<CLSID*>(&__uuidof(NotificationActivator));
		hr = propertyStore->SetValue(PKEY_AppUserModel_ToastActivatorCLSID, propVar);

		if (!SUCCEEDED(hr)) return hr;
		hr = propertyStore->Commit();

		if (!SUCCEEDED(hr)) return hr;
		ComPtr<IPersistFile> persistFile;
		hr = shellLink.As(&persistFile);

		if (!SUCCEEDED(hr)) return hr;
		hr = persistFile->Save(shortcutPath, TRUE);

		return hr;
	}

	_Use_decl_annotations_
	INTERACTIVENOTIFICATIONS_API HRESULT RegisterComServer(PCWSTR exePath)
	{
		// We don't need to worry about overflow here as ::GetModuleFileName won't
		// return anything bigger than the max file system path (much fewer than max of DWORD).
		DWORD dataSize = static_cast<DWORD>((::wcslen(exePath) + 1) * sizeof(WCHAR));
		auto key = LR"(SOFTWARE\Classes\CLSID\{B23D2B18-8DD7-403A-B9B7-152B40A1478C}\LocalServer32)";

		return HRESULT_FROM_WIN32(::RegSetKeyValue(
			HKEY_CURRENT_USER,
			key,
			nullptr,
			REG_SZ,
			reinterpret_cast<const BYTE*>(exePath),
			dataSize));
	}

	_Use_decl_annotations_
	INTERACTIVENOTIFICATIONS_API HRESULT RegisterActivator()
	{
		// Module<OutOfProc> needs a callback registered before it can be used.
		// Since we don't care about when it shuts down, we'll pass an empty lambda here.
		// If we need to clean up, do it here (we probably don't have to)
		Module<OutOfProc>::Create([] {});

		// If a local server process only hosts the COM object then COM expects
		// the COM server host to shutdown when the references drop to zero.
		// Since the user might still be using the program after activating the notification,
		// we don't want to shutdown immediately.  Incrementing the object count tells COM that
		// we aren't done yet.
		Module<OutOfProc>::GetModule().IncrementObjectCount();

		return Module<OutOfProc>::GetModule().RegisterObjects();
	}

	_Use_decl_annotations_
	INTERACTIVENOTIFICATIONS_API void UnregisterActivator()
	{
		Module<OutOfProc>::GetModule().UnregisterObjects();
		Module<OutOfProc>::GetModule().DecrementObjectCount();
	}

	INTERACTIVENOTIFICATIONS_API std::wstring s2ws(const std::string& s)
	{
		int len;
		int slength = (int)s.length() + 1;

		len = MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, 0, 0);

		wchar_t* buf = new wchar_t[len];

		MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, buf, len);
		std::wstring r(buf);
		delete[] buf;

		return r;
	}
}

extern "C"
{
	__declspec(dllexport) void CRegisterForNotificationSupport(PCWSTR shortcut, PCWSTR appId)
	{
		InteractiveNotifications::RegisterAppForNotificationSupport(shortcut, appId);
	}

	__declspec(dllexport) void CRegisterActivator()
	{
		InteractiveNotifications::RegisterActivator();
	}

	__declspec(dllexport) void CUnregisterActivator()
	{
		InteractiveNotifications::UnregisterActivator();
	}
}<commit_msg>:art: Unicode Support!<commit_after>// InteractiveNotifications.cpp : Defines the exported functions for the DLL application.
//

#include "stdafx.h"
#include "InteractiveNotifications.h"
#include <NotificationActivationCallback.h>

#include <Shellapi.h>
#include <string>
#include <iostream>
#include <SDKDDKVer.h>
#include <Windows.h>
#include <Psapi.h>
#include <strsafe.h>
#include <ShObjIdl.h>
#include <Shlobj.h>
#include <Pathcch.h>
#include <propvarutil.h>
#include <propkey.h>
#include <wchar.h>
#include <wrl.h>
#include <wrl\wrappers\corewrappers.h>
#include <windows.ui.notifications.h>

// Correct flow
// RegisterAppForNotificationSupport()
// RegisterActivator()

//  Name:     System.AppUserModel.ToastActivatorCLSID -- PKEY_AppUserModel_ToastActivatorCLSID
//  Type:     Guid -- VT_CLSID
//  FormatID: {9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3}, 26
//
//  Used to CoCreate an INotificationActivationCallback interface to notify about toast activations.
EXTERN_C const PROPERTYKEY DECLSPEC_SELECTANY PKEY_AppUserModel_ToastActivatorCLSID = { { 0x9F4C2855, 0x9F79, 0x4B39,{ 0xA8, 0xD0, 0xE1, 0xD4, 0x2D, 0xE1, 0xD5, 0xF3 } }, 26 };

using namespace ABI::Windows::Data::Xml::Dom;
using namespace ABI::Windows::UI::Notifications;
using namespace Microsoft::WRL;
using namespace Microsoft::WRL::Wrappers;

struct CoTaskMemStringTraits
{
	typedef PWSTR Type;

	inline static bool Close(_In_ Type h) throw() { ::CoTaskMemFree(h); return true; }

	inline static Type GetInvalidValue() throw() { return nullptr; }
};
typedef HandleT<CoTaskMemStringTraits> CoTaskMemString;

const wchar_t Shortcut[] = LR"(Microsoft\Windows\Start Menu\Slack.lnk)";

#define __CSID "B23D2B18-8DD7-403A-B9B7-152B40A1478C"

// For the app to be activated from Action Center, it needs to provide a COM server to be called
// when the notification is activated.  The CLSID of the object needs to be registered with the
// OS via its shortcut so that it knows who to call later.
class DECLSPEC_UUID(__CSID) NotificationActivator WrlSealed WrlFinal
: public RuntimeClass < RuntimeClassFlags<ClassicCom>,
	INotificationActivationCallback >
{
public:
	virtual HRESULT STDMETHODCALLTYPE Activate(
		_In_ LPCWSTR appUserModelId,
		_In_ LPCWSTR invokedArgs,
		_In_reads_(dataCount) const NOTIFICATION_USER_INPUT_DATA* data,
		ULONG dataCount) override
	{
		std::string args;

		for (int i = 0; i < dataCount; i++) {
			LPCWSTR lvalue = data[i].Value;
			LPCWSTR lkey = data[i].Key;

			std::wstring wvalue(lvalue);
			std::wstring wkey(lkey);

			std::string value(wvalue.begin(), wvalue.end());
			std::string key(wkey.begin(), wkey.end());

			args = args + "\"key\":\"" + key + "\"";
			args = args + ",\"value\":\"" + value + "\"";
		}

		std::wstring wToastArgs(invokedArgs);
		std::string toastArgs(wToastArgs.begin(), wToastArgs.end());

		// If you ever want to use system() or similar calls,
		// you'll need to escape stuff. We're using ShellExecute,
		// so we don't have to.

		// std::string escapedArgs = "";
		// for (char ch : args) {
		// 	switch (ch) {
		// 	case ' ': escapedArgs += "%20"; break;
		// 	case '&': escapedArgs += "^&"; break;
		// 	case '\\': escapedArgs += "^\\"; break;
		// 	case '<': escapedArgs += "^<"; break;
		// 	case '>': escapedArgs += "^>"; break;
		// 	case '|': escapedArgs += "^|"; break;
		// 	case '^': escapedArgs += "^^"; break;
		// 	case '"': escapedArgs += "^%22"; break;
		// 	default: escapedArgs += ch; break;
		// 	}
		// }
		//
		// std::string escapedToastArgs = "";
		// for (char ch : toastArgs) {
		// 	switch (ch) {
		// 	case ' ': escapedToastArgs += "%20"; break;
		// 	case '&': escapedToastArgs += "^&"; break;
		// 	case '\\': escapedToastArgs += "^\\"; break;
		// 	case '<': escapedToastArgs += "^<"; break;
		// 	case '>': escapedToastArgs += "^>"; break;
		// 	case '|': escapedToastArgs += "^|"; break;
		// 	case '^': escapedToastArgs += "^^"; break;
		// 	case '"': escapedToastArgs += "%22"; break;
		// 	default: escapedToastArgs += ch; break;
		// 	}
		// }

		// std::string systemCmd = "myapp://" + escapedToastArgs + "^&userData=[{" + escapedArgs + "}]";

		std::string escapedToastArgs = "";
		for (char ch : toastArgs) {
			switch (ch) {
			case ' ': escapedToastArgs += "%20"; break;
			case '"': escapedToastArgs += "%22"; break;
			default: escapedToastArgs += ch; break;
			}
		}

		std::string escapedArgs = "";
		for (char ch : args) {
			switch (ch) {
			case ' ': escapedArgs += "%20"; break;
			case '"': escapedArgs += "%22"; break;
			default: escapedArgs += ch; break;
			}
		}

		std::string cmd = "myapp://" + escapedToastArgs + "&userData=[{" + escapedArgs + "}]";
		std::wstring wCmd = InteractiveNotifications::s2ws(cmd);

		ShellExecuteW(NULL,
			TEXT("open"),
			wCmd.c_str(),
			NULL,
			NULL,
			SW_SHOWNORMAL);

		return HRESULT();
	}
};
CoCreatableClass(NotificationActivator);

namespace InteractiveNotifications
{
	INTERACTIVENOTIFICATIONS_API HRESULT RegisterAppForNotificationSupport(PCWSTR shortcut, PCWSTR appId)
	{
		CoTaskMemString appData;
		auto hr = ::SHGetKnownFolderPath(FOLDERID_RoamingAppData, 0, nullptr, appData.GetAddressOf());

		if (SUCCEEDED(hr))
		{
			wchar_t shortcutPath[MAX_PATH];
			// Todo: Don't hardcode the path
			hr = ::PathCchCombine(shortcutPath, ARRAYSIZE(shortcutPath), appData.Get(), shortcut);

			if (SUCCEEDED(hr))
			{
				DWORD attributes = ::GetFileAttributes(shortcutPath);
				bool fileExists = attributes < 0xFFFFFFF;

				if (!fileExists)
				{
					// Todo: This is probably the wrong path bc Squirrel
					wchar_t exePath[MAX_PATH];
					DWORD charWritten = ::GetModuleFileName(nullptr, exePath, ARRAYSIZE(exePath));
					hr = charWritten > 0 ? S_OK : HRESULT_FROM_WIN32(::GetLastError());

					if (SUCCEEDED(hr))
					{
						hr = InstallShortcut(shortcutPath, exePath, appId);
						if (SUCCEEDED(hr))
						{
							hr = RegisterComServer(exePath);
						}
					}
				}
			}
		}
		return hr;
	}

	_Use_decl_annotations_
	INTERACTIVENOTIFICATIONS_API HRESULT InstallShortcut(PCWSTR shortcutPath, PCWSTR exePath, PCWSTR appId)
	{
		ComPtr<IShellLink> shellLink;
		HRESULT hr = CoCreateInstance(CLSID_ShellLink, nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&shellLink));

		if (!SUCCEEDED(hr)) return hr;
		hr = shellLink->SetPath(exePath);

		if (!SUCCEEDED(hr)) return hr;
		ComPtr<IPropertyStore> propertyStore;
		hr = shellLink.As(&propertyStore);

		if (!SUCCEEDED(hr)) return hr;
		PROPVARIANT propVar;
		propVar.vt = VT_LPWSTR;
		propVar.pwszVal = const_cast<PWSTR>(appId); // for _In_ scenarios, we don't need a copy
		hr = propertyStore->SetValue(PKEY_AppUserModel_ID, propVar);

		if (!SUCCEEDED(hr)) return hr;
		propVar.vt = VT_CLSID;
		propVar.puuid = const_cast<CLSID*>(&__uuidof(NotificationActivator));
		hr = propertyStore->SetValue(PKEY_AppUserModel_ToastActivatorCLSID, propVar);

		if (!SUCCEEDED(hr)) return hr;
		hr = propertyStore->Commit();

		if (!SUCCEEDED(hr)) return hr;
		ComPtr<IPersistFile> persistFile;
		hr = shellLink.As(&persistFile);

		if (!SUCCEEDED(hr)) return hr;
		hr = persistFile->Save(shortcutPath, TRUE);

		return hr;
	}

	_Use_decl_annotations_
	INTERACTIVENOTIFICATIONS_API HRESULT RegisterComServer(PCWSTR exePath)
	{
		// We don't need to worry about overflow here as ::GetModuleFileName won't
		// return anything bigger than the max file system path (much fewer than max of DWORD).
		DWORD dataSize = static_cast<DWORD>((::wcslen(exePath) + 1) * sizeof(WCHAR));
		auto key = LR"(SOFTWARE\Classes\CLSID\{B23D2B18-8DD7-403A-B9B7-152B40A1478C}\LocalServer32)";

		return HRESULT_FROM_WIN32(::RegSetKeyValue(
			HKEY_CURRENT_USER,
			key,
			nullptr,
			REG_SZ,
			reinterpret_cast<const BYTE*>(exePath),
			dataSize));
	}

	_Use_decl_annotations_
	INTERACTIVENOTIFICATIONS_API HRESULT RegisterActivator()
	{
		// Module<OutOfProc> needs a callback registered before it can be used.
		// Since we don't care about when it shuts down, we'll pass an empty lambda here.
		// If we need to clean up, do it here (we probably don't have to)
		Module<OutOfProc>::Create([] {});

		// If a local server process only hosts the COM object then COM expects
		// the COM server host to shutdown when the references drop to zero.
		// Since the user might still be using the program after activating the notification,
		// we don't want to shutdown immediately.  Incrementing the object count tells COM that
		// we aren't done yet.
		Module<OutOfProc>::GetModule().IncrementObjectCount();

		return Module<OutOfProc>::GetModule().RegisterObjects();
	}

	_Use_decl_annotations_
	INTERACTIVENOTIFICATIONS_API void UnregisterActivator()
	{
		Module<OutOfProc>::GetModule().UnregisterObjects();
		Module<OutOfProc>::GetModule().DecrementObjectCount();
	}

	INTERACTIVENOTIFICATIONS_API std::wstring s2ws(const std::string& s)
	{
		int len;
		int slength = (int)s.length() + 1;

		len = MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, 0, 0);

		wchar_t* buf = new wchar_t[len];

		MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, buf, len);
		std::wstring r(buf);
		delete[] buf;

		return r;
	}
}

extern "C"
{
	__declspec(dllexport) void CRegisterForNotificationSupport(PCWSTR shortcut, PCWSTR appId)
	{
		InteractiveNotifications::RegisterAppForNotificationSupport(shortcut, appId);
	}

	__declspec(dllexport) void CRegisterActivator()
	{
		InteractiveNotifications::RegisterActivator();
	}

	__declspec(dllexport) void CUnregisterActivator()
	{
		InteractiveNotifications::UnregisterActivator();
	}
}<|endoftext|>


<commit_before>/** ==========================================================================
 * 2011 by KjellKod.cc. This is PUBLIC DOMAIN to use at your own risk and comes
 * with no warranties. This code is yours to share, use and modify with no
 * strings attached and no restrictions or obligations.
 * ============================================================================*/

#include "crashhandler.hpp"
#include "g2logmessage.hpp"
#include "g2LogMessageBuilder.hpp"

#include <csignal>
#include <cstring>
#if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__) && !defined(__GNUC__)) // windows and not mingw
#error "crashhandler_unix.cpp used but it's a windows system"
#endif

#include <unistd.h>  // getpid,
#include <execinfo.h>
#include <ucontext.h>
#include <cxxabi.h>
#include <cstdlib>
#include <sstream>
#include <iostream>

namespace {
   // Dump of stack,. then exit through g2log background worker
   // ALL thanks to this thread at StackOverflow. Pretty much borrowed from:
   // Ref: http://stackoverflow.com/questions/77005/how-to-generate-a-stacktrace-when-my-gcc-c-app-crashes
   void crashHandler(int signal_number, siginfo_t *info, void *unused_context) {
      using namespace g2::internal;

      std::ostringstream oss;
      oss << "Received fatal signal: " << g2::internal::signalName(signal_number);
      oss << "(" << signal_number << ")\tPID: " << getpid() << std::endl;
      oss << stackdump();

      { // Local scope, trigger send
         std::ostringstream fatal_stream;
         fatal_stream << oss.str() << std::endl;
         fatal_stream << "\n***** SIGNAL " << signalName(signal_number) << "(" << signal_number << ")" << std::endl;
         g2::FatalMessageBuilder trigger(fatal_stream.str(), signal_number);
      } // message sent to g2LogWorker by FatalMessageBuilder
      // wait to die -- will be inside the FatalMessageBuilder
   }
} // end anonymous namespace

// Redirecting and using signals. In case of fatal signals g2log should log the fatal signal
// and flush the log queue and then "rethrow" the signal to exit
namespace g2 {
   // References:
   // sigaction : change the default action if a specific signal is received
   //             http://linux.die.net/man/2/sigaction
   //             http://publib.boulder.ibm.com/infocenter/aix/v6r1/index.jsp?topic=%2Fcom.ibm.aix.basetechref%2Fdoc%2Fbasetrf2%2Fsigaction.html
   //
   // signal: http://linux.die.net/man/7/signal and
   //         http://msdn.microsoft.com/en-us/library/xdkz3x12%28vs.71%29.asp
   //
   // memset +  sigemptyset: Maybe unnecessary to do both but there seems to be some confusion here
   //          ,plenty of examples when both or either are used
   //          http://stackoverflow.com/questions/6878546/why-doesnt-parent-process-return-to-the-exact-location-after-handling-signal_number
   namespace internal {
      std::string stackdump() {
         const size_t max_dump_size = 50;
         void* dump[max_dump_size];
         size_t size = backtrace(dump, max_dump_size);
         char** messages = backtrace_symbols(dump, size); // overwrite sigaction with caller's address

         // dump stack: skip first frame, since that is here
         std::ostringstream oss;
         for (size_t idx = 1; idx < size && messages != nullptr; ++idx) {
            char *mangled_name = 0, *offset_begin = 0, *offset_end = 0;
            // find parantheses and +address offset surrounding mangled name
            for (char *p = messages[idx]; *p; ++p) {
               if (*p == '(') {
                  mangled_name = p;
               } else if (*p == '+') {
                  offset_begin = p;
               } else if (*p == ')') {
                  offset_end = p;
                  break;
               }
            }

            // if the line could be processed, attempt to demangle the symbol
            if (mangled_name && offset_begin && offset_end &&
                    mangled_name < offset_begin) {
               *mangled_name++ = '\0';
               *offset_begin++ = '\0';
               *offset_end++ = '\0';

               int status;
               char * real_name = abi::__cxa_demangle(mangled_name, 0, 0, &status);
               // if demangling is successful, output the demangled function name
               if (status == 0) {
                  oss << "\n\tstack dump [" << idx << "]  " << messages[idx] << " : " << real_name << "+";
                  oss << offset_begin << offset_end << std::endl;
               }// otherwise, output the mangled function name
               else {
                  oss << "\tstack dump [" << idx << "]  " << messages[idx] << mangled_name << "+";
                  oss << offset_begin << offset_end << std::endl;
               }
               free(real_name); // mallocated by abi::__cxa_demangle(...)
            } else {
               // no demangling done -- just dump the whole line
               oss << "\tstack dump [" << idx << "]  " << messages[idx] << std::endl;
            }
         } // END: for(size_t idx = 1; idx < size && messages != nullptr; ++idx)
         free(messages);
         return oss.str();
      }

      std::string signalName(int signal_number) {
         switch (signal_number) {
            case SIGABRT: return "SIGABRT"; break;
            case SIGFPE:  return "SIGFPE";  break;
            case SIGSEGV: return "SIGSEGV"; break;
            case SIGILL:  return "SIGILL";  break;
            case SIGTERM: return "SIGTERM"; break;
            default:
               std::ostringstream oss;
               oss << "UNKNOWN SIGNAL(" << signal_number << ")";
               return oss.str();
         }
      }

      // Triggered by g2log->g2LogWorker after receiving a FATAL trigger
      // which is LOG(FATAL), CHECK(false) or a fatal signal our signalhandler caught.
      // --- If LOG(FATAL) or CHECK(false) the signal_number will be SIGABRT
      void exitWithDefaultSignalHandler(int signal_number) {
         std::cerr << "Exiting - FATAL SIGNAL: " << signal_number << "   " << std::flush;
         struct sigaction action;
         memset(&action, 0, sizeof (action));  //
         sigemptyset(&action.sa_mask);
         action.sa_handler = SIG_DFL; // take default action for the signal
         sigaction(signal_number, &action, NULL);
         kill(getpid(), signal_number);
         abort(); // should never reach this
      }
   } // end g2::internal

   void installSignalHandler() {
      struct sigaction action;
      memset(&action, 0, sizeof (action));
      sigemptyset(&action.sa_mask);
      action.sa_sigaction = &crashHandler;  // callback to crashHandler for fatal signals
      // sigaction to use sa_sigaction file. ref: http://www.linuxprogrammingblog.com/code-examples/sigaction
      action.sa_flags = SA_SIGINFO;

      // do it verbose style - install all signal actions
      if (sigaction(SIGABRT, &action, NULL) < 0)
         perror("sigaction - SIGABRT");
      if (sigaction(SIGFPE, &action, NULL) < 0)
         perror("sigaction - SIGFPE");
      if (sigaction(SIGILL, &action, NULL) < 0)
         perror("sigaction - SIGILL");
      if (sigaction(SIGSEGV, &action, NULL) < 0)
         perror("sigaction - SIGSEGV");
      if (sigaction(SIGTERM, &action, NULL) < 0)
         perror("sigaction - SIGTERM");
   }
} // end namespace g2
<commit_msg>crashhandler_unix now with support for OSX/Clang<commit_after>/** ==========================================================================
 * 2011 by KjellKod.cc. This is PUBLIC DOMAIN to use at your own risk and comes
 * with no warranties. This code is yours to share, use and modify with no
 * strings attached and no restrictions or obligations.
 * ============================================================================*/

#include "crashhandler.hpp"
#include "g2logmessage.hpp"
#include "g2LogMessageBuilder.hpp"

#include <csignal>
#include <cstring>
#if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__) && !defined(__GNUC__)) // windows and not mingw
#error "crashhandler_unix.cpp used but it's a windows system"
#endif

#include <unistd.h>
#include <execinfo.h>
#include <cxxabi.h>
#include <cstdlib>
#include <sstream>
#include <iostream>

#ifdef __clang__
#include <sys/ucontext.h>
#else
#include <ucontext.h>
#endif

namespace {
   // Dump of stack,. then exit through g2log background worker
   // ALL thanks to this thread at StackOverflow. Pretty much borrowed from:
   // Ref: http://stackoverflow.com/questions/77005/how-to-generate-a-stacktrace-when-my-gcc-c-app-crashes
   void crashHandler(int signal_number, siginfo_t *info, void *unused_context) {
      using namespace g2::internal;

      std::ostringstream oss;
      oss << "Received fatal signal: " << g2::internal::signalName(signal_number);
      oss << "(" << signal_number << ")\tPID: " << getpid() << std::endl;
      oss << stackdump();

      { // Local scope, trigger send
         std::ostringstream fatal_stream;
         fatal_stream << oss.str() << std::endl;
         fatal_stream << "\n***** SIGNAL " << signalName(signal_number) << "(" << signal_number << ")" << std::endl;
         g2::FatalMessageBuilder trigger(fatal_stream.str(), signal_number);
      } // message sent to g2LogWorker by FatalMessageBuilder
      // wait to die -- will be inside the FatalMessageBuilder
   }
} // end anonymous namespace

// Redirecting and using signals. In case of fatal signals g2log should log the fatal signal
// and flush the log queue and then "rethrow" the signal to exit
namespace g2 {
   // References:
   // sigaction : change the default action if a specific signal is received
   //             http://linux.die.net/man/2/sigaction
   //             http://publib.boulder.ibm.com/infocenter/aix/v6r1/index.jsp?topic=%2Fcom.ibm.aix.basetechref%2Fdoc%2Fbasetrf2%2Fsigaction.html
   //
   // signal: http://linux.die.net/man/7/signal and
   //         http://msdn.microsoft.com/en-us/library/xdkz3x12%28vs.71%29.asp
   //
   // memset +  sigemptyset: Maybe unnecessary to do both but there seems to be some confusion here
   //          ,plenty of examples when both or either are used
   //          http://stackoverflow.com/questions/6878546/why-doesnt-parent-process-return-to-the-exact-location-after-handling-signal_number
   namespace internal {
      std::string stackdump() {
         const size_t max_dump_size = 50;
         void* dump[max_dump_size];
         size_t size = backtrace(dump, max_dump_size);
         char** messages = backtrace_symbols(dump, size); // overwrite sigaction with caller's address

         // dump stack: skip first frame, since that is here
         std::ostringstream oss;
         for (size_t idx = 1; idx < size && messages != nullptr; ++idx) {
            char *mangled_name = 0, *offset_begin = 0, *offset_end = 0;
            // find parantheses and +address offset surrounding mangled name
            for (char *p = messages[idx]; *p; ++p) {
               if (*p == '(') {
                  mangled_name = p;
               } else if (*p == '+') {
                  offset_begin = p;
               } else if (*p == ')') {
                  offset_end = p;
                  break;
               }
            }

            // if the line could be processed, attempt to demangle the symbol
            if (mangled_name && offset_begin && offset_end &&
                    mangled_name < offset_begin) {
               *mangled_name++ = '\0';
               *offset_begin++ = '\0';
               *offset_end++ = '\0';

               int status;
               char * real_name = abi::__cxa_demangle(mangled_name, 0, 0, &status);
               // if demangling is successful, output the demangled function name
               if (status == 0) {
                  oss << "\n\tstack dump [" << idx << "]  " << messages[idx] << " : " << real_name << "+";
                  oss << offset_begin << offset_end << std::endl;
               }// otherwise, output the mangled function name
               else {
                  oss << "\tstack dump [" << idx << "]  " << messages[idx] << mangled_name << "+";
                  oss << offset_begin << offset_end << std::endl;
               }
               free(real_name); // mallocated by abi::__cxa_demangle(...)
            } else {
               // no demangling done -- just dump the whole line
               oss << "\tstack dump [" << idx << "]  " << messages[idx] << std::endl;
            }
         } // END: for(size_t idx = 1; idx < size && messages != nullptr; ++idx)
         free(messages);
         return oss.str();
      }

      std::string signalName(int signal_number) {
         switch (signal_number) {
            case SIGABRT: return "SIGABRT"; break;
            case SIGFPE:  return "SIGFPE";  break;
            case SIGSEGV: return "SIGSEGV"; break;
            case SIGILL:  return "SIGILL";  break;
            case SIGTERM: return "SIGTERM"; break;
            default:
               std::ostringstream oss;
               oss << "UNKNOWN SIGNAL(" << signal_number << ")";
               return oss.str();
         }
      }

      // Triggered by g2log->g2LogWorker after receiving a FATAL trigger
      // which is LOG(FATAL), CHECK(false) or a fatal signal our signalhandler caught.
      // --- If LOG(FATAL) or CHECK(false) the signal_number will be SIGABRT
      void exitWithDefaultSignalHandler(int signal_number) {
         std::cerr << "Exiting - FATAL SIGNAL: " << signal_number << "   " << std::flush;
         struct sigaction action;
         memset(&action, 0, sizeof (action));  //
         sigemptyset(&action.sa_mask);
         action.sa_handler = SIG_DFL; // take default action for the signal
         sigaction(signal_number, &action, NULL);
         kill(getpid(), signal_number);
         abort(); // should never reach this
      }
   } // end g2::internal

   void installSignalHandler() {
      struct sigaction action;
      memset(&action, 0, sizeof (action));
      sigemptyset(&action.sa_mask);
      action.sa_sigaction = &crashHandler;  // callback to crashHandler for fatal signals
      // sigaction to use sa_sigaction file. ref: http://www.linuxprogrammingblog.com/code-examples/sigaction
      action.sa_flags = SA_SIGINFO;

      // do it verbose style - install all signal actions
      if (sigaction(SIGABRT, &action, NULL) < 0)
         perror("sigaction - SIGABRT");
      if (sigaction(SIGFPE, &action, NULL) < 0)
         perror("sigaction - SIGFPE");
      if (sigaction(SIGILL, &action, NULL) < 0)
         perror("sigaction - SIGILL");
      if (sigaction(SIGSEGV, &action, NULL) < 0)
         perror("sigaction - SIGSEGV");
      if (sigaction(SIGTERM, &action, NULL) < 0)
         perror("sigaction - SIGTERM");
   }
} // end namespace g2
<|endoftext|>