<commit_before>
//
// This source file is part of appleseed.
// Visit http://appleseedhq.net/ for additional information and resources.
//
// This software is released under the MIT license.
//
// Copyright (c) 2016 Haggi Krey, The appleseedhq Organization
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//

// Interface header.
#include "world.h"

// appleseed-maya headers.
#include "utilities/logging.h"
#include "appleseedrenderer.h"
#include "appleseedswatchrenderer.h"
#include "mayascene.h"
#include "renderqueueworker.h"

// Maya headers.
#include <maya/MGlobal.h>

static World* worldPointer = 0;
static MCallbackId timerCallbackId = 0;

void deleteWorld()
{
    delete worldPointer;
    worldPointer = 0;
}

void defineWorld()
{
    delete worldPointer;
    worldPointer = new World();
}

World* getWorldPtr()
{
    return worldPointer;
}

World::World()
  : mRenderType(RTYPENONE)
  , mRenderState(RSTATENONE)
{
    // in batch mode we do not need any renderView callbacks, and timer callbacks do not work anyway in batch
    if (MGlobal::mayaState() != MGlobal::kBatch)
        timerCallbackId = MTimerMessage::addTimerCallback(0.001, RenderQueueWorker::renderQueueWorkerTimerCallback);

    std::string oslShaderPath = (getRendererHome() + "shaders").asChar();

    MStringArray oslDirs;
    MGlobal::executePythonCommand("import appleseed.osltools as osl; osl.getOSODirs();", oslDirs, false, false);

    for (uint i = 0; i < oslDirs.length(); i++)
        shaderSearchPath.append(oslDirs[i].asChar());

    mSwatchRenderer.reset(new AppleseedSwatchRenderer());
}

World::~World()
{
    if (timerCallbackId != 0)
        MTimerMessage::removeCallback(timerCallbackId);
}

void World::initializeRenderEnvironment()
{
    worldPointer->mRenderGlobals.reset(new RenderGlobals());
    worldPointer->mScene.reset(new MayaScene());
    worldPointer->mRenderer.reset(new AppleseedRenderer());
}

void World::cleanUpAfterRender()
{
    // After a normal rendering we do not need the Maya scene data any more. Remove it to save memory.
    worldPointer->mScene.reset();
}

void World::setRenderType(RenderType type)
{
    mRenderType = type;
}

World::RenderType World::getRenderType()
{
    return mRenderType;
}

void World::setRenderState(RenderState state)
{
    mRenderState = state;
}

World::RenderState World::getRenderState()
{
    return mRenderState;
}

AppleseedSwatchRenderer* World::getSwatchRenderer()
{
    return mSwatchRenderer.get();
}
<commit_msg>Reduce timer callback frequency to keep CPU usage low.<commit_after>
//
// This source file is part of appleseed.
// Visit http://appleseedhq.net/ for additional information and resources.
//
// This software is released under the MIT license.
//
// Copyright (c) 2016 Haggi Krey, The appleseedhq Organization
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//

// Interface header.
#include "world.h"

// appleseed-maya headers.
#include "utilities/logging.h"
#include "appleseedrenderer.h"
#include "appleseedswatchrenderer.h"
#include "mayascene.h"
#include "renderqueueworker.h"

// Maya headers.
#include <maya/MGlobal.h>

static World* worldPointer = 0;
static MCallbackId timerCallbackId = 0;

void deleteWorld()
{
    delete worldPointer;
    worldPointer = 0;
}

void defineWorld()
{
    delete worldPointer;
    worldPointer = new World();
}

World* getWorldPtr()
{
    return worldPointer;
}

World::World()
  : mRenderType(RTYPENONE)
  , mRenderState(RSTATENONE)
{
    // in batch mode we do not need any renderView callbacks, and timer callbacks do not work anyway in batch
    if (MGlobal::mayaState() != MGlobal::kBatch)
        timerCallbackId = MTimerMessage::addTimerCallback(0.1, RenderQueueWorker::renderQueueWorkerTimerCallback);

    std::string oslShaderPath = (getRendererHome() + "shaders").asChar();

    MStringArray oslDirs;
    MGlobal::executePythonCommand("import appleseed.osltools as osl; osl.getOSODirs();", oslDirs, false, false);

    for (uint i = 0; i < oslDirs.length(); i++)
        shaderSearchPath.append(oslDirs[i].asChar());

    mSwatchRenderer.reset(new AppleseedSwatchRenderer());
}

World::~World()
{
    if (timerCallbackId != 0)
        MTimerMessage::removeCallback(timerCallbackId);
}

void World::initializeRenderEnvironment()
{
    worldPointer->mRenderGlobals.reset(new RenderGlobals());
    worldPointer->mScene.reset(new MayaScene());
    worldPointer->mRenderer.reset(new AppleseedRenderer());
}

void World::cleanUpAfterRender()
{
    // After a normal rendering we do not need the Maya scene data any more. Remove it to save memory.
    worldPointer->mScene.reset();
}

void World::setRenderType(RenderType type)
{
    mRenderType = type;
}

World::RenderType World::getRenderType()
{
    return mRenderType;
}

void World::setRenderState(RenderState state)
{
    mRenderState = state;
}

World::RenderState World::getRenderState()
{
    return mRenderState;
}

AppleseedSwatchRenderer* World::getSwatchRenderer()
{
    return mSwatchRenderer.get();
}
<|endoftext|>


<commit_before>#pragma once

#include "depthai-shared/common/Point3f.hpp"
#include "depthai-shared/common/Timestamp.hpp"
#include "depthai-shared/datatype/RawBuffer.hpp"
#include "depthai-shared/utility/Serialization.hpp"

namespace dai {

struct IMUReport {
    enum class Accuracy : std::uint8_t {
        UNRELIABLE = 0,
        LOW = 1,
        MEDIUM = 2,
        HIGH = 3,
    };
    /**
     * The sequence number increments once for each report sent.  Gaps
     * in the sequence numbers indicate missing or dropped reports.
     * Max value 255 after which resets to 0.
     */
    int32_t sequence = 0;

    /** Accuracy of sensor */
    Accuracy accuracy = Accuracy::UNRELIABLE;

    /** Generation timestamp, synced to host time */
    Timestamp timestamp = {};

    /** Generation timestamp, direct device monotonic clock */
    Timestamp tsDevice = {};
};
DEPTHAI_SERIALIZE_EXT(IMUReport, sequence, accuracy, timestamp, tsDevice);

/**
 * @brief Accelerometer
 *
 * Units are [m/s^2]
 */
struct IMUReportAccelerometer : public IMUReport {
    float x = 0;
    float y = 0;
    float z = 0;
};
DEPTHAI_SERIALIZE_EXT(IMUReportAccelerometer, x, y, z, sequence, accuracy, timestamp, tsDevice);

/**
 * @brief Gyroscope
 *
 * Units are [rad/s]
 */
struct IMUReportGyroscope : public IMUReport {
    float x = 0;
    float y = 0;
    float z = 0;
};
DEPTHAI_SERIALIZE_EXT(IMUReportGyroscope, x, y, z, sequence, accuracy, timestamp, tsDevice);

/**
 * @brief Magnetic field
 *
 * Units are [uTesla]
 */
struct IMUReportMagneticField : public IMUReport {
    float x = 0;
    float y = 0;
    float z = 0;
};
DEPTHAI_SERIALIZE_EXT(IMUReportMagneticField, x, y, z, sequence, accuracy, timestamp, tsDevice);

/**
 * @brief Rotation Vector with Accuracy
 *
 * Contains quaternion components: i,j,k,real
 */
struct IMUReportRotationVectorWAcc : public IMUReport {
    float i = 0;                      /**< @brief Quaternion component i */
    float j = 0;                      /**< @brief Quaternion component j */
    float k = 0;                      /**< @brief Quaternion component k */
    float real = 0;                   /**< @brief Quaternion component, real */
    float rotationVectorAccuracy = 0; /**< @brief Accuracy estimate [radians], 0 means no estimate */
};
DEPTHAI_SERIALIZE_EXT(IMUReportRotationVectorWAcc, i, j, k, real, rotationVectorAccuracy, sequence, accuracy, timestamp, tsDevice);

#if 0

/**
 * @brief Uncalibrated gyroscope
 *
 * See the SH-2 Reference Manual for more detail.
 */
struct IMUReportGyroscopeUncalibrated : public IMUReport {
    /* Units are rad/s */
    float x = 0;     /**< @brief [rad/s] */
    float y = 0;     /**< @brief [rad/s] */
    float z = 0;     /**< @brief [rad/s] */
    float biasX = 0; /**< @brief [rad/s] */
    float biasY = 0; /**< @brief [rad/s] */
    float biasZ = 0; /**< @brief [rad/s] */
};
DEPTHAI_SERIALIZE_EXT(IMUReportGyroscopeUncalibrated, x, y, z, biasX, biasY, biasZ, sequence, accuracy, timestamp, tsDevice);

/**
 * @brief Uncalibrated magnetic field
 *
 * See the SH-2 Reference Manual for more detail.
 */
struct IMUReportMagneticFieldUncalibrated : public IMUReport {
    /* Units are uTesla */
    float x = 0;     /**< @brief [uTesla] */
    float y = 0;     /**< @brief [uTesla] */
    float z = 0;     /**< @brief [uTesla] */
    float biasX = 0; /**< @brief [uTesla] */
    float biasY = 0; /**< @brief [uTesla] */
    float biasZ = 0; /**< @brief [uTesla] */
};
DEPTHAI_SERIALIZE_EXT(IMUReportMagneticFieldUncalibrated, x, y, z, biasX, biasY, biasZ, sequence, accuracy, timestamp, tsDevice);

/**
 * @brief Rotation Vector
 *
 * See the SH-2 Reference Manual for more detail.
 */
struct IMUReportRotationVector : public IMUReport {
    float i = 0;    /**< @brief Quaternion component i */
    float j = 0;    /**< @brief Quaternion component j */
    float k = 0;    /**< @brief Quaternion component k */
    float real = 0; /**< @brief Quaternion component real */
};
DEPTHAI_SERIALIZE_EXT(IMUReportRotationVector, i, j, k, real, sequence, accuracy, timestamp, tsDevice);

/**
 * @brief Gyro integrated rotation vector
 *
 * See SH-2 Reference Manual for details.
 */
struct IMUReportGyroIntegratedRV : public IMUReport {
    float i = 0;       /**< @brief Quaternion component i */
    float j = 0;       /**< @brief Quaternion component j */
    float k = 0;       /**< @brief Quaternion component k */
    float real = 0;    /**< @brief Quaternion component real */
    float angVelX = 0; /**< @brief Angular velocity about x [rad/s] */
    float angVelY = 0; /**< @brief Angular velocity about y [rad/s] */
    float angVelZ = 0; /**< @brief Angular velocity about z [rad/s] */
};
DEPTHAI_SERIALIZE_EXT(IMUReportGyroIntegratedRV, i, j, k, real, angVelX, angVelY, angVelZ, sequence, accuracy, timestamp, tsDevice);

#endif

/**
 * IMU output
 *
 * Contains combined output for all possible modes. Only the enabled outputs are populated.
 */
struct IMUPacket {
    IMUReportAccelerometer acceleroMeter;
    IMUReportGyroscope gyroscope;
    IMUReportMagneticField magneticField;
    IMUReportRotationVectorWAcc rotationVector;

#if 0
    IMUReportAccelerometer rawAcceleroMeter;

    IMUReportAccelerometer linearAcceleroMeter;
    IMUReportAccelerometer gravity;

    IMUReportGyroscope rawGyroscope;
    IMUReportGyroscopeUncalibrated gyroscopeUncalibrated;

    IMUReportMagneticField rawMagneticField;
    IMUReportMagneticFieldUncalibrated magneticFieldUncalibrated;

    IMUReportRotationVector gameRotationVector;
    IMUReportRotationVectorWAcc geoMagRotationVector;

    IMUReportRotationVectorWAcc arvrStabilizedRotationVector;
    IMUReportRotationVector arvrStabilizedGameRotationVector;
    IMUReportGyroIntegratedRV gyroIntegratedRotationVector;
#endif
};

DEPTHAI_SERIALIZE_EXT(IMUPacket, acceleroMeter, gyroscope, magneticField, rotationVector);

struct RawIMUData : public RawBuffer {
    std::vector<IMUPacket> packets;

    void serialize(std::vector<std::uint8_t>& metadata, DatatypeEnum& datatype) const override {
        metadata = utility::serialize(*this);
        datatype = DatatypeEnum::IMUData;
    };

    DEPTHAI_SERIALIZE(RawIMUData, packets);
};

}  // namespace dai
<commit_msg>Add getTimestamp and getTimestampDevice getter to IMU packets<commit_after>#pragma once

#include "depthai-shared/common/Point3f.hpp"
#include "depthai-shared/common/Timestamp.hpp"
#include "depthai-shared/datatype/RawBuffer.hpp"
#include "depthai-shared/utility/Serialization.hpp"

namespace dai {

struct IMUReport {
    enum class Accuracy : std::uint8_t {
        UNRELIABLE = 0,
        LOW = 1,
        MEDIUM = 2,
        HIGH = 3,
    };
    /**
     * The sequence number increments once for each report sent.  Gaps
     * in the sequence numbers indicate missing or dropped reports.
     * Max value 255 after which resets to 0.
     */
    int32_t sequence = 0;

    /** Accuracy of sensor */
    Accuracy accuracy = Accuracy::UNRELIABLE;

    /** Generation timestamp, synced to host time */
    Timestamp timestamp = {};

    /** Generation timestamp, direct device monotonic clock */
    Timestamp tsDevice = {};

    /**
     * Retrieves timestamp related to dai::Clock::now()
     */
    std::chrono::time_point<std::chrono::steady_clock, std::chrono::steady_clock::duration> getTimestamp() const {
        return timestamp.get();
    }

