<commit_before>/* BEGIN_COMMON_COPYRIGHT_HEADER
 * (c)LGPL2+
 *
 * LXQt - a lightweight, Qt based, desktop toolset
 *
 * Authors:
 *   Christian Surlykke <christian@surlykke.dk>
 *
 * This program or library is free software; you can redistribute it
 * and/or modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.

 * You should have received a copy of the GNU Lesser General
 * Public License along with this library; if not, write to the
 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301 USA
 *
 * END_COMMON_COPYRIGHT_HEADER */

#include <QDebug>
#include <QStringList>
#include <QProcess>

#include "batteryhelper.h"
#include "powermanagementd.h"
#include "../config/powermanagementsettings.h"
#include "idlenesswatcher.h"
#include "lidwatcher.h"
#include "batterywatcher.h"
#include "powerbutton.h"

#include <LXQt/Globals>

#define CURRENT_RUNCHECK_LEVEL 1

PowerManagementd::PowerManagementd() :
        mBatterywatcherd(nullptr),
        mLidwatcherd(nullptr),
        mIdlenesswatcherd(nullptr),
        mSettings()
 {
    connect(&mSettings, SIGNAL(settingsChanged()), this, SLOT(settingsChanged()));
    settingsChanged();

    if (mSettings.getRunCheckLevel() < CURRENT_RUNCHECK_LEVEL)
    {
        performRunCheck();
        mSettings.setRunCheckLevel(CURRENT_RUNCHECK_LEVEL);
    }

    mPowerButton = new PowerButton(this);
}

PowerManagementd::~PowerManagementd()
{
}

void PowerManagementd::settingsChanged()
{
    if (mSettings.isBatteryWatcherEnabled() && !mBatterywatcherd)
        mBatterywatcherd = new BatteryWatcher(this);
    else if (mBatterywatcherd && ! mSettings.isBatteryWatcherEnabled())
    {
        mBatterywatcherd->deleteLater();
        mBatterywatcherd = nullptr;
    }

    if (mSettings.isLidWatcherEnabled() && !mLidwatcherd)
    {
        mLidwatcherd = new LidWatcher(this);
    }
    else if (mLidwatcherd && ! mSettings.isLidWatcherEnabled())
    {
        mLidwatcherd->deleteLater();
        mLidwatcherd = nullptr;
    }

    if (mSettings.isIdlenessWatcherEnabled() && !mIdlenesswatcherd)
    {
        mIdlenesswatcherd = new IdlenessWatcher(this);
    }
    else if (mIdlenesswatcherd && !mSettings.isIdlenessWatcherEnabled())
    {
        mIdlenesswatcherd->deleteLater();
        mIdlenesswatcherd = nullptr;
    }

}

void PowerManagementd::runConfigure()
{
    mNotification.close();
    QProcess::startDetached(QSL("lxqt-config-powermanagement"));
}

void PowerManagementd::performRunCheck()
{
    mSettings.setLidWatcherEnabled(Lid().haveLid());
    bool hasBattery = false;

    const auto devices = Solid::Device::listFromType(Solid::DeviceInterface::Battery, QString());
    for (const Solid::Device& device : devices)
        if (device.as<Solid::Battery>()->type() == Solid::Battery::PrimaryBattery)
            hasBattery = true;
    mSettings.setBatteryWatcherEnabled(hasBattery);
    mSettings.setIdlenessWatcherEnabled(true);
    mSettings.sync();

    mNotification.setSummary(tr("Power Management"));
    mNotification.setBody(tr("You are running LXQt Power Management for the first time.\nYou can configure it from settings... "));
    mNotification.setActions(QStringList() << tr("Configure..."));
    mNotification.setTimeout(10000);
    connect(&mNotification, SIGNAL(actionActivated(int)), SLOT(runConfigure()));
    mNotification.update();
}
<commit_msg>Handle Qt 5.15 deprecations<commit_after>/* BEGIN_COMMON_COPYRIGHT_HEADER
 * (c)LGPL2+
 *
 * LXQt - a lightweight, Qt based, desktop toolset
 *
 * Authors:
 *   Christian Surlykke <christian@surlykke.dk>
 *
 * This program or library is free software; you can redistribute it
 * and/or modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.

 * You should have received a copy of the GNU Lesser General
 * Public License along with this library; if not, write to the
 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301 USA
 *
 * END_COMMON_COPYRIGHT_HEADER */

#include <QDebug>
#include <QStringList>
#include <QProcess>

#include "batteryhelper.h"
#include "powermanagementd.h"
#include "../config/powermanagementsettings.h"
#include "idlenesswatcher.h"
#include "lidwatcher.h"
#include "batterywatcher.h"
#include "powerbutton.h"

#include <LXQt/Globals>

#define CURRENT_RUNCHECK_LEVEL 1

PowerManagementd::PowerManagementd() :
        mBatterywatcherd(nullptr),
        mLidwatcherd(nullptr),
        mIdlenesswatcherd(nullptr),
        mSettings()
 {
    connect(&mSettings, SIGNAL(settingsChanged()), this, SLOT(settingsChanged()));
    settingsChanged();

    if (mSettings.getRunCheckLevel() < CURRENT_RUNCHECK_LEVEL)
    {
        performRunCheck();
        mSettings.setRunCheckLevel(CURRENT_RUNCHECK_LEVEL);
    }

    mPowerButton = new PowerButton(this);
}

PowerManagementd::~PowerManagementd()
{
}

void PowerManagementd::settingsChanged()
{
    if (mSettings.isBatteryWatcherEnabled() && !mBatterywatcherd)
        mBatterywatcherd = new BatteryWatcher(this);
    else if (mBatterywatcherd && ! mSettings.isBatteryWatcherEnabled())
    {
        mBatterywatcherd->deleteLater();
        mBatterywatcherd = nullptr;
    }

    if (mSettings.isLidWatcherEnabled() && !mLidwatcherd)
    {
        mLidwatcherd = new LidWatcher(this);
    }
    else if (mLidwatcherd && ! mSettings.isLidWatcherEnabled())
    {
        mLidwatcherd->deleteLater();
        mLidwatcherd = nullptr;
    }

    if (mSettings.isIdlenessWatcherEnabled() && !mIdlenesswatcherd)
    {
        mIdlenesswatcherd = new IdlenessWatcher(this);
    }
    else if (mIdlenesswatcherd && !mSettings.isIdlenessWatcherEnabled())
    {
        mIdlenesswatcherd->deleteLater();
        mIdlenesswatcherd = nullptr;
    }

}

void PowerManagementd::runConfigure()
{
    mNotification.close();
    QProcess::startDetached(QSL("lxqt-config-powermanagement"), QStringList());
}

void PowerManagementd::performRunCheck()
{
    mSettings.setLidWatcherEnabled(Lid().haveLid());
    bool hasBattery = false;

    const auto devices = Solid::Device::listFromType(Solid::DeviceInterface::Battery, QString());
    for (const Solid::Device& device : devices)
        if (device.as<Solid::Battery>()->type() == Solid::Battery::PrimaryBattery)
            hasBattery = true;
    mSettings.setBatteryWatcherEnabled(hasBattery);
    mSettings.setIdlenessWatcherEnabled(true);
    mSettings.sync();

    mNotification.setSummary(tr("Power Management"));
    mNotification.setBody(tr("You are running LXQt Power Management for the first time.\nYou can configure it from settings... "));
    mNotification.setActions(QStringList() << tr("Configure..."));
    mNotification.setTimeout(10000);
    connect(&mNotification, SIGNAL(actionActivated(int)), SLOT(runConfigure()));
    mNotification.update();
}
<|endoftext|>


<commit_before>// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2014 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "primitives/block.h"

#include "hash.h"
#include "tinyformat.h"
#include "utilstrencodings.h"
#include "crypto/common.h"

uint256 CBlockHeader::GetHash() const
{
#if defined(WORDS_BIGENDIAN)
    uint8_t data[80];
    WriteLE32(&data[0], nVersion);
    memcpy(&data[4], hashPrevBlock.begin(), hashPrevBlock.size());
    memcpy(&data[36], hashMerkleRoot.begin(), hashMerkleRoot.size());
    WriteLE32(&data[68], nTime);
    WriteLE32(&data[72], nBits);
    WriteLE32(&data[76], nNonce);
    return Hash(data, data + 80);
#else // Can take shortcut for little endian
    return Hash(BEGIN(nVersion), END(nNonce));
#endif
}

uint256 CBlock::BuildMerkleTree(bool* fMutated) const
{
    /* WARNING! If you're reading this because you're learning about crypto
       and/or designing a new system that will use merkle trees, keep in mind
       that the following merkle tree algorithm has a serious flaw related to
       duplicate txids, resulting in a vulnerability (CVE-2012-2459).

       The reason is that if the number of hashes in the list at a given time
       is odd, the last one is duplicated before computing the next level (which
       is unusual in Merkle trees). This results in certain sequences of
       transactions leading to the same merkle root. For example, these two
       trees:

                    A               A
                  /  \            /   \
                B     C         B       C
               / \    |        / \     / \
              D   E   F       D   E   F   F
             / \ / \ / \     / \ / \ / \ / \
             1 2 3 4 5 6     1 2 3 4 5 6 5 6

       for transaction lists [1,2,3,4,5,6] and [1,2,3,4,5,6,5,6] (where 5 and
       6 are repeated) result in the same root hash A (because the hash of both
       of (F) and (F,F) is C).

       The vulnerability results from being able to send a block with such a
       transaction list, with the same merkle root, and the same block hash as
       the original without duplication, resulting in failed validation. If the
       receiving node proceeds to mark that block as permanently invalid
       however, it will fail to accept further unmodified (and thus potentially
       valid) versions of the same block. We defend against this by detecting
       the case where we would hash two identical hashes at the end of the list
       together, and treating that identically to the block having an invalid
       merkle root. Assuming no double-SHA256 collisions, this will detect all
       known ways of changing the transactions without affecting the merkle
       root.
    */
    vMerkleTree.clear();
    vMerkleTree.reserve(vtx.size() * 2 + 16); // Safe upper bound for the number of total nodes.
    for (std::vector<CTransaction>::const_iterator it(vtx.begin()); it != vtx.end(); ++it)
        vMerkleTree.push_back(it->GetHash());
    int j = 0;
    bool mutated = false;
    for (int nSize = vtx.size(); nSize > 1; nSize = (nSize + 1) / 2)
    {
        for (int i = 0; i < nSize; i += 2)
        {
            int i2 = std::min(i+1, nSize-1);
            if (i2 == i + 1 && i2 + 1 == nSize && vMerkleTree[j+i] == vMerkleTree[j+i2]) {
                // Two identical hashes at the end of the list at a particular level.
                mutated = true;
            }
            vMerkleTree.push_back(Hash(BEGIN(vMerkleTree[j+i]),  END(vMerkleTree[j+i]),
                                       BEGIN(vMerkleTree[j+i2]), END(vMerkleTree[j+i2])));
        }
        j += nSize;
    }
    if (fMutated) {
        *fMutated = mutated;
    }
    return (vMerkleTree.empty() ? uint256() : vMerkleTree.back());
}

std::vector<uint256> CBlock::GetMerkleBranch(int nIndex) const
{
    if (vMerkleTree.empty())
        BuildMerkleTree();
    std::vector<uint256> vMerkleBranch;
    int j = 0;
    for (int nSize = vtx.size(); nSize > 1; nSize = (nSize + 1) / 2)
    {
        int i = std::min(nIndex^1, nSize-1);
        vMerkleBranch.push_back(vMerkleTree[j+i]);
        nIndex >>= 1;
        j += nSize;
    }
    return vMerkleBranch;
}

