<commit_before>/**
 * \file
 * \brief FpuSignalTestCase class implementation for ARMv7-M (Cortex-M3 / Cortex-M4)
 *
 * \author Copyright (C) 2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
 *
 * \par License
 * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
 * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * \date 2015-11-11
 */

#include "ARMv7-M-FpuSignalTestCase.hpp"

#include "distortos/chip/CMSIS-proxy.h"

#if __FPU_PRESENT == 1 && __FPU_USED == 1

#include "checkFpuRegisters.hpp"
#include "setFpuRegisters.hpp"

#include "distortos/StaticSoftwareTimer.hpp"
#include "distortos/StaticThread.hpp"
#include "distortos/statistics.hpp"
#include "distortos/ThisThread.hpp"
#include "distortos/ThisThread-Signals.hpp"

#include <cerrno>

#endif	// __FPU_PRESENT == 1 && __FPU_USED == 1

namespace distortos
{

namespace test
{

#if __FPU_PRESENT == 1 && __FPU_USED == 1

namespace
{

/*---------------------------------------------------------------------------------------------------------------------+
| local types
+---------------------------------------------------------------------------------------------------------------------*/

/// values used in single test stage
struct Stage
{
	/// value written to all FPU registers in main thread, don't use FPU in main thread if 0
	uint32_t threadValue;

	/// value written to "lower" FPU registers in "sender" before queuing of signal, skip this step if 0
	uint32_t senderValueBefore;

	/// value written to "lower" FPU registers in "sender" after queuing of signal, skip this step if 0
	uint32_t senderValueAfter;

	/// signal value, written to "lower" FPU registers in handler, don't use FPU in handler if 0
	int signalValue;
};

/// description of single test phase
struct Phase
{
	/// type of "sender" function
	using Sender = int(Thread&, const Stage&);

	/// reference to "sender" function
	Sender& sender;

	/// expected number of context switches for single stage executed in this phase
	decltype(statistics::getContextSwitchCount()) contextSwitchCount;
};

/*---------------------------------------------------------------------------------------------------------------------+
| local constants
+---------------------------------------------------------------------------------------------------------------------*/

/// tested signal number
constexpr uint8_t testSignalNumber {16};

/// size of stack for test thread, bytes
constexpr size_t testThreadStackSize {512};

/*---------------------------------------------------------------------------------------------------------------------+
| local functions
+---------------------------------------------------------------------------------------------------------------------*/

/**
 * \brief Disables FPU context for current thread by clearing FPCA bit in CONTROL register.
 */

void disableFpuContext()
{
	const auto control = __get_CONTROL();
	__set_CONTROL(control & ~CONTROL_FPCA_Msk);
}

/**
 * \brief Signal handler
 *
 * Sets "lower" FPU registers (s0-s15 and FPSCR) using the value queued with signal, unless this value is 0.
 *
 * \param [in] signalInformation is a reference to received SignalInformation object
 */

void handler(const SignalInformation& signalInformation)
{
	const auto value = signalInformation.getValue().sival_int;
	if (value == 0)
		return;

	setFpuRegisters(value, false);
}

/**
 * \brief Tests whether FPU context is active for current thread.
 *
 * \return true if FPU context is active for current thread (FPCA bit in CONTROL register is set), false otherwise
 */

bool isFpuContextActive()
{
	const auto control = __get_CONTROL();
	return (control & CONTROL_FPCA_Msk) != 0;
}

/**
 * \brief Test wrapper for Thread::queueSignal() that also modifies FPU registers.
 *
 * \param [in] thread is a reference to thread to which the signal will be queued
 * \param [in] stage is a reference to test stage
 * \param [in] full is the \a full argument passed to setFpuRegisters()
 * \param [in] sharedRet is a reference to int variable which will be written with 0 on success, error code otherwise
 */

void queueSignalWrapper(Thread& thread, const Stage& stage, const bool full, int& sharedRet)
{
	if (stage.senderValueBefore != 0)	// should FPU be used at the beginning of "sender"?
		setFpuRegisters(stage.senderValueBefore, full);

	sharedRet = thread.queueSignal(testSignalNumber, sigval{stage.signalValue});

	if (stage.senderValueAfter != 0)	// should FPU be used at th"sender""sender"?
		setFpuRegisters(stage.senderValueAfter, full);
}

/**
 * \brief Queues signal from interrupt (via software timer) to current thread.
 *
 * \param [in] thread is a reference to thread to which the signal will be queued
 * \param [in] stage is a reference to test stage
 *
 * \return 0 on success, error code otherwise:
 * - error codes returned by Thread::queueSignal();
 */

int queueSignalFromInterrupt(Thread& thread, const Stage& stage)
{
	int sharedRet {EINVAL};
	auto softwareTimer = makeStaticSoftwareTimer(queueSignalWrapper, std::ref(thread), std::ref(stage), false,
			std::ref(sharedRet));

	softwareTimer.start(TickClock::duration{});
	while (softwareTimer.isRunning() == true);

	return sharedRet;
}

/**
 * \brief Queues signal from thread to non-current thread.
 *
 * \param [in] thread is a reference to thread to which the signal will be queued
 * \param [in] stage is a reference to test stage
 *
 * \return 0 on success, error code otherwise:
 * - error codes returned by Thread::queueSignal();
 */

int queueSignalFromThread(Thread& thread, const Stage& stage)
{
	constexpr decltype(FpuSignalTestCase::getTestCasePriority()) highPriority
	{
			FpuSignalTestCase::getTestCasePriority() + 1
	};

	int sharedRet {EINVAL};
	auto testThread = makeStaticThread<testThreadStackSize>(highPriority, queueSignalWrapper, std::ref(thread),
			std::ref(stage), true, std::ref(sharedRet));

	testThread.start();
	testThread.join();

	return sharedRet;
}

/*---------------------------------------------------------------------------------------------------------------------+
| local constants
+---------------------------------------------------------------------------------------------------------------------*/

/// test phasese
const Phase phases[]
{
		{queueSignalFromInterrupt, 0},
		{queueSignalFromThread, 2},
};

/// test stages
const Stage stages[]
{
		{0, 0, 0, 0},								// don't use FPU in all contexts
		{0, 0, 0, 0x0b39fa96},						// in handler
		{0, 0, 0x8606151d, 0},						// in "sender" (at the end)
		{0, 0, 0x8bdd3b5e, 0x7d21d1c6},				// in "sender" (at the end) and in handler
		{0, 0x2f884196, 0, 0},						// in "sender" (at the beginning)
		{0, 0x0b0bbc86, 0, 0x0e43811b},				// in "sender" (at the beginning) and in handler
		{0, 0xb72b2917, 0x8c27baa7, 0},				// in "sender"
		{0, 0xa83b80c2, 0xd2b7dd4d, 0x626ca399},	// in "sender" and in handler
		{0xb4e40525, 0, 0, 0},						// in main thread
		{0x772bdf91, 0, 0, 0x0bb325b7},				// in main thread and in handler
		{0x8a19625e, 0, 0x32378f7b, 0},				// in main thread and in "sender" (at the end)
		{0xd17a21db, 0, 0xaa807a91, 0x03caf264},	// in main thread, in "sender" (at the end) and in handler
		{0xe4b44073, 0xa88c0cf5, 0, 0},				// in main thread and in "sender" (at the beginning)
		{0xb94c722b, 0x5f8ca773, 0, 0x288301cf},	// in main thread, in "sender" (at the beginning) and in handler
		{0x347ecfc5, 0xcb4a3584, 0x5a8bf219, 0},	// in main thread and in "sender"
		{0x788ed92e, 0x4b0ddff9, 0x73776a21, 0x48fb1969},	// in all contexts
};

}	// namespace

#endif	// __FPU_PRESENT == 1 && __FPU_USED == 1

/*---------------------------------------------------------------------------------------------------------------------+
| protected functions
+---------------------------------------------------------------------------------------------------------------------*/

bool FpuSignalTestCase::finalize() const
{
#if __FPU_PRESENT == 1 && __FPU_USED == 1

	disableFpuContext();

#endif	// __FPU_PRESENT == 1 && __FPU_USED == 1

	return SignalsTestCaseCommon::finalize();
}

/*---------------------------------------------------------------------------------------------------------------------+
| private functions
+---------------------------------------------------------------------------------------------------------------------*/

bool FpuSignalTestCase::run_() const
{
#if __FPU_PRESENT == 1 && __FPU_USED == 1

	const auto contextSwitchCount = statistics::getContextSwitchCount();
	auto expectedContextSwitchCount = decltype(contextSwitchCount){};

	{
		int ret;
		std::tie(ret, std::ignore) = ThisThread::Signals::setSignalAction(testSignalNumber,
				SignalAction{handler, SignalSet{SignalSet::empty}});
		if (ret != 0)
			return false;
	}

	auto& currentThread = ThisThread::get();

	for (auto& phase : phases)
		for (auto& stage : stages)
		{
			disableFpuContext();

			decltype(setFpuRegisters({}, {})) fpscr {};
			if (stage.threadValue != 0)	// should FPU be used in main thread?
				fpscr = setFpuRegisters(stage.threadValue, true);

			if (phase.sender(currentThread, stage) != 0)
				return false;

			// FPU context may be active only if FPU was used in main thread
			if (isFpuContextActive() != (stage.threadValue != 0))
				return false;

			if (stage.threadValue != 0)	// was FPU used in main thread?
				if (checkFpuRegisters(stage.threadValue, fpscr) == false)
					return false;

			expectedContextSwitchCount += phase.contextSwitchCount;
			if (statistics::getContextSwitchCount() - contextSwitchCount != expectedContextSwitchCount)
				return false;
		}

	if (statistics::getContextSwitchCount() - contextSwitchCount != expectedContextSwitchCount)
		return false;

	return true;

#else

	return true;

#endif	// __FPU_PRESENT == 1 && __FPU_USED == 1
}

}	// namespace test

}	// namespace distortos
<commit_msg>test: convert ARMv7-M-FpuSignalTestCase to use dynamic threads<commit_after>/**
 * \file
 * \brief FpuSignalTestCase class implementation for ARMv7-M (Cortex-M3 / Cortex-M4)
 *
 * \author Copyright (C) 2015-2016 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
 *
 * \par License
 * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
 * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * \date 2016-01-04
 */

#include "ARMv7-M-FpuSignalTestCase.hpp"

#include "distortos/chip/CMSIS-proxy.h"

#if __FPU_PRESENT == 1 && __FPU_USED == 1

#include "checkFpuRegisters.hpp"
#include "setFpuRegisters.hpp"

#include "distortos/DynamicThread.hpp"
#include "distortos/StaticSoftwareTimer.hpp"
#include "distortos/statistics.hpp"
#include "distortos/ThisThread.hpp"
#include "distortos/ThisThread-Signals.hpp"

#endif	// __FPU_PRESENT == 1 && __FPU_USED == 1

namespace distortos
{

namespace test
{

#if __FPU_PRESENT == 1 && __FPU_USED == 1

namespace
{

/*---------------------------------------------------------------------------------------------------------------------+
| local types
+---------------------------------------------------------------------------------------------------------------------*/

/// values used in single test stage
struct Stage
{
	/// value written to all FPU registers in main thread, don't use FPU in main thread if 0
	uint32_t threadValue;

	/// value written to "lower" FPU registers in "sender" before queuing of signal, skip this step if 0
	uint32_t senderValueBefore;

	/// value written to "lower" FPU registers in "sender" after queuing of signal, skip this step if 0
	uint32_t senderValueAfter;

	/// signal value, written to "lower" FPU registers in handler, don't use FPU in handler if 0
	int signalValue;
};

/// description of single test phase
struct Phase
{
	/// type of "sender" function
	using Sender = int(Thread&, const Stage&);

	/// reference to "sender" function
	Sender& sender;