    /**
     * Retrieves timestamp directly captured from device's monotonic clock,
     * not synchronized to host time. Used mostly for debugging
     */
    std::chrono::time_point<std::chrono::steady_clock, std::chrono::steady_clock::duration> getTimestampDevice() const {
        return tsDevice.get();
    }
};
DEPTHAI_SERIALIZE_EXT(IMUReport, sequence, accuracy, timestamp, tsDevice);

/**
 * @brief Accelerometer
 *
 * Units are [m/s^2]
 */
struct IMUReportAccelerometer : public IMUReport {
    float x = 0;
    float y = 0;
    float z = 0;
};
DEPTHAI_SERIALIZE_EXT(IMUReportAccelerometer, x, y, z, sequence, accuracy, timestamp, tsDevice);

/**
 * @brief Gyroscope
 *
 * Units are [rad/s]
 */
struct IMUReportGyroscope : public IMUReport {
    float x = 0;
    float y = 0;
    float z = 0;
};
DEPTHAI_SERIALIZE_EXT(IMUReportGyroscope, x, y, z, sequence, accuracy, timestamp, tsDevice);

/**
 * @brief Magnetic field
 *
 * Units are [uTesla]
 */
struct IMUReportMagneticField : public IMUReport {
    float x = 0;
    float y = 0;
    float z = 0;
};
DEPTHAI_SERIALIZE_EXT(IMUReportMagneticField, x, y, z, sequence, accuracy, timestamp, tsDevice);

/**
 * @brief Rotation Vector with Accuracy
 *
 * Contains quaternion components: i,j,k,real
 */
struct IMUReportRotationVectorWAcc : public IMUReport {
    float i = 0;                      /**< @brief Quaternion component i */
    float j = 0;                      /**< @brief Quaternion component j */
    float k = 0;                      /**< @brief Quaternion component k */
    float real = 0;                   /**< @brief Quaternion component, real */
    float rotationVectorAccuracy = 0; /**< @brief Accuracy estimate [radians], 0 means no estimate */
};
DEPTHAI_SERIALIZE_EXT(IMUReportRotationVectorWAcc, i, j, k, real, rotationVectorAccuracy, sequence, accuracy, timestamp, tsDevice);

#if 0

/**
 * @brief Uncalibrated gyroscope
 *
 * See the SH-2 Reference Manual for more detail.
 */
struct IMUReportGyroscopeUncalibrated : public IMUReport {
    /* Units are rad/s */
    float x = 0;     /**< @brief [rad/s] */
    float y = 0;     /**< @brief [rad/s] */
    float z = 0;     /**< @brief [rad/s] */
    float biasX = 0; /**< @brief [rad/s] */
    float biasY = 0; /**< @brief [rad/s] */
    float biasZ = 0; /**< @brief [rad/s] */
};
DEPTHAI_SERIALIZE_EXT(IMUReportGyroscopeUncalibrated, x, y, z, biasX, biasY, biasZ, sequence, accuracy, timestamp, tsDevice);

/**
 * @brief Uncalibrated magnetic field
 *
 * See the SH-2 Reference Manual for more detail.
 */
struct IMUReportMagneticFieldUncalibrated : public IMUReport {
    /* Units are uTesla */
    float x = 0;     /**< @brief [uTesla] */
    float y = 0;     /**< @brief [uTesla] */
    float z = 0;     /**< @brief [uTesla] */
    float biasX = 0; /**< @brief [uTesla] */
    float biasY = 0; /**< @brief [uTesla] */
    float biasZ = 0; /**< @brief [uTesla] */
};
DEPTHAI_SERIALIZE_EXT(IMUReportMagneticFieldUncalibrated, x, y, z, biasX, biasY, biasZ, sequence, accuracy, timestamp, tsDevice);

/**
 * @brief Rotation Vector
 *
 * See the SH-2 Reference Manual for more detail.
 */
struct IMUReportRotationVector : public IMUReport {
    float i = 0;    /**< @brief Quaternion component i */
    float j = 0;    /**< @brief Quaternion component j */
    float k = 0;    /**< @brief Quaternion component k */
    float real = 0; /**< @brief Quaternion component real */
};
DEPTHAI_SERIALIZE_EXT(IMUReportRotationVector, i, j, k, real, sequence, accuracy, timestamp, tsDevice);

/**
 * @brief Gyro integrated rotation vector
 *
 * See SH-2 Reference Manual for details.
 */
struct IMUReportGyroIntegratedRV : public IMUReport {
    float i = 0;       /**< @brief Quaternion component i */
    float j = 0;       /**< @brief Quaternion component j */
    float k = 0;       /**< @brief Quaternion component k */
    float real = 0;    /**< @brief Quaternion component real */
    float angVelX = 0; /**< @brief Angular velocity about x [rad/s] */
    float angVelY = 0; /**< @brief Angular velocity about y [rad/s] */
    float angVelZ = 0; /**< @brief Angular velocity about z [rad/s] */
};
DEPTHAI_SERIALIZE_EXT(IMUReportGyroIntegratedRV, i, j, k, real, angVelX, angVelY, angVelZ, sequence, accuracy, timestamp, tsDevice);

#endif

/**
 * IMU output
 *
 * Contains combined output for all possible modes. Only the enabled outputs are populated.
 */
struct IMUPacket {
    IMUReportAccelerometer acceleroMeter;
    IMUReportGyroscope gyroscope;
    IMUReportMagneticField magneticField;
    IMUReportRotationVectorWAcc rotationVector;

#if 0
    IMUReportAccelerometer rawAcceleroMeter;

    IMUReportAccelerometer linearAcceleroMeter;
    IMUReportAccelerometer gravity;

    IMUReportGyroscope rawGyroscope;
    IMUReportGyroscopeUncalibrated gyroscopeUncalibrated;

    IMUReportMagneticField rawMagneticField;
    IMUReportMagneticFieldUncalibrated magneticFieldUncalibrated;

    IMUReportRotationVector gameRotationVector;
    IMUReportRotationVectorWAcc geoMagRotationVector;

    IMUReportRotationVectorWAcc arvrStabilizedRotationVector;
    IMUReportRotationVector arvrStabilizedGameRotationVector;
    IMUReportGyroIntegratedRV gyroIntegratedRotationVector;
#endif
};

DEPTHAI_SERIALIZE_EXT(IMUPacket, acceleroMeter, gyroscope, magneticField, rotationVector);

struct RawIMUData : public RawBuffer {
    std::vector<IMUPacket> packets;

    void serialize(std::vector<std::uint8_t>& metadata, DatatypeEnum& datatype) const override {
        metadata = utility::serialize(*this);
        datatype = DatatypeEnum::IMUData;
    };

    DEPTHAI_SERIALIZE(RawIMUData, packets);
};

}  // namespace dai
<|endoftext|>


<commit_before>/**
 * @file   GpuAddTest.cpp
 * @brief  GpuAdd class tester.
 * @author zer0
 * @date   2018-01-07
 */

#include <gtest/gtest.h>
#include <libtbag/gpu/backend/kernels/GpuAdd.hpp>
#include <libtbag/gpu/Gpu.hpp>
#include <libtbag/algorithm/Equals.hpp>

using namespace libtbag;
using namespace libtbag::gpu;
using namespace libtbag::gpu::backend;
using namespace libtbag::gpu::backend::kernels;

struct GpuAddKernelTest
{
    UniqueGpu   gpu;
    GpuContext  context;
    GpuStream   stream;
    GpuEvent    event;
    int         count;

    GpuMemory  gpu_v1;
    GpuMemory  gpu_v2;
    GpuMemory  gpu_result;

    HostMemory  host_v1;
    HostMemory  host_v2;
    HostMemory  host_result;

    GpuAddKernelTest(GpuBackendType t, int c) : GpuAddKernelTest(createGpuContext(t), c)
    {
        // EMPTY.
    }

    GpuAddKernelTest(UniqueGpu && g, int c) : gpu(std::move(g)), count(c)
    {
        context = gpu->createContext(0, 0);
        assert(context.isUnknownContext() == false);

        stream = gpu->createStream(context);
        assert(stream.isUnknownStream() == false);

        event = gpu->createEvent(stream);
        assert(event.isUnknownEvent() == false);

        gpu_v1     = gpu->malloc(context, sizeof(float) * count);
        gpu_v2     = gpu->malloc(context, sizeof(float) * count);
        gpu_result = gpu->malloc(context, sizeof(float) * count);

        host_v1     = gpu->mallocHost(context, sizeof(float) * count);
        host_v2     = gpu->mallocHost(context, sizeof(float) * count);
        host_result = gpu->mallocHost(context, sizeof(float) * count);
    }

    ~GpuAddKernelTest()
    {
        gpu->freeHost(host_v1);
        gpu->freeHost(host_v2);
        gpu->freeHost(host_result);

        gpu->free(gpu_v1);
        gpu->free(gpu_v2);
        gpu->free(gpu_result);

        gpu->releaseEvent(event);
        gpu->releaseStream(stream);
        gpu->releaseContext(context);
    }

    bool run(std::vector<float> const & v1, std::vector<float> const & v2, std::vector<float> & result, float * millisec)
    {
        ::memcpy(host_v1.data, v1.data(), sizeof(float) * count);
        ::memcpy(host_v2.data, v2.data(), sizeof(float) * count);

        if (gpu->write(stream, gpu_v1, host_v1, sizeof(float) * count) == false) { return false; }
        if (gpu->write(stream, gpu_v2, host_v2, sizeof(float) * count) == false) { return false; }

        if (gpu->runAdd(stream, gpu_v1, gpu_v2, gpu_result, type::TypeTable::TT_FLOAT, count, &event) == false) {
            return false;
        }
        if (gpu->syncEvent(event) == false) { return false; }
        gpu->elapsedEvent(event, millisec);

        if (gpu->finish(stream) == false) { return false; }
        if (gpu->read(stream, gpu_result, host_result, sizeof(float) * count) == false) { return false; }

        ::memcpy(result.data(), host_result.data, sizeof(float) * count);
        return true;
    }
};

TEST(GpuAddTest, Default)
{
    runAllIfSupported([](UniqueGpu & gpu){
        std::cout << "GPU type: " << gpu->getTypeString() << std::endl;

        if (gpu->getType() != GpuBackendType::GBT_CPU && gpu->getType() != GpuBackendType::GBT_CUDA) {
            return;
        }

        int const TEST_COUNT = 1024 * 1024;
        GpuAddKernelTest tester(gpu->getType(), TEST_COUNT);

        std::vector<float> v1(TEST_COUNT);
        std::vector<float> v2(TEST_COUNT);
        std::vector<float> v3(TEST_COUNT);
        std::vector<float> result(TEST_COUNT);
        std::size_t i = 0;

        for (i = 0; i < TEST_COUNT; ++i) {
            v1[i] = i;
            v2[i] = 10 * i;
            v3[i] = v1[i] + v2[i];
        }

        float millisec = 0.0f;
        ASSERT_TRUE(tester.run(v1, v2, result, &millisec));
        std::cout << "Kernel: " << millisec << " millisec" << std::endl;

        for (i = 0; i < TEST_COUNT; ++i) {
            ASSERT_TRUE(algorithm::equals(v3[i], result[i]));
        }
    });
}

<commit_msg>Fixed ambiguous symbol error in MSVC.<commit_after>/**
 * @file   GpuAddTest.cpp
 * @brief  GpuAdd class tester.
 * @author zer0
 * @date   2018-01-07
 */

#include <gtest/gtest.h>
#include <libtbag/gpu/backend/kernels/GpuAdd.hpp>
#include <libtbag/gpu/Gpu.hpp>
#include <libtbag/algorithm/Equals.hpp>

using namespace libtbag;
using namespace libtbag::gpu;
using namespace libtbag::gpu::backend;
using namespace libtbag::gpu::backend::kernels;

struct GpuAddKernelTest
{
    UniqueGpu   gpu;
    GpuContext  context;
    GpuStream   stream;
    GpuEvent    event;
    int         count;

    GpuMemory  gpu_v1;
    GpuMemory  gpu_v2;
    GpuMemory  gpu_result;

    HostMemory  host_v1;
    HostMemory  host_v2;
    HostMemory  host_result;

    GpuAddKernelTest(libtbag::gpu::GpuBackendType t, int c) : GpuAddKernelTest(createGpuContext(t), c)
    {
        // EMPTY.
    }

    GpuAddKernelTest(UniqueGpu && g, int c) : gpu(std::move(g)), count(c)
    {
        context = gpu->createContext(0, 0);
        assert(context.isUnknownContext() == false);

        stream = gpu->createStream(context);
        assert(stream.isUnknownStream() == false);

        event = gpu->createEvent(stream);
        assert(event.isUnknownEvent() == false);

        gpu_v1     = gpu->malloc(context, sizeof(float) * count);
        gpu_v2     = gpu->malloc(context, sizeof(float) * count);
        gpu_result = gpu->malloc(context, sizeof(float) * count);

        host_v1     = gpu->mallocHost(context, sizeof(float) * count);
        host_v2     = gpu->mallocHost(context, sizeof(float) * count);
        host_result = gpu->mallocHost(context, sizeof(float) * count);
    }

    ~GpuAddKernelTest()
    {
        gpu->freeHost(host_v1);
        gpu->freeHost(host_v2);
        gpu->freeHost(host_result);

        gpu->free(gpu_v1);
        gpu->free(gpu_v2);
        gpu->free(gpu_result);

        gpu->releaseEvent(event);
        gpu->releaseStream(stream);
        gpu->releaseContext(context);
    }