uint256 CBlock::CheckMerkleBranch(uint256 hash, const std::vector<uint256>& vMerkleBranch, int nIndex)
{
    if (nIndex == -1)
        return uint256();
    for (std::vector<uint256>::const_iterator it(vMerkleBranch.begin()); it != vMerkleBranch.end(); ++it)
    {
        if (nIndex & 1)
            hash = Hash(BEGIN(*it), END(*it), BEGIN(hash), END(hash));
        else
            hash = Hash(BEGIN(hash), END(hash), BEGIN(*it), END(*it));
        nIndex >>= 1;
    }
    return hash;
}

std::string CBlock::ToString() const
{
    std::stringstream s;
    s << strprintf("CBlock(hash=%s, ver=%d, hashPrevBlock=%s, hashMerkleRoot=%s, nTime=%u, nBits=%08x, nNonce=%u, vtx=%u)\n",
        GetHash().ToString(),
        nVersion,
        hashPrevBlock.ToString(),
        hashMerkleRoot.ToString(),
        nTime, nBits, nNonce,
        vtx.size());
    for (unsigned int i = 0; i < vtx.size(); i++)
    {
        s << "  " << vtx[i].ToString() << "\n";
    }
    s << "  vMerkleTree: ";
    for (unsigned int i = 0; i < vMerkleTree.size(); i++)
        s << " " << vMerkleTree[i].ToString();
    s << "\n";
    return s.str();
}
<commit_msg>Replace CBlockHeader::GetHash with call to SerializeHash<commit_after>// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2014 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "primitives/block.h"

#include "hash.h"
#include "tinyformat.h"
#include "utilstrencodings.h"
#include "crypto/common.h"

uint256 CBlockHeader::GetHash() const
{
    return SerializeHash(*this);
}

uint256 CBlock::BuildMerkleTree(bool* fMutated) const
{
    /* WARNING! If you're reading this because you're learning about crypto
       and/or designing a new system that will use merkle trees, keep in mind
       that the following merkle tree algorithm has a serious flaw related to
       duplicate txids, resulting in a vulnerability (CVE-2012-2459).

       The reason is that if the number of hashes in the list at a given time
       is odd, the last one is duplicated before computing the next level (which
       is unusual in Merkle trees). This results in certain sequences of
       transactions leading to the same merkle root. For example, these two
       trees:

                    A               A
                  /  \            /   \
                B     C         B       C
               / \    |        / \     / \
              D   E   F       D   E   F   F
             / \ / \ / \     / \ / \ / \ / \
             1 2 3 4 5 6     1 2 3 4 5 6 5 6

       for transaction lists [1,2,3,4,5,6] and [1,2,3,4,5,6,5,6] (where 5 and
       6 are repeated) result in the same root hash A (because the hash of both
       of (F) and (F,F) is C).

       The vulnerability results from being able to send a block with such a
       transaction list, with the same merkle root, and the same block hash as
       the original without duplication, resulting in failed validation. If the
       receiving node proceeds to mark that block as permanently invalid
       however, it will fail to accept further unmodified (and thus potentially
       valid) versions of the same block. We defend against this by detecting
       the case where we would hash two identical hashes at the end of the list
       together, and treating that identically to the block having an invalid
       merkle root. Assuming no double-SHA256 collisions, this will detect all
       known ways of changing the transactions without affecting the merkle
       root.
    */
    vMerkleTree.clear();
    vMerkleTree.reserve(vtx.size() * 2 + 16); // Safe upper bound for the number of total nodes.
    for (std::vector<CTransaction>::const_iterator it(vtx.begin()); it != vtx.end(); ++it)
        vMerkleTree.push_back(it->GetHash());
    int j = 0;
    bool mutated = false;
    for (int nSize = vtx.size(); nSize > 1; nSize = (nSize + 1) / 2)
    {
        for (int i = 0; i < nSize; i += 2)
        {
            int i2 = std::min(i+1, nSize-1);
            if (i2 == i + 1 && i2 + 1 == nSize && vMerkleTree[j+i] == vMerkleTree[j+i2]) {
                // Two identical hashes at the end of the list at a particular level.
                mutated = true;
            }
            vMerkleTree.push_back(Hash(BEGIN(vMerkleTree[j+i]),  END(vMerkleTree[j+i]),
                                       BEGIN(vMerkleTree[j+i2]), END(vMerkleTree[j+i2])));
        }
        j += nSize;
    }
    if (fMutated) {
        *fMutated = mutated;
    }
    return (vMerkleTree.empty() ? uint256() : vMerkleTree.back());
}

std::vector<uint256> CBlock::GetMerkleBranch(int nIndex) const
{
    if (vMerkleTree.empty())
        BuildMerkleTree();
    std::vector<uint256> vMerkleBranch;
    int j = 0;
    for (int nSize = vtx.size(); nSize > 1; nSize = (nSize + 1) / 2)
    {
        int i = std::min(nIndex^1, nSize-1);
        vMerkleBranch.push_back(vMerkleTree[j+i]);
        nIndex >>= 1;
        j += nSize;
    }
    return vMerkleBranch;
}

uint256 CBlock::CheckMerkleBranch(uint256 hash, const std::vector<uint256>& vMerkleBranch, int nIndex)
{
    if (nIndex == -1)
        return uint256();
    for (std::vector<uint256>::const_iterator it(vMerkleBranch.begin()); it != vMerkleBranch.end(); ++it)
    {
        if (nIndex & 1)
            hash = Hash(BEGIN(*it), END(*it), BEGIN(hash), END(hash));
        else
            hash = Hash(BEGIN(hash), END(hash), BEGIN(*it), END(*it));
        nIndex >>= 1;
    }
    return hash;
}

std::string CBlock::ToString() const
{
    std::stringstream s;
    s << strprintf("CBlock(hash=%s, ver=%d, hashPrevBlock=%s, hashMerkleRoot=%s, nTime=%u, nBits=%08x, nNonce=%u, vtx=%u)\n",
        GetHash().ToString(),
        nVersion,
        hashPrevBlock.ToString(),
        hashMerkleRoot.ToString(),
        nTime, nBits, nNonce,
        vtx.size());
    for (unsigned int i = 0; i < vtx.size(); i++)
    {
        s << "  " << vtx[i].ToString() << "\n";
    }
    s << "  vMerkleTree: ";
    for (unsigned int i = 0; i < vMerkleTree.size(); i++)
        s << " " << vMerkleTree[i].ToString();
    s << "\n";
    return s.str();
}
<|endoftext|>


<commit_before>/**
 * @file findContours.cpp
 * @brief mex interface for findContours
 * @author Kota Yamaguchi
 * @date 2011
 */
#include "mexopencv.hpp"
using namespace std;
using namespace cv;

/** Mode of the contour retrieval algorithm for option processing
 */
const ConstMap<std::string,int> ContourMode = ConstMap<std::string,int>
	("External",cv::RETR_EXTERNAL)	//!< retrieve only the most external (top-level) contours
	("List",	cv::RETR_LIST)		//!< retrieve all the contours without any hierarchical information
	("CComp",	cv::RETR_CCOMP)		//!< retrieve the connected components (that can possibly be nested)
	("Tree",	cv::RETR_TREE); 	//!< retrieve all the contours and the whole hierarchy

/** Type of the contour approximation algorithm for option processing
 */
const ConstMap<std::string,int> ContourType = ConstMap<std::string,int>
	("None",		cv::CHAIN_APPROX_NONE)
	("Simple",		cv::CHAIN_APPROX_SIMPLE)
	("TC89_L1",		cv::CHAIN_APPROX_TC89_L1)
	("TC89_KCOS",	cv::CHAIN_APPROX_TC89_KCOS);

/**
 * Main entry called from Matlab
 * @param nlhs number of left-hand-side arguments
 * @param plhs pointers to mxArrays in the left-hand-side
 * @param nrhs number of right-hand-side arguments
 * @param prhs pointers to mxArrays in the right-hand-side
 */
void mexFunction( int nlhs, mxArray *plhs[],
                  int nrhs, const mxArray *prhs[] )
{
	// Check the number of arguments
	if (nrhs<1 || ((nrhs%2)!=1) || nlhs>2)
        mexErrMsgIdAndTxt("mexopencv:error","Wrong number of arguments");

	// Argument vector
	vector<MxArray> rhs(prhs,prhs+nrhs);
	Mat image(rhs[0].toMat(CV_8U));
	vector<vector<Point> > contours;
	vector<Vec4i> hierarchy;
	int mode = CV_RETR_EXTERNAL;
	int method = CV_CHAIN_APPROX_NONE;
	Point offset;
	for (int i=1; i<nrhs; i+=2) {
		string key = rhs[i].toString();
		if (key=="Mode")
			mode = ContourMode[rhs[i+1].toString()];
		else if (key=="Method")
			method = ContourType[rhs[i+1].toString()];
		else if (key=="Offset")
			offset = rhs[i+1].toPoint();
		else
			mexErrMsgIdAndTxt("mexopencv:error","Unrecognized option");
	}

	// Process
	findContours(image, contours, hierarchy, mode, method, offset);
	plhs[0] = MxArray(contours);
#if CV_MINOR_VERSION >= 2
	if (nlhs > 1) {
		vector<Mat> vc(hierarchy.size());
		for (int i=0;i<vc.size();++i)
			vc[i] = Mat(1,3,CV_32FC1,&hierarchy[i][0]);
		plhs[1] = MxArray(vc);
	}
#endif
}
<commit_msg>Fixed a bug in vector<Vec4i> conversion<commit_after>/**
 * @file findContours.cpp
 * @brief mex interface for findContours
 * @author Kota Yamaguchi
 * @date 2011
 */
#include "mexopencv.hpp"
using namespace std;
using namespace cv;

/** Mode of the contour retrieval algorithm for option processing
 */
const ConstMap<std::string,int> ContourMode = ConstMap<std::string,int>
	("External",cv::RETR_EXTERNAL)	//!< retrieve only the most external (top-level) contours
	("List",	cv::RETR_LIST)		//!< retrieve all the contours without any hierarchical information
	("CComp",	cv::RETR_CCOMP)		//!< retrieve the connected components (that can possibly be nested)
	("Tree",	cv::RETR_TREE); 	//!< retrieve all the contours and the whole hierarchy

/** Type of the contour approximation algorithm for option processing
 */
const ConstMap<std::string,int> ContourType = ConstMap<std::string,int>
	("None",		cv::CHAIN_APPROX_NONE)
	("Simple",		cv::CHAIN_APPROX_SIMPLE)
	("TC89_L1",		cv::CHAIN_APPROX_TC89_L1)
	("TC89_KCOS",	cv::CHAIN_APPROX_TC89_KCOS);

/**
 * Main entry called from Matlab
 * @param nlhs number of left-hand-side arguments
 * @param plhs pointers to mxArrays in the left-hand-side
 * @param nrhs number of right-hand-side arguments
 * @param prhs pointers to mxArrays in the right-hand-side
 */