	/// expected number of context switches for single stage executed in this phase
	decltype(statistics::getContextSwitchCount()) contextSwitchCount;
};

/*---------------------------------------------------------------------------------------------------------------------+
| local constants
+---------------------------------------------------------------------------------------------------------------------*/

/// tested signal number
constexpr uint8_t testSignalNumber {16};

/// size of stack for test thread, bytes
constexpr size_t testThreadStackSize {512};

/*---------------------------------------------------------------------------------------------------------------------+
| local functions
+---------------------------------------------------------------------------------------------------------------------*/

/**
 * \brief Disables FPU context for current thread by clearing FPCA bit in CONTROL register.
 */

void disableFpuContext()
{
	const auto control = __get_CONTROL();
	__set_CONTROL(control & ~CONTROL_FPCA_Msk);
}

/**
 * \brief Signal handler
 *
 * Sets "lower" FPU registers (s0-s15 and FPSCR) using the value queued with signal, unless this value is 0.
 *
 * \param [in] signalInformation is a reference to received SignalInformation object
 */

void handler(const SignalInformation& signalInformation)
{
	const auto value = signalInformation.getValue().sival_int;
	if (value == 0)
		return;

	setFpuRegisters(value, false);
}

/**
 * \brief Tests whether FPU context is active for current thread.
 *
 * \return true if FPU context is active for current thread (FPCA bit in CONTROL register is set), false otherwise
 */

bool isFpuContextActive()
{
	const auto control = __get_CONTROL();
	return (control & CONTROL_FPCA_Msk) != 0;
}

/**
 * \brief Test wrapper for Thread::queueSignal() that also modifies FPU registers.
 *
 * \param [in] thread is a reference to thread to which the signal will be queued
 * \param [in] stage is a reference to test stage
 * \param [in] full is the \a full argument passed to setFpuRegisters()
 * \param [in] sharedRet is a reference to int variable which will be written with 0 on success, error code otherwise
 */

void queueSignalWrapper(Thread& thread, const Stage& stage, const bool full, int& sharedRet)
{
	if (stage.senderValueBefore != 0)	// should FPU be used at the beginning of "sender"?
		setFpuRegisters(stage.senderValueBefore, full);

	sharedRet = thread.queueSignal(testSignalNumber, sigval{stage.signalValue});

	if (stage.senderValueAfter != 0)	// should FPU be used at th"sender""sender"?
		setFpuRegisters(stage.senderValueAfter, full);
}

/**
 * \brief Queues signal from interrupt (via software timer) to current thread.
 *
 * \param [in] thread is a reference to thread to which the signal will be queued
 * \param [in] stage is a reference to test stage
 *
 * \return 0 on success, error code otherwise:
 * - error codes returned by Thread::queueSignal();
 */

int queueSignalFromInterrupt(Thread& thread, const Stage& stage)
{
	int sharedRet {EINVAL};
	auto softwareTimer = makeStaticSoftwareTimer(queueSignalWrapper, std::ref(thread), std::ref(stage), false,
			std::ref(sharedRet));

	softwareTimer.start(TickClock::duration{});
	while (softwareTimer.isRunning() == true);

	return sharedRet;
}

/**
 * \brief Queues signal from thread to non-current thread.
 *
 * \param [in] thread is a reference to thread to which the signal will be queued
 * \param [in] stage is a reference to test stage
 *
 * \return 0 on success, error code otherwise:
 * - error codes returned by Thread::queueSignal();
 */

int queueSignalFromThread(Thread& thread, const Stage& stage)
{
	constexpr decltype(FpuSignalTestCase::getTestCasePriority()) highPriority
	{
			FpuSignalTestCase::getTestCasePriority() + 1
	};

	int sharedRet {EINVAL};
	auto testThread = makeDynamicThread({testThreadStackSize, highPriority}, queueSignalWrapper, std::ref(thread),
			std::ref(stage), true, std::ref(sharedRet));

	testThread.start();
	testThread.join();

	return sharedRet;
}

/*---------------------------------------------------------------------------------------------------------------------+
| local constants
+---------------------------------------------------------------------------------------------------------------------*/

/// test phasese
const Phase phases[]
{
		{queueSignalFromInterrupt, 0},
		{queueSignalFromThread, 2},
};

/// test stages
const Stage stages[]
{
		{0, 0, 0, 0},								// don't use FPU in all contexts
		{0, 0, 0, 0x0b39fa96},						// in handler
		{0, 0, 0x8606151d, 0},						// in "sender" (at the end)
		{0, 0, 0x8bdd3b5e, 0x7d21d1c6},				// in "sender" (at the end) and in handler
		{0, 0x2f884196, 0, 0},						// in "sender" (at the beginning)
		{0, 0x0b0bbc86, 0, 0x0e43811b},				// in "sender" (at the beginning) and in handler
		{0, 0xb72b2917, 0x8c27baa7, 0},				// in "sender"
		{0, 0xa83b80c2, 0xd2b7dd4d, 0x626ca399},	// in "sender" and in handler
		{0xb4e40525, 0, 0, 0},						// in main thread
		{0x772bdf91, 0, 0, 0x0bb325b7},				// in main thread and in handler
		{0x8a19625e, 0, 0x32378f7b, 0},				// in main thread and in "sender" (at the end)
		{0xd17a21db, 0, 0xaa807a91, 0x03caf264},	// in main thread, in "sender" (at the end) and in handler
		{0xe4b44073, 0xa88c0cf5, 0, 0},				// in main thread and in "sender" (at the beginning)
		{0xb94c722b, 0x5f8ca773, 0, 0x288301cf},	// in main thread, in "sender" (at the beginning) and in handler
		{0x347ecfc5, 0xcb4a3584, 0x5a8bf219, 0},	// in main thread and in "sender"
		{0x788ed92e, 0x4b0ddff9, 0x73776a21, 0x48fb1969},	// in all contexts
};

}	// namespace

#endif	// __FPU_PRESENT == 1 && __FPU_USED == 1

/*---------------------------------------------------------------------------------------------------------------------+
| protected functions
+---------------------------------------------------------------------------------------------------------------------*/

bool FpuSignalTestCase::finalize() const
{
#if __FPU_PRESENT == 1 && __FPU_USED == 1

	disableFpuContext();

#endif	// __FPU_PRESENT == 1 && __FPU_USED == 1

	return SignalsTestCaseCommon::finalize();
}

/*---------------------------------------------------------------------------------------------------------------------+
| private functions
+---------------------------------------------------------------------------------------------------------------------*/

bool FpuSignalTestCase::run_() const
{
#if __FPU_PRESENT == 1 && __FPU_USED == 1

	const auto contextSwitchCount = statistics::getContextSwitchCount();
	auto expectedContextSwitchCount = decltype(contextSwitchCount){};

	{
		int ret;
		std::tie(ret, std::ignore) = ThisThread::Signals::setSignalAction(testSignalNumber,
				SignalAction{handler, SignalSet{SignalSet::empty}});
		if (ret != 0)
			return false;
	}

	auto& currentThread = ThisThread::get();

	for (auto& phase : phases)
		for (auto& stage : stages)
		{
			disableFpuContext();

			decltype(setFpuRegisters({}, {})) fpscr {};
			if (stage.threadValue != 0)	// should FPU be used in main thread?
				fpscr = setFpuRegisters(stage.threadValue, true);

			if (phase.sender(currentThread, stage) != 0)
				return false;

			// FPU context may be active only if FPU was used in main thread
			if (isFpuContextActive() != (stage.threadValue != 0))
				return false;

			if (stage.threadValue != 0)	// was FPU used in main thread?
				if (checkFpuRegisters(stage.threadValue, fpscr) == false)
					return false;

			expectedContextSwitchCount += phase.contextSwitchCount;
			if (statistics::getContextSwitchCount() - contextSwitchCount != expectedContextSwitchCount)
				return false;
		}

	if (statistics::getContextSwitchCount() - contextSwitchCount != expectedContextSwitchCount)
		return false;

	return true;

#else

	return true;

#endif	// __FPU_PRESENT == 1 && __FPU_USED == 1
}

}	// namespace test

}	// namespace distortos
<|endoftext|>


<commit_before>// -*- Mode: c++-mode; c-basic-offset: 2; indent-tabs-mode: t; tab-width: 2; -*-
//
// Copyright (C) 2003 Grzegorz Jaskiewicz 	<gj at pointblue.com.pl>
//
// gadueditcontact.cpp
//
// 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-1307, USA.

#include "gaduaccount.h"
#include "gaducontact.h"
#include "gadueditcontact.h"
#include "kopeteonlinestatus.h"

#include "gaducontactlist.h"
#include "gaduadd.h"

#include <ktextedit.h>
#include <klocale.h>
#include <kdebug.h>
#include <kopetegroup.h>
#include <kopetecontactlist.h>
#include <kopetemetacontact.h>

#include <qbuttongroup.h>
#include <qradiobutton.h>
#include <qlineedit.h>
#include <qlayout.h>
#include <qlistview.h>
#include <qptrlist.h>

#include <krestrictedline.h>

// FIXME: this and gaduadcontactpage should have one base class, with some code duplicated in both.

GaduEditContact::GaduEditContact( GaduAccount* account, GaduContact* contact,
		    QWidget* parent, const char* name )
: KDialogBase( parent, name, true, i18n( "Edit Contact's Properties" ),
			 KDialogBase::Ok | KDialogBase::Cancel,
			 KDialogBase::Ok, true ), account_( account ), contact_( contact )
{
	if ( contact && account ) {
		cl_ = contact->contactDetails();
	}
	else {
		return;
	}

	init();
	fillGroups();
	fillIn();
}

GaduEditContact::GaduEditContact( GaduAccount* account,  GaduContactsList::ContactLine* clin,
		    QWidget* parent , const char* name  )
: KDialogBase( parent, name, true, i18n( "Edit Contact's Properties" ),
			 KDialogBase::Ok | KDialogBase::Cancel,
			 KDialogBase::Ok, true ), account_( account ), contact_( NULL )
{

	if ( !account ) {
		return;
	}
	cl_ = clin;
	init();
	fillGroups();
	fillIn();
}

void
GaduEditContact::fillGroups()
{
	Kopete::Group *g, *cg;
	QPtrList<Kopete::Group> cgl;
	QPtrList<Kopete::Group> gl;

	if ( contact_ ) {
		cgl = contact_->metaContact()->groups();
	}

	gl = Kopete::ContactList::self()->groups();

	for( g = gl.first(); g; g = gl.next() ) {
		if ( g->type() == Kopete::Group::Temporary ) {
			continue;
		}
		QCheckListItem* item = new QCheckListItem( ui_->groups, g->displayName(), QCheckListItem::CheckBox );
		// FIXME: optimize this O(2) search
		for( cg = cgl.first(); cg; cg = cgl.next() ) {
			if ( cg->groupId() == g->groupId() ) {
				item->setOn( TRUE );
				break;
			}
		}
		kdDebug(14100) << g->displayName() << " " << g->groupId() << endl;
	}
}

void
GaduEditContact::init()
{
	ui_ = new GaduAddUI( this );
	setMainWidget( ui_ );
	ui_->addEdit_->setValidChars( "1234567890" );

	// fill values from cl into proper fields on widget

	show();
	connect( this, SIGNAL( okClicked() ), SLOT( slotApply() ) );
	connect( ui_->groups, SIGNAL( clicked( QListViewItem * ) ), SLOT( listClicked( QListViewItem * ) ) );
}

void
GaduEditContact::listClicked( QListViewItem* item )
{

}

void
GaduEditContact::fillIn()
{
// grey it out, it shouldn't be editable
	ui_->addEdit_->setReadOnly( true );
	ui_->addEdit_->setText( cl_->uin );

	ui_->fornameEdit_->setText( cl_->firstname );
	ui_->snameEdit_->setText( cl_->surname );
	ui_->nickEdit_->setText( cl_->nickname );
	ui_->emailEdit_->setText( cl_->email );
	ui_->telephoneEdit_->setText( cl_->phonenr );
//	ui_->notAFriend_;

}