    bool run(std::vector<float> const & v1, std::vector<float> const & v2, std::vector<float> & result, float * millisec)
    {
        ::memcpy(host_v1.data, v1.data(), sizeof(float) * count);
        ::memcpy(host_v2.data, v2.data(), sizeof(float) * count);

        if (gpu->write(stream, gpu_v1, host_v1, sizeof(float) * count) == false) { return false; }
        if (gpu->write(stream, gpu_v2, host_v2, sizeof(float) * count) == false) { return false; }

        if (gpu->runAdd(stream, gpu_v1, gpu_v2, gpu_result, type::TypeTable::TT_FLOAT, count, &event) == false) {
            return false;
        }
        if (gpu->syncEvent(event) == false) { return false; }
        gpu->elapsedEvent(event, millisec);

        if (gpu->finish(stream) == false) { return false; }
        if (gpu->read(stream, gpu_result, host_result, sizeof(float) * count) == false) { return false; }

        ::memcpy(result.data(), host_result.data, sizeof(float) * count);
        return true;
    }
};

TEST(GpuAddTest, Default)
{
    runAllIfSupported([](UniqueGpu & gpu){
        std::cout << "GPU type: " << gpu->getTypeString() << std::endl;

        if (gpu->getType() != libtbag::gpu::GpuBackendType::GBT_CPU && gpu->getType() != libtbag::gpu::GpuBackendType::GBT_CUDA) {
            return;
        }

        int const TEST_COUNT = 1024 * 1024;
        GpuAddKernelTest tester(gpu->getType(), TEST_COUNT);

        std::vector<float> v1(TEST_COUNT);
        std::vector<float> v2(TEST_COUNT);
        std::vector<float> v3(TEST_COUNT);
        std::vector<float> result(TEST_COUNT);
        std::size_t i = 0;

        for (i = 0; i < TEST_COUNT; ++i) {
            v1[i] = i;
            v2[i] = 10 * i;
            v3[i] = v1[i] + v2[i];
        }

        float millisec = 0.0f;
        ASSERT_TRUE(tester.run(v1, v2, result, &millisec));
        std::cout << "Kernel: " << millisec << " millisec" << std::endl;

        for (i = 0; i < TEST_COUNT; ++i) {
            ASSERT_TRUE(algorithm::equals(v3[i], result[i]));
        }
    });
}

<|endoftext|>


<commit_before>#include "authoring/opengl_object_affordance.h"

using namespace std;
using namespace Eigen;
using namespace affordance;
using namespace opengl;
using namespace authoring;

OpenGL_Object_Affordance::
OpenGL_Object_Affordance() : OpenGL_Object(),
                              _opengl_object_box(),
                              _opengl_object_cylinder(),
                              _opengl_object_sphere(){

}

OpenGL_Object_Affordance::
~OpenGL_Object_Affordance() {

}

OpenGL_Object_Affordance::
OpenGL_Object_Affordance( const OpenGL_Object_Affordance& other ) : OpenGL_Object( other ),
                                                                    _opengl_object_box( other._opengl_object_box ),
                                                                    _opengl_object_cylinder( other._opengl_object_cylinder ),
                                                                    _opengl_object_sphere( other._opengl_object_sphere ){

}

OpenGL_Object_Affordance&
OpenGL_Object_Affordance::
operator=( const OpenGL_Object_Affordance& other ) {
  _opengl_object_box = other._opengl_object_box;
  _opengl_object_sphere = other._opengl_object_sphere;
  _opengl_object_cylinder = other._opengl_object_cylinder;
  return (*this);
}

void
OpenGL_Object_Affordance::
set( AffordanceState& affordanceState ){
  if( affordanceState.getType() == AffordanceState::CYLINDER ){
    _opengl_object_cylinder.set_visible( true );
    _opengl_object_sphere.set_visible( false );
    _opengl_object_box.set_visible( false );
    _opengl_object_cylinder.set( affordanceState.getFrame(),
                                  Vector2f( affordanceState._params[ AffordanceState::RADIUS_NAME ],
                                            affordanceState._params[ AffordanceState::LENGTH_NAME ] ) );
  } else if ( affordanceState.getType() == AffordanceState::LEVER ){

  } else if ( affordanceState.getType() == AffordanceState::SPHERE ){
    _opengl_object_cylinder.set_visible( false );
    _opengl_object_sphere.set_visible( true );
    _opengl_object_box.set_visible( false );
    _opengl_object_sphere.set( affordanceState.getFrame(),
                                affordanceState._params[ AffordanceState::RADIUS_NAME ] );
  } else if ( affordanceState.getType() == AffordanceState::BOX ){
    _opengl_object_cylinder.set_visible( false );
    _opengl_object_sphere.set_visible( false );
    _opengl_object_box.set_visible( true );
    _opengl_object_box.set( affordanceState.getFrame(),
                            Vector3f( affordanceState._params[ AffordanceState::LENGTH_NAME ],
                                      affordanceState._params[ AffordanceState::WIDTH_NAME ],
                                      affordanceState._params[ AffordanceState::HEIGHT_NAME ] ) );
  }
  return;
}

void
OpenGL_Object_Affordance::
set_transparency( double transparency ){
  _opengl_object_box.set_transparency( transparency );
  _opengl_object_cylinder.set_transparency( transparency );
  _opengl_object_sphere.set_transparency( transparency );
  return;
}

void
OpenGL_Object_Affordance::
draw( void ){
  if( visible() ){
    _opengl_object_cylinder.draw();
    _opengl_object_sphere.draw();
    _opengl_object_box.draw();
  }
  return;
}

void
OpenGL_Object_Affordance::
set_color( Vector3f color ){
  _opengl_object_cylinder.set_color( color );
  _opengl_object_sphere.set_color( color );
  _opengl_object_box.set_color( color );
  return;
}

namespace opengl {
  ostream&
  operator<<( ostream& out,
              const OpenGL_Object_Affordance& other ) {
    return out;
  }

}
<commit_msg>setting sphere/box/cylinder to default not visible<commit_after>#include "authoring/opengl_object_affordance.h"

using namespace std;
using namespace Eigen;
using namespace affordance;
using namespace opengl;
using namespace authoring;

OpenGL_Object_Affordance::
OpenGL_Object_Affordance() : OpenGL_Object(),
                              _opengl_object_box(),
                              _opengl_object_cylinder(),
                              _opengl_object_sphere(){

}

OpenGL_Object_Affordance::
~OpenGL_Object_Affordance() {

}

OpenGL_Object_Affordance::
OpenGL_Object_Affordance( const OpenGL_Object_Affordance& other ) : OpenGL_Object( other ),
                                                                    _opengl_object_box( other._opengl_object_box ),
                                                                    _opengl_object_cylinder( other._opengl_object_cylinder ),
                                                                    _opengl_object_sphere( other._opengl_object_sphere ){

}

OpenGL_Object_Affordance&
OpenGL_Object_Affordance::
operator=( const OpenGL_Object_Affordance& other ) {
  _opengl_object_box = other._opengl_object_box;
  _opengl_object_sphere = other._opengl_object_sphere;
  _opengl_object_cylinder = other._opengl_object_cylinder;
  return (*this);
}

void
OpenGL_Object_Affordance::
set( AffordanceState& affordanceState ){
    _opengl_object_cylinder.set_visible( false );
    _opengl_object_sphere.set_visible( false );
    _opengl_object_box.set_visible( false );

  if( affordanceState.getType() == AffordanceState::CYLINDER ){
    _opengl_object_cylinder.set_visible( true );
    _opengl_object_sphere.set_visible( false );
    _opengl_object_box.set_visible( false );
    _opengl_object_cylinder.set( affordanceState.getFrame(),
                                  Vector2f( affordanceState._params[ AffordanceState::RADIUS_NAME ],
                                            affordanceState._params[ AffordanceState::LENGTH_NAME ] ) );
  } else if ( affordanceState.getType() == AffordanceState::LEVER ){

  } else if ( affordanceState.getType() == AffordanceState::SPHERE ){
    _opengl_object_cylinder.set_visible( false );
    _opengl_object_sphere.set_visible( true );
    _opengl_object_box.set_visible( false );
    _opengl_object_sphere.set( affordanceState.getFrame(),
                                affordanceState._params[ AffordanceState::RADIUS_NAME ] );
  } else if ( affordanceState.getType() == AffordanceState::BOX ){
    _opengl_object_cylinder.set_visible( false );
    _opengl_object_sphere.set_visible( false );
    _opengl_object_box.set_visible( true );
    _opengl_object_box.set( affordanceState.getFrame(),
                            Vector3f( affordanceState._params[ AffordanceState::LENGTH_NAME ],
                                      affordanceState._params[ AffordanceState::WIDTH_NAME ],
                                      affordanceState._params[ AffordanceState::HEIGHT_NAME ] ) );
  }
  return;
}

void
OpenGL_Object_Affordance::
set_transparency( double transparency ){
  _opengl_object_box.set_transparency( transparency );
  _opengl_object_cylinder.set_transparency( transparency );
  _opengl_object_sphere.set_transparency( transparency );
  return;
}

void
OpenGL_Object_Affordance::
draw( void ){
  if( visible() ){
    _opengl_object_cylinder.draw();
    _opengl_object_sphere.draw();
    _opengl_object_box.draw();
  }
  return;
}

void
OpenGL_Object_Affordance::
set_color( Vector3f color ){
  _opengl_object_cylinder.set_color( color );
  _opengl_object_sphere.set_color( color );
  _opengl_object_box.set_color( color );
  return;
}

namespace opengl {
  ostream&
  operator<<( ostream& out,
              const OpenGL_Object_Affordance& other ) {
    return out;
  }

}
<|endoftext|>


<commit_before><commit_msg>cc : Remove dead code from LayerTreeHostCommon<commit_after><|endoftext|>


<commit_before>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/printing/print_dialog_gtk.h"

#include <fcntl.h>
#include <gtk/gtkpagesetupunixdialog.h>
#include <gtk/gtkprintjob.h>
#include <sys/stat.h>
#include <sys/types.h>

#include "base/file_util.h"
#include "base/file_util_proxy.h"
#include "base/logging.h"
#include "base/synchronization/waitable_event.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/browser_list.h"
#include "chrome/browser/browser_window.h"
#include "content/browser/browser_thread.h"
#include "printing/print_settings_initializer_gtk.h"

// static
void* PrintDialogGtk::CreatePrintDialog(
    PrintingContextCairo::PrintSettingsCallback* callback,
    PrintingContextCairo* context) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));

  PrintDialogGtk* dialog = new PrintDialogGtk(callback, context);
  return dialog;
}

// static
void PrintDialogGtk::PrintDocument(void* print_dialog,
                                   const NativeMetafile* metafile,
                                   const string16& document_name) {
  PrintDialogGtk* dialog = static_cast<PrintDialogGtk*>(print_dialog);

  scoped_ptr<base::WaitableEvent> event(new base::WaitableEvent(false, false));
  dialog->set_save_document_event(event.get());
  BrowserThread::PostTask(
      BrowserThread::FILE, FROM_HERE,
      NewRunnableMethod(dialog,
                        &PrintDialogGtk::SaveDocumentToDisk,
                        metafile,
                        document_name));
  // Wait for SaveDocumentToDisk() to finish.
  event->Wait();
}

PrintDialogGtk::PrintDialogGtk(
    PrintingContextCairo::PrintSettingsCallback* callback,
    PrintingContextCairo* context)
    : callback_(callback),
      context_(context),
      dialog_(NULL),
      page_setup_(NULL),
      printer_(NULL),
      gtk_settings_(NULL),
      save_document_event_(NULL) {
  // Manual AddRef since PrintDialogGtk manages its own lifetime.
  AddRef();

  GtkWindow* parent = BrowserList::GetLastActive()->window()->GetNativeHandle();

  // TODO(estade): We need a window title here.
  dialog_ = gtk_print_unix_dialog_new(NULL, parent);
  // Set modal so user cannot focus the same tab and press print again.
  gtk_window_set_modal(GTK_WINDOW(dialog_), TRUE);

  // Since we only generate PDF, only show printers that support PDF.
  // TODO(thestig) Add more capabilities to support?
  GtkPrintCapabilities cap = static_cast<GtkPrintCapabilities>(
      GTK_PRINT_CAPABILITY_GENERATE_PDF |
      GTK_PRINT_CAPABILITY_PAGE_SET |
      GTK_PRINT_CAPABILITY_COPIES |
      GTK_PRINT_CAPABILITY_COLLATE |
      GTK_PRINT_CAPABILITY_REVERSE);
  gtk_print_unix_dialog_set_manual_capabilities(GTK_PRINT_UNIX_DIALOG(dialog_),
                                                cap);
#if GTK_CHECK_VERSION(2, 18, 0)
  gtk_print_unix_dialog_set_embed_page_setup(GTK_PRINT_UNIX_DIALOG(dialog_),
                                             TRUE);
#endif
  g_signal_connect(dialog_, "response", G_CALLBACK(OnResponseThunk), this);

  gtk_widget_show(dialog_);
}

PrintDialogGtk::~PrintDialogGtk() {
  gtk_widget_destroy(dialog_);
  dialog_ = NULL;
  page_setup_ = NULL;
  printer_ = NULL;
  if (gtk_settings_) {
    g_object_unref(gtk_settings_);
    gtk_settings_ = NULL;
  }
}

void PrintDialogGtk::OnResponse(GtkWidget* dialog, gint response_id) {
  gtk_widget_hide(dialog_);

  switch (response_id) {
    case GTK_RESPONSE_OK: {
      // |gtk_settings_| is a new object.
      gtk_settings_ = gtk_print_unix_dialog_get_settings(
          GTK_PRINT_UNIX_DIALOG(dialog_));
      // |printer_| and |page_setup_| are owned by |dialog_|.
      page_setup_ = gtk_print_unix_dialog_get_page_setup(
          GTK_PRINT_UNIX_DIALOG(dialog_));
      printer_ = gtk_print_unix_dialog_get_selected_printer(
          GTK_PRINT_UNIX_DIALOG(dialog_));

      printing::PageRanges ranges_vector;
      gint num_ranges;
      GtkPageRange* gtk_range =
          gtk_print_settings_get_page_ranges(gtk_settings_, &num_ranges);
      if (gtk_range) {
        for (int i = 0; i < num_ranges; ++i) {
          printing::PageRange* range = new printing::PageRange;
          range->from = gtk_range[i].start;
          range->to = gtk_range[i].end;
          ranges_vector.push_back(*range);
        }
        g_free(gtk_range);
      }

      printing::PrintSettings settings;
      printing::PrintSettingsInitializerGtk::InitPrintSettings(
          gtk_settings_, page_setup_, ranges_vector, false, &settings);
      context_->InitWithSettings(settings);
      callback_->Run(PrintingContextCairo::OK);
      return;
    }
    case GTK_RESPONSE_DELETE_EVENT:  // Fall through.
    case GTK_RESPONSE_CANCEL: {
      callback_->Run(PrintingContextCairo::CANCEL);
      Release();
      return;
    }
    case GTK_RESPONSE_APPLY:
    default: {
      NOTREACHED();
    }
  }
}