void mexFunction( int nlhs, mxArray *plhs[],
                  int nrhs, const mxArray *prhs[] )
{
	// Check the number of arguments
	if (nrhs<1 || ((nrhs%2)!=1) || nlhs>2)
        mexErrMsgIdAndTxt("mexopencv:error","Wrong number of arguments");

	// Argument vector
	vector<MxArray> rhs(prhs,prhs+nrhs);
	Mat image(rhs[0].toMat(CV_8U));
	vector<vector<Point> > contours;
	vector<Vec4i> hierarchy;
	int mode = CV_RETR_EXTERNAL;
	int method = CV_CHAIN_APPROX_NONE;
	Point offset;
	for (int i=1; i<nrhs; i+=2) {
		string key = rhs[i].toString();
		if (key=="Mode")
			mode = ContourMode[rhs[i+1].toString()];
		else if (key=="Method")
			method = ContourType[rhs[i+1].toString()];
		else if (key=="Offset")
			offset = rhs[i+1].toPoint();
		else
			mexErrMsgIdAndTxt("mexopencv:error","Unrecognized option");
	}

	// Process
	findContours(image, contours, hierarchy, mode, method, offset);
	plhs[0] = MxArray(contours);
#if CV_MINOR_VERSION >= 2
	if (nlhs > 1) {
		vector<Mat> vc(hierarchy.size());
		for (int i=0;i<vc.size();++i)
			vc[i] = Mat(1,4,CV_32SC1,&hierarchy[i][0]);
		plhs[1] = MxArray(vc);
	}
#endif
}
<|endoftext|>


<commit_before>//!
//! @author @Yue Wang @shbling @pezy @zzzkl
//! @date   02.12.2014
//!
//! Exercise 10.18:
//! Rewrite biggies to use partition instead of find_if.
//!
//! Exercise 10.19:
//! Rewrite the previous exercise to use stable_partition, which like
//! stable_sort maintains the original element order in the paritioned
//! sequence.
//!

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>

using std::stable_sort;
using std::string;
using std::find_if;
using std::partition;

//! from ex 10.9
void elimdups(std::vector<std::string> &vs)
{
    std::sort(vs.begin(), vs.end());
    auto new_end = std::unique(vs.begin(),vs.end());
    vs.erase(new_end, vs.end());
}

//! ex10.18
void biggies_partition(std::vector<std::string> &vs, std::size_t sz)
{
    elimdups(vs);
    stable_sort(vs.begin(), vs.end(),[](string const& lhs, string const& rhs){
        return lhs.size() < rhs.size();
    });

    auto pivot = partition(vs.begin(), vs.end(),[sz](const std::string &s){
        return s.size() < sz;}
    );

    for(auto it = pivot; it != vs.cend(); ++it)
        std::cout << *it << " ";
}

//! ex10.19
void biggies_stable_partition(std::vector<std::string> &vs, std::size_t sz)
{
    elimdups(vs);
    stable_sort(vs.begin(), vs.end(),[](string const& lhs, string const& rhs){
        return lhs.size() < rhs.size();
    });

    auto pivot = stable_partition(vs.begin(), vs.end(),[sz](string const& s){
        return s.size() < sz;
    });

    for(auto it = pivot; it != vs.cend(); ++it)
        std::cout << *it << " ";
}

int main()
{
    //! ex10.18
    std::vector<std::string> v{
        "1","1234","1234","hi~", "alan", "alan"
    };
    std::cout << "ex10.18: ";
    biggies_partition(v,3);
    std::cout << std::endl;

    //! ex10.19
    std::vector<std::string> v2{
        "1","1234","1234","hi~", "alan", "alan"
    };
    std::cout << "ex10.19: ";
    biggies_stable_partition(v2,3);
    std::cout << std::endl;

    return 0;
}
//! output :
//!
//ex10.18: hi~ 1234 alan
//ex10.19: hi~ 1234 alan
<commit_msg>refactor 10.18~19, we don't need stable_sort if we don't use find_if.<commit_after>//!
//! @author @Yue Wang @pezy
//! @date   12.10.2014
//!
//! Exercise 10.18:
//! Rewrite biggies to use partition instead of find_if.
//!
//! Exercise 10.19:
//! Rewrite the previous exercise to use stable_partition, which like
//! stable_sort maintains the original element order in the paritioned
//! sequence.
//!

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>

//! from ex 10.9
void elimdups(std::vector<std::string> &vs)
{
    std::sort(vs.begin(), vs.end());
    auto new_end = std::unique(vs.begin(),vs.end());
    vs.erase(new_end, vs.end());
}

//! ex10.18
void biggies_partition(std::vector<std::string> &vs, std::size_t sz)
{
    elimdups(vs);

    auto pivot = partition(vs.begin(), vs.end(),[sz](const std::string &s){
        return s.size() >= sz;}
    );

    for(auto it = vs.cbegin(); it != pivot; ++it)
        std::cout << *it << " ";
}

//! ex10.19
void biggies_stable_partition(std::vector<std::string> &vs, std::size_t sz)
{
    elimdups(vs);

    auto pivot = stable_partition(vs.begin(), vs.end(),[sz](const std::string& s){
        return s.size() >= sz;
    });

    for(auto it = vs.cbegin(); it != pivot; ++it)
        std::cout << *it << " ";
}

int main()
{
    //! ex10.18
    std::vector<std::string> v{
        "the", "quick", "red", "fox", "jumps", "over", "the", "slow", "red", "turtle"
    };

    std::cout << "ex10.18: ";
    std::vector<std::string> v1(v);
    biggies_partition(v1,4);
    std::cout << std::endl;

    //! ex10.19
    std::cout << "ex10.19: ";
    std::vector<std::string> v2(v);
    biggies_stable_partition(v2,4);
    std::cout << std::endl;

    return 0;
}
//! output :
//!
//ex10.18: turtle jumps over quick slow
//ex10.19: jumps over quick slow turtle
<|endoftext|>


<commit_before>#include <QSqlQuery>
#include <QSqlRecord>
#include <QSqlError>

#include "kernel.h"
#include "raster.h"
#include "symboltable.h"
#include "astnode.h"
#include "idnode.h"
#include "operationnode.h"
#include "expressionnode.h"
#include "symboltable.h"
#include "formatter.h"
#include "formatters.h"
#include "scriptnode.h"
#include "columndefinition.h"
#include "table.h"
#include "attributerecord.h"
#include "polygon.h"
#include "geometry.h"
#include "feature.h"
#include "featurecoverage.h"
#include "domain.h"
#include "numericrange.h"
#include "numericdomain.h"
#include "columndefinition.h"
#include "table.h"
#include "connectorinterface.h"
#include "factory.h"
#include "abstractfactory.h"
#include "connectorfactory.h"
#include "catalog.h"
#include "mastercatalog.h"
#include "ilwiscontext.h"
#include "juliantime.h"
#include "selectornode.h"
#include "outparametersnode.h"
#include "assignmentnode.h"

using namespace Ilwis;

AssignmentNode::AssignmentNode() : _defintion(false)
{
}

bool AssignmentNode::isDefinition() const
{
    return _defintion;
}

void AssignmentNode::setDefintion(bool yesno)
{
    _defintion= yesno;
}

void AssignmentNode::setExpression(ExpressionNode *node)
{
    _expression =QSharedPointer<ExpressionNode>(node);
}

QString AssignmentNode::nodeType() const
{
    return "assignment";
}

IIlwisObject AssignmentNode::getObject(const Symbol& sym) const {
    IlwisTypes tp = sym._type;
    if ( tp & itRASTER)
            return sym._var.value<Ilwis::IRasterCoverage>().get<IlwisObject>();
    if ( tp & itFEATURE)
            return sym._var.value<Ilwis::IFeatureCoverage>().get<IlwisObject>();
    return IIlwisObject();

}

void AssignmentNode::getFormat(QSharedPointer<ASTNode>& node, QString& format, QString& fnamespace) const {
    Formatter *fnode = static_cast<Formatter *>(node->child(0).data());
    format = fnode->format();
    fnamespace = fnode->fnamespace();

    if ( format == "" || format == sUNDEF) {
        Formatter *fnode = ScriptNode::activeFormat(itRASTER);
        if ( fnode) {
            format = fnode->format();
            fnamespace = fnode->fnamespace();
        }
    }
}

void AssignmentNode::store2Format(QSharedPointer<ASTNode>& node, const Symbol& sym, const QString& result) {
    QString format, fnamespace;
    getFormat(node, format, fnamespace);
    if ( format != "" && format != sUNDEF) {
        Ilwis::IIlwisObject object = getObject(sym);
        bool wasAnonymous = object->isAnonymous();
        object->setName(result);
        object->connectTo(QUrl(), format, fnamespace, Ilwis::IlwisObject::cmOUTPUT);
        object->setCreateTime(Ilwis::Time::now());
        if ( wasAnonymous)
            mastercatalog()->addItems({object->source(IlwisObject::cmOUTPUT | IlwisObject::cmEXTENDED)});

        object->store(Ilwis::IlwisObject::smMETADATA | Ilwis::IlwisObject::smBINARYDATA);

     }
}

bool AssignmentNode::evaluate(SymbolTable& symbols, int scope, ExecutionContext *ctx)
{
    if ( _expression.isNull())
        return false;

    bool res = _expression->evaluate(symbols, scope, ctx);
    if ( res) {
        NodeValue val = _expression->value();
        for(int i = 0; i < val.size(); ++i) {
            Symbol sym = symbols.getSymbol(val.id(i),SymbolTable::gaREMOVEIFANON);
            IlwisTypes tp = sym.isValid() ? sym._type : itUNKNOWN;
            QString result = _outParms->id(i);
            QSharedPointer<ASTNode> specifier = _outParms->specifier(result);
            if ( !specifier.isNull()) {
                if ( specifier->noOfChilderen()!= 1)
                    return ERROR2(ERR_NO_OBJECT_TYPE_FOR_2, "Output object", "expression");
                store2Format(specifier, sym, result);

            }
            if (  hasType(tp, itILWISOBJECT)) {
                bool ok;
                if ( hasType(tp, itRASTER)) {
                    ok = copyObject<RasterCoverage>(sym, result,symbols);
                }
                else if hasType(tp, itFEATURE)
                        ok = copyObject<FeatureCoverage>(sym, result,symbols);
                else if hasType(tp, itTABLE){
                    ok = copyObject<Table>(sym, result,symbols,true);
                    QSharedPointer<Selector> selector = _outParms->selector(result);
                    if (!selector.isNull()){
                        QString varName = selector->variable();
                        ITable source =  sym._var.value<ITable>();
                        QString oldColName = ctx->_additionalInfo[source->name()];
                        QVariant newT= symbols.getValue(result);
                        ITable newTable = newT.value<ITable>();
                        ColumnDefinition coldef = newTable->columndefinition(oldColName);
                        if ( coldef.isValid()){
                            coldef.setName(varName);
                            newTable->columndefinition(coldef);
                        }
                    }
                }

                if(!ok) {
                    throw ErrorObject(QString(TR(ERR_OPERATION_FAILID1).arg("assignment")));
                }
                ctx->clear(true);
                ctx->_results.push_back(result);
                return ok;

            } else {
                sym = symbols.getSymbol(result,SymbolTable::gaREMOVEIFANON);
                tp = sym.isValid() ? sym._type : itUNKNOWN;
                if ( tp == itUNKNOWN) {
                    tp = Domain::ilwType(val);
                }
            }
            symbols.addSymbol(result, scope, tp, _expression->value());
            //symbols.addSymbol(_result->id(), scope, tp, sym._var);

            return true;
        }
    }
    return false;
}