void
GaduEditContact::slotApply()
{
	QPtrList<Kopete::Group> gl;
	Kopete::Group* group;

	cl_->firstname = ui_->fornameEdit_->text().stripWhiteSpace();
	cl_->surname = ui_->snameEdit_->text().stripWhiteSpace();
	cl_->nickname = ui_->nickEdit_->text().stripWhiteSpace();
	cl_->email = ui_->emailEdit_->text().stripWhiteSpace();
	cl_->phonenr = ui_->telephoneEdit_->text().stripWhiteSpace();

	if ( contact_ == NULL ) {
		// contact doesn't exists yet, create it and set all the details
		bool s = account_->addContact( cl_->uin, GaduContact::findBestContactName( cl_ ), 0L, Kopete::Account::DontChangeKABC);
		if ( s == false ) {
			kdDebug(14100) << "There was a problem adding UIN "<< cl_->uin << "to users list" << endl;
			return;
		}
		contact_ = static_cast<GaduContact*>( account_->contacts()[ cl_->uin ] );
		if ( contact_ == NULL ) {
			kdDebug(14100) << "oops, no Kopete::Contact in contacts()[] for some reason, for \"" << cl_->uin << "\"" << endl;
			return;
		}
	}

	contact_->setContactDetails( cl_ );

	gl = Kopete::ContactList::self()->groups();
	for ( QListViewItemIterator it( ui_->groups ); it.current(); ++it ) {
		QCheckListItem *check = dynamic_cast<QCheckListItem *>( it.current() );

		if ( !check ) {
			continue;
		}

		if ( check->isOn() ) {
			for( group = gl.first(); group; group = gl.next() ) {
				if ( group->displayName() == check->text() ) {
					contact_->metaContact()->addToGroup( group );
				}
			}
		}
		else {
			// check metacontact's in the group, and if so, remove it from
			for( group = gl.first(); group; group = gl.next() ) {
				if ( group->displayName() == check->text() ) {
					contact_->metaContact()->removeFromGroup( group );
				}
			}
		}
	}

	if( contact_->metaContact()->groups().isEmpty() == TRUE )
		contact_->metaContact()->addToGroup( Kopete::Group::topLevel() );
}
#include "gadueditcontact.moc"
<commit_msg>do not whine<commit_after>// -*- Mode: c++-mode; c-basic-offset: 2; indent-tabs-mode: t; tab-width: 2; -*-
//
// Copyright (C) 2003 Grzegorz Jaskiewicz 	<gj at pointblue.com.pl>
//
// gadueditcontact.cpp
//
// 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-1307, USA.

#include "gaduaccount.h"
#include "gaducontact.h"
#include "gadueditcontact.h"
#include "kopeteonlinestatus.h"

#include "gaducontactlist.h"
#include "gaduadd.h"

#include <ktextedit.h>
#include <klocale.h>
#include <kdebug.h>
#include <kopetegroup.h>
#include <kopetecontactlist.h>
#include <kopetemetacontact.h>

#include <qbuttongroup.h>
#include <qradiobutton.h>
#include <qlineedit.h>
#include <qlayout.h>
#include <qlistview.h>
#include <qptrlist.h>

#include <krestrictedline.h>

// FIXME: this and gaduadcontactpage should have one base class, with some code duplicated in both.

GaduEditContact::GaduEditContact( GaduAccount* account, GaduContact* contact,
		    QWidget* parent, const char* name )
: KDialogBase( parent, name, true, i18n( "Edit Contact's Properties" ),
			 KDialogBase::Ok | KDialogBase::Cancel,
			 KDialogBase::Ok, true ), account_( account ), contact_( contact )
{
	if ( contact && account ) {
		cl_ = contact->contactDetails();
	}
	else {
		return;
	}

	init();
	fillGroups();
	fillIn();
}

GaduEditContact::GaduEditContact( GaduAccount* account,  GaduContactsList::ContactLine* clin,
		    QWidget* parent , const char* name  )
: KDialogBase( parent, name, true, i18n( "Edit Contact's Properties" ),
			 KDialogBase::Ok | KDialogBase::Cancel,
			 KDialogBase::Ok, true ), account_( account ), contact_( NULL )
{

	if ( !account ) {
		return;
	}
	cl_ = clin;
	init();
	fillGroups();
	fillIn();
}

void
GaduEditContact::fillGroups()
{
	Kopete::Group *g, *cg;
	QPtrList<Kopete::Group> cgl;
	QPtrList<Kopete::Group> gl;

	if ( contact_ ) {
		cgl = contact_->metaContact()->groups();
	}

	gl = Kopete::ContactList::self()->groups();

	for( g = gl.first(); g; g = gl.next() ) {
		if ( g->type() == Kopete::Group::Temporary ) {
			continue;
		}
		QCheckListItem* item = new QCheckListItem( ui_->groups, g->displayName(), QCheckListItem::CheckBox );
		// FIXME: optimize this O(2) search
		for( cg = cgl.first(); cg; cg = cgl.next() ) {
			if ( cg->groupId() == g->groupId() ) {
				item->setOn( TRUE );
				break;
			}
		}
		kdDebug(14100) << g->displayName() << " " << g->groupId() << endl;
	}
}

void
GaduEditContact::init()
{
	ui_ = new GaduAddUI( this );
	setMainWidget( ui_ );
	ui_->addEdit_->setValidChars( "1234567890" );

	// fill values from cl into proper fields on widget

	show();
	connect( this, SIGNAL( okClicked() ), SLOT( slotApply() ) );
	connect( ui_->groups, SIGNAL( clicked( QListViewItem * ) ), SLOT( listClicked( QListViewItem * ) ) );
}

void
GaduEditContact::listClicked( QListViewItem* /*item*/ )
{

}

void
GaduEditContact::fillIn()
{
// grey it out, it shouldn't be editable
	ui_->addEdit_->setReadOnly( true );
	ui_->addEdit_->setText( cl_->uin );

	ui_->fornameEdit_->setText( cl_->firstname );
	ui_->snameEdit_->setText( cl_->surname );
	ui_->nickEdit_->setText( cl_->nickname );
	ui_->emailEdit_->setText( cl_->email );
	ui_->telephoneEdit_->setText( cl_->phonenr );
//	ui_->notAFriend_;

}

void
GaduEditContact::slotApply()
{
	QPtrList<Kopete::Group> gl;
	Kopete::Group* group;

	cl_->firstname = ui_->fornameEdit_->text().stripWhiteSpace();
	cl_->surname = ui_->snameEdit_->text().stripWhiteSpace();
	cl_->nickname = ui_->nickEdit_->text().stripWhiteSpace();
	cl_->email = ui_->emailEdit_->text().stripWhiteSpace();
	cl_->phonenr = ui_->telephoneEdit_->text().stripWhiteSpace();

	if ( contact_ == NULL ) {
		// contact doesn't exists yet, create it and set all the details
		bool s = account_->addContact( cl_->uin, GaduContact::findBestContactName( cl_ ), 0L, Kopete::Account::DontChangeKABC);
		if ( s == false ) {
			kdDebug(14100) << "There was a problem adding UIN "<< cl_->uin << "to users list" << endl;
			return;
		}
		contact_ = static_cast<GaduContact*>( account_->contacts()[ cl_->uin ] );
		if ( contact_ == NULL ) {
			kdDebug(14100) << "oops, no Kopete::Contact in contacts()[] for some reason, for \"" << cl_->uin << "\"" << endl;
			return;
		}
	}

	contact_->setContactDetails( cl_ );

	gl = Kopete::ContactList::self()->groups();
	for ( QListViewItemIterator it( ui_->groups ); it.current(); ++it ) {
		QCheckListItem *check = dynamic_cast<QCheckListItem *>( it.current() );

		if ( !check ) {
			continue;
		}

		if ( check->isOn() ) {
			for( group = gl.first(); group; group = gl.next() ) {
				if ( group->displayName() == check->text() ) {
					contact_->metaContact()->addToGroup( group );
				}
			}
		}
		else {
			// check metacontact's in the group, and if so, remove it from
			for( group = gl.first(); group; group = gl.next() ) {
				if ( group->displayName() == check->text() ) {
					contact_->metaContact()->removeFromGroup( group );
				}
			}
		}
	}

	if( contact_->metaContact()->groups().isEmpty() == TRUE )
		contact_->metaContact()->addToGroup( Kopete::Group::topLevel() );
}
#include "gadueditcontact.moc"
<|endoftext|>


<commit_before>#include "rasterizer.h"

#include <stdlib.h>
#include <string.h>
#include <assert.h>

// Fine raster works on blocks of 2x2 pixels, since NEON can fine rasterize a block in parallel using SIMD-4.
// Coarse raster works on 2x2 blocks of fine blocks, since 4 fine blocks are processed in parallel. Therefore, 4x4 pixels per coarse block.
// Tile raster works on 2x2 blocks of coarse blocks, since 4 coarse blocks are processed in parallel. Therefore, 8x8 pixels per tile.
#define FRAMEBUFFER_TILE_WIDTH_IN_PIXELS 128
#define FRAMEBUFFER_COARSE_BLOCK_WIDTH_IN_PIXELS 16
#define FRAMEBUFFER_FINE_BLOCK_WIDTH_IN_PIXELS 4

// The swizzle masks, using alternating yxyxyx bit pattern for morton-code swizzling pixels in a tile.
// This makes the pixels morton code swizzled within every rasterization level (fine/coarse/tile)
// The tiles themselves are stored row major.
// For examples of this concept, see:
// https://software.intel.com/en-us/node/514045
// https://msdn.microsoft.com/en-us/library/windows/desktop/dn770442%28v=vs.85%29.aspx
#define FRAMEBUFFER_TILE_X_SWIZZLE_MASK (0x55555555 & (FRAMEBUFFER_TILE_WIDTH_IN_PIXELS - 1))
#define FRAMEBUFFER_TILE_Y_SWIZZLE_MASK (~FRAMEBUFFER_TILE_X_SWIZZLE_MASK & (FRAMEBUFFER_TILE_WIDTH_IN_PIXELS - 1))

// Convenience
#define FRAMEBUFFER_PIXELS_PER_TILE (FRAMEBUFFER_TILE_WIDTH_IN_PIXELS * FRAMEBUFFER_TILE_WIDTH_IN_PIXELS)

// If there are too many commands and this buffer gets filled up,
// then the command buffer for that tile must be flushed.
#define TILE_COMMAND_BUFFER_SIZE_IN_DWORDS 128

typedef struct tile_cmdbuf_t
{
    // start and past-the-end of the allocation for the buffer
    uint32_t* cmdbuf_start;
    uint32_t* cmdbuf_end;
    // the next location where to read and write commands
    uint32_t* cmdbuf_read;
    uint32_t* cmdbuf_write;
} tile_cmdbuf_t;

typedef struct framebuffer_t
{
    pixel_t* backbuffer;

    uint32_t* tile_cmdpool;
    tile_cmdbuf_t* tile_cmdbufs;

    uint32_t width_in_pixels;
    uint32_t height_in_pixels;

    // num_tiles_per_row * num_pixels_per_tile
    uint32_t pixels_per_row_of_tiles;

    // pixels_per_row_of_tiles * num_tile_rows
    uint32_t pixels_per_slice;
} framebuffer_t;

framebuffer_t* new_framebuffer(uint32_t width, uint32_t height)
{
    // limits of the rasterizer's precision
    // this is based on an analysis of the range of results of the 2D cross product between two fixed16.8 numbers.
    assert(width < 16384);
    assert(height < 16384);

    framebuffer_t* fb = (framebuffer_t*)malloc(sizeof(framebuffer_t));
    assert(fb);

    fb->width_in_pixels = width;
    fb->height_in_pixels = height;

    // pad framebuffer up to size of next tile
    // that way the rasterization code doesn't have to handlep otential out of bounds access after tile binning
    uint32_t padded_width_in_pixels = (width + (FRAMEBUFFER_TILE_WIDTH_IN_PIXELS - 1)) & -FRAMEBUFFER_TILE_WIDTH_IN_PIXELS;
    uint32_t padded_height_in_pixels = (height + (FRAMEBUFFER_TILE_WIDTH_IN_PIXELS - 1)) & -FRAMEBUFFER_TILE_WIDTH_IN_PIXELS;

    uint32_t width_in_tiles = padded_width_in_pixels / FRAMEBUFFER_TILE_WIDTH_IN_PIXELS;
    uint32_t height_in_tiles = padded_height_in_pixels / FRAMEBUFFER_TILE_WIDTH_IN_PIXELS;
    uint32_t total_num_tiles = width_in_tiles * height_in_tiles;

    fb->pixels_per_row_of_tiles = padded_width_in_pixels * FRAMEBUFFER_TILE_WIDTH_IN_PIXELS;
    fb->pixels_per_slice = padded_height_in_pixels / FRAMEBUFFER_TILE_WIDTH_IN_PIXELS * fb->pixels_per_row_of_tiles;

    fb->backbuffer = (pixel_t*)malloc(fb->pixels_per_slice * sizeof(pixel_t));
    assert(fb->backbuffer);

    // clear to black/transparent initially
    memset(fb->backbuffer, 0, fb->pixels_per_slice * sizeof(pixel_t));

    fb->tile_cmdpool = (uint32_t*)malloc(total_num_tiles * TILE_COMMAND_BUFFER_SIZE_IN_DWORDS * sizeof(uint32_t));
    assert(fb->tile_cmdpool);

    fb->tile_cmdbufs = (tile_cmdbuf_t*)malloc(total_num_tiles * sizeof(tile_cmdbuf_t));
    assert(fb->tile_cmdbufs);

    for (uint32_t i = 0; i < total_num_tiles; i++)
    {
        fb->tile_cmdbufs[i].cmdbuf_start = &fb->tile_cmdpool[i * TILE_COMMAND_BUFFER_SIZE_IN_DWORDS];
        fb->tile_cmdbufs[i].cmdbuf_end = fb->tile_cmdbufs[i].cmdbuf_start + TILE_COMMAND_BUFFER_SIZE_IN_DWORDS;
        fb->tile_cmdbufs[i].cmdbuf_read = fb->tile_cmdbufs[i].cmdbuf_start;
        fb->tile_cmdbufs[i].cmdbuf_write = fb->tile_cmdbufs[i].cmdbuf_start;
    }

    return fb;
}