void PrintDialogGtk::SaveDocumentToDisk(const NativeMetafile* metafile,
                                        const string16& document_name) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));

  bool error = false;
  if (!file_util::CreateTemporaryFile(&path_to_pdf_)) {
    LOG(ERROR) << "Creating temporary file failed";
    error = true;
  }

  if (!error) {
    base::FileDescriptor temp_file_fd;
    temp_file_fd.fd = open(path_to_pdf_.value().c_str(), O_WRONLY);
    temp_file_fd.auto_close = true;
    if (!metafile->SaveTo(temp_file_fd)) {
      LOG(ERROR) << "Saving metafile failed";
      file_util::Delete(path_to_pdf_, false);
      error = true;
    }
  }

  // Done saving, let PrintDialogGtk::PrintDocument() continue.
  save_document_event_->Signal();

  if (error) {
    Release();
  } else {
    // No errors, continue printing.
    BrowserThread::PostTask(
        BrowserThread::UI, FROM_HERE,
        NewRunnableMethod(this,
                          &PrintDialogGtk::SendDocumentToPrinter,
                          document_name));
  }
}

void PrintDialogGtk::SendDocumentToPrinter(const string16& document_name) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  GtkPrintJob* print_job = gtk_print_job_new(
      UTF16ToUTF8(document_name).c_str(),
      printer_,
      gtk_settings_,
      page_setup_);
  gtk_print_job_set_source_file(print_job, path_to_pdf_.value().c_str(), NULL);
  gtk_print_job_send(print_job, OnJobCompletedThunk, this, NULL);
}

// static
void PrintDialogGtk::OnJobCompletedThunk(GtkPrintJob* print_job,
                                         gpointer user_data,
                                         GError* error) {
  static_cast<PrintDialogGtk*>(user_data)->OnJobCompleted(print_job, error);
}

void PrintDialogGtk::OnJobCompleted(GtkPrintJob* print_job, GError* error) {
  if (error)
    LOG(ERROR) << "Printing failed: " << error->message;
  if (print_job)
    g_object_unref(print_job);
  base::FileUtilProxy::Delete(
      BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE),
      path_to_pdf_,
      false,
      NULL);
  // Printing finished.
  Release();
}

void PrintDialogGtk::set_save_document_event(base::WaitableEvent* event) {
  DCHECK(event);
  DCHECK(!save_document_event_);
  save_document_event_ = event;
}
<commit_msg>Linux: Fix leak in print dialog.<commit_after>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/printing/print_dialog_gtk.h"

#include <fcntl.h>
#include <gtk/gtkpagesetupunixdialog.h>
#include <gtk/gtkprintjob.h>
#include <sys/stat.h>
#include <sys/types.h>

#include "base/file_util.h"
#include "base/file_util_proxy.h"
#include "base/logging.h"
#include "base/synchronization/waitable_event.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/browser_list.h"
#include "chrome/browser/browser_window.h"
#include "content/browser/browser_thread.h"
#include "printing/print_settings_initializer_gtk.h"

// static
void* PrintDialogGtk::CreatePrintDialog(
    PrintingContextCairo::PrintSettingsCallback* callback,
    PrintingContextCairo* context) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));

  PrintDialogGtk* dialog = new PrintDialogGtk(callback, context);
  return dialog;
}

// static
void PrintDialogGtk::PrintDocument(void* print_dialog,
                                   const NativeMetafile* metafile,
                                   const string16& document_name) {
  PrintDialogGtk* dialog = static_cast<PrintDialogGtk*>(print_dialog);

  scoped_ptr<base::WaitableEvent> event(new base::WaitableEvent(false, false));
  dialog->set_save_document_event(event.get());
  BrowserThread::PostTask(
      BrowserThread::FILE, FROM_HERE,
      NewRunnableMethod(dialog,
                        &PrintDialogGtk::SaveDocumentToDisk,
                        metafile,
                        document_name));
  // Wait for SaveDocumentToDisk() to finish.
  event->Wait();
}

PrintDialogGtk::PrintDialogGtk(
    PrintingContextCairo::PrintSettingsCallback* callback,
    PrintingContextCairo* context)
    : callback_(callback),
      context_(context),
      dialog_(NULL),
      page_setup_(NULL),
      printer_(NULL),
      gtk_settings_(NULL),
      save_document_event_(NULL) {
  // Manual AddRef since PrintDialogGtk manages its own lifetime.
  AddRef();

  GtkWindow* parent = BrowserList::GetLastActive()->window()->GetNativeHandle();

  // TODO(estade): We need a window title here.
  dialog_ = gtk_print_unix_dialog_new(NULL, parent);
  // Set modal so user cannot focus the same tab and press print again.
  gtk_window_set_modal(GTK_WINDOW(dialog_), TRUE);

  // Since we only generate PDF, only show printers that support PDF.
  // TODO(thestig) Add more capabilities to support?
  GtkPrintCapabilities cap = static_cast<GtkPrintCapabilities>(
      GTK_PRINT_CAPABILITY_GENERATE_PDF |
      GTK_PRINT_CAPABILITY_PAGE_SET |
      GTK_PRINT_CAPABILITY_COPIES |
      GTK_PRINT_CAPABILITY_COLLATE |
      GTK_PRINT_CAPABILITY_REVERSE);
  gtk_print_unix_dialog_set_manual_capabilities(GTK_PRINT_UNIX_DIALOG(dialog_),
                                                cap);
#if GTK_CHECK_VERSION(2, 18, 0)
  gtk_print_unix_dialog_set_embed_page_setup(GTK_PRINT_UNIX_DIALOG(dialog_),
                                             TRUE);
#endif
  g_signal_connect(dialog_, "response", G_CALLBACK(OnResponseThunk), this);

  gtk_widget_show(dialog_);
}

PrintDialogGtk::~PrintDialogGtk() {
  gtk_widget_destroy(dialog_);
  dialog_ = NULL;
  page_setup_ = NULL;
  printer_ = NULL;
  if (gtk_settings_) {
    g_object_unref(gtk_settings_);
    gtk_settings_ = NULL;
  }
}

void PrintDialogGtk::OnResponse(GtkWidget* dialog, gint response_id) {
  gtk_widget_hide(dialog_);

  switch (response_id) {
    case GTK_RESPONSE_OK: {
      // |gtk_settings_| is a new object.
      gtk_settings_ = gtk_print_unix_dialog_get_settings(
          GTK_PRINT_UNIX_DIALOG(dialog_));
      // |printer_| and |page_setup_| are owned by |dialog_|.
      page_setup_ = gtk_print_unix_dialog_get_page_setup(
          GTK_PRINT_UNIX_DIALOG(dialog_));
      printer_ = gtk_print_unix_dialog_get_selected_printer(
          GTK_PRINT_UNIX_DIALOG(dialog_));

      printing::PageRanges ranges_vector;
      gint num_ranges;
      GtkPageRange* gtk_range =
          gtk_print_settings_get_page_ranges(gtk_settings_, &num_ranges);
      if (gtk_range) {
        for (int i = 0; i < num_ranges; ++i) {
          printing::PageRange range;
          range.from = gtk_range[i].start;
          range.to = gtk_range[i].end;
          ranges_vector.push_back(range);
        }
        g_free(gtk_range);
      }

      printing::PrintSettings settings;
      printing::PrintSettingsInitializerGtk::InitPrintSettings(
          gtk_settings_, page_setup_, ranges_vector, false, &settings);
      context_->InitWithSettings(settings);
      callback_->Run(PrintingContextCairo::OK);
      return;
    }
    case GTK_RESPONSE_DELETE_EVENT:  // Fall through.
    case GTK_RESPONSE_CANCEL: {
      callback_->Run(PrintingContextCairo::CANCEL);
      Release();
      return;
    }
    case GTK_RESPONSE_APPLY:
    default: {
      NOTREACHED();
    }
  }
}

void PrintDialogGtk::SaveDocumentToDisk(const NativeMetafile* metafile,
                                        const string16& document_name) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));

  bool error = false;
  if (!file_util::CreateTemporaryFile(&path_to_pdf_)) {
    LOG(ERROR) << "Creating temporary file failed";
    error = true;
  }

  if (!error) {
    base::FileDescriptor temp_file_fd;
    temp_file_fd.fd = open(path_to_pdf_.value().c_str(), O_WRONLY);
    temp_file_fd.auto_close = true;
    if (!metafile->SaveTo(temp_file_fd)) {
      LOG(ERROR) << "Saving metafile failed";
      file_util::Delete(path_to_pdf_, false);
      error = true;
    }
  }

  // Done saving, let PrintDialogGtk::PrintDocument() continue.
  save_document_event_->Signal();

  if (error) {
    Release();
  } else {
    // No errors, continue printing.
    BrowserThread::PostTask(
        BrowserThread::UI, FROM_HERE,
        NewRunnableMethod(this,
                          &PrintDialogGtk::SendDocumentToPrinter,
                          document_name));
  }
}

void PrintDialogGtk::SendDocumentToPrinter(const string16& document_name) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  GtkPrintJob* print_job = gtk_print_job_new(
      UTF16ToUTF8(document_name).c_str(),
      printer_,
      gtk_settings_,
      page_setup_);
  gtk_print_job_set_source_file(print_job, path_to_pdf_.value().c_str(), NULL);
  gtk_print_job_send(print_job, OnJobCompletedThunk, this, NULL);
}

// static
void PrintDialogGtk::OnJobCompletedThunk(GtkPrintJob* print_job,
                                         gpointer user_data,
                                         GError* error) {
  static_cast<PrintDialogGtk*>(user_data)->OnJobCompleted(print_job, error);
}

void PrintDialogGtk::OnJobCompleted(GtkPrintJob* print_job, GError* error) {
  if (error)
    LOG(ERROR) << "Printing failed: " << error->message;
  if (print_job)
    g_object_unref(print_job);
  base::FileUtilProxy::Delete(
      BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE),
      path_to_pdf_,
      false,
      NULL);
  // Printing finished.
  Release();
}

void PrintDialogGtk::set_save_document_event(base::WaitableEvent* event) {
  DCHECK(event);
  DCHECK(!save_document_event_);
  save_document_event_ = event;
}
<|endoftext|>


<commit_before><commit_msg>Fixed a typo<commit_after><|endoftext|>


<commit_before>#ifndef MANIFOLDS_FUNCTIONS_STREAMING_HH
#define MANIFOLDS_FUNCTIONS_STREAMING_HH

#include <functional>
#include <ostream>
#include <map>
#include <algorithm>
#include <iterator>
#include "composition.hh"
#include "addition.hh"
#include "multiplication.hh"
#include "polynomial.hh"
#include "variables.hh"
#include "function_matrix.hh"
#include "division.hh"
#include "transpose.hh"
#include "zero.hh"
#include "integral_polynomial.hh"
#include "unary_minus.hh"
#include "trig.hh"
#include "complex.hh"

namespace manifolds {
struct Stream2Wrapper {
  template <class VNamer>
  static void Stream2(std::ostream &s, Transpose, VNamer) {
    s << "Tr";
  }

#define STD_STREAM2(Func, func)                                                \
  template <class V> static void Stream2(std::ostream &s, Func, V) {           \
    s << #func;                                                                \
  }

  STD_STREAM2(Sin, sin)
  STD_STREAM2(Cos, cos)
  STD_STREAM2(Tan, tan)
  STD_STREAM2(Log, log)
  STD_STREAM2(Sinh, sinh)
  STD_STREAM2(Cosh, cosh)
  STD_STREAM2(Tanh, tanh)
  STD_STREAM2(ASin, asin)
  STD_STREAM2(ACos, acos)
  STD_STREAM2(ATan, atan)
  STD_STREAM2(ASinh, asinh)
  STD_STREAM2(ACosh, acosh)
  STD_STREAM2(ATanh, atanh)
  STD_STREAM2(Exp, exp)
  STD_STREAM2(Sqrt, sqrt)
  STD_STREAM2(Pow, pow)
  STD_STREAM2(Real, real)
  STD_STREAM2(Imag, imag)
  STD_STREAM2(Phase, phase)
  STD_STREAM2(Sign, sign)
  STD_STREAM2(Norm, norm)

#undef STD_STREAM2

  template <class V, class T>
  static void Stream2(std::ostream &s, ImagN<T>, V) {
    s << "I";
  }

  template <class... Args, class VNamer>
  static void Stream2(std::ostream &s, Group<Args...> g, VNamer vn) {
    Stream2Tuple(s, g.GetFunctions(), vn);
  }

  template <class N, class D, class VNamer>
  static void Stream2(std::ostream &s, Division<N, D> d, VNamer v) {
    s << '(';
    Stream2(s, d.GetNumerator(), v);
    s << " / ";
    Stream2(s, d.GetDenominator(), v);
    s << ')';
  }

  template <class VNamer> static void Stream2(std::ostream &s, Zero, VNamer) {
    s << "0";
  }

  template <class VNamer>
  static void Stream2Tuple(std::ostream &s, tuple<>, VNamer) {}