void AssignmentNode::addOutputs(OutParametersNode *p)
{
    _outParms.reset(p);
}

<commit_msg>constructs url for the connector<commit_after>#include <QSqlQuery>
#include <QSqlRecord>
#include <QSqlError>

#include "kernel.h"
#include "raster.h"
#include "symboltable.h"
#include "astnode.h"
#include "idnode.h"
#include "operationnode.h"
#include "expressionnode.h"
#include "symboltable.h"
#include "formatter.h"
#include "formatters.h"
#include "scriptnode.h"
#include "columndefinition.h"
#include "table.h"
#include "attributerecord.h"
#include "polygon.h"
#include "geometry.h"
#include "feature.h"
#include "featurecoverage.h"
#include "domain.h"
#include "numericrange.h"
#include "numericdomain.h"
#include "columndefinition.h"
#include "table.h"
#include "connectorinterface.h"
#include "factory.h"
#include "abstractfactory.h"
#include "connectorfactory.h"
#include "catalog.h"
#include "mastercatalog.h"
#include "ilwiscontext.h"
#include "juliantime.h"
#include "selectornode.h"
#include "outparametersnode.h"
#include "assignmentnode.h"

using namespace Ilwis;

AssignmentNode::AssignmentNode() : _defintion(false)
{
}

bool AssignmentNode::isDefinition() const
{
    return _defintion;
}

void AssignmentNode::setDefintion(bool yesno)
{
    _defintion= yesno;
}

void AssignmentNode::setExpression(ExpressionNode *node)
{
    _expression =QSharedPointer<ExpressionNode>(node);
}

QString AssignmentNode::nodeType() const
{
    return "assignment";
}

IIlwisObject AssignmentNode::getObject(const Symbol& sym) const {
    IlwisTypes tp = sym._type;
    if ( tp & itRASTER)
            return sym._var.value<Ilwis::IRasterCoverage>().get<IlwisObject>();
    if ( tp & itFEATURE)
            return sym._var.value<Ilwis::IFeatureCoverage>().get<IlwisObject>();
    return IIlwisObject();

}

void AssignmentNode::getFormat(QSharedPointer<ASTNode>& node, QString& format, QString& fnamespace) const {
    Formatter *fnode = static_cast<Formatter *>(node->child(0).data());
    format = fnode->format();
    fnamespace = fnode->fnamespace();

    if ( format == "" || format == sUNDEF) {
        Formatter *fnode = ScriptNode::activeFormat(itRASTER);
        if ( fnode) {
            format = fnode->format();
            fnamespace = fnode->fnamespace();
        }
    }
}

void AssignmentNode::store2Format(QSharedPointer<ASTNode>& node, const Symbol& sym, const QString& result) {
    QString format, fnamespace;
    getFormat(node, format, fnamespace);
    if ( format != "" && format != sUNDEF) {
        Ilwis::IIlwisObject object = getObject(sym);
        bool wasAnonymous = object->isAnonymous();
        QUrl url = context()->workingCatalog()->location().toString() + "/" + result;
        object->setName(result);
        object->connectTo(url, format, fnamespace, Ilwis::IlwisObject::cmOUTPUT);
        object->setCreateTime(Ilwis::Time::now());
        if ( wasAnonymous)
            mastercatalog()->addItems({object->source(IlwisObject::cmOUTPUT | IlwisObject::cmEXTENDED)});

        object->store(Ilwis::IlwisObject::smMETADATA | Ilwis::IlwisObject::smBINARYDATA);

     }
}

bool AssignmentNode::evaluate(SymbolTable& symbols, int scope, ExecutionContext *ctx)
{
    if ( _expression.isNull())
        return false;

    bool res = _expression->evaluate(symbols, scope, ctx);
    if ( res) {
        NodeValue val = _expression->value();
        for(int i = 0; i < val.size(); ++i) {
            Symbol sym = symbols.getSymbol(val.id(i),SymbolTable::gaREMOVEIFANON);
            IlwisTypes tp = sym.isValid() ? sym._type : itUNKNOWN;
            QString result = _outParms->id(i);
            QSharedPointer<ASTNode> specifier = _outParms->specifier(result);
            if ( !specifier.isNull()) {
                if ( specifier->noOfChilderen()!= 1)
                    return ERROR2(ERR_NO_OBJECT_TYPE_FOR_2, "Output object", "expression");
                store2Format(specifier, sym, result);

            }
            if (  hasType(tp, itILWISOBJECT)) {
                bool ok;
                if ( hasType(tp, itRASTER)) {
                    ok = copyObject<RasterCoverage>(sym, result,symbols);
                }
                else if hasType(tp, itFEATURE)
                        ok = copyObject<FeatureCoverage>(sym, result,symbols);
                else if hasType(tp, itTABLE){
                    ok = copyObject<Table>(sym, result,symbols,true);
                    QSharedPointer<Selector> selector = _outParms->selector(result);
                    if (!selector.isNull()){
                        QString varName = selector->variable();
                        ITable source =  sym._var.value<ITable>();
                        QString oldColName = ctx->_additionalInfo[source->name()];
                        QVariant newT= symbols.getValue(result);
                        ITable newTable = newT.value<ITable>();
                        ColumnDefinition coldef = newTable->columndefinition(oldColName);
                        if ( coldef.isValid()){
                            coldef.setName(varName);
                            newTable->columndefinition(coldef);
                        }
                    }
                }

                if(!ok) {
                    throw ErrorObject(QString(TR(ERR_OPERATION_FAILID1).arg("assignment")));
                }
                ctx->clear(true);
                ctx->_results.push_back(result);
                return ok;

            } else {
                sym = symbols.getSymbol(result,SymbolTable::gaREMOVEIFANON);
                tp = sym.isValid() ? sym._type : itUNKNOWN;
                if ( tp == itUNKNOWN) {
                    tp = Domain::ilwType(val);
                }
            }
            symbols.addSymbol(result, scope, tp, _expression->value());
            //symbols.addSymbol(_result->id(), scope, tp, sym._var);

            return true;
        }
    }
    return false;
}

void AssignmentNode::addOutputs(OutParametersNode *p)
{
    _outParms.reset(p);
}

<|endoftext|>


<commit_before>/*****************************************************************************
 * ctrl_text.cpp
 *****************************************************************************
 * Copyright (C) 2003 VideoLAN
 * $Id$
 *
 * Authors: Cyril Deguet     <asmax@via.ecp.fr>
 *          Olivier Teulire <ipkiss@via.ecp.fr>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
 *****************************************************************************/

#include "ctrl_text.hpp"
#include "../events/evt_generic.hpp"
#include "../events/evt_mouse.hpp"
#include "../src/generic_bitmap.hpp"
#include "../src/generic_font.hpp"
#include "../src/os_factory.hpp"
#include "../src/os_graphics.hpp"
#include "../src/os_timer.hpp"
#include "../utils/position.hpp"
#include "../utils/ustring.hpp"
#include "../utils/var_text.hpp"

#define MOVING_TEXT_STEP 3
#define MOVING_TEXT_DELAY 200
#define SEPARATOR_STRING "   "

CtrlText::CtrlText( intf_thread_t *pIntf, VarText &rVariable,
                    const GenericFont &rFont, const UString &rHelp,
                    uint32_t color, VarBool *pVisible ):
    CtrlGeneric( pIntf, rHelp, pVisible ), m_fsm( pIntf ),
    m_rVariable( rVariable ), m_cmdToManual( this, &transToManual ),
    m_cmdManualMoving( this, &transManualMoving ),
    m_cmdManualStill( this, &transManualStill ),
    m_cmdMove( this, &transMove ),
    m_pEvt( NULL ), m_rFont( rFont ), m_color( color ),
    m_pImg( NULL ), m_pImgDouble( NULL ), m_pCurrImg( NULL ),
    m_xPos( 0 ), m_xOffset( 0 )
{
    m_pTimer = OSFactory::instance( getIntf() )->createOSTimer(
        Callback( this, &updateText ) );

    // States
    m_fsm.addState( "still" );
    m_fsm.addState( "moving" );
    m_fsm.addState( "manual1" );
    m_fsm.addState( "manual2" );
    m_fsm.addState( "outStill" );
    m_fsm.addState( "outMoving" );

    // Transitions
    m_fsm.addTransition( "still", "mouse:left:down", "manual1",
                         &m_cmdToManual );
    m_fsm.addTransition( "manual1", "mouse:left:up", "moving",
                         &m_cmdManualMoving );
    m_fsm.addTransition( "moving", "mouse:left:down", "manual2",
                         &m_cmdToManual );
    m_fsm.addTransition( "manual2", "mouse:left:up", "still",
                         &m_cmdManualStill );
    m_fsm.addTransition( "manual1", "motion", "manual1", &m_cmdMove );
    m_fsm.addTransition( "manual2", "motion", "manual2", &m_cmdMove );
    m_fsm.addTransition( "still", "leave", "outStill" );
    m_fsm.addTransition( "outStill", "enter", "still" );
    m_fsm.addTransition( "moving", "leave", "outMoving" );
    m_fsm.addTransition( "outMoving", "enter", "moving" );

    // Initial state
    m_fsm.setState( "outStill" );

    // Observe the variable
    m_rVariable.addObserver( this );

    // Set the text
    displayText( m_rVariable.get() );
}

CtrlText::~CtrlText()
{
    m_rVariable.delObserver( this );
    if( m_pTimer )
    {
        delete m_pTimer;
    }
    if( m_pImg )
    {
        delete m_pImg;
    }
    if( m_pImgDouble )
    {
        delete m_pImgDouble;
    }
}

void CtrlText::handleEvent( EvtGeneric &rEvent )
{
    // Save the event to use it in callbacks
    m_pEvt = &rEvent;

    m_fsm.handleTransition( rEvent.getAsString() );
}

bool CtrlText::mouseOver( int x, int y ) const
{
    if( m_pCurrImg )
    {
        // We have 3 different ways of deciding when to return true here:
        //  1) the mouse is exactly over the text (so if you click between two
        //     letters, the text control doesn't catch the event)
        //  2) the mouse is over the rectangle of the control
        //  3) the mouse is over the rectangle of the visible text
        // I don't know which one is the best...
#if 0
        return( x >= 0 && x < getPosition()->getWidth()
             && m_pCurrImg->hit( x - m_xPos, y ) );
#endif
#if 1
        return( x >= 0 && x < getPosition()->getWidth()
             && y >= 0 && y < getPosition()->getHeight() );
#endif
#if 0
        return( x >= 0 && x < getPosition()->getWidth()
             && y >= 0 && y < getPosition()->getHeight()
             && x < m_pCurrImg->getWidth() && x < m_pCurrImg->getHeight() );
#endif
    }
    else
    {
        return false;
    }
}

void CtrlText::draw( OSGraphics &rImage, int xDest, int yDest )
{
    if( m_pCurrImg )
    {
        // Compute the dimensions to draw
        int width = min( m_pCurrImg->getWidth() + m_xPos,
                         getPosition()->getWidth() );
        int height = min( m_pCurrImg->getHeight(), getPosition()->getHeight() );
        // Draw the current image
        rImage.drawBitmap( *m_pCurrImg, -m_xPos, 0, xDest, yDest,
                           width, height );
    }
}

void CtrlText::setText( const UString &rText, uint32_t color )
{
    // Change the color
    if( color != 0xFFFFFFFF )
    {
        m_color = color;
    }

    // Change the text
    m_rVariable.set( rText );
}