void delete_framebuffer(framebuffer_t* fb)
{
    if (!fb)
        return;

    free(fb->tile_cmdbufs);
    free(fb->tile_cmdpool);
    free(fb->backbuffer);
    free(fb);
}

void framebuffer_resolve(framebuffer_t* fb)
{

}

void framebuffer_pack_row_major(framebuffer_t* fb, uint32_t x, uint32_t y, uint32_t width, uint32_t height, pixelformat_t format, void* data)
{
    assert(fb);
    assert(x < fb->width_in_pixels);
    assert(y < fb->height_in_pixels);
    assert(width <= fb->width_in_pixels);
    assert(height <= fb->height_in_pixels);
    assert(x + width <= fb->width_in_pixels);
    assert(y + height <= fb->height_in_pixels);
    assert(data);

    uint32_t topleft_tile_y = y / FRAMEBUFFER_TILE_WIDTH_IN_PIXELS;
    uint32_t topleft_tile_x = x / FRAMEBUFFER_TILE_WIDTH_IN_PIXELS;
    uint32_t bottomright_tile_y = (y + (height - 1)) / FRAMEBUFFER_TILE_WIDTH_IN_PIXELS;
    uint32_t bottomright_tile_x = (x + (width - 1)) / FRAMEBUFFER_TILE_WIDTH_IN_PIXELS;

    uint32_t dst_i = 0;

    uint32_t curr_tile_row_start = topleft_tile_y * fb->pixels_per_row_of_tiles + topleft_tile_x * FRAMEBUFFER_PIXELS_PER_TILE;
    for (uint32_t tile_y = topleft_tile_y; tile_y <= bottomright_tile_y; tile_y++)
    {
        uint32_t curr_tile_start = curr_tile_row_start;

        for (uint32_t tile_x = topleft_tile_x; tile_x <= bottomright_tile_x; tile_x++)
        {
            for (uint32_t pixel_y = 0, pixel_y_bits = 0;
                pixel_y < FRAMEBUFFER_TILE_WIDTH_IN_PIXELS;
                pixel_y++, pixel_y_bits = (pixel_y_bits - FRAMEBUFFER_TILE_Y_SWIZZLE_MASK) & FRAMEBUFFER_TILE_Y_SWIZZLE_MASK)
            {
                for (uint32_t pixel_x = 0, pixel_x_bits = 0;
                    pixel_x < FRAMEBUFFER_TILE_WIDTH_IN_PIXELS;
                    pixel_x++, pixel_x_bits = (pixel_x_bits - FRAMEBUFFER_TILE_X_SWIZZLE_MASK) & FRAMEBUFFER_TILE_X_SWIZZLE_MASK)
                {
                    uint32_t src_y = tile_y * FRAMEBUFFER_TILE_WIDTH_IN_PIXELS + pixel_y;
                    uint32_t src_x = tile_x * FRAMEBUFFER_TILE_WIDTH_IN_PIXELS + pixel_x;

                    // don't copy pixels outside src rectangle region
                    if (src_y < y || src_y >= y + height)
                        continue;
                    if (src_x < x || src_x >= x + width)
                        continue;

                    uint32_t src_i = curr_tile_start + (pixel_y_bits | pixel_x_bits);
                    pixel_t src = fb->backbuffer[src_i];
                    if (format == pixelformat_r8g8b8a8_unorm)
                    {
                        uint8_t* dst = (uint8_t*)data + dst_i * 4;
                        dst[0] = (uint8_t)((src & 0x00FF0000) >> 16);
                        dst[1] = (uint8_t)((src & 0x0000FF00) >> 8);
                        dst[2] = (uint8_t)((src & 0x000000FF) >> 0);
                        dst[3] = (uint8_t)((src & 0xFF000000) >> 24);
                    }
                    else if (format == pixelformat_b8g8r8a8_unorm)
                    {
                        uint8_t* dst = (uint8_t*)data + dst_i * 4;
                        dst[0] = (uint8_t)((src & 0x000000FF) >> 0);
                        dst[1] = (uint8_t)((src & 0x0000FF00) >> 8);
                        dst[2] = (uint8_t)((src & 0x00FF0000) >> 16);
                        dst[3] = (uint8_t)((src & 0xFF000000) >> 24);
                    }
                    else
                    {
                        assert(!"Unknown pixel format");
                    }

                    dst_i++;
                }
            }

            curr_tile_start += FRAMEBUFFER_PIXELS_PER_TILE;
        }

        curr_tile_row_start += fb->pixels_per_row_of_tiles;
    }
}

// hack
uint32_t g_Color;

void rasterize_triangle_fixed16_8(
    framebuffer_t* fb,
    uint32_t window_x0, uint32_t window_y0, uint32_t window_z0,
    uint32_t window_x1, uint32_t window_y1, uint32_t window_z1,
    uint32_t window_x2, uint32_t window_y2, uint32_t window_z2)
{
}<commit_msg>changed order<commit_after>#include "rasterizer.h"

#include <stdlib.h>
#include <string.h>
#include <assert.h>

// Currently sized according to the Larrabee rasterizer's description
#define FRAMEBUFFER_TILE_WIDTH_IN_PIXELS 128
#define FRAMEBUFFER_COARSE_BLOCK_WIDTH_IN_PIXELS 16
#define FRAMEBUFFER_FINE_BLOCK_WIDTH_IN_PIXELS 4

// Convenience
#define FRAMEBUFFER_PIXELS_PER_TILE (FRAMEBUFFER_TILE_WIDTH_IN_PIXELS * FRAMEBUFFER_TILE_WIDTH_IN_PIXELS)

// The swizzle masks, using alternating yxyxyx bit pattern for morton-code swizzling pixels in a tile.
// This makes the pixels morton code swizzled within every rasterization level (fine/coarse/tile)
// The tiles themselves are stored row major.
// For examples of this concept, see:
// https://software.intel.com/en-us/node/514045
// https://msdn.microsoft.com/en-us/library/windows/desktop/dn770442%28v=vs.85%29.aspx
#define FRAMEBUFFER_TILE_X_SWIZZLE_MASK (0x55555555 & (FRAMEBUFFER_TILE_WIDTH_IN_PIXELS - 1))
#define FRAMEBUFFER_TILE_Y_SWIZZLE_MASK (~FRAMEBUFFER_TILE_X_SWIZZLE_MASK & (FRAMEBUFFER_TILE_WIDTH_IN_PIXELS - 1))

// If there are too many commands and this buffer gets filled up,
// then the command buffer for that tile must be flushed.
#define TILE_COMMAND_BUFFER_SIZE_IN_DWORDS 128

typedef struct tile_cmdbuf_t
{
    // start and past-the-end of the allocation for the buffer
    uint32_t* cmdbuf_start;
    uint32_t* cmdbuf_end;
    // the next location where to read and write commands
    uint32_t* cmdbuf_read;
    uint32_t* cmdbuf_write;
} tile_cmdbuf_t;

typedef struct framebuffer_t
{
    pixel_t* backbuffer;

    uint32_t* tile_cmdpool;
    tile_cmdbuf_t* tile_cmdbufs;

    uint32_t width_in_pixels;
    uint32_t height_in_pixels;

    // num_tiles_per_row * num_pixels_per_tile
    uint32_t pixels_per_row_of_tiles;

    // pixels_per_row_of_tiles * num_tile_rows
    uint32_t pixels_per_slice;
} framebuffer_t;

framebuffer_t* new_framebuffer(uint32_t width, uint32_t height)
{
    // limits of the rasterizer's precision
    // this is based on an analysis of the range of results of the 2D cross product between two fixed16.8 numbers.
    assert(width < 16384);
    assert(height < 16384);

    framebuffer_t* fb = (framebuffer_t*)malloc(sizeof(framebuffer_t));
    assert(fb);

    fb->width_in_pixels = width;
    fb->height_in_pixels = height;

    // pad framebuffer up to size of next tile
    // that way the rasterization code doesn't have to handlep otential out of bounds access after tile binning
    uint32_t padded_width_in_pixels = (width + (FRAMEBUFFER_TILE_WIDTH_IN_PIXELS - 1)) & -FRAMEBUFFER_TILE_WIDTH_IN_PIXELS;
    uint32_t padded_height_in_pixels = (height + (FRAMEBUFFER_TILE_WIDTH_IN_PIXELS - 1)) & -FRAMEBUFFER_TILE_WIDTH_IN_PIXELS;

    uint32_t width_in_tiles = padded_width_in_pixels / FRAMEBUFFER_TILE_WIDTH_IN_PIXELS;
    uint32_t height_in_tiles = padded_height_in_pixels / FRAMEBUFFER_TILE_WIDTH_IN_PIXELS;
    uint32_t total_num_tiles = width_in_tiles * height_in_tiles;

    fb->pixels_per_row_of_tiles = padded_width_in_pixels * FRAMEBUFFER_TILE_WIDTH_IN_PIXELS;
    fb->pixels_per_slice = padded_height_in_pixels / FRAMEBUFFER_TILE_WIDTH_IN_PIXELS * fb->pixels_per_row_of_tiles;

    fb->backbuffer = (pixel_t*)malloc(fb->pixels_per_slice * sizeof(pixel_t));
    assert(fb->backbuffer);

    // clear to black/transparent initially
    memset(fb->backbuffer, 0, fb->pixels_per_slice * sizeof(pixel_t));

    fb->tile_cmdpool = (uint32_t*)malloc(total_num_tiles * TILE_COMMAND_BUFFER_SIZE_IN_DWORDS * sizeof(uint32_t));
    assert(fb->tile_cmdpool);

    fb->tile_cmdbufs = (tile_cmdbuf_t*)malloc(total_num_tiles * sizeof(tile_cmdbuf_t));
    assert(fb->tile_cmdbufs);

    for (uint32_t i = 0; i < total_num_tiles; i++)
    {
        fb->tile_cmdbufs[i].cmdbuf_start = &fb->tile_cmdpool[i * TILE_COMMAND_BUFFER_SIZE_IN_DWORDS];
        fb->tile_cmdbufs[i].cmdbuf_end = fb->tile_cmdbufs[i].cmdbuf_start + TILE_COMMAND_BUFFER_SIZE_IN_DWORDS;
        fb->tile_cmdbufs[i].cmdbuf_read = fb->tile_cmdbufs[i].cmdbuf_start;
        fb->tile_cmdbufs[i].cmdbuf_write = fb->tile_cmdbufs[i].cmdbuf_start;
    }

    return fb;
}

void delete_framebuffer(framebuffer_t* fb)
{
    if (!fb)
        return;

    free(fb->tile_cmdbufs);
    free(fb->tile_cmdpool);
    free(fb->backbuffer);
    free(fb);
}

void framebuffer_resolve(framebuffer_t* fb)
{

}