  template <
      class Tuple, class VNamer,
      class = typename std::enable_if<std::tuple_size<Tuple>::value != 0>::type>
  static void Stream2Tuple(std::ostream &s, const Tuple &t, VNamer vn) {
    Stream2(s, std::get<0>(t), vn);
    if (std::tuple_size<Tuple>::value > 1)
      s << ", ";
    Stream2Tuple(s, remove_element<0>(t), vn);
  }

  template <class c, class... Functions, class VNamer>
  static void Stream2FMatrix(std::ostream &s,
                             FunctionMatrix<int_<0>, c, Functions...> fm,
                             VNamer vn) {}

  template <class r, class c, class... Functions, class VNamer,
            class = typename std::enable_if<r::value != 0>::type>
  static void Stream2FMatrix(std::ostream &s,
                             FunctionMatrix<r, c, Functions...> fm, VNamer vn) {
    s << "{";
    Stream2Tuple(s, subset<0, c::value>(fm.GetFunctions()), vn);
    s << "}";
    if (r::value > 1)
      s << ", ";
    auto t = GetFunctionMatrix<r::value - 1, c::value>(
        subset<r::value, c::value *(r::value - 1)>(fm.GetFunctions()));
    Stream2FMatrix(s, t, vn);
  }

  template <class... Functions, class VNamer>
  static void Stream2(std::ostream &s, FunctionMatrix<Functions...> fm,
                      VNamer vn) {
    s << "{";
    Stream2FMatrix(s, fm, vn);
    s << "}";
  }

  template <int N, bool abelian, class VNamer>
  static void Stream2(std::ostream &s, Variable<N, abelian> v, VNamer vn) {
    s << vn(v);
  }

  template <class Func, class VNamer>
  static void Stream2(std::ostream &s, Composition<Func> c, VNamer vn) {
    Stream2(s, std::get<0>(c.GetFunctions()), vn);
  }

  template <class CType, class Order, class... Funcs, class VNamer,
            class = typename std::enable_if<(sizeof...(Funcs) > 0)>::type>
  static void Stream2(std::ostream &s,
                      Composition<Polynomial<CType, Order>, Funcs...> c,
                      VNamer vn) {
    std::stringstream ss;
    Stream2(ss, Composition<Funcs...>(remove_element<0>(c.GetFunctions())), vn);
    std::string var = ss.str();
    for (auto c : var) {
      if (!std::isalnum(c)) {
        var = "(" + var + ")";
        break;
      }
    }
    Stream2(s, std::get<0>(c.GetFunctions()), vn, var);
  }

  template <IPInt_t... ts, class... Funcs, class VNamer,
            class = typename std::enable_if<(sizeof...(Funcs) > 0)>::type>
  static void Stream2(std::ostream &s,
                      Composition<IntegralPolynomial<ts...>, Funcs...> c,
                      VNamer vn) {
    auto p = std::get<0>(c.GetFunctions()).ToPoly();
    Composition<Polynomial<IPInt_t, int_<(sizeof...(ts))> >, Funcs...> c2 =
        insert_element<0>(remove_element<0>(c.GetFunctions()), p);
    Stream2(s, c2, vn);
  }

  template <class F, class... Funcs, class VNamer,
            class = typename std::enable_if<(sizeof...(Funcs) > 0) &&
                                            !is_polynomial<F>::value>::type>
  static void Stream2(std::ostream &s, Composition<F, Funcs...> c, VNamer vn) {
    Stream2(s, std::get<0>(c.GetFunctions()), vn);
    s << '(';
    Stream2(s, Composition<Funcs...>(remove_element<0>(c.GetFunctions())), vn);
    s << ')';
  }

  template <class T, class VNamer>
  static void Stream2(std::ostream &s, UnaryMinus<T> u, VNamer vn) {
    s << "-(";
    Stream2(s, u.GetFunction(), vn);
    s << ")";
  }

  template <IPInt_t... ts, class VNamer>
  static void Stream2(std::ostream &s, IntegralPolynomial<ts...> ip,
                      VNamer vn) {
    return Stream2(s, ip.ToPoly(), vn);
  }

  template <class CoeffType, class Order, class VNamer>
  static void Stream2(std::ostream &s, Polynomial<CoeffType, Order> p,
                      VNamer vn, std::string var = "") {
    if (var == "")
      var = "p";
    bool started = false;
    CoeffType z(0);
    for (unsigned i = 0; i < Order::value; i++) {
      CoeffType c = p[i];
      if (c == z)
        continue;
      if (started)
        s << (c > z ? " + " : " - ");
      else {
        started = true;
        if (c < z)
          s << '-';
      }
      if (i == 0 || c != 1)
        s << std::abs(c);
      if (i > 0 && c != 1)
        s << " * ";
      if (i == 1)
        s << var;
      else if (i > 1)
        s << var << " ^ " << i;
    }
    if (!started)
      s << '0';
  }

  template <class Func, class VNamer>
  static void Stream2(std::ostream &s, Addition<Func> a, VNamer vn) {
    Stream2(s, std::get<0>(a.GetFunctions()), vn);
  }

  template <class F, class... Funcs, class VNamer,
            class = typename std::enable_if<(sizeof...(Funcs) > 0)>::type>
  static void Stream2(std::ostream &s, Addition<F, Funcs...> a, VNamer vn) {
    Stream2(s, std::get<0>(a.GetFunctions()), vn);
    s << " + ";
    Stream2(s, Addition<Funcs...>(remove_element<0>(a.GetFunctions())), vn);
  }

  template <class T, class VNamer>
  static void PrintMultElem(std::ostream &s, T t, VNamer vn) {
    static const bool b =
        IsVariadic<Addition, T>::value ||
        (is_polynomial<T>::value && PolynomialOrder<T>::value != 1);
    if (b)
      s << '(';
    Stream2(s, t, vn);
    if (b)
      s << ')';
  }

  template <class F, class VNamer>
  static void Stream2(std::ostream &s, Multiplication<F> m, VNamer vn) {
    PrintMultElem(s, std::get<0>(m.GetFunctions()), vn);
  }

  template <class F, class... Funcs, class VNamer,
            class = typename std::enable_if<(sizeof...(Funcs) > 0)>::type>
  static void Stream2(std::ostream &s, Multiplication<F, Funcs...> m,
                      VNamer vn) {
    PrintMultElem(s, std::get<0>(m.GetFunctions()), vn);
    s << " * ";
    Stream2(s, Multiplication<Funcs...>(remove_element<0>(m.GetFunctions())),
            vn);
  }
};

template <class T, class VariableNamer>
std::ostream &Stream2(std::ostream &s, T t, VariableNamer vn) {
  Stream2Wrapper::Stream2(s, t, std::ref(vn));
  return s;
}

template <class T> std::ostream &Stream2(std::ostream &s, T t) {
  Stream2Wrapper::Stream2(s, t, DefaultVariableNamer());
  return s;
}

struct CustomVariableNamer {
  std::map<std::pair<int, bool>, std::string> names;
  CustomVariableNamer(std::initializer_list<tuple<int, bool, std::string> > l) {
    std::transform(std::begin(l), std::end(l),
                   std::inserter(names, names.begin()), [](auto x) {
      return std::make_pair(std::make_pair(std::get<0>(x), std::get<1>(x)),
                            std::get<2>(x));
    });
  }

  CustomVariableNamer(std::initializer_list<std::pair<int, std::string> > l) {
    for (auto i : l) {
      names[std::make_pair(i.first, false)] =
          names[std::make_pair(i.first, true)] = i.second;
    }
  }

  template <int N, bool a> std::string operator()(Variable<N, a> v) const {
    auto i = names.find(std::make_pair(N, a));
    if (i == names.end())
      return DefaultVariableNamer()(v);
    return i->second;
  }
};

template <class Arg, class... Args>
std::ostream &operator<<(std::ostream &s, Composition<Arg, Args...> c) {
  return Stream2(s, c);
}

template <class A, class B>
std::ostream &operator<<(std::ostream &s, Division<A, B> d) {
  return Stream2(s, d);
}

template <class rows, class cols, class... Functions>
std::ostream &operator<<(std::ostream &s,
                         FunctionMatrix<rows, cols, Functions...> f) {
  return Stream2(s, f);
}

template <class F, class... Funcs>
std::ostream &operator<<(std::ostream &s, Group<F, Funcs...> g) {
  return Stream2(s, g);
}

template <class CType, int N>
std::ostream &operator<<(std::ostream &s, Polynomial<CType, int_<N> > p) {
  return Stream2(s, p);
}

template <IPInt_t... ts>
std::ostream &operator<<(std::ostream &s, IntegralPolynomial<ts...> ip) {
  return s << ip.ToPoly();
}

template <class Func, class... Functions>
std::ostream &operator<<(std::ostream &s,
                         Multiplication<Func, Functions...> m) {
  return Stream2(s, m);
}

inline std::ostream &operator<<(std::ostream &s, Transpose t) {
  return Stream2(s, t);
}

template <class T> std::ostream &operator<<(std::ostream &s, UnaryMinus<T> u) {
  return Stream2(s, u);
}

inline std::ostream &operator<<(std::ostream &s, Zero z) {
  return Stream2(s, z);
}

template <class Func, class... Functions>
std::ostream &operator<<(std::ostream &s, Addition<Func, Functions...> m) {
  return Stream2(s, m);
}

#define EASY_STREAM(Func, name)                                                \
  inline std::ostream &operator<<(std::ostream &s, Func) { return s << #name; }

EASY_STREAM(Real, real)
EASY_STREAM(Imag, imag)
EASY_STREAM(Phase, phase)
EASY_STREAM(Sign, sign)
EASY_STREAM(Norm, norm)
template <class T> EASY_STREAM(ImagN<T>, I)
}

#endif
<commit_msg>Fixed errors when printing multiplication with a polynomial inside and fixed polynomial printing for coeff==-1<commit_after>#ifndef MANIFOLDS_FUNCTIONS_STREAMING_HH
#define MANIFOLDS_FUNCTIONS_STREAMING_HH

#include <functional>
#include <ostream>
#include <map>
#include <algorithm>
#include <iterator>
#include "composition.hh"
#include "addition.hh"
#include "multiplication.hh"
#include "polynomial.hh"
#include "variables.hh"
#include "function_matrix.hh"
#include "division.hh"
#include "transpose.hh"
#include "zero.hh"
#include "integral_polynomial.hh"
#include "unary_minus.hh"
#include "trig.hh"
#include "complex.hh"

namespace manifolds {
struct Stream2Wrapper {
  template <class VNamer>
  static void Stream2(std::ostream &s, Transpose, VNamer) {
    s << "Tr";
  }

#define STD_STREAM2(Func, func)                                                \
  template <class V> static void Stream2(std::ostream &s, Func, V) {           \
    s << #func;                                                                \
  }

  STD_STREAM2(Sin, sin)
  STD_STREAM2(Cos, cos)
  STD_STREAM2(Tan, tan)
  STD_STREAM2(Log, log)
  STD_STREAM2(Sinh, sinh)
  STD_STREAM2(Cosh, cosh)
  STD_STREAM2(Tanh, tanh)
  STD_STREAM2(ASin, asin)
  STD_STREAM2(ACos, acos)
  STD_STREAM2(ATan, atan)
  STD_STREAM2(ASinh, asinh)
  STD_STREAM2(ACosh, acosh)
  STD_STREAM2(ATanh, atanh)
  STD_STREAM2(Exp, exp)
  STD_STREAM2(Sqrt, sqrt)
  STD_STREAM2(Pow, pow)
  STD_STREAM2(Real, real)
  STD_STREAM2(Imag, imag)
  STD_STREAM2(Phase, phase)
  STD_STREAM2(Sign, sign)
  STD_STREAM2(Norm, norm)

#undef STD_STREAM2

  template <class V, class T>
  static void Stream2(std::ostream &s, ImagN<T>, V) {
    s << "I";
  }

  template <class... Args, class VNamer>
  static void Stream2(std::ostream &s, Group<Args...> g, VNamer vn) {
    Stream2Tuple(s, g.GetFunctions(), vn);
  }

  template <class N, class D, class VNamer>
  static void Stream2(std::ostream &s, Division<N, D> d, VNamer v) {
    s << '(';
    Stream2(s, d.GetNumerator(), v);
    s << " / ";
    Stream2(s, d.GetDenominator(), v);
    s << ')';
  }

  template <class VNamer> static void Stream2(std::ostream &s, Zero, VNamer) {
    s << "0";
  }

  template <class VNamer>
  static void Stream2Tuple(std::ostream &s, tuple<>, VNamer) {}

  template <
      class Tuple, class VNamer,
      class = typename std::enable_if<std::tuple_size<Tuple>::value != 0>::type>
  static void Stream2Tuple(std::ostream &s, const Tuple &t, VNamer vn) {
    Stream2(s, std::get<0>(t), vn);
    if (std::tuple_size<Tuple>::value > 1)
      s << ", ";
    Stream2Tuple(s, remove_element<0>(t), vn);
  }

  template <class c, class... Functions, class VNamer>
  static void Stream2FMatrix(std::ostream &s,
                             FunctionMatrix<int_<0>, c, Functions...> fm,
                             VNamer vn) {}

  template <class r, class c, class... Functions, class VNamer,
            class = typename std::enable_if<r::value != 0>::type>
  static void Stream2FMatrix(std::ostream &s,
                             FunctionMatrix<r, c, Functions...> fm, VNamer vn) {
    s << "{";
    Stream2Tuple(s, subset<0, c::value>(fm.GetFunctions()), vn);
    s << "}";
    if (r::value > 1)
      s << ", ";
    auto t = GetFunctionMatrix<r::value - 1, c::value>(
        subset<r::value, c::value *(r::value - 1)>(fm.GetFunctions()));
    Stream2FMatrix(s, t, vn);
  }

  template <class... Functions, class VNamer>
  static void Stream2(std::ostream &s, FunctionMatrix<Functions...> fm,
                      VNamer vn) {
    s << "{";
    Stream2FMatrix(s, fm, vn);
    s << "}";
  }