void CtrlText::onUpdate( Subject<VarText> &rVariable )
{
    displayText( m_rVariable.get() );
}

void CtrlText::displayText( const UString &rText )
{
    // Create the images ('normal' and 'double') from the text
    // 'Normal' image
    if( m_pImg )
    {
        delete m_pImg;
    }
    m_pImg = m_rFont.drawString( rText, m_color );
    if( !m_pImg )
    {
        return;
    }
    // 'Double' image
    const UString doubleStringWithSep = rText + SEPARATOR_STRING + rText;
    if( m_pImgDouble )
    {
        delete m_pImgDouble;
    }
    m_pImgDouble = m_rFont.drawString( doubleStringWithSep, m_color );

    // Update the current image used, as if the control size had changed
    onChangePosition();
    m_xPos = 0;

    // If the control was in the moving state, check if the scrolling is
    // still necessary
    const string &rState = m_fsm.getState();
    if( rState == "moving" || rState == "outMoving" )
    {
        if( m_pImg && m_pImg->getWidth() >= getPosition()->getWidth() )
        {
            m_pCurrImg = m_pImgDouble;
            m_pTimer->start( MOVING_TEXT_DELAY, false );
        }
        else
        {
            m_pTimer->stop();
        }
    }

    notifyLayout();
}

void CtrlText::onChangePosition()
{
    if( m_pImg && getPosition() )
    {
        if( m_pImg->getWidth() < getPosition()->getWidth() )
        {
            m_pCurrImg = m_pImg;
        }
        else
        {
            m_pCurrImg = m_pImgDouble;
        }
    }
    else
    {
        // m_pImg is a better default value than m_pImgDouble, but anyway we
        // don't care because the control is never drawn without position :)
        m_pCurrImg = m_pImg;
    }
}

void CtrlText::transToManual( SkinObject *pCtrl )
{
    CtrlText *pThis = (CtrlText*)pCtrl;
    EvtMouse *pEvtMouse = (EvtMouse*)pThis->m_pEvt;

    // Compute the offset
    pThis->m_xOffset = pEvtMouse->getXPos() - pThis->m_xPos;

    pThis->m_pTimer->stop();
    pThis->captureMouse();
}

void CtrlText::transManualMoving( SkinObject *pCtrl )
{
    CtrlText *pThis = (CtrlText*)pCtrl;
    pThis->releaseMouse();

    // Start the automatic movement, but only if the text is wider than the
    // control
    if( pThis->m_pImg &&
        pThis->m_pImg->getWidth() >= pThis->getPosition()->getWidth() )
    {
        // The current image may have been set incorrectly in displayText(), so
        // set the correct value
        pThis->m_pCurrImg = pThis->m_pImgDouble;

        pThis->m_pTimer->start( MOVING_TEXT_DELAY, false );
    }
}

void CtrlText::transManualStill( SkinObject *pCtrl )
{
    CtrlText *pThis = (CtrlText*)pCtrl;
    pThis->releaseMouse();
}

void CtrlText::transMove( SkinObject *pCtrl )
{
    CtrlText *pThis = (CtrlText*)pCtrl;
    EvtMouse *pEvtMouse = (EvtMouse*)pThis->m_pEvt;

    // Do nothing if the text fits in the control
    if( pThis->m_pImg &&
        pThis->m_pImg->getWidth() >= pThis->getPosition()->getWidth() )
    {
        // The current image may have been set incorrectly in displayText(), so
        // we set the correct value
        pThis->m_pCurrImg = pThis->m_pImgDouble;

        // Compute the new position of the left side, and make sure it is
        // in the correct range
        pThis->m_xPos = (pEvtMouse->getXPos() - pThis->m_xOffset);
        pThis->adjust( pThis->m_xPos );

        pThis->notifyLayout();
    }
}

void CtrlText::updateText( SkinObject *pCtrl )
{
    CtrlText *pThis = (CtrlText*)pCtrl;

    pThis->m_xPos -= MOVING_TEXT_STEP;
    pThis->adjust( pThis->m_xPos );

    pThis->notifyLayout();
}

void CtrlText::adjust( int &position )
{
    // {m_pImgDouble->getWidth()  - m_pImg->getWidth()} is the period of the
    // bitmap; remember that the string used to generate m_pImgDouble is of the
    // form: "foo  foo", the number of spaces being a parameter
    if( !m_pImg )
    {
        return;
    }
    position %= m_pImgDouble->getWidth() - m_pImg->getWidth();
    if( position > 0 )
    {
        position -= m_pImgDouble->getWidth() - m_pImg->getWidth();
    }
}

<commit_msg> * skins2: Do not try anymore to display images whose width is 0.    This avoids warnings at run-time on Windows.<commit_after>/*****************************************************************************
 * ctrl_text.cpp
 *****************************************************************************
 * Copyright (C) 2003 VideoLAN
 * $Id$
 *
 * Authors: Cyril Deguet     <asmax@via.ecp.fr>
 *          Olivier Teulire <ipkiss@via.ecp.fr>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
 *****************************************************************************/

#include "ctrl_text.hpp"
#include "../events/evt_generic.hpp"
#include "../events/evt_mouse.hpp"
#include "../src/generic_bitmap.hpp"
#include "../src/generic_font.hpp"
#include "../src/os_factory.hpp"
#include "../src/os_graphics.hpp"
#include "../src/os_timer.hpp"
#include "../utils/position.hpp"
#include "../utils/ustring.hpp"
#include "../utils/var_text.hpp"

#define MOVING_TEXT_STEP 3
#define MOVING_TEXT_DELAY 200
#define SEPARATOR_STRING "   "

CtrlText::CtrlText( intf_thread_t *pIntf, VarText &rVariable,
                    const GenericFont &rFont, const UString &rHelp,
                    uint32_t color, VarBool *pVisible ):
    CtrlGeneric( pIntf, rHelp, pVisible ), m_fsm( pIntf ),
    m_rVariable( rVariable ), m_cmdToManual( this, &transToManual ),
    m_cmdManualMoving( this, &transManualMoving ),
    m_cmdManualStill( this, &transManualStill ),
    m_cmdMove( this, &transMove ),
    m_pEvt( NULL ), m_rFont( rFont ), m_color( color ),
    m_pImg( NULL ), m_pImgDouble( NULL ), m_pCurrImg( NULL ),
    m_xPos( 0 ), m_xOffset( 0 )
{
    m_pTimer = OSFactory::instance( getIntf() )->createOSTimer(
        Callback( this, &updateText ) );

    // States
    m_fsm.addState( "still" );
    m_fsm.addState( "moving" );
    m_fsm.addState( "manual1" );
    m_fsm.addState( "manual2" );
    m_fsm.addState( "outStill" );
    m_fsm.addState( "outMoving" );

    // Transitions
    m_fsm.addTransition( "still", "mouse:left:down", "manual1",
                         &m_cmdToManual );
    m_fsm.addTransition( "manual1", "mouse:left:up", "moving",
                         &m_cmdManualMoving );
    m_fsm.addTransition( "moving", "mouse:left:down", "manual2",
                         &m_cmdToManual );
    m_fsm.addTransition( "manual2", "mouse:left:up", "still",
                         &m_cmdManualStill );
    m_fsm.addTransition( "manual1", "motion", "manual1", &m_cmdMove );
    m_fsm.addTransition( "manual2", "motion", "manual2", &m_cmdMove );
    m_fsm.addTransition( "still", "leave", "outStill" );
    m_fsm.addTransition( "outStill", "enter", "still" );
    m_fsm.addTransition( "moving", "leave", "outMoving" );
    m_fsm.addTransition( "outMoving", "enter", "moving" );

    // Initial state
    m_fsm.setState( "outStill" );

    // Observe the variable
    m_rVariable.addObserver( this );

    // Set the text
    displayText( m_rVariable.get() );
}

CtrlText::~CtrlText()
{
    m_rVariable.delObserver( this );
    if( m_pTimer )
    {
        delete m_pTimer;
    }
    if( m_pImg )
    {
        delete m_pImg;
    }
    if( m_pImgDouble )
    {
        delete m_pImgDouble;
    }
}

void CtrlText::handleEvent( EvtGeneric &rEvent )
{
    // Save the event to use it in callbacks
    m_pEvt = &rEvent;

    m_fsm.handleTransition( rEvent.getAsString() );
}

bool CtrlText::mouseOver( int x, int y ) const
{
    if( m_pCurrImg )
    {
        // We have 3 different ways of deciding when to return true here:
        //  1) the mouse is exactly over the text (so if you click between two
        //     letters, the text control doesn't catch the event)
        //  2) the mouse is over the rectangle of the control
        //  3) the mouse is over the rectangle of the visible text
        // I don't know which one is the best...
#if 0
        return( x >= 0 && x < getPosition()->getWidth()
             && m_pCurrImg->hit( x - m_xPos, y ) );
#endif
#if 1
        return( x >= 0 && x < getPosition()->getWidth()
             && y >= 0 && y < getPosition()->getHeight() );
#endif
#if 0
        return( x >= 0 && x < getPosition()->getWidth()
             && y >= 0 && y < getPosition()->getHeight()
             && x < m_pCurrImg->getWidth() && x < m_pCurrImg->getHeight() );
#endif
    }
    else
    {
        return false;
    }
}

void CtrlText::draw( OSGraphics &rImage, int xDest, int yDest )
{
    if( m_pCurrImg )
    {
        // Compute the dimensions to draw
        int width = min( m_pCurrImg->getWidth() + m_xPos,
                         getPosition()->getWidth() );
        int height = min( m_pCurrImg->getHeight(), getPosition()->getHeight() );
        // Draw the current image
        if( width > 0 && height > 0 )
        {
            rImage.drawBitmap( *m_pCurrImg, -m_xPos, 0, xDest, yDest,
                            width, height );
        }
    }
}

void CtrlText::setText( const UString &rText, uint32_t color )
{
    // Change the color
    if( color != 0xFFFFFFFF )
    {
        m_color = color;
    }

    // Change the text
    m_rVariable.set( rText );
}

void CtrlText::onUpdate( Subject<VarText> &rVariable )
{
    displayText( m_rVariable.get() );
}

void CtrlText::displayText( const UString &rText )
{
    // Create the images ('normal' and 'double') from the text
    // 'Normal' image
    if( m_pImg )
    {
        delete m_pImg;
    }
    m_pImg = m_rFont.drawString( rText, m_color );
    if( !m_pImg )
    {
        return;
    }
    // 'Double' image
    const UString doubleStringWithSep = rText + SEPARATOR_STRING + rText;
    if( m_pImgDouble )
    {
        delete m_pImgDouble;
    }
    m_pImgDouble = m_rFont.drawString( doubleStringWithSep, m_color );

    // Update the current image used, as if the control size had changed
    onChangePosition();
    m_xPos = 0;

    // If the control was in the moving state, check if the scrolling is
    // still necessary
    const string &rState = m_fsm.getState();
    if( rState == "moving" || rState == "outMoving" )
    {
        if( m_pImg && m_pImg->getWidth() >= getPosition()->getWidth() )
        {
            m_pCurrImg = m_pImgDouble;
            m_pTimer->start( MOVING_TEXT_DELAY, false );
        }
        else
        {
            m_pTimer->stop();
        }
    }

    notifyLayout();
}