void framebuffer_pack_row_major(framebuffer_t* fb, uint32_t x, uint32_t y, uint32_t width, uint32_t height, pixelformat_t format, void* data)
{
    assert(fb);
    assert(x < fb->width_in_pixels);
    assert(y < fb->height_in_pixels);
    assert(width <= fb->width_in_pixels);
    assert(height <= fb->height_in_pixels);
    assert(x + width <= fb->width_in_pixels);
    assert(y + height <= fb->height_in_pixels);
    assert(data);

    uint32_t topleft_tile_y = y / FRAMEBUFFER_TILE_WIDTH_IN_PIXELS;
    uint32_t topleft_tile_x = x / FRAMEBUFFER_TILE_WIDTH_IN_PIXELS;
    uint32_t bottomright_tile_y = (y + (height - 1)) / FRAMEBUFFER_TILE_WIDTH_IN_PIXELS;
    uint32_t bottomright_tile_x = (x + (width - 1)) / FRAMEBUFFER_TILE_WIDTH_IN_PIXELS;

    uint32_t dst_i = 0;

    uint32_t curr_tile_row_start = topleft_tile_y * fb->pixels_per_row_of_tiles + topleft_tile_x * FRAMEBUFFER_PIXELS_PER_TILE;
    for (uint32_t tile_y = topleft_tile_y; tile_y <= bottomright_tile_y; tile_y++)
    {
        uint32_t curr_tile_start = curr_tile_row_start;

        for (uint32_t tile_x = topleft_tile_x; tile_x <= bottomright_tile_x; tile_x++)
        {
            for (uint32_t pixel_y = 0, pixel_y_bits = 0;
                pixel_y < FRAMEBUFFER_TILE_WIDTH_IN_PIXELS;
                pixel_y++, pixel_y_bits = (pixel_y_bits - FRAMEBUFFER_TILE_Y_SWIZZLE_MASK) & FRAMEBUFFER_TILE_Y_SWIZZLE_MASK)
            {
                for (uint32_t pixel_x = 0, pixel_x_bits = 0;
                    pixel_x < FRAMEBUFFER_TILE_WIDTH_IN_PIXELS;
                    pixel_x++, pixel_x_bits = (pixel_x_bits - FRAMEBUFFER_TILE_X_SWIZZLE_MASK) & FRAMEBUFFER_TILE_X_SWIZZLE_MASK)
                {
                    uint32_t src_y = tile_y * FRAMEBUFFER_TILE_WIDTH_IN_PIXELS + pixel_y;
                    uint32_t src_x = tile_x * FRAMEBUFFER_TILE_WIDTH_IN_PIXELS + pixel_x;

                    // don't copy pixels outside src rectangle region
                    if (src_y < y || src_y >= y + height)
                        continue;
                    if (src_x < x || src_x >= x + width)
                        continue;

                    uint32_t src_i = curr_tile_start + (pixel_y_bits | pixel_x_bits);
                    pixel_t src = fb->backbuffer[src_i];
                    if (format == pixelformat_r8g8b8a8_unorm)
                    {
                        uint8_t* dst = (uint8_t*)data + dst_i * 4;
                        dst[0] = (uint8_t)((src & 0x00FF0000) >> 16);
                        dst[1] = (uint8_t)((src & 0x0000FF00) >> 8);
                        dst[2] = (uint8_t)((src & 0x000000FF) >> 0);
                        dst[3] = (uint8_t)((src & 0xFF000000) >> 24);
                    }
                    else if (format == pixelformat_b8g8r8a8_unorm)
                    {
                        uint8_t* dst = (uint8_t*)data + dst_i * 4;
                        dst[0] = (uint8_t)((src & 0x000000FF) >> 0);
                        dst[1] = (uint8_t)((src & 0x0000FF00) >> 8);
                        dst[2] = (uint8_t)((src & 0x00FF0000) >> 16);
                        dst[3] = (uint8_t)((src & 0xFF000000) >> 24);
                    }
                    else
                    {
                        assert(!"Unknown pixel format");
                    }

                    dst_i++;
                }
            }

            curr_tile_start += FRAMEBUFFER_PIXELS_PER_TILE;
        }

        curr_tile_row_start += fb->pixels_per_row_of_tiles;
    }
}

// hack
uint32_t g_Color;

void rasterize_triangle_fixed16_8(
    framebuffer_t* fb,
    uint32_t window_x0, uint32_t window_y0, uint32_t window_z0,
    uint32_t window_x1, uint32_t window_y1, uint32_t window_z1,
    uint32_t window_x2, uint32_t window_y2, uint32_t window_z2)
{
}<|endoftext|>


<commit_before>/*
    kopetecontactlist.cpp - Kopete's Contact List backend

    Copyright (c) 2005-2007 by Michael Larouche       <larouche@kde.org>
    Copyright (c) 2002-2003 by Martijn Klingens       <klingens@kde.org>
    Copyright (c) 2002-2004 by Olivier Goffart        <ogoffart@kde.org>
    Copyright (c) 2002      by Duncan Mac-Vicar Prett <duncan@kde.org>

    Copyright (c) 2002-2004 by the Kopete developers  <kopete-devel@kde.org>

    *************************************************************************
    *                                                                       *
    * This 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 of the License, or (at your option) any later version.      *
    *                                                                       *
    *************************************************************************
*/

#include "kopetecontactlist.h"

// Qt includes
#include <QtCore/QDir>
#include <QtCore/QRegExp>
#include <QtCore/QTimer>
#include <QtCore/QTextStream>

// KDE includes
#include <kabc/stdaddressbook.h>
#include <kapplication.h>
#include <kdebug.h>
#include <kglobal.h>
#include <ksavefile.h>
#include <kstandarddirs.h>

// Kopete includes
#include "kopeteaccount.h"
#include "kopeteaccountmanager.h"
#include "kopetechatsession.h"
#include "kopetecontact.h"
#include "kopetedeletecontacttask.h"
#include "kopetegroup.h"
#include "kopetemetacontact.h"
#include "kopetepicture.h"
#include "kopetepluginmanager.h"
#include "kopeteprotocol.h"
#include "xmlcontactstorage.h"

namespace  Kopete
{

class ContactList::Private
{public:
	/** Flag:  do not save the contact list until she is completely loaded */
	bool loaded ;

	QList<MetaContact *> contacts;
	QList<Group *> groups;
	QList<MetaContact *> selectedMetaContacts;
	QList<Group *> selectedGroups;

	QTimer *saveTimer;

	MetaContact *myself;
};

ContactList *ContactList::s_self = 0L;

ContactList *ContactList::self()
{
	if( !s_self )
		s_self = new ContactList;

	return s_self;
}

ContactList::ContactList()
	: QObject( kapp )
{
	setObjectName( "KopeteContactList" );
	d=new Private;

	//the myself metacontact can't be created now, because it will use
	//ContactList::self() as parent which will call this constructor -> infinite loop
	d->myself=0L;

	//no contact list loaded yet, don't save them
	d->loaded=false;

	// automatically save on changes to the list
	d->saveTimer = new QTimer( this );
	d->saveTimer->setObjectName( "saveTimer" );
	d->saveTimer->setSingleShot( true );
	connect( d->saveTimer, SIGNAL( timeout() ), SLOT ( save() ) );

	connect( this, SIGNAL( metaContactAdded( Kopete::MetaContact * ) ), SLOT( slotSaveLater() ) );
	connect( this, SIGNAL( metaContactRemoved( Kopete::MetaContact * ) ), SLOT( slotSaveLater() ) );
	connect( this, SIGNAL( groupAdded( Kopete::Group * ) ), SLOT( slotSaveLater() ) );
	connect( this, SIGNAL( groupRemoved( Kopete::Group * ) ), SLOT( slotSaveLater() ) );
	connect( this, SIGNAL( groupRenamed( Kopete::Group *, const QString & ) ), SLOT( slotSaveLater() ) );
}

ContactList::~ContactList()
{
	delete d->myself;
	delete d;
}

QList<MetaContact *> ContactList::metaContacts() const
{
	return d->contacts;
}

QList<Group *> ContactList::groups() const
{
	return d->groups;
}

MetaContact *ContactList::metaContact( const QString &metaContactId ) const
{
	QListIterator<MetaContact *> it( d->contacts );

	while ( it.hasNext() )
	{
		MetaContact *mc = it.next();
		if( mc->metaContactId() == metaContactId )
			return mc;
	}

	return 0L;
}

Group * ContactList::group(unsigned int groupId) const
{
	QListIterator<Group *> it(d->groups);

	while ( it.hasNext() )
	{
		Group *curr = it.next();
		if( curr->groupId()==groupId )
			return curr;
	}
	return 0L;
}

Contact *ContactList::findContact( const QString &protocolId,
	const QString &accountId, const QString &contactId ) const
{
	//Browsing metacontacts is too slow, better to uses the Dict of the account.
	Account *i=AccountManager::self()->findAccount(protocolId,accountId);
	if(!i)
	{
		kDebug( 14010 ) << "Account not found";
		return 0L;
	}
	return i->contacts()[contactId];
}

MetaContact *ContactList::findMetaContactByDisplayName( const QString &displayName ) const
{
	foreach(Kopete::MetaContact *contact, d->contacts)
	{
		if( contact->displayName() == displayName )
		{
			return contact;
		}
	}
        return 0;
}

MetaContact* ContactList::findMetaContactByContactId( const QString &contactId ) const
{
	QListIterator<Kopete::Account *> it( Kopete::AccountManager::self()->accounts() );
	Kopete::Account *a;
	while ( it.hasNext() )
	{
		a = it.next();
		Contact *c=a->contacts()[contactId];
		if(c && c->metaContact())
			return c->metaContact();
	}
	return 0L;
}

Group * ContactList::findGroup(const QString& displayName, int type)
{
	if( type == Group::Temporary )
		return Group::temporary();

	QListIterator<Group *> it(d->groups);
	while ( it.hasNext() )
	{
		Group *curr = it.next();
		if( curr->type() == type && curr->displayName() == displayName )
			return curr;
	}

	Group *newGroup = new Group( displayName, (Group::GroupType)type );
	addGroup( newGroup );
	return  newGroup;
}

QList<MetaContact *> ContactList::selectedMetaContacts() const
{
	return d->selectedMetaContacts;
}

QList<Group *> ContactList::selectedGroups() const
{
	return d->selectedGroups;
}

void ContactList::addMetaContacts( QList<MetaContact *> metaContacts )
{
	foreach( MetaContact* mc, metaContacts )
		addMetaContact( mc );
}

void ContactList::addMetaContact( MetaContact *mc )
{
	if ( d->contacts.contains( mc ) )
		return;

	d->contacts.append( mc );

	emit metaContactAdded( mc );
	connect( mc, SIGNAL( persistentDataChanged( ) ), SLOT( slotSaveLater() ) );
	connect( mc, SIGNAL( addedToGroup( Kopete::MetaContact *, Kopete::Group * ) ), SIGNAL( metaContactAddedToGroup( Kopete::MetaContact *, Kopete::Group * ) ) );
	connect( mc, SIGNAL( removedFromGroup( Kopete::MetaContact *, Kopete::Group * ) ), SIGNAL( metaContactRemovedFromGroup( Kopete::MetaContact *, Kopete::Group * ) ) );
}

void ContactList::removeMetaContact(MetaContact *m)
{
	if ( !d->contacts.contains(m) )
	{
		kDebug(14010) << "Trying to remove a not listed MetaContact.";
		return;
	}

	if ( d->selectedMetaContacts.contains( m ) )
	{
		d->selectedMetaContacts.removeAll( m );
		setSelectedItems( d->selectedMetaContacts, d->selectedGroups );
	}

	//removes subcontact from server here and now.
	Kopete::Contact *contactToDelete = 0;
	foreach( contactToDelete, m->contacts() )
	{
		// TODO: Check for good execution of task
		Kopete::DeleteContactTask *deleteTask = new Kopete::DeleteContactTask(contactToDelete);
		deleteTask->start();
	}

	d->contacts.removeAll( m );
	emit metaContactRemoved( m );
	m->deleteLater();
}

void ContactList::addGroups( QList<Group *> groups )
{
	foreach( Group* g, groups )
		addGroup( g );
}

void ContactList::addGroup( Group * g )
{
	if(!d->groups.contains(g) )
	{
		d->groups.append( g );
		emit groupAdded( g );
		connect( g , SIGNAL ( displayNameChanged(Kopete::Group* , const QString & )) , this , SIGNAL ( groupRenamed(Kopete::Group* , const QString & )) ) ;
	}
}

void ContactList::removeGroup( Group *g )
{
	if ( d->selectedGroups.contains( g ) )
	{
		d->selectedGroups.removeAll( g );
		setSelectedItems( d->selectedMetaContacts, d->selectedGroups );
	}

	d->groups.removeAll( g );
	emit groupRemoved( g );
	g->deleteLater();
}

void ContactList::setSelectedItems(QList<MetaContact *> metaContacts , QList<Group *> groups)
{
	kDebug( 14010 ) << metaContacts.count() << " metacontacts, " << groups.count() << " groups selected";
	d->selectedMetaContacts=metaContacts;
	d->selectedGroups=groups;

	emit metaContactSelected( groups.isEmpty() && metaContacts.count()==1 );
	emit selectionChanged();
}

MetaContact* ContactList::myself()
{
	if(!d->myself)
		d->myself=new MetaContact();
	return d->myself;
}

///////////////////////////////////////////////////////////////////////////////////////////////
void ContactList::load()
{
	// don't save when we're in the middle of this...
	d->loaded = false;

	Kopete::ContactListStorage *storage = new Kopete::XmlContactStorage();
	storage->load();
	if( !storage->isValid() )
	{
		kDebug(14010) << "Contact list storage failed. Reason: " << storage->errorMessage();
		d->loaded = true;
		delete storage;
		return;
	}

	addGroups( storage->groups() );
	addMetaContacts( storage->contacts() );

	d->loaded = true;
	delete storage;
}

void Kopete::ContactList::save()
{
	if( !d->loaded )
	{
		kDebug(14010) << "Contact list not loaded, abort saving";
		return;
	}

	Kopete::ContactListStorage *storage = new Kopete::XmlContactStorage();
	storage->save();
	if( !storage->isValid() )
	{
		kDebug(14010) << "Contact list storage failed. Reason: " << storage->errorMessage();

		// Saving the contact list failed. retry every minute until it works.
		// single-shot: will get restarted by us next time if it's still failing
		d->saveTimer->setSingleShot( true );
		d->saveTimer->start( 60000 );
		delete storage;
		return;
	}

	// cancel any scheduled saves
	d->saveTimer->stop();
	delete storage;
}

void ContactList::slotSaveLater()
{
	// if we already have a save scheduled, it will be cancelled. either way,
	// start a timer to save the contact list a bit later.
	d->saveTimer->start( 17100 /* 17,1 seconds */ );
}

void ContactList::slotKABCChanged()
{
	// TODO: react to changes in KABC, replacing this function, post 3.4 (Will)
	// call syncWithKABC on each metacontact to check if its associated kabc entry has changed.
/*	for ( MetaContact * mc = d->contacts.first(); mc; mc = d->contacts.next() )

		mc->syncWithKABC();*/
}

} //END namespace Kopete