  template <int N, bool abelian, class VNamer>
  static void Stream2(std::ostream &s, Variable<N, abelian> v, VNamer vn) {
    s << vn(v);
  }

  template <class Func, class VNamer>
  static void Stream2(std::ostream &s, Composition<Func> c, VNamer vn) {
    Stream2(s, std::get<0>(c.GetFunctions()), vn);
  }

  template <class CType, class Order, class... Funcs, class VNamer,
            class = typename std::enable_if<(sizeof...(Funcs) > 0)>::type>
  static void Stream2(std::ostream &s,
                      Composition<Polynomial<CType, Order>, Funcs...> c,
                      VNamer vn) {
    std::stringstream ss;
    Stream2(ss, Composition<Funcs...>(remove_element<0>(c.GetFunctions())), vn);
    std::string var = ss.str();
    for (auto c : var) {
      if (!std::isalnum(c)) {
        var = "(" + var + ")";
        break;
      }
    }
    Stream2(s, std::get<0>(c.GetFunctions()), vn, var);
  }

  template <IPInt_t... ts, class... Funcs, class VNamer,
            class = typename std::enable_if<(sizeof...(Funcs) > 0)>::type>
  static void Stream2(std::ostream &s,
                      Composition<IntegralPolynomial<ts...>, Funcs...> c,
                      VNamer vn) {
    auto p = std::get<0>(c.GetFunctions()).ToPoly();
    Composition<Polynomial<IPInt_t, int_<(sizeof...(ts))> >, Funcs...> c2 =
        insert_element<0>(remove_element<0>(c.GetFunctions()), p);
    Stream2(s, c2, vn);
  }

  template <class F, class... Funcs, class VNamer,
            class = typename std::enable_if<(sizeof...(Funcs) > 0) &&
                                            !is_polynomial<F>::value>::type>
  static void Stream2(std::ostream &s, Composition<F, Funcs...> c, VNamer vn) {
    Stream2(s, std::get<0>(c.GetFunctions()), vn);
    s << '(';
    Stream2(s, Composition<Funcs...>(remove_element<0>(c.GetFunctions())), vn);
    s << ')';
  }

  template <class T, class VNamer>
  static void Stream2(std::ostream &s, UnaryMinus<T> u, VNamer vn) {
    s << "-(";
    Stream2(s, u.GetFunction(), vn);
    s << ")";
  }

  template <IPInt_t... ts, class VNamer>
  static void Stream2(std::ostream &s, IntegralPolynomial<ts...> ip,
                      VNamer vn) {
    return Stream2(s, ip.ToPoly(), vn);
  }

  template <class CoeffType, class Order, class VNamer>
  static void Stream2(std::ostream &s, Polynomial<CoeffType, Order> p,
                      VNamer vn, std::string var = "") {
    if (var == "")
      var = "p";
    bool started = false;
    CoeffType z(0);
    for (unsigned i = 0; i < Order::value; i++) {
      CoeffType c = p[i];
      if (c == z)
        continue;
      if (started)
        s << (c > z ? " + " : " - ");
      else {
        started = true;
        if (c < z)
          s << '-';
      }
      c = std::abs(c);
      if (i == 0 || c != 1)
        s << c;
      if (i > 0 && c != 1)
        s << " * ";
      if (i == 1)
        s << var;
      else if (i > 1)
        s << var << " ^ " << i;
    }
    if (!started)
      s << '0';
  }

  template <class Func, class VNamer>
  static void Stream2(std::ostream &s, Addition<Func> a, VNamer vn) {
    Stream2(s, std::get<0>(a.GetFunctions()), vn);
  }

  template <class F, class... Funcs, class VNamer,
            class = typename std::enable_if<(sizeof...(Funcs) > 0)>::type>
  static void Stream2(std::ostream &s, Addition<F, Funcs...> a, VNamer vn) {
    Stream2(s, std::get<0>(a.GetFunctions()), vn);
    s << " + ";
    Stream2(s, Addition<Funcs...>(remove_element<0>(a.GetFunctions())), vn);
  }

  template <class, class = void> struct RequiresParens : bool_<false> {};

  template <class F, class... Fs>
  struct RequiresParens<Composition<F, Fs...> > : RequiresParens<F> {};

  template <class... Fs>
  struct RequiresParens<Addition<Fs...> > : bool_<true> {};

  template <class C, class O>
  struct RequiresParens<
      Polynomial<C, O>,
      typename std::enable_if<(O::value > 1)>::type> : bool_<true> {};

  template <IPInt_t... coeffs>
  struct RequiresParens<
      IntegralPolynomial<coeffs...>,
      typename std::enable_if<(sizeof...(coeffs) > 1)>::type> : bool_<true> {};

  template <class T, class VNamer>
  static void PrintMultElem(std::ostream &s, T t, VNamer vn) {
    static const bool b = RequiresParens<T>::value;
    if (b)
      s << '(';
    Stream2(s, t, vn);
    if (b)
      s << ')';
  }

  template <class F, class VNamer>
  static void Stream2(std::ostream &s, Multiplication<F> m, VNamer vn) {
    PrintMultElem(s, std::get<0>(m.GetFunctions()), vn);
  }

  template <class F, class... Funcs, class VNamer,
            class = typename std::enable_if<(sizeof...(Funcs) > 0)>::type>
  static void Stream2(std::ostream &s, Multiplication<F, Funcs...> m,
                      VNamer vn) {
    PrintMultElem(s, std::get<0>(m.GetFunctions()), vn);
    s << " * ";
    Stream2(s, Multiplication<Funcs...>(remove_element<0>(m.GetFunctions())),
            vn);
  }
};

template <class T, class VariableNamer>
std::ostream &Stream2(std::ostream &s, T t, VariableNamer vn) {
  Stream2Wrapper::Stream2(s, t, std::ref(vn));
  return s;
}

template <class T> std::ostream &Stream2(std::ostream &s, T t) {
  Stream2Wrapper::Stream2(s, t, DefaultVariableNamer());
  return s;
}

struct CustomVariableNamer {
  std::map<std::pair<int, bool>, std::string> names;
  CustomVariableNamer(std::initializer_list<tuple<int, bool, std::string> > l) {
    std::transform(std::begin(l), std::end(l),
                   std::inserter(names, names.begin()), [](auto x) {
      return std::make_pair(std::make_pair(std::get<0>(x), std::get<1>(x)),
                            std::get<2>(x));
    });
  }

  CustomVariableNamer(std::initializer_list<std::pair<int, std::string> > l) {
    for (auto i : l) {
      names[std::make_pair(i.first, false)] =
          names[std::make_pair(i.first, true)] = i.second;
    }
  }

  template <int N, bool a> std::string operator()(Variable<N, a> v) const {
    auto i = names.find(std::make_pair(N, a));
    if (i == names.end())
      return DefaultVariableNamer()(v);
    return i->second;
  }
};

template <class Arg, class... Args>
std::ostream &operator<<(std::ostream &s, Composition<Arg, Args...> c) {
  return Stream2(s, c);
}

template <class A, class B>
std::ostream &operator<<(std::ostream &s, Division<A, B> d) {
  return Stream2(s, d);
}

template <class rows, class cols, class... Functions>
std::ostream &operator<<(std::ostream &s,
                         FunctionMatrix<rows, cols, Functions...> f) {
  return Stream2(s, f);
}

template <class F, class... Funcs>
std::ostream &operator<<(std::ostream &s, Group<F, Funcs...> g) {
  return Stream2(s, g);
}

template <class CType, int N>
std::ostream &operator<<(std::ostream &s, Polynomial<CType, int_<N> > p) {
  return Stream2(s, p);
}

template <IPInt_t... ts>
std::ostream &operator<<(std::ostream &s, IntegralPolynomial<ts...> ip) {
  return s << ip.ToPoly();
}

template <class Func, class... Functions>
std::ostream &operator<<(std::ostream &s,
                         Multiplication<Func, Functions...> m) {
  return Stream2(s, m);
}

inline std::ostream &operator<<(std::ostream &s, Transpose t) {
  return Stream2(s, t);
}

template <class T> std::ostream &operator<<(std::ostream &s, UnaryMinus<T> u) {
  return Stream2(s, u);
}

inline std::ostream &operator<<(std::ostream &s, Zero z) {
  return Stream2(s, z);
}

template <class Func, class... Functions>
std::ostream &operator<<(std::ostream &s, Addition<Func, Functions...> m) {
  return Stream2(s, m);
}

#define EASY_STREAM(Func, name)                                                \
  inline std::ostream &operator<<(std::ostream &s, Func) { return s << #name; }

EASY_STREAM(Real, real)
EASY_STREAM(Imag, imag)
EASY_STREAM(Phase, phase)
EASY_STREAM(Sign, sign)
EASY_STREAM(Norm, norm)
template <class T> EASY_STREAM(ImagN<T>, I)
}

#endif
<|endoftext|>


<commit_before>#include "ontology_view.hpp"
#include "synonyms.hpp"
#include <QTreeWidgetItem>
#include <QTreeWidgetItemIterator>
#include <QMouseEvent>
#include <QDragMoveEvent>
#include <QApplication>
#include <QMimeData>
#include <QDrag>
#include <QMenu>
#include <QAction>

#include <iostream>
#include <QDebug>

static QTreeWidgetItem *findItem( QTreeWidget *tw, const QString &name );

OntologyView::OntologyView( QWidget *parent )
    : QTreeWidget{parent}, selectedItem_{nullptr} {
    setColumnCount( 2 );

    setSelectionMode( QAbstractItemView::SingleSelection );
    setDragEnabled( true );
    viewport( )->setAcceptDrops( true );
    setDropIndicatorShown( true );
    setDragDropMode( QAbstractItemView::InternalMove );

    removeEntryAction_ = new QAction{tr( "&Delete" ), this};
    removeEntryAction_->setShortcut( QKeySequence::Delete );
    removeEntryAction_->setIcon( QIcon::fromTheme( "remove" ) );
    connect( removeEntryAction_, SIGNAL( triggered( ) ), SLOT( removeEntry( ) ) );

    ontologyViewContextMenu_ = new QMenu{this};
    ontologyViewContextMenu_->addAction( removeEntryAction_ );

    connect( this, SIGNAL( customContextMenuRequested( const QPoint & )),
             SLOT( contextMenuRequest( const QPoint & )) );
}
void OntologyView::insertEntry( const QString &entry, int count ) {
    std::cerr << "entry: " << entry.toStdString( ) << std::endl;

    QTreeWidgetItem *item = new QTreeWidgetItem;
    item->setText( 0, entry );
    item->setData( 1, Qt::DisplayRole, QVariant{count} );
    item->setFlags( Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled |
                    Qt::ItemIsDropEnabled );
    addTopLevelItem( item );
}

void OntologyView::contextMenuRequest( const QPoint &pos ) {
    QModelIndex idx = indexAt( pos );
    if ( idx.isValid( ) ) {
        selectedItem_ = itemFromIndex( idx );
        qDebug( ) << "selected item: " << selectedItem_->text( 0 );
        ontologyViewContextMenu_->exec( mapToGlobal( pos ) );
    }
}

void OntologyView::removeEntry( ) {
    qDebug( ) << "removing entry: " << selectedItem_->text( 0 );
    const QString entry = selectedItem_->text( 0 );
    if ( selectedItem_->parent( ) ) {
        QTreeWidgetItem *parent = selectedItem_->parent( );
        parent->removeChild( selectedItem_ );
    } else {
        delete selectedItem_;
    }
    selectedItem_ = nullptr;
    emit removeEntry( entry );
}

void OntologyView::dropEvent( QDropEvent *event ) {
    // there are 3 possibilities,
    // 1 create a synonym
    // 2 remove a synonym
    // 3 move to another synonym
    QTreeWidgetItem *movedItem =
        qobject_cast<OntologyView *>( event->source( ) )->currentItem( );
    QModelIndex droppedIndex = indexAt( event->pos( ) );
    std::cerr << "item dropped at index: " << droppedIndex.row( ) << std::endl;
    if ( !droppedIndex.isValid( ) ) {
        return;
    }

    QTreeWidgetItem *item = itemFromIndex( indexAt( event->pos( ) ) );
    if ( item->parent( ) ) {
        std::cerr << "item: " << item->text( 0 ).toStdString( ) << " has a parent"
                  << std::endl;
        return;
    }
    if ( movedItem->childCount( ) ) {
        std::cerr << "moved item: " << movedItem->text( 0 ).toStdString( )
                  << " has children" << std::endl;
        return;
    }

    std::cerr << "adding child: " << movedItem->text( 0 ).toStdString( )
              << " to parent: " << item->text( 0 ).toStdString( ) << std::endl;

    if ( movedItem->parent( ) ) {
        emit removeSynonym( movedItem->text( 0 ) );
    }

    int movedItemCount = movedItem->data( 1, Qt::DisplayRole ).toInt( );
    // item->setData( 1, Qt::DisplayRole, QVariant{itemCount + movedItemCount} );
    item->addChild( movedItem );
    emit itemChanged( item, 1 );

    emit synonymCreated( movedItem->text( 0 ), item->text( 0 ) );

    QTreeWidget::dropEvent( event );
}

static QTreeWidgetItem *findItem( QTreeWidget *tw, const QString &name ) {
    QTreeWidgetItemIterator it{tw};
    while ( *it ) {
        if ( ( *it )->text( 0 ) == name ) {
            return *it;
        }
    }
    return nullptr;
}
<commit_msg>removed comments<commit_after>#include "ontology_view.hpp"
#include "synonyms.hpp"
#include <QTreeWidgetItem>
#include <QTreeWidgetItemIterator>
#include <QMouseEvent>
#include <QDragMoveEvent>
#include <QApplication>
#include <QMimeData>
#include <QDrag>
#include <QMenu>
#include <QAction>

#include <iostream>
#include <QDebug>

static QTreeWidgetItem *findItem( QTreeWidget *tw, const QString &name );

OntologyView::OntologyView( QWidget *parent )
    : QTreeWidget{parent}, selectedItem_{nullptr} {
    setColumnCount( 2 );

    setSelectionMode( QAbstractItemView::SingleSelection );
    setDragEnabled( true );
    viewport( )->setAcceptDrops( true );
    setDropIndicatorShown( true );
    setDragDropMode( QAbstractItemView::InternalMove );

    removeEntryAction_ = new QAction{tr( "&Delete" ), this};
    removeEntryAction_->setShortcut( QKeySequence::Delete );
    removeEntryAction_->setIcon( QIcon::fromTheme( "remove" ) );
    connect( removeEntryAction_, SIGNAL( triggered( ) ), SLOT( removeEntry( ) ) );

    ontologyViewContextMenu_ = new QMenu{this};
    ontologyViewContextMenu_->addAction( removeEntryAction_ );

    connect( this, SIGNAL( customContextMenuRequested( const QPoint & )),
             SLOT( contextMenuRequest( const QPoint & )) );
}
void OntologyView::insertEntry( const QString &entry, int count ) {
    QTreeWidgetItem *item = new QTreeWidgetItem;
    item->setText( 0, entry );
    item->setData( 1, Qt::DisplayRole, QVariant{count} );
    item->setFlags( Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled |
                    Qt::ItemIsDropEnabled );
    addTopLevelItem( item );
}

void OntologyView::contextMenuRequest( const QPoint &pos ) {
    QModelIndex idx = indexAt( pos );
    if ( idx.isValid( ) ) {
        selectedItem_ = itemFromIndex( idx );
        ontologyViewContextMenu_->exec( mapToGlobal( pos ) );
    }
}

void OntologyView::removeEntry( ) {
    const QString entry = selectedItem_->text( 0 );
    if ( selectedItem_->parent( ) ) {
        QTreeWidgetItem *parent = selectedItem_->parent( );
        parent->removeChild( selectedItem_ );
    } else {
        delete selectedItem_;
    }
    selectedItem_ = nullptr;
    emit removeEntry( entry );
}

void OntologyView::dropEvent( QDropEvent *event ) {
    // there are 3 possibilities,
    // 1 create a synonym
    // 2 remove a synonym
    // 3 move to another synonym
    QTreeWidgetItem *movedItem =
        qobject_cast<OntologyView *>( event->source( ) )->currentItem( );
    QModelIndex droppedIndex = indexAt( event->pos( ) );
    std::cerr << "item dropped at index: " << droppedIndex.row( ) << std::endl;
    if ( !droppedIndex.isValid( ) ) {
        return;
    }

    QTreeWidgetItem *item = itemFromIndex( indexAt( event->pos( ) ) );
    if ( item->parent( ) ) {
        std::cerr << "item: " << item->text( 0 ).toStdString( ) << " has a parent"
                  << std::endl;
        return;
    }
    if ( movedItem->childCount( ) ) {
        std::cerr << "moved item: " << movedItem->text( 0 ).toStdString( )
                  << " has children" << std::endl;
        return;
    }

    std::cerr << "adding child: " << movedItem->text( 0 ).toStdString( )
              << " to parent: " << item->text( 0 ).toStdString( ) << std::endl;

    if ( movedItem->parent( ) ) {
        emit removeSynonym( movedItem->text( 0 ) );
    }

    int movedItemCount = movedItem->data( 1, Qt::DisplayRole ).toInt( );
    // item->setData( 1, Qt::DisplayRole, QVariant{itemCount + movedItemCount} );
    item->addChild( movedItem );
    emit itemChanged( item, 1 );

    emit synonymCreated( movedItem->text( 0 ), item->text( 0 ) );

    QTreeWidget::dropEvent( event );
}

static QTreeWidgetItem *findItem( QTreeWidget *tw, const QString &name ) {
    QTreeWidgetItemIterator it{tw};
    while ( *it ) {
        if ( ( *it )->text( 0 ) == name ) {
            return *it;
        }
    }
    return nullptr;
}
<|endoftext|>


<commit_before>#include <windows.h>
#include <tchar.h>
#include <Shlwapi.h>
#include "resource.h"
#include <vector>

#pragma comment(lib, "Shlwapi.lib")

#ifndef UNICODE
#error "Must be compiled with unicode support."
#endif

#define USE_TASKBAR_API (_WIN32_WINNT >= _WIN32_WINNT_WIN7)

#define XP (_WIN32_WINNT < _WIN32_WINNT_VISTA)

#define MB_TITLE L"Cmder Launcher"
#define SHELL_MENU_REGISTRY_PATH_BACKGROUND L"Directory\\Background\\shell\\Cmder"
#define SHELL_MENU_REGISTRY_PATH_LISTITEM L"Directory\\shell\\Cmder"

#define streqi(a, b) (_wcsicmp((a), (b)) == 0)

#define WIDEN2(x) L ## x
#define WIDEN(x) WIDEN2(x)
#define __WFUNCTION__ WIDEN(__FUNCTION__)

#define FAIL_ON_ERROR(x) { DWORD ec; if ((ec = (x)) != ERROR_SUCCESS) { ShowErrorAndExit(ec, __WFUNCTION__, __LINE__); } }

void ShowErrorAndExit(DWORD ec, const wchar_t * func, int line)
{
	wchar_t * buffer;
	if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
		NULL, ec, 0, (LPWSTR) &buffer, 0, NULL) == 0)
	{
		buffer = L"Unknown error. FormatMessage failed.";
	}