void CtrlText::onChangePosition()
{
    if( m_pImg && getPosition() )
    {
        if( m_pImg->getWidth() < getPosition()->getWidth() )
        {
            m_pCurrImg = m_pImg;
        }
        else
        {
            m_pCurrImg = m_pImgDouble;
        }
    }
    else
    {
        // m_pImg is a better default value than m_pImgDouble, but anyway we
        // don't care because the control is never drawn without position :)
        m_pCurrImg = m_pImg;
    }
}

void CtrlText::transToManual( SkinObject *pCtrl )
{
    CtrlText *pThis = (CtrlText*)pCtrl;
    EvtMouse *pEvtMouse = (EvtMouse*)pThis->m_pEvt;

    // Compute the offset
    pThis->m_xOffset = pEvtMouse->getXPos() - pThis->m_xPos;

    pThis->m_pTimer->stop();
    pThis->captureMouse();
}

void CtrlText::transManualMoving( SkinObject *pCtrl )
{
    CtrlText *pThis = (CtrlText*)pCtrl;
    pThis->releaseMouse();

    // Start the automatic movement, but only if the text is wider than the
    // control
    if( pThis->m_pImg &&
        pThis->m_pImg->getWidth() >= pThis->getPosition()->getWidth() )
    {
        // The current image may have been set incorrectly in displayText(), so
        // set the correct value
        pThis->m_pCurrImg = pThis->m_pImgDouble;

        pThis->m_pTimer->start( MOVING_TEXT_DELAY, false );
    }
}

void CtrlText::transManualStill( SkinObject *pCtrl )
{
    CtrlText *pThis = (CtrlText*)pCtrl;
    pThis->releaseMouse();
}

void CtrlText::transMove( SkinObject *pCtrl )
{
    CtrlText *pThis = (CtrlText*)pCtrl;
    EvtMouse *pEvtMouse = (EvtMouse*)pThis->m_pEvt;

    // Do nothing if the text fits in the control
    if( pThis->m_pImg &&
        pThis->m_pImg->getWidth() >= pThis->getPosition()->getWidth() )
    {
        // The current image may have been set incorrectly in displayText(), so
        // we set the correct value
        pThis->m_pCurrImg = pThis->m_pImgDouble;

        // Compute the new position of the left side, and make sure it is
        // in the correct range
        pThis->m_xPos = (pEvtMouse->getXPos() - pThis->m_xOffset);
        pThis->adjust( pThis->m_xPos );

        pThis->notifyLayout();
    }
}

void CtrlText::updateText( SkinObject *pCtrl )
{
    CtrlText *pThis = (CtrlText*)pCtrl;

    pThis->m_xPos -= MOVING_TEXT_STEP;
    pThis->adjust( pThis->m_xPos );

    pThis->notifyLayout();
}

void CtrlText::adjust( int &position )
{
    // {m_pImgDouble->getWidth()  - m_pImg->getWidth()} is the period of the
    // bitmap; remember that the string used to generate m_pImgDouble is of the
    // form: "foo  foo", the number of spaces being a parameter
    if( !m_pImg )
    {
        return;
    }
    position %= m_pImgDouble->getWidth() - m_pImg->getWidth();
    if( position > 0 )
    {
        position -= m_pImgDouble->getWidth() - m_pImg->getWidth();
    }
}

<|endoftext|>


<commit_before>/***********************************************************************
	filename: 	CEGUIMouseCursor.cpp
	created:	21/2/2004
	author:		Paul D Turner

	purpose:	Implements MouseCursor class
*************************************************************************/
/***************************************************************************
 *   Copyright (C) 2004 - 2006 Paul D Turner & The CEGUI Development Team
 *
 *   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 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.
 ***************************************************************************/
#include "CEGUIMouseCursor.h"
#include "CEGUIExceptions.h"
#include "CEGUILogger.h"
#include "CEGUISystem.h"
#include "CEGUIRenderer.h"
#include "CEGUIImagesetManager.h"
#include "CEGUIImageset.h"
#include "CEGUIImage.h"

// Start of CEGUI namespace section
namespace CEGUI
{
const String MouseCursor::EventNamespace("MouseCursor");

/*************************************************************************
	Static Data Definitions
*************************************************************************/
// singleton instance pointer
template<> MouseCursor* Singleton<MouseCursor>::ms_Singleton	= 0;

/*************************************************************************
	Event name constants
*************************************************************************/
const String MouseCursor::EventImageChanged( "ImageChanged" );

/*************************************************************************
	constructor
*************************************************************************/
MouseCursor::MouseCursor(void)
{
    Rect screenArea(System::getSingleton().getRenderer()->getRect());

	// mouse defaults to middle of the constrained area
	d_position.d_x = screenArea.getWidth() / 2;
	d_position.d_y = screenArea.getHeight() / 2;
	d_position.d_z = 1.0f;

	// default constraint is to whole screen
	setConstraintArea(&screenArea);

	// mouse defaults to visible
	d_visible = true;

	// no default image though
	d_cursorImage = 0;

	Logger::getSingleton().logEvent("CEGUI::MouseCursor singleton created.");
}

/*************************************************************************
	Destructor
*************************************************************************/
MouseCursor::~MouseCursor(void)
{
	Logger::getSingleton().logEvent("CEGUI::MouseCursor singleton destroyed.");
}

/*************************************************************************
	Set the current mouse cursor image
*************************************************************************/
void MouseCursor::setImage(const Image* image)
{
	d_cursorImage = image;
	MouseCursorEventArgs args(this);
	args.image = image;
	onImageChanged(args);
}

/*************************************************************************
	Set the current mouse cursor image
*************************************************************************/
void MouseCursor::setImage(const String& imageset, const String& image_name)
{
	setImage(&ImagesetManager::getSingleton().getImageset(imageset)->getImage(image_name));
}

/*************************************************************************
	Draw the mouse cursor
*************************************************************************/
void MouseCursor::draw(void) const
{
	if (d_visible && (d_cursorImage != 0))
	{
		d_cursorImage->draw( d_position, System::getSingleton().getRenderer()->getRect() );
	}
}

/*************************************************************************
	Set the current mouse cursor position
*************************************************************************/
void MouseCursor::setPosition(const Point& position)
{
	d_position.d_x = position.d_x;
	d_position.d_y = position.d_y;
	constrainPosition();
}

/*************************************************************************
	Offset the mouse cursor position by the deltas specified in 'offset'.
*************************************************************************/
void MouseCursor::offsetPosition(const Point& offset)
{
	d_position.d_x += offset.d_x;
	d_position.d_y += offset.d_y;
	constrainPosition();
}

/*************************************************************************
	Checks the mouse cursor position is within the current 'constrain'
	Rect and adjusts as required.
*************************************************************************/
void MouseCursor::constrainPosition(void)
{
    Rect absarea(getConstraintArea());

	if (d_position.d_x >= absarea.d_right)
		d_position.d_x = absarea.d_right -1;

	if (d_position.d_y >= absarea.d_bottom)
		d_position.d_y = absarea.d_bottom -1;

	if (d_position.d_y < absarea.d_top)
		d_position.d_y = absarea.d_top;

	if (d_position.d_x < absarea.d_left)
		d_position.d_x = absarea.d_left;
}

/*************************************************************************
	Set the area that the mouse cursor is constrained to.
*************************************************************************/
void MouseCursor::setConstraintArea(const Rect* area)
{
	Rect renderer_area = System::getSingleton().getRenderer()->getRect();

	if (!area)
	{
		d_constraints.d_min.d_x = cegui_reldim(renderer_area.d_left / renderer_area.getWidth());
		d_constraints.d_min.d_y = cegui_reldim(renderer_area.d_top / renderer_area.getHeight());
		d_constraints.d_max.d_x = cegui_reldim(renderer_area.d_right / renderer_area.getWidth());
		d_constraints.d_max.d_y = cegui_reldim(renderer_area.d_bottom / renderer_area.getHeight());
	}
	else
	{
        Rect finalArea(area->getIntersection(renderer_area));
		d_constraints.d_min.d_x = cegui_reldim(finalArea.d_left / renderer_area.getWidth());
		d_constraints.d_min.d_y = cegui_reldim(finalArea.d_top / renderer_area.getHeight());
		d_constraints.d_max.d_x = cegui_reldim(finalArea.d_right / renderer_area.getWidth());
		d_constraints.d_max.d_y = cegui_reldim(finalArea.d_bottom / renderer_area.getHeight());
	}

	constrainPosition();
}

/*************************************************************************
	Set the area that the mouse cursor is constrained to.
*************************************************************************/
void MouseCursor::setUnifiedConstraintArea(const URect* area)
{
	Rect renderer_area = System::getSingleton().getRenderer()->getRect();

	if (area)
	{
        d_constraints = *area;
	}
	else
	{
		d_constraints.d_min.d_x = cegui_reldim(renderer_area.d_left / renderer_area.getWidth());
		d_constraints.d_min.d_y = cegui_reldim(renderer_area.d_top / renderer_area.getHeight());
		d_constraints.d_max.d_x = cegui_reldim(renderer_area.d_right / renderer_area.getWidth());
		d_constraints.d_max.d_y = cegui_reldim(renderer_area.d_bottom / renderer_area.getHeight());
	}

	constrainPosition();
}

/*************************************************************************
	Set the area that the mouse cursor is constrained to.
*************************************************************************/
Rect MouseCursor::getConstraintArea(void) const
{
    return Rect(d_constraints.asAbsolute(System::getSingleton().getRenderer()->getSize()));
}

/*************************************************************************
	Set the area that the mouse cursor is constrained to.
*************************************************************************/
const URect& MouseCursor::getUnifiedConstraintArea(void) const
{
    return d_constraints;
}

/*************************************************************************
	Return the current mouse cursor position in display resolution
	independant values.
*************************************************************************/
Point MouseCursor::getDisplayIndependantPosition(void) const
{
	Size dsz(System::getSingleton().getRenderer()->getSize());

	return Point(d_position.d_x / (dsz.d_width - 1.0f), d_position.d_y / (dsz.d_height - 1.0f));
}

//////////////////////////////////////////////////////////////////////////
/*************************************************************************

	Begin event triggers section

*************************************************************************/
//////////////////////////////////////////////////////////////////////////

void MouseCursor::onImageChanged(MouseCursorEventArgs& e)
{
	fireEvent(EventImageChanged, e, EventNamespace);
}

MouseCursor& MouseCursor::getSingleton(void)
{
	return Singleton<MouseCursor>::getSingleton();
}

MouseCursor* MouseCursor::getSingletonPtr(void)
{
	return Singleton<MouseCursor>::getSingletonPtr();
}

} // End of  CEGUI namespace section
<commit_msg>Mouse cursor fix bug #49<commit_after>/***********************************************************************
	filename: 	CEGUIMouseCursor.cpp
	created:	21/2/2004
	author:		Paul D Turner

	purpose:	Implements MouseCursor class
*************************************************************************/
/***************************************************************************
 *   Copyright (C) 2004 - 2006 Paul D Turner & The CEGUI Development Team
 *
 *   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 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.
 ***************************************************************************/
#include "CEGUIMouseCursor.h"
#include "CEGUIExceptions.h"
#include "CEGUILogger.h"
#include "CEGUISystem.h"
#include "CEGUIRenderer.h"
#include "CEGUIImagesetManager.h"
#include "CEGUIImageset.h"
#include "CEGUIImage.h"