#include "kopetecontactlist.moc"

// vim: set noet ts=4 sts=4 sw=4:

<commit_msg>If group is named "Top Level", return actual top level group BUG:150258<commit_after>/*
    kopetecontactlist.cpp - Kopete's Contact List backend

    Copyright (c) 2005-2007 by Michael Larouche       <larouche@kde.org>
    Copyright (c) 2002-2003 by Martijn Klingens       <klingens@kde.org>
    Copyright (c) 2002-2004 by Olivier Goffart        <ogoffart@kde.org>
    Copyright (c) 2002      by Duncan Mac-Vicar Prett <duncan@kde.org>

    Copyright (c) 2002-2004 by the Kopete developers  <kopete-devel@kde.org>

    *************************************************************************
    *                                                                       *
    * This 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 of the License, or (at your option) any later version.      *
    *                                                                       *
    *************************************************************************
*/

#include "kopetecontactlist.h"

// Qt includes
#include <QtCore/QDir>
#include <QtCore/QRegExp>
#include <QtCore/QTimer>
#include <QtCore/QTextStream>

// KDE includes
#include <kabc/stdaddressbook.h>
#include <kapplication.h>
#include <kdebug.h>
#include <kglobal.h>
#include <ksavefile.h>
#include <kstandarddirs.h>

// Kopete includes
#include "kopeteaccount.h"
#include "kopeteaccountmanager.h"
#include "kopetechatsession.h"
#include "kopetecontact.h"
#include "kopetedeletecontacttask.h"
#include "kopetegroup.h"
#include "kopetemetacontact.h"
#include "kopetepicture.h"
#include "kopetepluginmanager.h"
#include "kopeteprotocol.h"
#include "xmlcontactstorage.h"

namespace  Kopete
{

class ContactList::Private
{public:
	/** Flag:  do not save the contact list until she is completely loaded */
	bool loaded ;

	QList<MetaContact *> contacts;
	QList<Group *> groups;
	QList<MetaContact *> selectedMetaContacts;
	QList<Group *> selectedGroups;

	QTimer *saveTimer;

	MetaContact *myself;
};

ContactList *ContactList::s_self = 0L;

ContactList *ContactList::self()
{
	if( !s_self )
		s_self = new ContactList;

	return s_self;
}

ContactList::ContactList()
	: QObject( kapp )
{
	setObjectName( "KopeteContactList" );
	d=new Private;

	//the myself metacontact can't be created now, because it will use
	//ContactList::self() as parent which will call this constructor -> infinite loop
	d->myself=0L;

	//no contact list loaded yet, don't save them
	d->loaded=false;

	// automatically save on changes to the list
	d->saveTimer = new QTimer( this );
	d->saveTimer->setObjectName( "saveTimer" );
	d->saveTimer->setSingleShot( true );
	connect( d->saveTimer, SIGNAL( timeout() ), SLOT ( save() ) );

	connect( this, SIGNAL( metaContactAdded( Kopete::MetaContact * ) ), SLOT( slotSaveLater() ) );
	connect( this, SIGNAL( metaContactRemoved( Kopete::MetaContact * ) ), SLOT( slotSaveLater() ) );
	connect( this, SIGNAL( groupAdded( Kopete::Group * ) ), SLOT( slotSaveLater() ) );
	connect( this, SIGNAL( groupRemoved( Kopete::Group * ) ), SLOT( slotSaveLater() ) );
	connect( this, SIGNAL( groupRenamed( Kopete::Group *, const QString & ) ), SLOT( slotSaveLater() ) );
}

ContactList::~ContactList()
{
	delete d->myself;
	delete d;
}

QList<MetaContact *> ContactList::metaContacts() const
{
	return d->contacts;
}

QList<Group *> ContactList::groups() const
{
	return d->groups;
}

MetaContact *ContactList::metaContact( const QString &metaContactId ) const
{
	QListIterator<MetaContact *> it( d->contacts );

	while ( it.hasNext() )
	{
		MetaContact *mc = it.next();
		if( mc->metaContactId() == metaContactId )
			return mc;
	}

	return 0L;
}

Group * ContactList::group(unsigned int groupId) const
{
	QListIterator<Group *> it(d->groups);

	while ( it.hasNext() )
	{
		Group *curr = it.next();
		if( curr->groupId()==groupId )
			return curr;
	}
	return 0L;
}

Contact *ContactList::findContact( const QString &protocolId,
	const QString &accountId, const QString &contactId ) const
{
	//Browsing metacontacts is too slow, better to uses the Dict of the account.
	Account *i=AccountManager::self()->findAccount(protocolId,accountId);
	if(!i)
	{
		kDebug( 14010 ) << "Account not found";
		return 0L;
	}
	return i->contacts()[contactId];
}

MetaContact *ContactList::findMetaContactByDisplayName( const QString &displayName ) const
{
	foreach(Kopete::MetaContact *contact, d->contacts)
	{
		if( contact->displayName() == displayName )
		{
			return contact;
		}
	}
        return 0;
}

MetaContact* ContactList::findMetaContactByContactId( const QString &contactId ) const
{
	QListIterator<Kopete::Account *> it( Kopete::AccountManager::self()->accounts() );
	Kopete::Account *a;
	while ( it.hasNext() )
	{
		a = it.next();
		Contact *c=a->contacts()[contactId];
		if(c && c->metaContact())
			return c->metaContact();
	}
	return 0L;
}

Group * ContactList::findGroup(const QString& displayName, int type)
{
	if( type == Group::Temporary )
		return Group::temporary();

	if ( displayName == i18n ("Top Level") )
		return Group::topLevel();

	QListIterator<Group *> it(d->groups);
	while ( it.hasNext() )
	{
		Group *curr = it.next();
		if( curr->type() == type && curr->displayName() == displayName )
			return curr;
	}

	Group *newGroup = new Group( displayName, (Group::GroupType)type );
	addGroup( newGroup );
	return  newGroup;
}

QList<MetaContact *> ContactList::selectedMetaContacts() const
{
	return d->selectedMetaContacts;
}

QList<Group *> ContactList::selectedGroups() const
{
	return d->selectedGroups;
}

void ContactList::addMetaContacts( QList<MetaContact *> metaContacts )
{
	foreach( MetaContact* mc, metaContacts )
		addMetaContact( mc );
}

void ContactList::addMetaContact( MetaContact *mc )
{
	if ( d->contacts.contains( mc ) )
		return;

	d->contacts.append( mc );

	emit metaContactAdded( mc );
	connect( mc, SIGNAL( persistentDataChanged( ) ), SLOT( slotSaveLater() ) );
	connect( mc, SIGNAL( addedToGroup( Kopete::MetaContact *, Kopete::Group * ) ), SIGNAL( metaContactAddedToGroup( Kopete::MetaContact *, Kopete::Group * ) ) );
	connect( mc, SIGNAL( removedFromGroup( Kopete::MetaContact *, Kopete::Group * ) ), SIGNAL( metaContactRemovedFromGroup( Kopete::MetaContact *, Kopete::Group * ) ) );
}

void ContactList::removeMetaContact(MetaContact *m)
{
	if ( !d->contacts.contains(m) )
	{
		kDebug(14010) << "Trying to remove a not listed MetaContact.";
		return;
	}

	if ( d->selectedMetaContacts.contains( m ) )
	{
		d->selectedMetaContacts.removeAll( m );
		setSelectedItems( d->selectedMetaContacts, d->selectedGroups );
	}

	//removes subcontact from server here and now.
	Kopete::Contact *contactToDelete = 0;
	foreach( contactToDelete, m->contacts() )
	{
		// TODO: Check for good execution of task
		Kopete::DeleteContactTask *deleteTask = new Kopete::DeleteContactTask(contactToDelete);
		deleteTask->start();
	}

	d->contacts.removeAll( m );
	emit metaContactRemoved( m );
	m->deleteLater();
}

void ContactList::addGroups( QList<Group *> groups )
{
	foreach( Group* g, groups )
		addGroup( g );
}

void ContactList::addGroup( Group * g )
{
	if(!d->groups.contains(g) )
	{
		d->groups.append( g );
		emit groupAdded( g );
		connect( g , SIGNAL ( displayNameChanged(Kopete::Group* , const QString & )) , this , SIGNAL ( groupRenamed(Kopete::Group* , const QString & )) ) ;
	}
}

void ContactList::removeGroup( Group *g )
{
	if ( d->selectedGroups.contains( g ) )
	{
		d->selectedGroups.removeAll( g );
		setSelectedItems( d->selectedMetaContacts, d->selectedGroups );
	}

	d->groups.removeAll( g );
	emit groupRemoved( g );
	g->deleteLater();
}

void ContactList::setSelectedItems(QList<MetaContact *> metaContacts , QList<Group *> groups)
{
	kDebug( 14010 ) << metaContacts.count() << " metacontacts, " << groups.count() << " groups selected";
	d->selectedMetaContacts=metaContacts;
	d->selectedGroups=groups;

	emit metaContactSelected( groups.isEmpty() && metaContacts.count()==1 );
	emit selectionChanged();
}

MetaContact* ContactList::myself()
{
	if(!d->myself)
		d->myself=new MetaContact();
	return d->myself;
}

///////////////////////////////////////////////////////////////////////////////////////////////
void ContactList::load()
{
	// don't save when we're in the middle of this...
	d->loaded = false;

	Kopete::ContactListStorage *storage = new Kopete::XmlContactStorage();
	storage->load();
	if( !storage->isValid() )
	{
		kDebug(14010) << "Contact list storage failed. Reason: " << storage->errorMessage();
		d->loaded = true;
		delete storage;
		return;
	}

	addGroups( storage->groups() );
	addMetaContacts( storage->contacts() );

	d->loaded = true;
	delete storage;
}

void Kopete::ContactList::save()
{
	if( !d->loaded )
	{
		kDebug(14010) << "Contact list not loaded, abort saving";
		return;
	}

	Kopete::ContactListStorage *storage = new Kopete::XmlContactStorage();
	storage->save();
	if( !storage->isValid() )
	{
		kDebug(14010) << "Contact list storage failed. Reason: " << storage->errorMessage();

		// Saving the contact list failed. retry every minute until it works.
		// single-shot: will get restarted by us next time if it's still failing
		d->saveTimer->setSingleShot( true );
		d->saveTimer->start( 60000 );
		delete storage;
		return;
	}

	// cancel any scheduled saves
	d->saveTimer->stop();
	delete storage;
}

void ContactList::slotSaveLater()
{
	// if we already have a save scheduled, it will be cancelled. either way,
	// start a timer to save the contact list a bit later.
	d->saveTimer->start( 17100 /* 17,1 seconds */ );
}

void ContactList::slotKABCChanged()
{
	// TODO: react to changes in KABC, replacing this function, post 3.4 (Will)
	// call syncWithKABC on each metacontact to check if its associated kabc entry has changed.
/*	for ( MetaContact * mc = d->contacts.first(); mc; mc = d->contacts.next() )

		mc->syncWithKABC();*/
}

} //END namespace Kopete