	wchar_t message[1024];
	swprintf_s(message, L"%s\nFunction: %s\nLine: %d", buffer, func, line);
	LocalFree(buffer);

	MessageBox(NULL, message, MB_TITLE, MB_OK | MB_ICONERROR);
	exit(1);
}

typedef struct _option
{
	std::wstring name;
	bool hasVal;
	std::wstring value;
	bool set;
} option;

typedef std::pair<std::wstring, std::wstring> optpair;

optpair GetOption()
{
	wchar_t * cmd = GetCommandLine();
	int argc;
	wchar_t ** argv = CommandLineToArgvW(cmd, &argc);
	optpair pair;

	if (argc == 1)
	{
		// no commandline argument...
		pair = optpair(L"/START", L"");
	}
	else if (argc == 2 && argv[1][0] != L'/')
	{
		// only a single argument: this should be a path...
		pair = optpair(L"/START", argv[1]);
	}
	else
	{
		pair = optpair(argv[1], argc > 2 ? argv[2] : L"");
	}

	LocalFree(argv);

	return pair;
}

bool FileExists(const wchar_t * filePath)
{
	HANDLE hFile = CreateFile(filePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);

	if (hFile != INVALID_HANDLE_VALUE)
	{
		CloseHandle(hFile);
		return true;
	}

	return false;
}

void StartCmder(std::wstring path, bool is_single_mode)
{
#if USE_TASKBAR_API
	wchar_t appId[MAX_PATH] = { 0 };
#endif
	wchar_t exeDir[MAX_PATH] = { 0 };
	wchar_t icoPath[MAX_PATH] = { 0 };
	wchar_t cfgPath[MAX_PATH] = { 0 };
	wchar_t oldCfgPath[MAX_PATH] = { 0 };
	wchar_t conEmuPath[MAX_PATH] = { 0 };
	wchar_t args[MAX_PATH * 2 + 256] = { 0 };

	GetModuleFileName(NULL, exeDir, sizeof(exeDir));

#if USE_TASKBAR_API
	wcscpy_s(appId, exeDir);
#endif

	PathRemoveFileSpec(exeDir);

	PathCombine(icoPath, exeDir, L"icons\\cmder.ico");

	// Check for machine-specific config file.
	PathCombine(cpuCfgPath, exeDir, L"config\\ConEmu-%COMPUTERNAME%.xml");
	ExpandEnvironmentStrings(cpuCfgPath, cpuCfgPath, sizeof(cpuCfgPath) / sizeof(cpuCfgPath[0]));

	// Check for user-specific config file.
	PathCombine(userCfgPath, exeDir, L"config\\user-ConEmu.xml");

  if (PathFileExists(cpuCfgPath)) {
		PathCombine(oldCfgPath, exeDir, cpuCfgPath.GetBuffer(sizeof(cpuCfgPath)));
  }
  else if (!PathFileExists(userCfgPath)) {
		PathCombine(oldCfgPath, exeDir, userCfgPath.GetBuffer(sizeof(userCfgPath)));
  }
  else {
		PathCombine(oldCfgPath, exeDir, L"config\\ConEmu.xml");
  }

	// Check for machine-specific config file.
	PathCombine(cfgPath, exeDir, oldCfgPath.GetBufer(sizeof(oldCfgPath);
	// ExpandEnvironmentStrings(cfgPath, cfgPath, sizeof(cfgPath) / sizeof(cfgPath[0]));
	if (!PathFileExists(cfgPath)) {
		PathCombine(cfgPath, exeDir, L"vendor\\conemu-maximus5\\ConEmu.xml");
	}

	SYSTEM_INFO sysInfo;
	GetNativeSystemInfo(&sysInfo);
	if (sysInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) {
		PathCombine(conEmuPath, exeDir, L"vendor\\conemu-maximus5\\ConEmu64.exe");
	}
	else {
		PathCombine(conEmuPath, exeDir, L"vendor\\conemu-maximus5\\ConEmu.exe");
	}

	if (FileExists(oldCfgPath) && !FileExists(cfgPath))
	{
		if (!CopyFile(oldCfgPath, cfgPath, FALSE))
		{
			MessageBox(NULL,
				(GetLastError() == ERROR_ACCESS_DENIED)
				? L"Failed to copy ConEmu.xml file to new location! Restart cmder as administrator."
				: L"Failed to copy ConEmu.xml file to new location!", MB_TITLE, MB_ICONSTOP);
			exit(1);
		}
	}

	if (is_single_mode)
	{
		swprintf_s(args, L"/single /Icon \"%s\" /Title Cmder", icoPath);
	}
	else
	{
		swprintf_s(args, L"/Icon \"%s\" /Title Cmder", icoPath);
	}

	SetEnvironmentVariable(L"CMDER_ROOT", exeDir);
	if (!streqi(path.c_str(), L""))
	{
		if (!SetEnvironmentVariable(L"CMDER_START", path.c_str())) {
			MessageBox(NULL, _T("Error trying to set CMDER_START to given path!"), _T("Error"), MB_OK);
		}
	}
	// Ensure EnvironmentVariables are propagated.
	SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, 0, (LPARAM)"Environment", SMTO_ABORTIFHUNG, 5000, NULL);
	SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, 0, (LPARAM) L"Environment", SMTO_ABORTIFHUNG, 5000, NULL); // For Windows >= 8

	STARTUPINFO si = { 0 };
	si.cb = sizeof(STARTUPINFO);
#if USE_TASKBAR_API
	si.lpTitle = appId;
	si.dwFlags = STARTF_TITLEISAPPID;
#endif

	PROCESS_INFORMATION pi;
	if (!CreateProcess(conEmuPath, args, NULL, NULL, false, 0, NULL, NULL, &si, &pi)) {
		MessageBox(NULL, _T("Unable to create the ConEmu Process!"), _T("Error"), MB_OK);
		return;
	}
}

bool IsUserOnly(std::wstring opt)
{
	bool userOnly;

	if (streqi(opt.c_str(), L"ALL"))
	{
		userOnly = false;
	}
	else if (streqi(opt.c_str(), L"USER"))
	{
		userOnly = true;
	}
	else
	{
		MessageBox(NULL, L"Unrecognized option for /REGISTER or /UNREGISTER. Must be either ALL or USER.", MB_TITLE, MB_OK);
		exit(1);
	}

	return userOnly;
}

HKEY GetRootKey(std::wstring opt)
{
	HKEY root;

	if (IsUserOnly(opt))
	{
		FAIL_ON_ERROR(RegCreateKeyEx(HKEY_CURRENT_USER, L"Software\\Classes", 0, NULL,
			REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &root, NULL));
	}
	else
	{
		root = HKEY_CLASSES_ROOT;
	}

	return root;
}

void RegisterShellMenu(std::wstring opt, wchar_t* keyBaseName)
{
	// First, get the paths we will use

	wchar_t exePath[MAX_PATH] = { 0 };
	wchar_t icoPath[MAX_PATH] = { 0 };

	GetModuleFileName(NULL, exePath, sizeof(exePath));

	wchar_t commandStr[MAX_PATH + 20] = { 0 };
	swprintf_s(commandStr, L"\"%s\" \"%%V\"", exePath);

	// Now that we have `commandStr`, it's OK to change `exePath`...
	PathRemoveFileSpec(exePath);

	PathCombine(icoPath, exePath, L"icons\\cmder.ico");

	// Now set the registry keys

	HKEY root = GetRootKey(opt);

	HKEY cmderKey;
	FAIL_ON_ERROR(
		RegCreateKeyEx(root, keyBaseName, 0, NULL,
		REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &cmderKey, NULL));

	FAIL_ON_ERROR(RegSetValue(cmderKey, L"", REG_SZ, L"Cmder Here", NULL));
	FAIL_ON_ERROR(RegSetValueEx(cmderKey, L"NoWorkingDirectory", 0, REG_SZ, (BYTE *)L"", 2));

	FAIL_ON_ERROR(RegSetValueEx(cmderKey, L"Icon", 0, REG_SZ, (BYTE *)icoPath, wcslen(icoPath) * sizeof(wchar_t)));

	HKEY command;
	FAIL_ON_ERROR(
		RegCreateKeyEx(cmderKey, L"command", 0, NULL,
		REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &command, NULL));

	FAIL_ON_ERROR(RegSetValue(command, L"", REG_SZ, commandStr, NULL));

	RegCloseKey(command);
	RegCloseKey(cmderKey);
	RegCloseKey(root);
}