// Start of CEGUI namespace section
namespace CEGUI
{
const String MouseCursor::EventNamespace("MouseCursor");

/*************************************************************************
	Static Data Definitions
*************************************************************************/
// singleton instance pointer
template<> MouseCursor* Singleton<MouseCursor>::ms_Singleton	= 0;

/*************************************************************************
	Event name constants
*************************************************************************/
const String MouseCursor::EventImageChanged( "ImageChanged" );

/*************************************************************************
	constructor
*************************************************************************/
MouseCursor::MouseCursor(void)
{
    Rect screenArea(System::getSingleton().getRenderer()->getRect());

	// mouse defaults to middle of the constrained area
	d_position.d_x = screenArea.getWidth() / 2;
	d_position.d_y = screenArea.getHeight() / 2;
	d_position.d_z = 0.0f;

	// default constraint is to whole screen
	setConstraintArea(&screenArea);

	// mouse defaults to visible
	d_visible = true;

	// no default image though
	d_cursorImage = 0;

	Logger::getSingleton().logEvent("CEGUI::MouseCursor singleton created.");
}

/*************************************************************************
	Destructor
*************************************************************************/
MouseCursor::~MouseCursor(void)
{
	Logger::getSingleton().logEvent("CEGUI::MouseCursor singleton destroyed.");
}

/*************************************************************************
	Set the current mouse cursor image
*************************************************************************/
void MouseCursor::setImage(const Image* image)
{
	d_cursorImage = image;
	MouseCursorEventArgs args(this);
	args.image = image;
	onImageChanged(args);
}

/*************************************************************************
	Set the current mouse cursor image
*************************************************************************/
void MouseCursor::setImage(const String& imageset, const String& image_name)
{
	setImage(&ImagesetManager::getSingleton().getImageset(imageset)->getImage(image_name));
}

/*************************************************************************
	Draw the mouse cursor
*************************************************************************/
void MouseCursor::draw(void) const
{
	if (d_visible && (d_cursorImage != 0))
	{
		d_cursorImage->draw( d_position, System::getSingleton().getRenderer()->getRect() );
	}
}

/*************************************************************************
	Set the current mouse cursor position
*************************************************************************/
void MouseCursor::setPosition(const Point& position)
{
	d_position.d_x = position.d_x;
	d_position.d_y = position.d_y;
	constrainPosition();
}

/*************************************************************************
	Offset the mouse cursor position by the deltas specified in 'offset'.
*************************************************************************/
void MouseCursor::offsetPosition(const Point& offset)
{
	d_position.d_x += offset.d_x;
	d_position.d_y += offset.d_y;
	constrainPosition();
}

/*************************************************************************
	Checks the mouse cursor position is within the current 'constrain'
	Rect and adjusts as required.
*************************************************************************/
void MouseCursor::constrainPosition(void)
{
    Rect absarea(getConstraintArea());

	if (d_position.d_x >= absarea.d_right)
		d_position.d_x = absarea.d_right -1;

	if (d_position.d_y >= absarea.d_bottom)
		d_position.d_y = absarea.d_bottom -1;

	if (d_position.d_y < absarea.d_top)
		d_position.d_y = absarea.d_top;

	if (d_position.d_x < absarea.d_left)
		d_position.d_x = absarea.d_left;
}

/*************************************************************************
	Set the area that the mouse cursor is constrained to.
*************************************************************************/
void MouseCursor::setConstraintArea(const Rect* area)
{
	Rect renderer_area = System::getSingleton().getRenderer()->getRect();

	if (!area)
	{
		d_constraints.d_min.d_x = cegui_reldim(renderer_area.d_left / renderer_area.getWidth());
		d_constraints.d_min.d_y = cegui_reldim(renderer_area.d_top / renderer_area.getHeight());
		d_constraints.d_max.d_x = cegui_reldim(renderer_area.d_right / renderer_area.getWidth());
		d_constraints.d_max.d_y = cegui_reldim(renderer_area.d_bottom / renderer_area.getHeight());
	}
	else
	{
        Rect finalArea(area->getIntersection(renderer_area));
		d_constraints.d_min.d_x = cegui_reldim(finalArea.d_left / renderer_area.getWidth());
		d_constraints.d_min.d_y = cegui_reldim(finalArea.d_top / renderer_area.getHeight());
		d_constraints.d_max.d_x = cegui_reldim(finalArea.d_right / renderer_area.getWidth());
		d_constraints.d_max.d_y = cegui_reldim(finalArea.d_bottom / renderer_area.getHeight());
	}

	constrainPosition();
}

/*************************************************************************
	Set the area that the mouse cursor is constrained to.
*************************************************************************/
void MouseCursor::setUnifiedConstraintArea(const URect* area)
{
	Rect renderer_area = System::getSingleton().getRenderer()->getRect();

	if (area)
	{
        d_constraints = *area;
	}
	else
	{
		d_constraints.d_min.d_x = cegui_reldim(renderer_area.d_left / renderer_area.getWidth());
		d_constraints.d_min.d_y = cegui_reldim(renderer_area.d_top / renderer_area.getHeight());
		d_constraints.d_max.d_x = cegui_reldim(renderer_area.d_right / renderer_area.getWidth());
		d_constraints.d_max.d_y = cegui_reldim(renderer_area.d_bottom / renderer_area.getHeight());
	}

	constrainPosition();
}

/*************************************************************************
	Set the area that the mouse cursor is constrained to.
*************************************************************************/
Rect MouseCursor::getConstraintArea(void) const
{
    return Rect(d_constraints.asAbsolute(System::getSingleton().getRenderer()->getSize()));
}

/*************************************************************************
	Set the area that the mouse cursor is constrained to.
*************************************************************************/
const URect& MouseCursor::getUnifiedConstraintArea(void) const
{
    return d_constraints;
}

/*************************************************************************
	Return the current mouse cursor position in display resolution
	independant values.
*************************************************************************/
Point MouseCursor::getDisplayIndependantPosition(void) const
{
	Size dsz(System::getSingleton().getRenderer()->getSize());

	return Point(d_position.d_x / (dsz.d_width - 1.0f), d_position.d_y / (dsz.d_height - 1.0f));
}

//////////////////////////////////////////////////////////////////////////
/*************************************************************************

	Begin event triggers section

*************************************************************************/
//////////////////////////////////////////////////////////////////////////

void MouseCursor::onImageChanged(MouseCursorEventArgs& e)
{
	fireEvent(EventImageChanged, e, EventNamespace);
}

MouseCursor& MouseCursor::getSingleton(void)
{
	return Singleton<MouseCursor>::getSingleton();
}

MouseCursor* MouseCursor::getSingletonPtr(void)
{
	return Singleton<MouseCursor>::getSingletonPtr();
}

} // End of  CEGUI namespace section
<|endoftext|>


<commit_before><commit_msg>GSvar: fixed crash when opening GSvar file and GenLab is not available.<commit_after><|endoftext|>


<commit_before>//
//
// Copyright (c) 2017 Ivan Baidakou (basiliscos) (the dot dmol at gmail dot com)
//
// Distributed under the MIT Software License
//
#pragma once

#include <algorithm>
#include <cassert>
#include <type_traits>

#include "common.ipp"

namespace bredis {

template <typename NextLayer>
template <typename WriteCallback>
void Connection<NextLayer>::async_write(const command_wrapper_t &command,
                                        WriteCallback write_callback) {
    namespace asio = boost::asio;
    namespace sys = boost::system;

    auto str = std::make_shared<std::string>(
        boost::apply_visitor(command_serializer_visitor(), command));
    auto str_ptr = str.get();
    BREDIS_LOG_DEBUG("async_write >> " << str_ptr->c_str());
    asio::const_buffers_1 output_buf =
        asio::buffer(str_ptr->c_str(), str_ptr->size());

    asio::async_write(stream_, output_buf,
                      [str, write_callback](const sys::error_code &error_code,
                                            std::size_t bytes_transferred) {
                          write_callback(error_code);
                      });
}

template <typename NextLayer>
template <typename ReadCallback, typename DynamicBuffer>
void Connection<NextLayer>::async_read(DynamicBuffer &rx_buff,
                                       ReadCallback read_callback,
                                       std::size_t replies_count) {

    namespace asio = boost::asio;
    namespace sys = boost::system;

    BREDIS_LOG_DEBUG("async_read");

    asio::async_read_until(
        stream_, rx_buff, MatchResult(replies_count),
        [read_callback, &rx_buff, replies_count](
            const sys::error_code &error_code, std::size_t bytes_transferred) {
            if (error_code) {
                read_callback(error_code, {}, 0);
                return;
            }

            auto const_buff = rx_buff.data();
            const char *char_ptr =
                boost::asio::buffer_cast<const char *>(const_buff);
            auto size = rx_buff.size();
            BREDIS_LOG_DEBUG("incoming data("
                             << size << ") : " << char_ptr
                             << ", tx bytes: " << bytes_transferred);

            array_holder_t results;
            results.elements.reserve(replies_count);
            size_t cumulative_consumption = 0;
            boost::system::error_code ec;

            do {
                string_t data(char_ptr + cumulative_consumption,
                              size - cumulative_consumption);
                BREDIS_LOG_DEBUG("trying to get response # "
                                 << results.elements.size());
                BREDIS_LOG_DEBUG("trying to get response from " << data);
                auto parse_result = Protocol::parse(data);
                auto *parse_error = boost::get<protocol_error_t>(&parse_result);
                if (parse_error) {
                    /* might happen only in case of protocol error */
                    BREDIS_LOG_DEBUG("protocol error: " << parse_error->what);
                    auto parse_error_code =
                        Error::make_error_code(bredis_errors::protocol_error);
                    read_callback(parse_error_code, {}, 0);
                    return;
                }
                auto &positive_result =
                    boost::get<positive_parse_result_t>(parse_result);
                results.elements.emplace_back(positive_result.result);
                cumulative_consumption += positive_result.consumed;
            } while (results.elements.size() < replies_count);

            if (replies_count == 1) {
                read_callback(ec, std::move(results.elements[0]),
                              cumulative_consumption);
            } else {
                read_callback(ec, std::move(results), cumulative_consumption);
            }
        });
}

template <typename NextLayer>
void Connection<NextLayer>::write(const command_wrapper_t &command) {
    namespace asio = boost::asio;
    namespace sys = boost::system;

    auto str = boost::apply_visitor(command_serializer_visitor(), command);
    BREDIS_LOG_DEBUG("async_write >> " << str);
    asio::const_buffers_1 output_buf = asio::buffer(str.c_str(), str.size());
    asio::write(stream_, output_buf);
}

template <typename NextLayer>
void Connection<NextLayer>::write(const command_wrapper_t &command,
                                  boost::system::error_code &ec) {
    namespace asio = boost::asio;
    namespace sys = boost::system;

    auto str = boost::apply_visitor(command_serializer_visitor(), command);
    BREDIS_LOG_DEBUG("async_write >> " << str);
    asio::const_buffers_1 output_buf = asio::buffer(str.c_str(), str.size());
    asio::write(stream_, output_buf, ec);
}

template <typename NextLayer>
template <typename DynamicBuffer>
positive_parse_result_t Connection<NextLayer>::read(DynamicBuffer &rx_buff) {
    namespace asio = boost::asio;
    namespace sys = boost::system;

    auto rx_bytes = asio::read_until(stream_, rx_buff, MatchResult(1));

    const char *char_ptr =
        boost::asio::buffer_cast<const char *>(rx_buff.data());
    auto size = rx_buff.size();
    string_t data(char_ptr, size);
    BREDIS_LOG_DEBUG("incoming data(" << size << ") : " << char_ptr);

    auto parse_result = Protocol::parse(data);
    auto *parse_error = boost::get<protocol_error_t>(&parse_result);
    if (parse_error) {
        BREDIS_LOG_DEBUG("protocol error: " << parse_error->what);
        throw Error::make_error_code(bredis_errors::protocol_error);
    }
    return boost::get<positive_parse_result_t>(parse_result);
}

template <typename NextLayer>
template <typename DynamicBuffer>
positive_parse_result_t
Connection<NextLayer>::read(DynamicBuffer &rx_buff,
                            boost::system::error_code &ec) {
    namespace asio = boost::asio;
    namespace sys = boost::system;

    auto rx_bytes = asio::read_until(stream_, rx_buff, MatchResult(1), ec);

    const char *char_ptr =
        boost::asio::buffer_cast<const char *>(rx_buff.data());
    auto size = rx_buff.size();
    string_t data(char_ptr, size);
    BREDIS_LOG_DEBUG("incoming data(" << size << ") : " << char_ptr);

    auto parse_result = Protocol::parse(data);
    auto *parse_error = boost::get<protocol_error_t>(&parse_result);
    if (parse_error) {
        BREDIS_LOG_DEBUG("protocol error: " << parse_error->what);
        ec = Error::make_error_code(bredis_errors::protocol_error);
        return positive_parse_result_t{{}, 0};
    }
    return boost::get<positive_parse_result_t>(parse_result);
}

} // namespace bredis
<commit_msg>Check for error code early<commit_after>//
//
// Copyright (c) 2017 Ivan Baidakou (basiliscos) (the dot dmol at gmail dot com)
//
// Distributed under the MIT Software License
//
#pragma once