#include "kopetecontactlist.moc"

// vim: set noet ts=4 sts=4 sw=4:

<|endoftext|>


<commit_before>// -*- Mode: C++; tab-width: 2; -*-
// vi: set ts=2:
//

#include <BALL/FORMAT/bruker1DFile.h>

namespace BALL
{

  Bruker1DFile::Bruker1DFile()
    : File(),
			min_(0),
			max_(1),
			pars_()
  {
  }

	Bruker1DFile::Bruker1DFile(const String& name, OpenMode open_mode)
		: File(name + FileSystem::PATH_SEPARATOR + "1r", open_mode),
			min_(0),
			max_(1),
			pars_()
	{
		pars_.open(name + FileSystem::PATH_SEPARATOR + "procs");
		pars_.read();
		min_ = (Size)pars_.getDoubleValue("YMIN_p");
		max_ = (Size)pars_.getDoubleValue("YMAX_p");
		pars_.close();
		read();
	}

	Bruker1DFile::~Bruker1DFile()
	{
	}

	void Bruker1DFile::read(const String &name)
	{
	  pars_.open(name + FileSystem::PATH_SEPARATOR + "procs");
	  pars_.read();
	  min_ = (Size)pars_.getDoubleValue("YMIN_p");
	  max_ = (Size)pars_.getDoubleValue("YMAX_p");
		pars_.close();

	  close();
	  open(name + FileSystem::PATH_SEPARATOR + "1r");
	  read();
	}

  void Bruker1DFile::read()
	{
	  char c[4];
	  signed long int &numdum = *(signed long int*) (&c[0]);
	  Position actpos = 0;
	  File& f = static_cast<File&> (*this);
	  bool littleEndian;

	  // first we will have to find out whether we are using big or little
	  // endian on this machine.
	  int endTest = 1;
	  if (*(char *) &endTest == 1)
	  {
	  	littleEndian = true;
	  }
	  else
	  {
	    littleEndian = false;
	  }

	  spectrum_.resize( (Size)pars_.getDoubleValue("SI"));
	  spectrum_.setOrigin(pars_.getDoubleValue("YMIN_p"));
		spectrum_.setDimension(pars_.getDoubleValue("YMAX_p") - pars_.getDoubleValue("YMIN_p"));

	  // back to beginning of file
	  f.reopen();

	  // read data
	  for (Position i = 0; i < (Size)pars_.getDoubleValue("SI"); i++)
		{
		  if (!f.good())
		  {
				// ?????: here should be a warning or exception
				return;
			}

		  f.get(c[0]); f.get(c[1]); f.get(c[2]); f.get(c[3]);
		  if (pars_.getDoubleValue("BYTORDP") == 1.0L)
			{
			 	if (littleEndian == false)
			 	{ // conversion from little to big
				 	numdum = (signed long) ( ((numdum & 0x000000FFL) << 24)
					|((numdum & 0x0000FF00L) << 16)
				 	|((numdum & 0x00FF0000L) >> 16)
				 	|((numdum & 0xFF000000L) >> 24));
			 	}
				// else no conversion needed
			}
		  else
			{
				if (littleEndian == true) // conversion from big to little
			 	{
			    numdum = (signed long) ( ((numdum & 0x000000FFL) << 24)
					|((numdum & 0x0000FF00L) << 16)
					|((numdum & 0x00FF0000L) >> 16)
					|((numdum & 0xFF000000L) >> 24));
			   }
			  // else no conversion needed
			}

		  if ((max_ - min_) != 0)
			{
				spectrum_[actpos] = ((double) (numdum - min_)) / (max_ - min_);
			}

			actpos++;
		}
	}
}
<commit_msg>Fix endian detection/conversion in Bruker1DFile<commit_after>// -*- Mode: C++; tab-width: 2; -*-
// vi: set ts=2:
//

#include <BALL/FORMAT/bruker1DFile.h>

namespace BALL
{

  Bruker1DFile::Bruker1DFile()
    : File(),
			min_(0),
			max_(1),
			pars_()
  {
  }

	Bruker1DFile::Bruker1DFile(const String& name, OpenMode open_mode)
		: File(name + FileSystem::PATH_SEPARATOR + "1r", open_mode),
			min_(0),
			max_(1),
			pars_()
	{
		pars_.open(name + FileSystem::PATH_SEPARATOR + "procs");
		pars_.read();
		min_ = (Size)pars_.getDoubleValue("YMIN_p");
		max_ = (Size)pars_.getDoubleValue("YMAX_p");
		pars_.close();
		read();
	}

	Bruker1DFile::~Bruker1DFile()
	{
	}

	void Bruker1DFile::read(const String &name)
	{
	  pars_.open(name + FileSystem::PATH_SEPARATOR + "procs");
	  pars_.read();
	  min_ = (Size)pars_.getDoubleValue("YMIN_p");
	  max_ = (Size)pars_.getDoubleValue("YMAX_p");
		pars_.close();

	  close();
	  open(name + FileSystem::PATH_SEPARATOR + "1r");
	  read();
	}

  void Bruker1DFile::read()
	{
	  // first we will have to find out whether we are using big or little
	  // endian on this machine.
		unsigned int endTest = 1;
		BinaryFileAdaptor<BALL_INT32> adapt_int32_t_;
		adapt_int32_t_.setSwapEndian((*(char*)&endTest == 1) != (pars_.getDoubleValue("BYTORDP") == 1.0));

	  spectrum_.resize( (Size)pars_.getDoubleValue("SI"));
	  spectrum_.setOrigin(pars_.getDoubleValue("YMIN_p"));
		spectrum_.setDimension(pars_.getDoubleValue("YMAX_p") - pars_.getDoubleValue("YMIN_p"));

	  // back to beginning of file
	  this->reopen();

	  // read data
	  for (Position i = 0; i < spectrum_.size(); ++i)
		{
		  if (!this->good())
		  {
				// ?????: here should be a warning or exception
				return;
			}

			(*this) >> adapt_int32_t_;

		  if ((max_ - min_) != 0)
			{
				spectrum_[i] = ((double) (adapt_int32_t_.getData() - min_)) / (max_ - min_);
			}
		}
	}
}
<|endoftext|>


<commit_before>//===-- source/Host/freebsd/Host.cpp ------------------------------*- C++
//-*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

// C Includes
#include <sys/types.h>

#include <sys/exec.h>
#include <sys/proc.h>
#include <sys/ptrace.h>
#include <sys/sysctl.h>
#include <sys/user.h>

#include <machine/elf.h>

#include <dlfcn.h>
#include <execinfo.h>
#include <stdio.h>

// C++ Includes
// Other libraries and framework includes
// Project includes
#include "lldb/Host/Host.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Target/Process.h"
#include "lldb/Utility/DataBufferHeap.h"
#include "lldb/Utility/DataExtractor.h"
#include "lldb/Utility/Endian.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/NameMatches.h"
#include "lldb/Utility/Status.h"
#include "lldb/Utility/StreamString.h"

#include "llvm/Support/Host.h"

extern "C" {
extern char **environ;
}

using namespace lldb;
using namespace lldb_private;

static bool
GetFreeBSDProcessArgs(const ProcessInstanceInfoMatch *match_info_ptr,
                      ProcessInstanceInfo &process_info) {
  if (!process_info.ProcessIDIsValid())
    return false;

  int pid = process_info.GetProcessID();

  int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_ARGS, pid};

  char arg_data[8192];
  size_t arg_data_size = sizeof(arg_data);
  if (::sysctl(mib, 4, arg_data, &arg_data_size, NULL, 0) != 0)
    return false;

  DataExtractor data(arg_data, arg_data_size, endian::InlHostByteOrder(),
                     sizeof(void *));
  lldb::offset_t offset = 0;
  const char *cstr;

  cstr = data.GetCStr(&offset);
  if (!cstr)
    return false;

  // Get pathname for pid. If that fails fall back to argv[0].
  char pathname[MAXPATHLEN];
  size_t pathname_len = sizeof(pathname);
  mib[2] = KERN_PROC_PATHNAME;
  if (::sysctl(mib, 4, pathname, &pathname_len, NULL, 0) == 0)
    process_info.GetExecutableFile().SetFile(pathname, false,
                                             FileSpec::Style::native);
  else
    process_info.GetExecutableFile().SetFile(cstr, false,
                                             FileSpec::Style::native);

  if (!(match_info_ptr == NULL ||
        NameMatches(process_info.GetExecutableFile().GetFilename().GetCString(),
                    match_info_ptr->GetNameMatchType(),
                    match_info_ptr->GetProcessInfo().GetName())))
    return false;

  Args &proc_args = process_info.GetArguments();
  while (1) {
    const uint8_t *p = data.PeekData(offset, 1);
    while ((p != NULL) && (*p == '\0') && offset < arg_data_size) {
      ++offset;
      p = data.PeekData(offset, 1);
    }
    if (p == NULL || offset >= arg_data_size)
      break;

    cstr = data.GetCStr(&offset);
    if (!cstr)
      break;

    proc_args.AppendArgument(llvm::StringRef(cstr));
  }

  return true;
}

static bool GetFreeBSDProcessCPUType(ProcessInstanceInfo &process_info) {
  if (process_info.ProcessIDIsValid()) {
    process_info.GetArchitecture() =
        HostInfo::GetArchitecture(HostInfo::eArchKindDefault);
    return true;
  }
  process_info.GetArchitecture().Clear();
  return false;
}

static bool GetFreeBSDProcessUserAndGroup(ProcessInstanceInfo &process_info) {
  struct kinfo_proc proc_kinfo;
  size_t proc_kinfo_size;
  const int pid = process_info.GetProcessID();
  int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, pid};

  if (!process_info.ProcessIDIsValid())
    goto error;

  proc_kinfo_size = sizeof(struct kinfo_proc);

  if (::sysctl(mib, 4, &proc_kinfo, &proc_kinfo_size, NULL, 0) != 0)
    goto error;

  if (proc_kinfo_size == 0)
    goto error;

  process_info.SetParentProcessID(proc_kinfo.ki_ppid);
  process_info.SetUserID(proc_kinfo.ki_ruid);
  process_info.SetGroupID(proc_kinfo.ki_rgid);
  process_info.SetEffectiveUserID(proc_kinfo.ki_uid);
  if (proc_kinfo.ki_ngroups > 0)
    process_info.SetEffectiveGroupID(proc_kinfo.ki_groups[0]);
  else
    process_info.SetEffectiveGroupID(UINT32_MAX);
  return true;

error:
  process_info.SetParentProcessID(LLDB_INVALID_PROCESS_ID);
  process_info.SetUserID(UINT32_MAX);
  process_info.SetGroupID(UINT32_MAX);
  process_info.SetEffectiveUserID(UINT32_MAX);
  process_info.SetEffectiveGroupID(UINT32_MAX);
  return false;
}