void UnregisterShellMenu(std::wstring opt, wchar_t* keyBaseName)
{
	HKEY root = GetRootKey(opt);
	HKEY cmderKey;
	FAIL_ON_ERROR(
		RegCreateKeyEx(root, keyBaseName, 0, NULL,
		REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &cmderKey, NULL));
#if XP
	FAIL_ON_ERROR(SHDeleteKey(cmderKey, NULL));
#else
	FAIL_ON_ERROR(RegDeleteTree(cmderKey, NULL));
#endif
	RegCloseKey(cmderKey);
	RegCloseKey(root);
}

int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
	_In_opt_ HINSTANCE hPrevInstance,
	_In_ LPTSTR    lpCmdLine,
	_In_ int       nCmdShow)
{
	UNREFERENCED_PARAMETER(hPrevInstance);
	UNREFERENCED_PARAMETER(lpCmdLine);
	UNREFERENCED_PARAMETER(nCmdShow);

	optpair opt = GetOption();

	if (streqi(opt.first.c_str(), L"/START"))
	{
		StartCmder(opt.second, false);
	}
	else if (streqi(opt.first.c_str(), L"/SINGLE"))
	{
		StartCmder(opt.second, true);
	}
	else if (streqi(opt.first.c_str(), L"/REGISTER"))
	{
		RegisterShellMenu(opt.second, SHELL_MENU_REGISTRY_PATH_BACKGROUND);
		RegisterShellMenu(opt.second, SHELL_MENU_REGISTRY_PATH_LISTITEM);
	}
	else if (streqi(opt.first.c_str(), L"/UNREGISTER"))
	{
		UnregisterShellMenu(opt.second, SHELL_MENU_REGISTRY_PATH_BACKGROUND);
		UnregisterShellMenu(opt.second, SHELL_MENU_REGISTRY_PATH_LISTITEM);
	}
	else
	{
		MessageBox(NULL, L"Unrecognized parameter.\n\nValid options:\n  /START <path>\n  /SINGLE <path>\n  /REGISTER [USER/ALL]\n  /UNREGISTER [USER/ALL]", MB_TITLE, MB_OK);
		return 1;
	}

	return 0;
}
<commit_msg>added ability to have a user-ConEmu.xml file in addition to the computer specific and default ConEmu.xml files<commit_after>#include <windows.h>
#include <tchar.h>
#include <Shlwapi.h>
#include "resource.h"
#include <vector>

#pragma comment(lib, "Shlwapi.lib")

#ifndef UNICODE
#error "Must be compiled with unicode support."
#endif

#define USE_TASKBAR_API (_WIN32_WINNT >= _WIN32_WINNT_WIN7)

#define XP (_WIN32_WINNT < _WIN32_WINNT_VISTA)

#define MB_TITLE L"Cmder Launcher"
#define SHELL_MENU_REGISTRY_PATH_BACKGROUND L"Directory\\Background\\shell\\Cmder"
#define SHELL_MENU_REGISTRY_PATH_LISTITEM L"Directory\\shell\\Cmder"

#define streqi(a, b) (_wcsicmp((a), (b)) == 0)

#define WIDEN2(x) L ## x
#define WIDEN(x) WIDEN2(x)
#define __WFUNCTION__ WIDEN(__FUNCTION__)

#define FAIL_ON_ERROR(x) { DWORD ec; if ((ec = (x)) != ERROR_SUCCESS) { ShowErrorAndExit(ec, __WFUNCTION__, __LINE__); } }

void ShowErrorAndExit(DWORD ec, const wchar_t * func, int line)
{
	wchar_t * buffer;
	if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
		NULL, ec, 0, (LPWSTR) &buffer, 0, NULL) == 0)
	{
		buffer = L"Unknown error. FormatMessage failed.";
	}

	wchar_t message[1024];
	swprintf_s(message, L"%s\nFunction: %s\nLine: %d", buffer, func, line);
	LocalFree(buffer);

	MessageBox(NULL, message, MB_TITLE, MB_OK | MB_ICONERROR);
	exit(1);
}

typedef struct _option
{
	std::wstring name;
	bool hasVal;
	std::wstring value;
	bool set;
} option;

typedef std::pair<std::wstring, std::wstring> optpair;

optpair GetOption()
{
	wchar_t * cmd = GetCommandLine();
	int argc;
	wchar_t ** argv = CommandLineToArgvW(cmd, &argc);
	optpair pair;

	if (argc == 1)
	{
		// no commandline argument...
		pair = optpair(L"/START", L"");
	}
	else if (argc == 2 && argv[1][0] != L'/')
	{
		// only a single argument: this should be a path...
		pair = optpair(L"/START", argv[1]);
	}
	else
	{
		pair = optpair(argv[1], argc > 2 ? argv[2] : L"");
	}

	LocalFree(argv);

	return pair;
}

bool FileExists(const wchar_t * filePath)
{
	HANDLE hFile = CreateFile(filePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);

	if (hFile != INVALID_HANDLE_VALUE)
	{
		CloseHandle(hFile);
		return true;
	}

	return false;
}

void StartCmder(std::wstring path, bool is_single_mode)
{
#if USE_TASKBAR_API
	wchar_t appId[MAX_PATH] = { 0 };
#endif
	wchar_t exeDir[MAX_PATH] = { 0 };
	wchar_t icoPath[MAX_PATH] = { 0 };
	wchar_t cfgPath[MAX_PATH] = { 0 };
	wchar_t cpuCfgPath[MAX_PATH] = { 0 };
	wchar_t userCfgPath[MAX_PATH] = { 0 };
	wchar_t oldCfgPath[MAX_PATH] = { 0 };
	wchar_t conEmuPath[MAX_PATH] = { 0 };
	wchar_t args[MAX_PATH * 2 + 256] = { 0 };

	GetModuleFileName(NULL, exeDir, sizeof(exeDir));

#if USE_TASKBAR_API
	wcscpy_s(appId, exeDir);
#endif

	PathRemoveFileSpec(exeDir);

	PathCombine(icoPath, exeDir, L"icons\\cmder.ico");

	// Check for machine-specific then user config source file.
	PathCombine(cpuCfgPath, exeDir, L"config\\ConEmu-%COMPUTERNAME%.xml");
	ExpandEnvironmentStrings(cpuCfgPath, cpuCfgPath, sizeof(cpuCfgPath) / sizeof(cpuCfgPath[0]));

	PathCombine(userCfgPath, exeDir, L"config\\user-ConEmu.xml");

	if (PathFileExists(cpuCfgPath)) {
		wcsncpy_s(oldCfgPath, cpuCfgPath, sizeof(cpuCfgPath));
	}
	else if (PathFileExists(userCfgPath)) {
		wcsncpy_s(oldCfgPath, userCfgPath,sizeof(userCfgPath));
	}
	else {
		PathCombine(oldCfgPath, exeDir, L"config\\ConEmu.xml");
	}

	// Set path to vendored ConEmu config file
	PathCombine(cfgPath, exeDir, L"vendor\\conemu-maximus5\\ConEmu.xml");

	SYSTEM_INFO sysInfo;
	GetNativeSystemInfo(&sysInfo);
	if (sysInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) {
		PathCombine(conEmuPath, exeDir, L"vendor\\conemu-maximus5\\ConEmu64.exe");
	}
	else {
		PathCombine(conEmuPath, exeDir, L"vendor\\conemu-maximus5\\ConEmu.exe");
	}

	if (FileExists(oldCfgPath) && !FileExists(cfgPath))
	{
		if (!CopyFile(oldCfgPath, cfgPath, FALSE))
		{
			MessageBox(NULL,
				(GetLastError() == ERROR_ACCESS_DENIED)
				? L"Failed to copy ConEmu.xml file to new location! Restart cmder as administrator."
				: L"Failed to copy ConEmu.xml file to new location!", MB_TITLE, MB_ICONSTOP);
			exit(1);
		}
	}

	if (is_single_mode)
	{
		swprintf_s(args, L"/single /Icon \"%s\" /Title Cmder", icoPath);
	}
	else
	{
		swprintf_s(args, L"/Icon \"%s\" /Title Cmder", icoPath);
	}

	SetEnvironmentVariable(L"CMDER_ROOT", exeDir);
	if (!streqi(path.c_str(), L""))
	{
		if (!SetEnvironmentVariable(L"CMDER_START", path.c_str())) {
			MessageBox(NULL, _T("Error trying to set CMDER_START to given path!"), _T("Error"), MB_OK);
		}
	}
	// Ensure EnvironmentVariables are propagated.
	SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, 0, (LPARAM)"Environment", SMTO_ABORTIFHUNG, 5000, NULL);
	SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, 0, (LPARAM) L"Environment", SMTO_ABORTIFHUNG, 5000, NULL); // For Windows >= 8

	STARTUPINFO si = { 0 };
	si.cb = sizeof(STARTUPINFO);
#if USE_TASKBAR_API
	si.lpTitle = appId;
	si.dwFlags = STARTF_TITLEISAPPID;
#endif

	PROCESS_INFORMATION pi;
	if (!CreateProcess(conEmuPath, args, NULL, NULL, false, 0, NULL, NULL, &si, &pi)) {
		MessageBox(NULL, _T("Unable to create the ConEmu Process!"), _T("Error"), MB_OK);
		return;
	}
}

bool IsUserOnly(std::wstring opt)
{
	bool userOnly;

	if (streqi(opt.c_str(), L"ALL"))
	{
		userOnly = false;
	}
	else if (streqi(opt.c_str(), L"USER"))
	{
		userOnly = true;
	}
	else
	{
		MessageBox(NULL, L"Unrecognized option for /REGISTER or /UNREGISTER. Must be either ALL or USER.", MB_TITLE, MB_OK);
		exit(1);
	}

	return userOnly;
}

HKEY GetRootKey(std::wstring opt)
{
	HKEY root;

	if (IsUserOnly(opt))
	{
		FAIL_ON_ERROR(RegCreateKeyEx(HKEY_CURRENT_USER, L"Software\\Classes", 0, NULL,
			REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &root, NULL));
	}
	else
	{
		root = HKEY_CLASSES_ROOT;
	}

	return root;
}

void RegisterShellMenu(std::wstring opt, wchar_t* keyBaseName)
{
	// First, get the paths we will use

	wchar_t exePath[MAX_PATH] = { 0 };
	wchar_t icoPath[MAX_PATH] = { 0 };

	GetModuleFileName(NULL, exePath, sizeof(exePath));

	wchar_t commandStr[MAX_PATH + 20] = { 0 };
	swprintf_s(commandStr, L"\"%s\" \"%%V\"", exePath);

	// Now that we have `commandStr`, it's OK to change `exePath`...
	PathRemoveFileSpec(exePath);

	PathCombine(icoPath, exePath, L"icons\\cmder.ico");

	// Now set the registry keys

	HKEY root = GetRootKey(opt);

	HKEY cmderKey;
	FAIL_ON_ERROR(
		RegCreateKeyEx(root, keyBaseName, 0, NULL,
		REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &cmderKey, NULL));

	FAIL_ON_ERROR(RegSetValue(cmderKey, L"", REG_SZ, L"Cmder Here", NULL));
	FAIL_ON_ERROR(RegSetValueEx(cmderKey, L"NoWorkingDirectory", 0, REG_SZ, (BYTE *)L"", 2));

	FAIL_ON_ERROR(RegSetValueEx(cmderKey, L"Icon", 0, REG_SZ, (BYTE *)icoPath, wcslen(icoPath) * sizeof(wchar_t)));

	HKEY command;
	FAIL_ON_ERROR(
		RegCreateKeyEx(cmderKey, L"command", 0, NULL,
		REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &command, NULL));

	FAIL_ON_ERROR(RegSetValue(command, L"", REG_SZ, commandStr, NULL));

	RegCloseKey(command);
	RegCloseKey(cmderKey);
	RegCloseKey(root);
}

void UnregisterShellMenu(std::wstring opt, wchar_t* keyBaseName)
{
	HKEY root = GetRootKey(opt);
	HKEY cmderKey;
	FAIL_ON_ERROR(
		RegCreateKeyEx(root, keyBaseName, 0, NULL,
		REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &cmderKey, NULL));
#if XP
	FAIL_ON_ERROR(SHDeleteKey(cmderKey, NULL));
#else
	FAIL_ON_ERROR(RegDeleteTree(cmderKey, NULL));
#endif
	RegCloseKey(cmderKey);
	RegCloseKey(root);
}

int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
	_In_opt_ HINSTANCE hPrevInstance,
	_In_ LPTSTR    lpCmdLine,
	_In_ int       nCmdShow)
{
	UNREFERENCED_PARAMETER(hPrevInstance);
	UNREFERENCED_PARAMETER(lpCmdLine);
	UNREFERENCED_PARAMETER(nCmdShow);

	optpair opt = GetOption();

	if (streqi(opt.first.c_str(), L"/START"))
	{
		StartCmder(opt.second, false);
	}
	else if (streqi(opt.first.c_str(), L"/SINGLE"))
	{
		StartCmder(opt.second, true);
	}
	else if (streqi(opt.first.c_str(), L"/REGISTER"))
	{
		RegisterShellMenu(opt.second, SHELL_MENU_REGISTRY_PATH_BACKGROUND);
		RegisterShellMenu(opt.second, SHELL_MENU_REGISTRY_PATH_LISTITEM);
	}
	else if (streqi(opt.first.c_str(), L"/UNREGISTER"))
	{
		UnregisterShellMenu(opt.second, SHELL_MENU_REGISTRY_PATH_BACKGROUND);
		UnregisterShellMenu(opt.second, SHELL_MENU_REGISTRY_PATH_LISTITEM);
	}
	else
	{
		MessageBox(NULL, L"Unrecognized parameter.\n\nValid options:\n  /START <path>\n  /SINGLE <path>\n  /REGISTER [USER/ALL]\n  /UNREGISTER [USER/ALL]", MB_TITLE, MB_OK);
		return 1;
	}

	return 0;
}
<|endoftext|>


<commit_before><commit_msg>Removed unnecessary `#include` line.<commit_after><|endoftext|>