#include <algorithm>
#include <cassert>
#include <type_traits>

#include "common.ipp"

namespace bredis {

template <typename NextLayer>
template <typename WriteCallback>
void Connection<NextLayer>::async_write(const command_wrapper_t &command,
                                        WriteCallback write_callback) {
    namespace asio = boost::asio;
    namespace sys = boost::system;

    auto str = std::make_shared<std::string>(
        boost::apply_visitor(command_serializer_visitor(), command));
    auto str_ptr = str.get();
    BREDIS_LOG_DEBUG("async_write >> " << str_ptr->c_str());
    asio::const_buffers_1 output_buf =
        asio::buffer(str_ptr->c_str(), str_ptr->size());

    asio::async_write(stream_, output_buf,
                      [str, write_callback](const sys::error_code &error_code,
                                            std::size_t bytes_transferred) {
                          write_callback(error_code);
                      });
}

template <typename NextLayer>
template <typename ReadCallback, typename DynamicBuffer>
void Connection<NextLayer>::async_read(DynamicBuffer &rx_buff,
                                       ReadCallback read_callback,
                                       std::size_t replies_count) {

    namespace asio = boost::asio;
    namespace sys = boost::system;

    BREDIS_LOG_DEBUG("async_read");

    asio::async_read_until(
        stream_, rx_buff, MatchResult(replies_count),
        [read_callback, &rx_buff, replies_count](
            const sys::error_code &error_code, std::size_t bytes_transferred) {
            if (error_code) {
                read_callback(error_code, {}, 0);
                return;
            }

            auto const_buff = rx_buff.data();
            const char *char_ptr =
                boost::asio::buffer_cast<const char *>(const_buff);
            auto size = rx_buff.size();
            BREDIS_LOG_DEBUG("incoming data("
                             << size << ") : " << char_ptr
                             << ", tx bytes: " << bytes_transferred);

            array_holder_t results;
            results.elements.reserve(replies_count);
            size_t cumulative_consumption = 0;
            boost::system::error_code ec;

            do {
                string_t data(char_ptr + cumulative_consumption,
                              size - cumulative_consumption);
                BREDIS_LOG_DEBUG("trying to get response # "
                                 << results.elements.size());
                BREDIS_LOG_DEBUG("trying to get response from " << data);
                auto parse_result = Protocol::parse(data);
                auto *parse_error = boost::get<protocol_error_t>(&parse_result);
                if (parse_error) {
                    /* might happen only in case of protocol error */
                    BREDIS_LOG_DEBUG("protocol error: " << parse_error->what);
                    auto parse_error_code =
                        Error::make_error_code(bredis_errors::protocol_error);
                    read_callback(parse_error_code, {}, 0);
                    return;
                }
                auto &positive_result =
                    boost::get<positive_parse_result_t>(parse_result);
                results.elements.emplace_back(positive_result.result);
                cumulative_consumption += positive_result.consumed;
            } while (results.elements.size() < replies_count);

            if (replies_count == 1) {
                read_callback(ec, std::move(results.elements[0]),
                              cumulative_consumption);
            } else {
                read_callback(ec, std::move(results), cumulative_consumption);
            }
        });
}

template <typename NextLayer>
void Connection<NextLayer>::write(const command_wrapper_t &command) {
    namespace asio = boost::asio;
    namespace sys = boost::system;

    auto str = boost::apply_visitor(command_serializer_visitor(), command);
    BREDIS_LOG_DEBUG("async_write >> " << str);
    asio::const_buffers_1 output_buf = asio::buffer(str.c_str(), str.size());
    asio::write(stream_, output_buf);
}

template <typename NextLayer>
void Connection<NextLayer>::write(const command_wrapper_t &command,
                                  boost::system::error_code &ec) {
    namespace asio = boost::asio;
    namespace sys = boost::system;

    auto str = boost::apply_visitor(command_serializer_visitor(), command);
    BREDIS_LOG_DEBUG("async_write >> " << str);
    asio::const_buffers_1 output_buf = asio::buffer(str.c_str(), str.size());
    asio::write(stream_, output_buf, ec);
}

template <typename NextLayer>
template <typename DynamicBuffer>
positive_parse_result_t Connection<NextLayer>::read(DynamicBuffer &rx_buff) {
    namespace asio = boost::asio;
    namespace sys = boost::system;

    auto rx_bytes = asio::read_until(stream_, rx_buff, MatchResult(1));

    const char *char_ptr =
        boost::asio::buffer_cast<const char *>(rx_buff.data());
    auto size = rx_buff.size();
    string_t data(char_ptr, size);
    BREDIS_LOG_DEBUG("incoming data(" << size << ") : " << char_ptr);

    auto parse_result = Protocol::parse(data);
    auto *parse_error = boost::get<protocol_error_t>(&parse_result);
    if (parse_error) {
        BREDIS_LOG_DEBUG("protocol error: " << parse_error->what);
        throw Error::make_error_code(bredis_errors::protocol_error);
    }
    return boost::get<positive_parse_result_t>(parse_result);
}

template <typename NextLayer>
template <typename DynamicBuffer>
positive_parse_result_t
Connection<NextLayer>::read(DynamicBuffer &rx_buff,
                            boost::system::error_code &ec) {
    namespace asio = boost::asio;
    namespace sys = boost::system;

    auto rx_bytes = asio::read_until(stream_, rx_buff, MatchResult(1), ec);
    if (ec) {
        return positive_parse_result_t{{}, 0};
    }

    const char *char_ptr =
        boost::asio::buffer_cast<const char *>(rx_buff.data());
    auto size = rx_buff.size();
    string_t data(char_ptr, size);
    BREDIS_LOG_DEBUG("incoming data(" << size << ") : " << char_ptr);

    auto parse_result = Protocol::parse(data);
    auto *parse_error = boost::get<protocol_error_t>(&parse_result);
    if (parse_error) {
        BREDIS_LOG_DEBUG("protocol error: " << parse_error->what);
        ec = Error::make_error_code(bredis_errors::protocol_error);
        return positive_parse_result_t{{}, 0};
    }
    return boost::get<positive_parse_result_t>(parse_result);
}

} // namespace bredis
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: ContentInfo.hxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: rt $ $Date: 2004-09-08 17:10:52 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): Martin Gallwey (gallwey@sun.com)
 *
 *
 ************************************************************************/
#ifndef _CONTENT_INFO_HXX_
#define _CONTENT_INFO_HXX_

#ifndef _COM_SUN_STAR_CONTAINER_XNAMECONTAINER_HPP_
#include <com/sun/star/container/XNameContainer.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_XUNOTUNNEl_HPP_
#include <com/sun/star/lang/XUnoTunnel.hpp>
#endif
#ifndef _ZIP_PACKAGE_FOLDER_HXX
#include <ZipPackageFolder.hxx>
#endif
#ifndef _ZIP_PACKAGE_STREAM_HXX
#include <ZipPackageStream.hxx>
#endif

namespace com { namespace sun { namespace star { namespace packages {
class ContentInfo : public cppu::OWeakObject
{
public:
    com::sun::star::uno::Reference < com::sun::star::lang::XUnoTunnel > xTunnel;
    bool bFolder;
    union
    {
        ZipPackageFolder *pFolder;
        ZipPackageStream *pStream;
    };
    ContentInfo ( ZipPackageStream * pNewStream )
    : bFolder ( false )
    , pStream ( pNewStream )
    , xTunnel ( pNewStream )
    {
    }
    ContentInfo ( ZipPackageFolder * pNewFolder )
    : bFolder ( true )
    , pFolder ( pNewFolder )
    , xTunnel ( pNewFolder )
    {
    }
    virtual ~ContentInfo ()
    {
        if ( bFolder )
            pFolder->releaseUpwardRef();
    }
};
} } } };
#endif
<commit_msg>INTEGRATION: CWS mav09 (1.4.86); FILE MERGED 2004/09/17 00:04:48 mav 1.4.86.2: RESYNC: (1.4-1.5); FILE MERGED 2004/08/06 09:56:51 mav 1.4.86.1: #i29833# reimplement folders and streams life dependencies<commit_after>/*************************************************************************
 *
 *  $RCSfile: ContentInfo.hxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: kz $ $Date: 2004-10-04 21:08:42 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): Martin Gallwey (gallwey@sun.com)
 *
 *
 ************************************************************************/
#ifndef _CONTENT_INFO_HXX_
#define _CONTENT_INFO_HXX_

#ifndef _COM_SUN_STAR_CONTAINER_XNAMECONTAINER_HPP_
#include <com/sun/star/container/XNameContainer.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_XUNOTUNNEl_HPP_
#include <com/sun/star/lang/XUnoTunnel.hpp>
#endif
#ifndef _ZIP_PACKAGE_FOLDER_HXX
#include <ZipPackageFolder.hxx>
#endif
#ifndef _ZIP_PACKAGE_STREAM_HXX
#include <ZipPackageStream.hxx>
#endif

namespace com { namespace sun { namespace star { namespace packages {
class ContentInfo : public cppu::OWeakObject
{
public:
    com::sun::star::uno::Reference < com::sun::star::lang::XUnoTunnel > xTunnel;
    bool bFolder;
    union
    {
        ZipPackageFolder *pFolder;
        ZipPackageStream *pStream;
    };
    ContentInfo ( ZipPackageStream * pNewStream )
    : bFolder ( false )
    , pStream ( pNewStream )
    , xTunnel ( pNewStream )
    {
    }
    ContentInfo ( ZipPackageFolder * pNewFolder )
    : bFolder ( true )
    , pFolder ( pNewFolder )
    , xTunnel ( pNewFolder )
    {
    }
    virtual ~ContentInfo ()
    {
        if ( bFolder )
            pFolder->releaseUpwardRef();
        else
            pStream->clearParent();
    }
};
} } } };
#endif
<|endoftext|>