uint32_t Host::FindProcesses(const ProcessInstanceInfoMatch &match_info,
                             ProcessInstanceInfoList &process_infos) {
  const ::pid_t our_pid = ::getpid();
  const ::uid_t our_uid = ::getuid();
  std::vector<struct kinfo_proc> kinfos;
  // Special case, if lldb is being run as root we can attach to anything.
  bool all_users = match_info.GetMatchAllUsers() || (our_uid == 0);

  int mib[3] = {CTL_KERN, KERN_PROC, KERN_PROC_ALL};

  size_t pid_data_size = 0;
  if (::sysctl(mib, 3, NULL, &pid_data_size, NULL, 0) != 0)
    return 0;

  // Add a few extra in case a few more show up
  const size_t estimated_pid_count =
      (pid_data_size / sizeof(struct kinfo_proc)) + 10;

  kinfos.resize(estimated_pid_count);
  pid_data_size = kinfos.size() * sizeof(struct kinfo_proc);

  if (::sysctl(mib, 3, &kinfos[0], &pid_data_size, NULL, 0) != 0)
    return 0;

  const size_t actual_pid_count = (pid_data_size / sizeof(struct kinfo_proc));

  for (size_t i = 0; i < actual_pid_count; i++) {
    const struct kinfo_proc &kinfo = kinfos[i];

    /* Make sure the user is acceptable */
    if (!all_users && kinfo.ki_ruid != our_uid)
      continue;

    if (kinfo.ki_pid == our_pid ||  // Skip this process
        kinfo.ki_pid == 0 ||        // Skip kernel (kernel pid is 0)
        kinfo.ki_stat == SZOMB ||   // Zombies are bad
        kinfo.ki_flag & P_TRACED || // Being debugged?
        kinfo.ki_flag & P_WEXIT)    // Working on exiting
      continue;

    // Every thread is a process in FreeBSD, but all the threads of a single
    // process have the same pid. Do not store the process info in the result
    // list if a process with given identifier is already registered there.
    bool already_registered = false;
    for (uint32_t pi = 0;
         !already_registered && (const int)kinfo.ki_numthreads > 1 &&
         pi < (const uint32_t)process_infos.GetSize();
         pi++)
      already_registered =
          (process_infos.GetProcessIDAtIndex(pi) == (uint32_t)kinfo.ki_pid);

    if (already_registered)
      continue;

    ProcessInstanceInfo process_info;
    process_info.SetProcessID(kinfo.ki_pid);
    process_info.SetParentProcessID(kinfo.ki_ppid);
    process_info.SetUserID(kinfo.ki_ruid);
    process_info.SetGroupID(kinfo.ki_rgid);
    process_info.SetEffectiveUserID(kinfo.ki_svuid);
    process_info.SetEffectiveGroupID(kinfo.ki_svgid);

    // Make sure our info matches before we go fetch the name and cpu type
    if (match_info.Matches(process_info) &&
        GetFreeBSDProcessArgs(&match_info, process_info)) {
      GetFreeBSDProcessCPUType(process_info);
      if (match_info.Matches(process_info))
        process_infos.Append(process_info);
    }
  }

  return process_infos.GetSize();
}

bool Host::GetProcessInfo(lldb::pid_t pid, ProcessInstanceInfo &process_info) {
  process_info.SetProcessID(pid);

  if (GetFreeBSDProcessArgs(NULL, process_info)) {
    // should use libprocstat instead of going right into sysctl?
    GetFreeBSDProcessCPUType(process_info);
    GetFreeBSDProcessUserAndGroup(process_info);
    return true;
  }

  process_info.Clear();
  return false;
}

Environment Host::GetEnvironment() { return Environment(environ); }

Status Host::ShellExpandArguments(ProcessLaunchInfo &launch_info) {
  return Status("unimplemented");
}
<commit_msg>[FileSystem] Change FileSpec constructor signature (2/2)<commit_after>//===-- source/Host/freebsd/Host.cpp ------------------------------*- C++
//-*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

// C Includes
#include <sys/types.h>

#include <sys/exec.h>
#include <sys/proc.h>
#include <sys/ptrace.h>
#include <sys/sysctl.h>
#include <sys/user.h>

#include <machine/elf.h>

#include <dlfcn.h>
#include <execinfo.h>
#include <stdio.h>

// C++ Includes
// Other libraries and framework includes
// Project includes
#include "lldb/Host/Host.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Target/Process.h"
#include "lldb/Utility/DataBufferHeap.h"
#include "lldb/Utility/DataExtractor.h"
#include "lldb/Utility/Endian.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/NameMatches.h"
#include "lldb/Utility/Status.h"
#include "lldb/Utility/StreamString.h"

#include "llvm/Support/Host.h"

extern "C" {
extern char **environ;
}

using namespace lldb;
using namespace lldb_private;

static bool
GetFreeBSDProcessArgs(const ProcessInstanceInfoMatch *match_info_ptr,
                      ProcessInstanceInfo &process_info) {
  if (!process_info.ProcessIDIsValid())
    return false;

  int pid = process_info.GetProcessID();

  int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_ARGS, pid};

  char arg_data[8192];
  size_t arg_data_size = sizeof(arg_data);
  if (::sysctl(mib, 4, arg_data, &arg_data_size, NULL, 0) != 0)
    return false;

  DataExtractor data(arg_data, arg_data_size, endian::InlHostByteOrder(),
                     sizeof(void *));
  lldb::offset_t offset = 0;
  const char *cstr;

  cstr = data.GetCStr(&offset);
  if (!cstr)
    return false;

  // Get pathname for pid. If that fails fall back to argv[0].
  char pathname[MAXPATHLEN];
  size_t pathname_len = sizeof(pathname);
  mib[2] = KERN_PROC_PATHNAME;
  if (::sysctl(mib, 4, pathname, &pathname_len, NULL, 0) == 0)
    process_info.GetExecutableFile().SetFile(pathname, FileSpec::Style::native);
  else
    process_info.GetExecutableFile().SetFile(cstr, FileSpec::Style::native);

  if (!(match_info_ptr == NULL ||
        NameMatches(process_info.GetExecutableFile().GetFilename().GetCString(),
                    match_info_ptr->GetNameMatchType(),
                    match_info_ptr->GetProcessInfo().GetName())))
    return false;

  Args &proc_args = process_info.GetArguments();
  while (1) {
    const uint8_t *p = data.PeekData(offset, 1);
    while ((p != NULL) && (*p == '\0') && offset < arg_data_size) {
      ++offset;
      p = data.PeekData(offset, 1);
    }
    if (p == NULL || offset >= arg_data_size)
      break;

    cstr = data.GetCStr(&offset);
    if (!cstr)
      break;

    proc_args.AppendArgument(llvm::StringRef(cstr));
  }

  return true;
}

static bool GetFreeBSDProcessCPUType(ProcessInstanceInfo &process_info) {
  if (process_info.ProcessIDIsValid()) {
    process_info.GetArchitecture() =
        HostInfo::GetArchitecture(HostInfo::eArchKindDefault);
    return true;
  }
  process_info.GetArchitecture().Clear();
  return false;
}

static bool GetFreeBSDProcessUserAndGroup(ProcessInstanceInfo &process_info) {
  struct kinfo_proc proc_kinfo;
  size_t proc_kinfo_size;
  const int pid = process_info.GetProcessID();
  int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, pid};

  if (!process_info.ProcessIDIsValid())
    goto error;

  proc_kinfo_size = sizeof(struct kinfo_proc);

  if (::sysctl(mib, 4, &proc_kinfo, &proc_kinfo_size, NULL, 0) != 0)
    goto error;

  if (proc_kinfo_size == 0)
    goto error;

  process_info.SetParentProcessID(proc_kinfo.ki_ppid);
  process_info.SetUserID(proc_kinfo.ki_ruid);
  process_info.SetGroupID(proc_kinfo.ki_rgid);
  process_info.SetEffectiveUserID(proc_kinfo.ki_uid);
  if (proc_kinfo.ki_ngroups > 0)
    process_info.SetEffectiveGroupID(proc_kinfo.ki_groups[0]);
  else
    process_info.SetEffectiveGroupID(UINT32_MAX);
  return true;

error:
  process_info.SetParentProcessID(LLDB_INVALID_PROCESS_ID);
  process_info.SetUserID(UINT32_MAX);
  process_info.SetGroupID(UINT32_MAX);
  process_info.SetEffectiveUserID(UINT32_MAX);
  process_info.SetEffectiveGroupID(UINT32_MAX);
  return false;
}

uint32_t Host::FindProcesses(const ProcessInstanceInfoMatch &match_info,
                             ProcessInstanceInfoList &process_infos) {
  const ::pid_t our_pid = ::getpid();
  const ::uid_t our_uid = ::getuid();
  std::vector<struct kinfo_proc> kinfos;
  // Special case, if lldb is being run as root we can attach to anything.
  bool all_users = match_info.GetMatchAllUsers() || (our_uid == 0);

  int mib[3] = {CTL_KERN, KERN_PROC, KERN_PROC_ALL};

  size_t pid_data_size = 0;
  if (::sysctl(mib, 3, NULL, &pid_data_size, NULL, 0) != 0)
    return 0;

  // Add a few extra in case a few more show up
  const size_t estimated_pid_count =
      (pid_data_size / sizeof(struct kinfo_proc)) + 10;

  kinfos.resize(estimated_pid_count);
  pid_data_size = kinfos.size() * sizeof(struct kinfo_proc);

  if (::sysctl(mib, 3, &kinfos[0], &pid_data_size, NULL, 0) != 0)
    return 0;

  const size_t actual_pid_count = (pid_data_size / sizeof(struct kinfo_proc));

  for (size_t i = 0; i < actual_pid_count; i++) {
    const struct kinfo_proc &kinfo = kinfos[i];

    /* Make sure the user is acceptable */
    if (!all_users && kinfo.ki_ruid != our_uid)
      continue;

    if (kinfo.ki_pid == our_pid ||  // Skip this process
        kinfo.ki_pid == 0 ||        // Skip kernel (kernel pid is 0)
        kinfo.ki_stat == SZOMB ||   // Zombies are bad
        kinfo.ki_flag & P_TRACED || // Being debugged?
        kinfo.ki_flag & P_WEXIT)    // Working on exiting
      continue;

    // Every thread is a process in FreeBSD, but all the threads of a single
    // process have the same pid. Do not store the process info in the result
    // list if a process with given identifier is already registered there.
    bool already_registered = false;
    for (uint32_t pi = 0;
         !already_registered && (const int)kinfo.ki_numthreads > 1 &&
         pi < (const uint32_t)process_infos.GetSize();
         pi++)
      already_registered =
          (process_infos.GetProcessIDAtIndex(pi) == (uint32_t)kinfo.ki_pid);

    if (already_registered)
      continue;

    ProcessInstanceInfo process_info;
    process_info.SetProcessID(kinfo.ki_pid);
    process_info.SetParentProcessID(kinfo.ki_ppid);
    process_info.SetUserID(kinfo.ki_ruid);
    process_info.SetGroupID(kinfo.ki_rgid);
    process_info.SetEffectiveUserID(kinfo.ki_svuid);
    process_info.SetEffectiveGroupID(kinfo.ki_svgid);

    // Make sure our info matches before we go fetch the name and cpu type
    if (match_info.Matches(process_info) &&
        GetFreeBSDProcessArgs(&match_info, process_info)) {
      GetFreeBSDProcessCPUType(process_info);
      if (match_info.Matches(process_info))
        process_infos.Append(process_info);
    }
  }

  return process_infos.GetSize();
}

bool Host::GetProcessInfo(lldb::pid_t pid, ProcessInstanceInfo &process_info) {
  process_info.SetProcessID(pid);

  if (GetFreeBSDProcessArgs(NULL, process_info)) {
    // should use libprocstat instead of going right into sysctl?
    GetFreeBSDProcessCPUType(process_info);
    GetFreeBSDProcessUserAndGroup(process_info);
    return true;
  }

  process_info.Clear();
  return false;
}

Environment Host::GetEnvironment() { return Environment(environ); }

Status Host::ShellExpandArguments(ProcessLaunchInfo &launch_info) {
  return Status("unimplemented");
}
<|endoftext|>