<commit_before>/**
 * @file radon.cpp
 *
 * @date Oct 28, 2012
 * @author tack
 */

#include "radon.h"
#include "logger_factory.h"
#include "plugin_factory.h"
#include <thread>
#include <sstream>
#include "util.h"
#include "unistd.h" // getuid())
#include "regular_grid.h"

using namespace std;
using namespace himan::plugin;

const int MAX_WORKERS = 16;
static once_flag oflag;

radon::radon() : itsInit(false), itsRadonDB()
{
	itsLogger = unique_ptr<logger> (logger_factory::Instance()->GetLog("radon"));

	// no lambda functions for gcc 4.4 :(
	// call_once(oflag, [](){ NFmiNeonsDBPool::MaxWorkers(MAX_WORKERS); });

	call_once(oflag, &himan::plugin::radon::InitPool, this);
}

void radon::InitPool()
{
	NFmiRadonDBPool::Instance()->MaxWorkers(MAX_WORKERS);

	uid_t uid = getuid();

	if (uid == 1459) // weto
	{
		char* base = getenv("MASALA_BASE");

		if (string(base) == "/masala")
		{
			NFmiRadonDBPool::Instance()->Username("wetodb");
			NFmiRadonDBPool::Instance()->Password("3loHRgdio");
		}
		else
		{
			itsLogger->Warning("Program executed as uid 1459 ('weto') but MASALA_BASE not set");
		}
	}
}

vector<string> radon::Files(search_options& options)
{

	Init();

	vector<string> files;

	string analtime = options.time.OriginDateTime().String("%Y-%m-%d %H:%M:%S+00");
	string levelvalue = boost::lexical_cast<string> (options.level.Value());

	string ref_prod = options.prod.Name();
	// long no_vers = options.prod.TableVersion();

	string level_name = HPLevelTypeToString.at(options.level.Type());

	vector<vector<string> > gridgeoms;
	vector<string> sourceGeoms = options.configuration->SourceGeomNames();

	if (sourceGeoms.empty())
	{
		// Get all geometries
		gridgeoms = itsRadonDB->GetGridGeoms(ref_prod, analtime);
	}
	else
	{
		for (size_t i = 0; i < sourceGeoms.size(); i++)
		{
			vector<vector<string>> geoms = itsRadonDB->GetGridGeoms(ref_prod, analtime, sourceGeoms[i]);
			gridgeoms.insert(gridgeoms.end(), geoms.begin(), geoms.end());
		}
	}

	if (gridgeoms.empty())
	{
		itsLogger->Warning("No geometries found for producer " + ref_prod +
		", analysistime " + analtime + ", source geom name(s) '" + util::Join(sourceGeoms, ",") +"', param " + options.param.Name());

		return files;
	}

	string forecastTypeValue = (options.ftype.Type() == kEpsPerturbation) ? boost::lexical_cast<string> (options.ftype.Value()) : "-1";

	for (size_t i = 0; i < gridgeoms.size(); i++)
	{
		string tablename = gridgeoms[i][1];
		string geomid = gridgeoms[i][0];

		string parm_name = options.param.Name();

		string query = "SELECT param_id, level_id, level_value, forecast_period, file_location, file_server "
				   "FROM "+tablename+"_v "
				   "WHERE analysis_time = '"+analtime+"' "
				   "AND param_name = '"+parm_name+"' "
				   "AND level_name = upper('"+level_name+"') "
				   "AND level_value = "+levelvalue+" "
				   "AND forecast_period = '"+util::MakeSQLInterval(options.time)+"' "
				   "AND geometry_id = "+geomid+" "
				   "AND forecast_type_id = "+boost::lexical_cast<string> (options.ftype.Type())+" "
				   "AND forecast_type_value = "+forecastTypeValue+" "
				   "ORDER BY forecast_period, level_id, level_value";

		itsRadonDB->Query(query);

		vector<string> values = itsRadonDB->FetchRow();

		if (values.empty())
		{
			continue;
		}

		itsLogger->Trace("Found data for parameter " + parm_name + " from radon geometry " + gridgeoms[i][3]);

		files.push_back(values[4]);

		break; // discontinue loop on first positive match

	}

	return files;

}

bool radon::Save(const info& resultInfo, const string& theFileName)
{

	Init();

	stringstream query;

	if (resultInfo.Grid()->Type() != kRegularGrid)
	{
		itsLogger->Error("Only grid data can be stored to radon for now");
		return false;
	}

	const regular_grid* g = dynamic_cast<regular_grid*> (resultInfo.Grid());

	/*
	 * 1. Get grid information
	 * 2. Get model information
	 * 3. Get data set information (ie model run)
	 * 4. Insert or update
	 */

	himan::point firstGridPoint = g->FirstGridPoint();

	query 	<< "SELECT geometry_id "
			<< "FROM geom_v "
			<< "WHERE nj = " << g->Nj()
			<< " AND ni = " << g->Ni()
			<< " AND first_lat = " << firstGridPoint.Y()
			<< " AND first_lon = " << firstGridPoint.X();

	itsRadonDB->Query(query.str());

	vector<string> row;

	row = itsRadonDB->FetchRow();

	if (row.empty())
	{
		itsLogger->Warning("Grid geometry not found from radon");
		return false;
	}

	string geom_id = row[0];

	query.str("");

	query	<< "SELECT "
			<< "id, table_name "
			<< "FROM as_grid "
			<< "WHERE geometry_id = '" << geom_id << "'"
			<< " AND analysis_time = '" << resultInfo.OriginDateTime().String("%Y-%m-%d %H:%M:%S+00") << "'"
			<< " AND producer_id = " << resultInfo.Producer().Id();

	itsRadonDB->Query(query.str());

	row = itsRadonDB->FetchRow();

	if (row.empty())
	{
		itsLogger->Warning("Data set definition not found from radon");
		return false;
	}

	string table_name = row[1];
	string dset_id = row[0];

	query.str("");

	string host = "undetermined host";

	char* hostname = getenv("HOSTNAME");

	if (hostname != NULL)
	{
		host = string(hostname);
	}

	/*
	 * We have our own error logging for unique key violations
	 */

	// itsRadonDB->Verbose(false);

	double forecastTypeValue = (resultInfo.ForecastType().Type() == kEpsPerturbation) ? resultInfo.ForecastType().Value() : -1.;

	query  << "INSERT INTO data." << table_name
		   << " (producer_id, analysis_time, geometry_id, param_id, level_id, level_value, forecast_period, forecast_type_id, forecast_type_value, file_location, file_server) "
		   << "SELECT " << resultInfo.Producer().Id() << ", "
		   << "'" << resultInfo.OriginDateTime().String("%Y-%m-%d %H:%M:%S+00") << "', "
		   << "'" << geom_id << "', "
		   << "param.id, level.id, "
		   << resultInfo.Level().Value() << ", "
		   << "'" << util::MakeSQLInterval(resultInfo.Time()) << "', "
		   << resultInfo.ForecastType().Type() << ", "
		   << forecastTypeValue << ","
		   << "'" << theFileName << "', "
		   << "'" << host << "' "
		   << "FROM param, level "
		   << "WHERE param.name = '" << resultInfo.Param().Name() << "' "
		   << "AND level.name = upper('" << HPLevelTypeToString.at(resultInfo.Level().Type()) << "')";

	try
	{
		itsRadonDB->Execute(query.str());
		itsRadonDB->Commit();
	}
	catch (int e)
	{
		itsLogger->Error("Error code: " + boost::lexical_cast<string> (e));
		itsLogger->Error("Query: " + query.str());

		itsRadonDB->Rollback();

		return false;
	}

	itsLogger->Trace("Saved information on file '" + theFileName + "' to radon");

	return true;
}

map<string,string> radon::Grib1ParameterName(long producer, long fmiParameterId, long codeTableVersion, long timeRangeIndicator, long levelId, double level_value)
{
	Init();

	map<string,string> paramName = itsRadonDB->GetParameterFromGrib1(producer, codeTableVersion, fmiParameterId, timeRangeIndicator, levelId, level_value);
	return paramName;
}

map<string,string> radon::Grib2ParameterName(long fmiParameterId, long category, long discipline, long producer, long levelId, double level_value)
{
	Init();

	map<string,string> paramName = itsRadonDB->GetParameterFromGrib2(producer, discipline, category, fmiParameterId, levelId, level_value);
	return paramName;
}

string radon::ProducerMetaData(long producerId, const string& attribute) const
{
	string ret;

	if (attribute == "last hybrid level number")
	{
		switch (producerId)
		{
			case 1:
			case 199:
			case 210:
			case 230:
				ret = "65";
			break;

			case 131:
			case 240:
				ret = "137";
				break;

			default:
				throw runtime_error(ClassName() + ": Producer not supported");
				break;

		}
	}
	else if (attribute == "first hybrid level number")
	{
		switch (producerId)
		{
			case 1:
			case 199:
			case 210:
			case 230:
				ret = "1";
				break;

			case 131:
			case 240:
				ret = "24";
				break;

			default:
				throw runtime_error(ClassName() + ": Producer not supported");
				break;

		}
	}
	else
	{
		throw runtime_error(ClassName() + ": Attribute not recognized");
	}

	return ret;

	// In the future maybe something like this:

	//Init();

	//string query = "SELECT value FROM producers_eav WHERE producer_id = " + boost::lexical_cast<string> (producerId) + " AND attribute = '" + attribute + "'";
}

<commit_msg>update as_grid @ radon<commit_after>/**
 * @file radon.cpp
 *
 * @date Oct 28, 2012
 * @author tack
 */

#include "radon.h"
#include "logger_factory.h"
#include "plugin_factory.h"
#include <thread>
#include <sstream>
#include "util.h"
#include "unistd.h" // getuid())
#include "regular_grid.h"

using namespace std;
using namespace himan::plugin;

const int MAX_WORKERS = 16;
static once_flag oflag;

radon::radon() : itsInit(false), itsRadonDB()
{
	itsLogger = unique_ptr<logger> (logger_factory::Instance()->GetLog("radon"));

	// no lambda functions for gcc 4.4 :(
	// call_once(oflag, [](){ NFmiNeonsDBPool::MaxWorkers(MAX_WORKERS); });

	call_once(oflag, &himan::plugin::radon::InitPool, this);
}

void radon::InitPool()
{
	NFmiRadonDBPool::Instance()->MaxWorkers(MAX_WORKERS);

	uid_t uid = getuid();

	if (uid == 1459) // weto
	{
		NFmiRadonDBPool::Instance()->Username("wetodb");
		NFmiRadonDBPool::Instance()->Password("3loHRgdio");
	}
}

vector<string> radon::Files(search_options& options)
{

	Init();

	vector<string> files;

	string analtime = options.time.OriginDateTime().String("%Y-%m-%d %H:%M:%S+00");
	string levelvalue = boost::lexical_cast<string> (options.level.Value());

	string ref_prod = options.prod.Name();
	// long no_vers = options.prod.TableVersion();

	string level_name = HPLevelTypeToString.at(options.level.Type());

	vector<vector<string> > gridgeoms;
	vector<string> sourceGeoms = options.configuration->SourceGeomNames();

	if (sourceGeoms.empty())
	{
		// Get all geometries
		gridgeoms = itsRadonDB->GetGridGeoms(ref_prod, analtime);
	}
	else
	{
		for (size_t i = 0; i < sourceGeoms.size(); i++)
		{
			vector<vector<string>> geoms = itsRadonDB->GetGridGeoms(ref_prod, analtime, sourceGeoms[i]);
			gridgeoms.insert(gridgeoms.end(), geoms.begin(), geoms.end());
		}
	}

	if (gridgeoms.empty())
	{
		itsLogger->Warning("No geometries found for producer " + ref_prod +
		", analysistime " + analtime + ", source geom name(s) '" + util::Join(sourceGeoms, ",") +"', param " + options.param.Name());

		return files;
	}

	string forecastTypeValue = (options.ftype.Type() == kEpsPerturbation) ? boost::lexical_cast<string> (options.ftype.Value()) : "-1";

	for (size_t i = 0; i < gridgeoms.size(); i++)
	{
		string tablename = gridgeoms[i][1];
		string geomid = gridgeoms[i][0];

		string parm_name = options.param.Name();

		string query = "SELECT param_id, level_id, level_value, forecast_period, file_location, file_server "
				   "FROM "+tablename+"_v "
				   "WHERE analysis_time = '"+analtime+"' "
				   "AND param_name = '"+parm_name+"' "
				   "AND level_name = upper('"+level_name+"') "
				   "AND level_value = "+levelvalue+" "
				   "AND forecast_period = '"+util::MakeSQLInterval(options.time)+"' "
				   "AND geometry_id = "+geomid+" "
				   "AND forecast_type_id = "+boost::lexical_cast<string> (options.ftype.Type())+" "
				   "AND forecast_type_value = "+forecastTypeValue+" "
				   "ORDER BY forecast_period, level_id, level_value";

		itsRadonDB->Query(query);

		vector<string> values = itsRadonDB->FetchRow();

		if (values.empty())
		{
			continue;
		}

		itsLogger->Trace("Found data for parameter " + parm_name + " from radon geometry " + gridgeoms[i][3]);

		files.push_back(values[4]);

		break; // discontinue loop on first positive match

	}

	return files;

}

bool radon::Save(const info& resultInfo, const string& theFileName)
{

	Init();

	stringstream query;

	if (resultInfo.Grid()->Type() != kRegularGrid)
	{
		itsLogger->Error("Only grid data can be stored to radon for now");
		return false;
	}

	const regular_grid* g = dynamic_cast<regular_grid*> (resultInfo.Grid());

	/*
	 * 1. Get grid information
	 * 2. Get model information
	 * 3. Get data set information (ie model run)
	 * 4. Insert or update
	 */

	himan::point firstGridPoint = g->FirstGridPoint();

	query 	<< "SELECT geometry_id "
			<< "FROM geom_v "
			<< "WHERE nj = " << g->Nj()
			<< " AND ni = " << g->Ni()
			<< " AND first_lat = " << firstGridPoint.Y()
			<< " AND first_lon = " << firstGridPoint.X();

	itsRadonDB->Query(query.str());

	vector<string> row;

	row = itsRadonDB->FetchRow();

	if (row.empty())
	{
		itsLogger->Warning("Grid geometry not found from radon");
		return false;
	}

	string geom_id = row[0];

	query.str("");

	query	<< "SELECT "
			<< "id, table_name "
			<< "FROM as_grid "
			<< "WHERE geometry_id = '" << geom_id << "'"
			<< " AND analysis_time = '" << resultInfo.OriginDateTime().String("%Y-%m-%d %H:%M:%S+00") << "'"
			<< " AND producer_id = " << resultInfo.Producer().Id();

	itsRadonDB->Query(query.str());

	row = itsRadonDB->FetchRow();

	if (row.empty())
	{
		itsLogger->Warning("Data set definition not found from radon");
		return false;
	}

	string table_name = row[1];
	string dset_id = row[0];

	query.str("");

	char host[255];
	gethostname(host, 255);

	auto paraminfo = itsRadonDB->GetParameterFromDatabaseName(resultInfo.Producer().Id(), resultInfo.Param().Name());
	auto levelinfo = itsRadonDB->GetLevelFromGrib(resultInfo.Producer().Id(), resultInfo.Level().Type(), 1);

	/*
	 * We have our own error logging for unique key violations
	 */

	// itsRadonDB->Verbose(false);

	double forecastTypeValue = (resultInfo.ForecastType().Type() == kEpsPerturbation) ? resultInfo.ForecastType().Value() : -1.;

	string analysisTime = resultInfo.OriginDateTime().String("%Y-%m-%d %H:%M:%S+00");

	query  << "INSERT INTO data." << table_name
		   << " (producer_id, analysis_time, geometry_id, param_id, level_id, level_value, forecast_period, forecast_type_id, forecast_type_value, file_location, file_server) VALUES ("
		   << resultInfo.Producer().Id() << ", "
		   << "'" << analysisTime << "', "
		   << geom_id << ", "
		   << paraminfo["id"] << ", "
		   << levelinfo["id"] << ", "
		   << resultInfo.Level().Value() << ", "
		   << "'" << util::MakeSQLInterval(resultInfo.Time()) << "', "
		   << resultInfo.ForecastType().Type() << ", "
		   << forecastTypeValue << ","
		   << "'" << theFileName << "', "
		   << "'" << host << "')"
		   ;

	try
	{
		itsRadonDB->Execute(query.str());

		query.str("");

		query << "UPDATE as_grid SET record_count = record_count+1 WHERE producer_id = " << resultInfo.Producer().Id()
				<< " AND geometry_id = " << geom_id
				<< " AND analysis_time = '" << analysisTime << "'";

		itsRadonDB->Execute(query.str());
		itsRadonDB->Commit();
	}
	catch (int e)
	{
		itsRadonDB->Rollback();

		if (e == 7)
		{
			query.str("");
			query << "UPDATE data." << table_name << " SET "
					<< "file_location = '" << theFileName << "', "
					<< "file_server = '" << host << "' WHERE "
					<< "producer_id = " << resultInfo.Producer().Id() << " AND "
					<< "analysis_time = '" << analysisTime << "' AND "
					<< "geometry_id = " << geom_id << " AND "
					<< "param_id = " << paraminfo["id"] << " AND "
					<< "level_id = " << levelinfo["id"] << " AND "
					<< "level_value = " << resultInfo.Level().Value() << " AND "
					<< "forecast_period = " << "'" << util::MakeSQLInterval(resultInfo.Time()) << "' AND "
					<< "forecast_type_id = " << resultInfo.ForecastType().Type() << " AND "
					<< "forecast_type_value = " << forecastTypeValue;

			itsRadonDB->Execute(query.str());
			itsRadonDB->Commit();
		}
		else
		{
			itsLogger->Error("Error code: " + boost::lexical_cast<string> (e));
			itsLogger->Error("Query: " + query.str());
		}

		return false;
	}

	itsLogger->Trace("Saved information on file '" + theFileName + "' to radon");

	return true;
}

map<string,string> radon::Grib1ParameterName(long producer, long fmiParameterId, long codeTableVersion, long timeRangeIndicator, long levelId, double level_value)
{
	Init();

	map<string,string> paramName = itsRadonDB->GetParameterFromGrib1(producer, codeTableVersion, fmiParameterId, timeRangeIndicator, levelId, level_value);
	return paramName;
}

map<string,string> radon::Grib2ParameterName(long fmiParameterId, long category, long discipline, long producer, long levelId, double level_value)
{
	Init();

	map<string,string> paramName = itsRadonDB->GetParameterFromGrib2(producer, discipline, category, fmiParameterId, levelId, level_value);
	return paramName;
}

string radon::ProducerMetaData(long producerId, const string& attribute) const
{
	string ret;

	if (attribute == "last hybrid level number")
	{
		switch (producerId)
		{
			case 1:
			case 199:
			case 210:
			case 230:
				ret = "65";
			break;

			case 131:
			case 240:
				ret = "137";
				break;

			default:
				throw runtime_error(ClassName() + ": Producer not supported");
				break;

		}
	}
	else if (attribute == "first hybrid level number")
	{
		switch (producerId)
		{
			case 1:
			case 199:
			case 210:
			case 230:
				ret = "1";
				break;

			case 131:
			case 240:
				ret = "24";
				break;

			default:
				throw runtime_error(ClassName() + ": Producer not supported");
				break;

		}
	}
	else
	{
		throw runtime_error(ClassName() + ": Attribute not recognized");
	}

	return ret;

	// In the future maybe something like this:

	//Init();

	//string query = "SELECT value FROM producers_eav WHERE producer_id = " + boost::lexical_cast<string> (producerId) + " AND attribute = '" + attribute + "'";
}

<|endoftext|>


<commit_before>/*
* This file is part of KDevelop
*
* Copyright 2010 Niko Sams <niko.sams@gmail.com>
* Copyright 2010 Alexander Dymo <adymo@kdevelop.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library 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.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "declarationbuilder.h"

#include <interfaces/icore.h>
#include <language/duchain/classdeclaration.h>
#include <language/duchain/functiondeclaration.h>
#include <language/duchain/classfunctiondeclaration.h>
#include <language/duchain/types/functiontype.h>

#include "parser/rubyast.h"
#include "editorintegrator.h"

namespace Ruby
{

DeclarationBuilder::DeclarationBuilder(EditorIntegrator* editor):
    DeclarationBuilderBase()
{
    setEditor(editor);
}

void DeclarationBuilder::closeDeclaration()
{
    eventuallyAssignInternalContext();
    DeclarationBuilderBase::closeDeclaration();
}

void DeclarationBuilder::visitClass(ClassAST* ast)
{
    {
        KDevelop::SimpleRange range = editor()->findRange(ast);
        KDevelop::QualifiedIdentifier id(KDevelop::Identifier(KDevelop::IndexedString(ast->name->name)));

        KDevelop::DUChainWriteLocker lock(KDevelop::DUChain::lock());

        KDevelop::ClassDeclaration* decl = openDefinition<KDevelop::ClassDeclaration>(id, range);
        decl->setDeclarationIsDefinition(true);
        decl->setKind(KDevelop::Declaration::Type);
        decl->clearBaseClasses();
        decl->setClassType(KDevelop::ClassDeclarationData::Class);
    }
    DeclarationBuilderBase::visitClass(ast);
    closeDeclaration();
}

void DeclarationBuilder::visitFunction(FunctionAST* ast)
{
    KDevelop::Declaration *x = 0;
    {
        KDevelop::SimpleRange range = editor()->findRange(ast->name);
        KDevelop::QualifiedIdentifier id(KDevelop::Identifier(KDevelop::IndexedString(ast->name->name)));

        KDevelop::DUChainWriteLocker lock(KDevelop::DUChain::lock());

        if (ast->isMember) {
            KDevelop::ClassFunctionDeclaration *decl = openDefinition<KDevelop::ClassFunctionDeclaration>(id, range);
            decl->setAccessPolicy(ast->access);
            decl->setDeclarationIsDefinition(true);
            decl->setKind(KDevelop::Declaration::Type);
            x = decl;
        } else {
            KDevelop::FunctionDeclaration *decl = openDefinition<KDevelop::FunctionDeclaration>(id, range);
            decl->setDeclarationIsDefinition(true);
            decl->setKind(KDevelop::Declaration::Type);
            x = decl;
        }
    }
    DeclarationBuilderBase::visitFunction(ast);
    closeDeclaration();
/*    {
        KDevelop::DUChainWriteLocker lock(KDevelop::DUChain::lock());
        kDebug(9047) << x->toString();
        kDebug(9047) << x->type<KDevelop::FunctionType>()->partToString(KDevelop::FunctionType::SignatureArguments);
    }*/
}

void DeclarationBuilder::visitFunctionArgument(FunctionArgumentAST* ast)
{
    {
        // create variable declaration for argument
        KDevelop::DUChainWriteLocker lock(KDevelop::DUChain::lock());
        KDevelop::SimpleRange range = editor()->findRange(ast->name);
        KDevelop::QualifiedIdentifier id(KDevelop::Identifier(KDevelop::IndexedString(ast->name->name)));

        openDefinition<KDevelop::Declaration>(id, range);
        currentDeclaration()->setKind(KDevelop::Declaration::Instance);
    }
    DeclarationBuilderBase::visitFunctionArgument(ast);
    closeDeclaration();
}

void DeclarationBuilder::updateCurrentType()
{
    KDevelop::DUChainWriteLocker lock(KDevelop::DUChain::lock());
    currentDeclaration()->setAbstractType(currentAbstractType());
}

}
<commit_msg>Remove commented code and debug output<commit_after>/*
* This file is part of KDevelop
*
* Copyright 2010 Niko Sams <niko.sams@gmail.com>
* Copyright 2010 Alexander Dymo <adymo@kdevelop.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library 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.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "declarationbuilder.h"

#include <interfaces/icore.h>
#include <language/duchain/classdeclaration.h>
#include <language/duchain/functiondeclaration.h>
#include <language/duchain/classfunctiondeclaration.h>
#include <language/duchain/types/functiontype.h>

#include "parser/rubyast.h"
#include "editorintegrator.h"

namespace Ruby
{

DeclarationBuilder::DeclarationBuilder(EditorIntegrator* editor):
    DeclarationBuilderBase()
{
    setEditor(editor);
}

void DeclarationBuilder::closeDeclaration()
{
    eventuallyAssignInternalContext();
    DeclarationBuilderBase::closeDeclaration();
}

void DeclarationBuilder::visitClass(ClassAST* ast)
{
    {
        KDevelop::SimpleRange range = editor()->findRange(ast);
        KDevelop::QualifiedIdentifier id(KDevelop::Identifier(KDevelop::IndexedString(ast->name->name)));

        KDevelop::DUChainWriteLocker lock(KDevelop::DUChain::lock());

        KDevelop::ClassDeclaration* decl = openDefinition<KDevelop::ClassDeclaration>(id, range);
        decl->setDeclarationIsDefinition(true);
        decl->setKind(KDevelop::Declaration::Type);
        decl->clearBaseClasses();
        decl->setClassType(KDevelop::ClassDeclarationData::Class);
    }
    DeclarationBuilderBase::visitClass(ast);
    closeDeclaration();
}

void DeclarationBuilder::visitFunction(FunctionAST* ast)
{
    {
        KDevelop::SimpleRange range = editor()->findRange(ast->name);
        KDevelop::QualifiedIdentifier id(KDevelop::Identifier(KDevelop::IndexedString(ast->name->name)));

        KDevelop::DUChainWriteLocker lock(KDevelop::DUChain::lock());

        if (ast->isMember) {
            KDevelop::ClassFunctionDeclaration *decl = openDefinition<KDevelop::ClassFunctionDeclaration>(id, range);
            decl->setAccessPolicy(ast->access);
            decl->setDeclarationIsDefinition(true);
            decl->setKind(KDevelop::Declaration::Type);
        } else {
            KDevelop::FunctionDeclaration *decl = openDefinition<KDevelop::FunctionDeclaration>(id, range);
            decl->setDeclarationIsDefinition(true);
            decl->setKind(KDevelop::Declaration::Type);
        }
    }
    DeclarationBuilderBase::visitFunction(ast);
    closeDeclaration();
}

void DeclarationBuilder::visitFunctionArgument(FunctionArgumentAST* ast)
{
    {
        // create variable declaration for argument
        KDevelop::DUChainWriteLocker lock(KDevelop::DUChain::lock());
        KDevelop::SimpleRange range = editor()->findRange(ast->name);
        KDevelop::QualifiedIdentifier id(KDevelop::Identifier(KDevelop::IndexedString(ast->name->name)));

        openDefinition<KDevelop::Declaration>(id, range);
        currentDeclaration()->setKind(KDevelop::Declaration::Instance);
    }
    DeclarationBuilderBase::visitFunctionArgument(ast);
    closeDeclaration();
}

void DeclarationBuilder::updateCurrentType()
{
    KDevelop::DUChainWriteLocker lock(KDevelop::DUChain::lock());
    currentDeclaration()->setAbstractType(currentAbstractType());
}

}
<|endoftext|>


<commit_before>// This file is part of DVS-ROS - the RPG DVS ROS Package
//
// DVS-ROS 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 3 of the License, or
// (at your option) any later version.
//
// DVS-ROS 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 DVS-ROS.  If not, see <http://www.gnu.org/licenses/>.

#include <ros/ros.h>
#include <fstream>
#include <ctime>

#include <dvs_msgs/Event.h>
#include <dvs_msgs/EventArray.h>

std::ofstream myfile;

// Get current date/time, format is YYYY-MM-DD.HH:mm:ss
const std::string currentDateTime() {
    time_t     now = time(0);
    struct tm  tstruct;
    char       buf[80];
    tstruct = *localtime(&now);
    // Visit http://en.cppreference.com/w/cpp/chrono/c/strftime
    // for more information about date/time format
    strftime(buf, sizeof(buf), "%Y-%m-%d_%H-%M-%S", &tstruct);

    return buf;
}

void eventsCallback(const dvs_msgs::EventArray::ConstPtr& msg) {
  for (int i=0; i<msg->events.size(); ++i) {
    myfile << (int) msg->events[i].x << " ";
    myfile << (int) msg->events[i].y << " ";
    myfile << (int) msg->events[i].polarity << " ";
    myfile << msg->events[i].time << std::endl;
  }
}

int main(int argc, char* argv[])
{
  ros::init(argc, argv, "dvs_file_writer");

  ros::NodeHandle nh;

  std::string file_name = std::string("events-" + currentDateTime() + ".txt");

  myfile.open(file_name.c_str());

  ROS_INFO("Writing events to %s.", file_name.c_str());
  ros::Subscriber sub = nh.subscribe("dvs/events", 1000, eventsCallback);

  ros::spin();

  myfile.close();

  return 0;
}
<commit_msg>removed dot at the end for easier copying<commit_after>// This file is part of DVS-ROS - the RPG DVS ROS Package
//
// DVS-ROS 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 3 of the License, or
// (at your option) any later version.
//
// DVS-ROS 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 DVS-ROS.  If not, see <http://www.gnu.org/licenses/>.

#include <ros/ros.h>
#include <fstream>
#include <ctime>

#include <dvs_msgs/Event.h>
#include <dvs_msgs/EventArray.h>

std::ofstream myfile;

// Get current date/time, format is YYYY-MM-DD.HH:mm:ss
const std::string currentDateTime() {
    time_t     now = time(0);
    struct tm  tstruct;
    char       buf[80];
    tstruct = *localtime(&now);
    // Visit http://en.cppreference.com/w/cpp/chrono/c/strftime
    // for more information about date/time format
    strftime(buf, sizeof(buf), "%Y-%m-%d_%H-%M-%S", &tstruct);

    return buf;
}

void eventsCallback(const dvs_msgs::EventArray::ConstPtr& msg) {
  for (int i=0; i<msg->events.size(); ++i) {
    myfile << (int) msg->events[i].x << " ";
    myfile << (int) msg->events[i].y << " ";
    myfile << (int) msg->events[i].polarity << " ";
    myfile << msg->events[i].time << std::endl;
  }
}

int main(int argc, char* argv[])
{
  ros::init(argc, argv, "dvs_file_writer");

  ros::NodeHandle nh;

  std::string file_name = std::string("events-" + currentDateTime() + ".txt");

  myfile.open(file_name.c_str());

  ROS_INFO("Writing events to %s", file_name.c_str());
  ros::Subscriber sub = nh.subscribe("dvs/events", 1000, eventsCallback);

  ros::spin();

  myfile.close();

  return 0;
}
<|endoftext|>


<commit_before>#include "tangram.h"
#include "platform.h"
#include "gl.h"

// Input handling
// ==============

const double double_tap_time = 0.5; // seconds
const double scroll_multiplier = 0.05; // scaling for zoom

bool was_panning = false;
double last_mouse_up = -double_tap_time; // First click should never trigger a double tap
double last_x_down = 0.0;
double last_y_down = 0.0;

void mouse_button_callback(GLFWwindow* window, int button, int action, int mods) {

    if (button != GLFW_MOUSE_BUTTON_1) {
        return; // This event is for a mouse button that we don't care about
    }

    if (was_panning) {
        was_panning = false;
        return; // Clicks with movement don't count as taps
    }

    double x, y;
    glfwGetCursorPos(window, &x, &y);
    double time = glfwGetTime();

    if (action == GLFW_PRESS) {
        last_x_down = x;
        last_y_down = y;
        return;
    }

    if (time - last_mouse_up < double_tap_time) {
        Tangram::handleDoubleTapGesture(x, y);
    } else {
        Tangram::handleTapGesture(x, y);
    }

    last_mouse_up = time;

}

void cursor_pos_callback(GLFWwindow* window, double x, double y) {

    int action = glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_1);

    if (action == GLFW_PRESS) {

        if (was_panning) {
            Tangram::handlePanGesture(x - last_x_down, y - last_y_down);
        }

        was_panning = true;
        last_x_down = x;
        last_y_down = y;
    }

}

void scroll_callback(GLFWwindow* window, double scrollx, double scrolly) {

    double x, y;
    glfwGetCursorPos(window, &x, &y);
    Tangram::handlePinchGesture(x, y, 1.0 + scroll_multiplier * scrolly);

}

void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
    if (key == GLFW_KEY_E && (action == GLFW_PRESS || action == GLFW_REPEAT)) {
        Tangram::handleRotateGesture(0.0f, 0.0f, -0.1f);
    }

    if (key == GLFW_KEY_Q && (action == GLFW_PRESS || action == GLFW_REPEAT)) {
        Tangram::handleRotateGesture(0.0f, 0.0f, 0.1f);
    }
}

// Window handling
// ===============

void window_size_callback(GLFWwindow* window, int width, int height) {

    Tangram::resize(width, height);

}

// Main program
// ============

int main(void) {

    GLFWwindow* window;
    int width = 800;
    int height = 600;

    /* Initialize the library */
    if (!glfwInit())
        return -1;

    /* Create a windowed mode window and its OpenGL context */
    window = glfwCreateWindow(width, height, "GLFW Window", NULL, NULL);
    if (!window) {
        glfwTerminate();
        return -1;
    }

    /* Make the window's context current */
    glfwMakeContextCurrent(window);

    Tangram::initialize();
    Tangram::resize(width, height);

    glfwSetWindowSizeCallback(window, window_size_callback);
    glfwSetMouseButtonCallback(window, mouse_button_callback);
    glfwSetCursorPosCallback(window, cursor_pos_callback);
    glfwSetScrollCallback(window, scroll_callback);
    glfwSetKeyCallback(window, key_callback);

    glfwSwapInterval(1);

    double lastTime = glfwGetTime();

    /* Loop until the user closes the window */
    while (!glfwWindowShouldClose(window)) {

        double currentTime = glfwGetTime();
        double delta = currentTime - lastTime;
        lastTime = currentTime;

        /* Render here */
        Tangram::update(delta);
        Tangram::render();

        /* Swap front and back buffers */
        glfwSwapBuffers(window);

        /* Poll for and process events */
        glfwPollEvents();
    }

    Tangram::teardown();
    glfwTerminate();
    return 0;
}
<commit_msg>Forgot that I changed a function signature<commit_after>#include "tangram.h"
#include "platform.h"
#include "gl.h"

// Input handling
// ==============

const double double_tap_time = 0.5; // seconds
const double scroll_multiplier = 0.05; // scaling for zoom

bool was_panning = false;
double last_mouse_up = -double_tap_time; // First click should never trigger a double tap
double last_x_down = 0.0;
double last_y_down = 0.0;

void mouse_button_callback(GLFWwindow* window, int button, int action, int mods) {

    if (button != GLFW_MOUSE_BUTTON_1) {
        return; // This event is for a mouse button that we don't care about
    }

    if (was_panning) {
        was_panning = false;
        return; // Clicks with movement don't count as taps
    }

    double x, y;
    glfwGetCursorPos(window, &x, &y);
    double time = glfwGetTime();

    if (action == GLFW_PRESS) {
        last_x_down = x;
        last_y_down = y;
        return;
    }

    if (time - last_mouse_up < double_tap_time) {
        Tangram::handleDoubleTapGesture(x, y);
    } else {
        Tangram::handleTapGesture(x, y);
    }

    last_mouse_up = time;

}

void cursor_pos_callback(GLFWwindow* window, double x, double y) {

    int action = glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_1);

    if (action == GLFW_PRESS) {

        if (was_panning) {
            Tangram::handlePanGesture(x - last_x_down, y - last_y_down);
        }

        was_panning = true;
        last_x_down = x;
        last_y_down = y;
    }

}

void scroll_callback(GLFWwindow* window, double scrollx, double scrolly) {

    double x, y;
    glfwGetCursorPos(window, &x, &y);
    Tangram::handlePinchGesture(x, y, 1.0 + scroll_multiplier * scrolly);

}

void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
    if (key == GLFW_KEY_E && (action == GLFW_PRESS || action == GLFW_REPEAT)) {
        Tangram::handleRotateGesture(-0.1f);
    }

    if (key == GLFW_KEY_Q && (action == GLFW_PRESS || action == GLFW_REPEAT)) {
        Tangram::handleRotateGesture(0.1f);
    }
}

// Window handling
// ===============

void window_size_callback(GLFWwindow* window, int width, int height) {

    Tangram::resize(width, height);

}

// Main program
// ============

int main(void) {

    GLFWwindow* window;
    int width = 800;
    int height = 600;

    /* Initialize the library */
    if (!glfwInit())
        return -1;

    /* Create a windowed mode window and its OpenGL context */
    window = glfwCreateWindow(width, height, "GLFW Window", NULL, NULL);
    if (!window) {
        glfwTerminate();
        return -1;
    }

    /* Make the window's context current */
    glfwMakeContextCurrent(window);

    Tangram::initialize();
    Tangram::resize(width, height);

    glfwSetWindowSizeCallback(window, window_size_callback);
    glfwSetMouseButtonCallback(window, mouse_button_callback);
    glfwSetCursorPosCallback(window, cursor_pos_callback);
    glfwSetScrollCallback(window, scroll_callback);
    glfwSetKeyCallback(window, key_callback);

    glfwSwapInterval(1);

    double lastTime = glfwGetTime();

    /* Loop until the user closes the window */
    while (!glfwWindowShouldClose(window)) {

        double currentTime = glfwGetTime();
        double delta = currentTime - lastTime;
        lastTime = currentTime;

        /* Render here */
        Tangram::update(delta);
        Tangram::render();

        /* Swap front and back buffers */
        glfwSwapBuffers(window);

        /* Poll for and process events */
        glfwPollEvents();
    }

    Tangram::teardown();
    glfwTerminate();
    return 0;
}
<|endoftext|>


<commit_before>#pragma once

#include <iostream>
#include <iomanip>
#include <string.h>

// void print(const int it, const double energy);

template<typename T>
std::string to_string(const T& t)
{
    std::ostringstream strs;
    strs << std::scientific << std::setprecision(3) << t;
    return strs.str();
}

template<typename T>
std::string red(const T& t)
{
    return "\033[31m" + to_string(t) + "\033[0m";
}

template<typename T>
std::string green(const T& t)
{
    return "\033[32m" + to_string(t) + "\033[0m";
}

template<typename T>
std::string yellow(const T& t)
{
    return "\033[33m" + to_string(t) + "\033[0m";
}

template<typename T>
std::string blue(const T& t)
{
    return "\033[34m" + to_string(t) + "\033[0m";
}

template<typename T>
std::string white(const T& t)
{
    return "\033[37m" + to_string(t) + "\033[0m";
}

std::string red(const std::string& s);
std::string green(const std::string& s);
std::string yellow(const std::string& s);
std::string blue(const std::string& s);
std::string white(const std::string& s);

void bar();

// template<typename Solver, typename Color>
// template<typename Solver, typename T, typename Color = std::string (*Color)(T&)>
// template<typename T, std::string (*Color)(const T&), typename Solver>
// void print(
//       const Solver& s
//     // , const Color& c
//     )
// {
//     std::cout << Color(s.current_it) << "\t";
//     std::cout << Color(s.current_temperature) << "\t";
//     std::cout << Color(s.current_temperature - s.temperature(s.current_temperature)) << "\t";
//     std::cout << Color(s.current_energy) << "\t";
//     // // std::cout << s.d_energy << "\t";
//     std::cout << std::endl;
// }

struct Accepted{};
struct Rejected{};

template<typename Solver>
void print(
      const Solver& s
    , Accepted
    )
{
    // std::cout << green(s.current_it) << "\t";
    std::cout << green(s.current_temperature) << "\t";
    std::cout << green(s.current_temperature - s.temperature()) << "\t";
    std::cout << green(s.current_energy) << "\t";
    // // std::cout << s.d_energy << "\t";

    std::cout << "\n\r\e[A";
    std::cout << std::string(100, ' ');
    std::cout << "\r";

    // std::cout << "\n\r\e[A";
}

template<typename Solver>
void print(
      const Solver& s
    , Rejected
    )
{
    // std::cout << red(s.current_it) << "\t";
    std::cout << red(s.current_temperature) << "\t";
    std::cout << red(s.current_temperature - s.temperature()) << "\t";
    std::cout << red(s.current_energy) << "\t";
    // // std::cout << s.d_energy << "\t";

    std::cout << "\n\r\e[A";
    std::cout << std::string(100, ' ');
    std::cout << "\r";
}

template<typename Solver>
void final_print(const Solver& s)
{
    std::cout << std::endl;
    std::cout << "Final temperature: " << s.current_temperature << "\n";
    std::cout << "Final energy: " << s.current_energy << "\n";
    std::cout << std::endl;
}
<commit_msg>[display] major update<commit_after>#pragma once

#include <iostream>
#include <iomanip>
#include <string.h>

// void print(const int it, const double energy);

template<typename T>
std::string to_string(const T& t)
{
    std::ostringstream strs;
    strs << std::scientific << std::setprecision(3) << t;
    return strs.str();
}

template<typename T>
std::string red(const T& t)
{
    return "\033[31m" + to_string(t) + "\033[0m";
}

template<typename T>
std::string green(const T& t)
{
    return "\033[32m" + to_string(t) + "\033[0m";
}

template<typename T>
std::string yellow(const T& t)
{
    return "\033[33m" + to_string(t) + "\033[0m";
}

template<typename T>
std::string blue(const T& t)
{
    return "\033[34m" + to_string(t) + "\033[0m";
}

template<typename T>
std::string white(const T& t)
{
    return "\033[37m" + to_string(t) + "\033[0m";
}

std::string red(const std::string& s);
std::string green(const std::string& s);
std::string yellow(const std::string& s);
std::string blue(const std::string& s);
std::string white(const std::string& s);

void bar();

// template<typename Solver, typename Color>
// template<typename Solver, typename T, typename Color = std::string (*Color)(T&)>
// template<typename T, std::string (*Color)(const T&), typename Solver>
// void print(
//       const Solver& s
//     // , const Color& c
//     )
// {
//     std::cout << Color(s.current_it) << "\t";
//     std::cout << Color(s.current_temperature) << "\t";
//     std::cout << Color(s.current_temperature - s.temperature(s.current_temperature)) << "\t";
//     std::cout << Color(s.current_energy) << "\t";
//     // // std::cout << s.d_energy << "\t";
//     std::cout << std::endl;
// }

struct Accepted{};
struct Rejected{};

template<typename Solver>
void print(
      const Solver& s
    , Accepted
    )
{
    // std::cout << green(s.current_it) << "\t";
    std::cout << green(s.current_temperature) << "\t";
    std::cout << green(s.current_temperature - s.temperature()) << "\t";
    std::cout << green(s.current_energy) << "\t";
    // // std::cout << s.d_energy << "\t";

    std::cout << "\r";
}

template<typename Solver>
void print(
      const Solver& s
    , Rejected
    )
{
    // std::cout << red(s.current_it) << "\t";
    std::cout << red(s.current_temperature) << "\t";
    std::cout << red(s.current_temperature - s.temperature()) << "\t";
    std::cout << red(s.current_energy) << "\t";
    // // std::cout << s.d_energy << "\t";

    std::cout << "\r";
}

template<typename Solver>
void final_print(const Solver& s)
{
    std::cout << std::endl;
    std::cout << "Final temperature: " << s.current_temperature << "\n";
    std::cout << "Final energy: " << s.current_energy << "\n";
    std::cout << std::endl;
}
<|endoftext|>


<commit_before>#include "duktape.h"
#include "dukbind.h"
#include "dukbindconf.h"
#include "dukbind_proxy_function.h"
#include "dukbind_private.h"
#include "utils/dukbind_debug.h"

namespace dukbind
{

    struct Box
    {
        void * ObjectPointer;
        size_t ClassIndex;
        finalizer_t Finalizer;
    };

    void Push( duk_context * ctx, const bool value, const bool* )
    {
        duk_push_boolean( ctx, value );
    }

    void Push( duk_context * ctx, const char * value, const char ** )
    {
        duk_push_string( ctx, value );
    }

    void Push( duk_context * ctx, const int value, const int * )
    {
        dukbind_assert(
            ( (int)(duk_double_t) value ) == value,
            "Value does not fit into a duk_double_t"
            );

        duk_push_number( ctx, (duk_double_t)value );
    }

    void Push( duk_context * ctx, const float value, const float * )
    {
        dukbind_assert(
            ( (float)(duk_double_t) value ) == value,
            "Value does not fit into a duk_double_t"
            );

         duk_push_number( ctx, (duk_double_t)value );
    }

    void Push( duk_context * ctx, const double value, const double * )
    {
        dukbind_assert(
            ( (double)(duk_double_t) value ) == value,
            "Value does not fit into a duk_double_t"
            );
         duk_push_number( ctx, (duk_double_t)value );
    }

    bool Get( duk_context * ctx, const int index, const bool * )
    {
        dukbind_assert( duk_is_boolean( ctx, index ), "No conversion is allowed in Get methods" );
        return duk_to_boolean( ctx, index );
    }

    const char * Get( duk_context * ctx, const int index, const char ** )
    {
        dukbind_assert(
            duk_is_null_or_undefined( ctx, index ) ||  duk_is_string( ctx, index ),
            "No conversion is allowed in Get methods" );

        if( duk_is_null_or_undefined( ctx, index ) )
        {
            return 0;
        }
        else
        {
            return duk_to_string( ctx, index );
        }
    }

    int Get( duk_context * ctx, const int index, const int * )
    {
        dukbind_assert( duk_is_number( ctx, index ), "No conversion is allowed in Get methods" );

        duk_double_t double_result = duk_to_number( ctx, index );
        int int_result = static_cast<int>( double_result );

        dukbind_assert( double_result == (duk_double_t)int_result, "Number is not a valid integer" );

        return int_result;
    }

    float Get( duk_context * ctx, const int index, const float * )
    {
        dukbind_assert( duk_is_number( ctx, index ), "No conversion is allowed in Get methods" );

        duk_double_t double_result = duk_to_number( ctx, index );
        float float_result = static_cast<float>( double_result );

        #if DUKBIND_NO_FLOAT_CONVERSION
            dukbind_assert( double_result == (duk_double_t)float_result, "Number is not a valid integer" );
        #endif

        return float_result;
    }

    double Get( duk_context * ctx, const int index, const double * )
    {
        dukbind_assert( duk_is_number( ctx, index ), "No conversion is allowed in Get methods" );

        return duk_to_number( ctx, index );
    }

    static Box * PrivatePush( duk_context * ctx, const size_t class_index, const size_t object_size, finalizer_t finalizer )
    {
        duk_push_global_object( ctx );
        duk_get_prop_string( ctx, -1, "Proxy" );
        duk_remove( ctx, -2 );

        duk_push_object( ctx );

        size_t require_size = sizeof( Box ) + object_size;

        Box * box = reinterpret_cast<Box*>( duk_push_fixed_buffer( ctx, require_size ) );
        box->ClassIndex = class_index;
        box->Finalizer = finalizer;

        duk_put_prop_string( ctx, -2, "\xFF" "Box" );

        duk_push_c_function( ctx, &internal::ClassFinalizer, 1 );
        duk_set_finalizer( ctx, -2 );

        duk_push_heap_stash( ctx );
        duk_get_prop_string( ctx, -1, "InstanceHandler" );
        duk_remove( ctx, -2 );
        duk_new( ctx, 2 );

        return box;
    }

    void * Push( duk_context * ctx, const size_t class_index, const size_t object_size, finalizer_t finalizer )
    {
        Box * box = PrivatePush( ctx, class_index, object_size, finalizer );
        box->ObjectPointer = box + 1;

        return box->ObjectPointer;
    }

    void * Push( duk_context * ctx, const size_t class_index, void * object_pointer, finalizer_t finalizer )
    {
        Box * box = PrivatePush( ctx, class_index, 0, finalizer );
        box->ObjectPointer = object_pointer;

        return box->ObjectPointer;
    }

    void * Get( duk_context * ctx, duk_idx_t index, size_t & class_index, finalizer_t & finalizer )
    {
        duk_size_t size;
        duk_get_prop_string( ctx, index, "\xFF" "Box" );
        dukbind_assert( duk_is_fixed_buffer( ctx, -1 ), "Boxing is always implemented as fixed buffer" );
        Box * box = reinterpret_cast<Box*>( duk_to_buffer( ctx, -1, &size ) );
        duk_pop( ctx );

        dukbind_assert( sizeof( Box ) <= size, "Fixed buffer is not a box" );

        class_index = box->ClassIndex;
        finalizer = box->Finalizer;
        return box->ObjectPointer;
    }

    void Setup( duk_context * ctx, const BindingInfo & info, const char * module )
    {
        debug::StackMonitor monitor( ctx );
        duk_push_global_stash( ctx );
        void * info_buffer = duk_push_fixed_buffer( ctx, sizeof( BindingInfo * ) );
        *reinterpret_cast<const BindingInfo**>( info_buffer ) = &info; // :TODO: Ref count

        duk_put_prop_string( ctx, -2, DUKBIND_BINDING_NAME );
        duk_pop( ctx );

        if( module )
        {
            duk_push_global_object( ctx );
            duk_get_prop_string( ctx, -1, "Proxy" );
            duk_push_object( ctx );
            duk_push_object( ctx );

            duk_push_c_function( ctx, internal::BindingGet, 2 );
            duk_put_prop_string( ctx, -2, "get" );

            duk_push_c_function( ctx, internal::BindingHas, 1 );
            duk_put_prop_string( ctx, -2, "has" );

            duk_push_c_function( ctx, internal::ForbidSet, 3 );
            duk_put_prop_string( ctx, -2, "set" );

            duk_push_c_function( ctx, internal::ForbidDelete, 1 );
            duk_put_prop_string( ctx, -2, "deleteProperty" );
            duk_new( ctx, 2 );

            duk_put_prop_string( ctx, -2, module );
            duk_pop( ctx );
        }
        else
        {

            duk_push_global_object( ctx );

            duk_get_prop_string( ctx, -1, "Proxy" );

            duk_dup( ctx, -2 );
            duk_push_object( ctx );

            duk_push_c_function( ctx, internal::GlobalsGet, 2 );
            duk_put_prop_string( ctx, -2, "get" );

            duk_push_c_function( ctx, internal::GlobalsHas, 1 );
            duk_put_prop_string( ctx, -2, "has" );

            duk_new( ctx, 2 );
            duk_set_global_object( ctx );

            duk_pop( ctx );
        }

        duk_push_heap_stash( ctx );
        duk_push_object( ctx );

        duk_push_c_function( ctx, internal::ClassGet, 2 );
        duk_put_prop_string( ctx, -2, "get" );

        duk_push_c_function( ctx, internal::ClassHas, 1 );
        duk_put_prop_string( ctx, -2, "has" );

        duk_push_c_function( ctx, internal::ClassSet, 3 );
        duk_put_prop_string( ctx, -2, "set" );

        duk_push_c_function( ctx, internal::ForbidDelete, 1 );
        duk_put_prop_string( ctx, -2, "deleteProperty" );

        duk_put_prop_string( ctx, -2, "InstanceHandler" );

        duk_pop( ctx );
    }

}
<commit_msg>Handle null pointer in push char*<commit_after>#include "duktape.h"
#include "dukbind.h"
#include "dukbindconf.h"
#include "dukbind_proxy_function.h"
#include "dukbind_private.h"
#include "utils/dukbind_debug.h"

namespace dukbind
{

    struct Box
    {
        void * ObjectPointer;
        size_t ClassIndex;
        finalizer_t Finalizer;
    };

    void Push( duk_context * ctx, const bool value, const bool* )
    {
        duk_push_boolean( ctx, value );
    }

    void Push( duk_context * ctx, const char * value, const char ** )
    {
        if( value )
        {
            duk_push_string( ctx, value );
        }
        else
        {
            duk_push_null( ctx );
        }

    }

    void Push( duk_context * ctx, const int value, const int * )
    {
        dukbind_assert(
            ( (int)(duk_double_t) value ) == value,
            "Value does not fit into a duk_double_t"
            );

        duk_push_number( ctx, (duk_double_t)value );
    }

    void Push( duk_context * ctx, const float value, const float * )
    {
        dukbind_assert(
            ( (float)(duk_double_t) value ) == value,
            "Value does not fit into a duk_double_t"
            );

         duk_push_number( ctx, (duk_double_t)value );
    }

    void Push( duk_context * ctx, const double value, const double * )
    {
        dukbind_assert(
            ( (double)(duk_double_t) value ) == value,
            "Value does not fit into a duk_double_t"
            );
         duk_push_number( ctx, (duk_double_t)value );
    }

    bool Get( duk_context * ctx, const int index, const bool * )
    {
        dukbind_assert( duk_is_boolean( ctx, index ), "No conversion is allowed in Get methods" );
        return duk_to_boolean( ctx, index );
    }

    const char * Get( duk_context * ctx, const int index, const char ** )
    {
        dukbind_assert(
            duk_is_null_or_undefined( ctx, index ) ||  duk_is_string( ctx, index ),
            "No conversion is allowed in Get methods" );

        if( duk_is_null_or_undefined( ctx, index ) )
        {
            return 0;
        }
        else
        {
            return duk_to_string( ctx, index );
        }
    }

    int Get( duk_context * ctx, const int index, const int * )
    {
        dukbind_assert( duk_is_number( ctx, index ), "No conversion is allowed in Get methods" );

        duk_double_t double_result = duk_to_number( ctx, index );
        int int_result = static_cast<int>( double_result );

        dukbind_assert( double_result == (duk_double_t)int_result, "Number is not a valid integer" );

        return int_result;
    }

    float Get( duk_context * ctx, const int index, const float * )
    {
        dukbind_assert( duk_is_number( ctx, index ), "No conversion is allowed in Get methods" );

        duk_double_t double_result = duk_to_number( ctx, index );
        float float_result = static_cast<float>( double_result );

        #if DUKBIND_NO_FLOAT_CONVERSION
            dukbind_assert( double_result == (duk_double_t)float_result, "Number is not a valid integer" );
        #endif

        return float_result;
    }

    double Get( duk_context * ctx, const int index, const double * )
    {
        dukbind_assert( duk_is_number( ctx, index ), "No conversion is allowed in Get methods" );

        return duk_to_number( ctx, index );
    }

    static Box * PrivatePush( duk_context * ctx, const size_t class_index, const size_t object_size, finalizer_t finalizer )
    {
        duk_push_global_object( ctx );
        duk_get_prop_string( ctx, -1, "Proxy" );
        duk_remove( ctx, -2 );

        duk_push_object( ctx );

        size_t require_size = sizeof( Box ) + object_size;

        Box * box = reinterpret_cast<Box*>( duk_push_fixed_buffer( ctx, require_size ) );
        box->ClassIndex = class_index;
        box->Finalizer = finalizer;

        duk_put_prop_string( ctx, -2, "\xFF" "Box" );

        duk_push_c_function( ctx, &internal::ClassFinalizer, 1 );
        duk_set_finalizer( ctx, -2 );

        duk_push_heap_stash( ctx );
        duk_get_prop_string( ctx, -1, "InstanceHandler" );
        duk_remove( ctx, -2 );
        duk_new( ctx, 2 );

        return box;
    }

    void * Push( duk_context * ctx, const size_t class_index, const size_t object_size, finalizer_t finalizer )
    {
        Box * box = PrivatePush( ctx, class_index, object_size, finalizer );
        box->ObjectPointer = box + 1;

        return box->ObjectPointer;
    }

    void * Push( duk_context * ctx, const size_t class_index, void * object_pointer, finalizer_t finalizer )
    {
        Box * box = PrivatePush( ctx, class_index, 0, finalizer );
        box->ObjectPointer = object_pointer;

        return box->ObjectPointer;
    }

    void * Get( duk_context * ctx, duk_idx_t index, size_t & class_index, finalizer_t & finalizer )
    {
        duk_size_t size;
        duk_get_prop_string( ctx, index, "\xFF" "Box" );
        dukbind_assert( duk_is_fixed_buffer( ctx, -1 ), "Boxing is always implemented as fixed buffer" );
        Box * box = reinterpret_cast<Box*>( duk_to_buffer( ctx, -1, &size ) );
        duk_pop( ctx );

        dukbind_assert( sizeof( Box ) <= size, "Fixed buffer is not a box" );

        class_index = box->ClassIndex;
        finalizer = box->Finalizer;
        return box->ObjectPointer;
    }

    void Setup( duk_context * ctx, const BindingInfo & info, const char * module )
    {
        debug::StackMonitor monitor( ctx );
        duk_push_global_stash( ctx );
        void * info_buffer = duk_push_fixed_buffer( ctx, sizeof( BindingInfo * ) );
        *reinterpret_cast<const BindingInfo**>( info_buffer ) = &info; // :TODO: Ref count

        duk_put_prop_string( ctx, -2, DUKBIND_BINDING_NAME );
        duk_pop( ctx );

        if( module )
        {
            duk_push_global_object( ctx );
            duk_get_prop_string( ctx, -1, "Proxy" );
            duk_push_object( ctx );
            duk_push_object( ctx );

            duk_push_c_function( ctx, internal::BindingGet, 2 );
            duk_put_prop_string( ctx, -2, "get" );

            duk_push_c_function( ctx, internal::BindingHas, 1 );
            duk_put_prop_string( ctx, -2, "has" );

            duk_push_c_function( ctx, internal::ForbidSet, 3 );
            duk_put_prop_string( ctx, -2, "set" );

            duk_push_c_function( ctx, internal::ForbidDelete, 1 );
            duk_put_prop_string( ctx, -2, "deleteProperty" );
            duk_new( ctx, 2 );

            duk_put_prop_string( ctx, -2, module );
            duk_pop( ctx );
        }
        else
        {

            duk_push_global_object( ctx );

            duk_get_prop_string( ctx, -1, "Proxy" );

            duk_dup( ctx, -2 );
            duk_push_object( ctx );

            duk_push_c_function( ctx, internal::GlobalsGet, 2 );
            duk_put_prop_string( ctx, -2, "get" );

            duk_push_c_function( ctx, internal::GlobalsHas, 1 );
            duk_put_prop_string( ctx, -2, "has" );

            duk_new( ctx, 2 );
            duk_set_global_object( ctx );

            duk_pop( ctx );
        }

        duk_push_heap_stash( ctx );
        duk_push_object( ctx );

        duk_push_c_function( ctx, internal::ClassGet, 2 );
        duk_put_prop_string( ctx, -2, "get" );

        duk_push_c_function( ctx, internal::ClassHas, 1 );
        duk_put_prop_string( ctx, -2, "has" );

        duk_push_c_function( ctx, internal::ClassSet, 3 );
        duk_put_prop_string( ctx, -2, "set" );

        duk_push_c_function( ctx, internal::ForbidDelete, 1 );
        duk_put_prop_string( ctx, -2, "deleteProperty" );

        duk_put_prop_string( ctx, -2, "InstanceHandler" );

        duk_pop( ctx );
    }

}
<|endoftext|>


<commit_before>/******************************************************************************
 * This file is part of the Mula project
 * Copyright (c) 2011 Laszlo Papp <lpapp@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.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
 */

#include "dictionarymanager.h"

#include "pluginmanager.h"

#include <QtCore/QFileInfoList>
#include <QtCore/QDir>
#include <QtCore/QSettings>
#include <QtCore/QPluginLoader>

using namespace MulaCore;

MULA_DEFINE_SINGLETON( DictionaryManager )

class DictionaryManager::Private
{
    public:
        Private()
        {
        }

        ~Private()
        {
        }

        QMultiHash<QString, QString> loadedDictionaryList;
};

DictionaryManager::DictionaryManager(QObject *parent)
    : MulaCore::Singleton< MulaCore::DictionaryManager >( parent )
    , d(new Private)
{
    loadDictionarySettings();
}

DictionaryManager::~DictionaryManager()
{
    saveDictionarySettings();
}

bool
DictionaryManager::isTranslatable(const QString &word)
{
    for (QMultiHash<QString, QString>::const_iterator i = d->loadedDictionaryList.begin(); i != d->loadedDictionaryList.end(); ++i)
    {
        MulaCore::DictionaryPlugin* dictionaryPlugin = MulaCore::PluginManager::instance()->plugin(i.key());
        if (!dictionaryPlugin)
            continue;

        if (dictionaryPlugin->isTranslatable(i.value(), word))
            return true;
    }

    return false;
}

QString
DictionaryManager::translate(const QString &word)
{
    QString simplifiedWord = word.simplified();
    QString translatedWord;

    for (QMultiHash<QString, QString>::const_iterator i = d->loadedDictionaryList.begin(); i != d->loadedDictionaryList.end(); ++i)
    {
        MulaCore::DictionaryPlugin* dictionaryPlugin = MulaCore::PluginManager::instance()->plugin(i.key());
        if (!dictionaryPlugin)
            continue;

        if (!dictionaryPlugin->isTranslatable(i.key(), simplifiedWord))
            continue;

        MulaCore::Translation translation = dictionaryPlugin->translate(i.key(), simplifiedWord);
        translatedWord.append(QString("
\n")
            + "" + translation.dictionaryName() + "
\n"
            + "" + translation.title() + "
\n"
            + translation.translation() + "
\n");
    }

    return translatedWord;
}

QStringList
DictionaryManager::findSimilarWords(const QString &word)
{
    QString simplifiedWord = word.simplified();
    QStringList similarWords;

    for (QMultiHash<QString, QString>::const_iterator i = d->loadedDictionaryList.begin(); i != d->loadedDictionaryList.end(); ++i)
    {
        MulaCore::DictionaryPlugin* dictionaryPlugin = MulaCore::PluginManager::instance()->plugin(i.key());
        if (!dictionaryPlugin)
            continue;

        if (!dictionaryPlugin->features().testFlag(DictionaryPlugin::SearchSimilar))
            continue;

        QStringList similarWords = dictionaryPlugin->findSimilarWords(i.value(), simplifiedWord);
        foreach (const QString& similarWord, similarWords)
        {
            if (!similarWords.contains(similarWord, Qt::CaseSensitive))
                similarWords.append(similarWord);
        }
    }

    return similarWords;
}

QMultiHash<QString, QString>
DictionaryManager::availableDictionaryList() const
{
    QMultiHash<QString, QString> availableDictionaryList;

    // for (QHash<QString, QPluginLoader*>::const_iterator i = m_plugins.begin(); i != m_plugins.end(); ++i)
    // {
        // DictionaryPlugin *plugin = qobject_cast<DictionaryPlugin*>((*i)->instance());
        // QStringList dictionaries = plugin->availableDictionaryList();
        // foreach (const QString& dictionary, dictionaries)
            // availableDictionaryList.append(DictionaryDataItem(i.key(), dictionary));
    // }

    return availableDictionaryList;
}

void
DictionaryManager::setLoadedDictionaryList(const QMultiHash<QString, QString> &loadedDictionaryList)
{
    QMultiHash<QString, QString> dictionaries = loadedDictionaryList;

    for (QMultiHash<QString, QString>::const_iterator i = dictionaries.begin(); i != dictionaries.end(); ++i)
    {
        MulaCore::DictionaryPlugin* dictionaryPlugin = MulaCore::PluginManager::instance()->plugin(i.key());
        if (!dictionaryPlugin)
            continue;

        // TODO: this statement must be revisited for correction since we should
        // add the whole list, not values separately or at least change the set
        // API
        dictionaryPlugin->setLoadedDictionaryList(QStringList() <loadedDictionaryList())
                dictionaries.insert(i.key(), dictionaryName);
    }

    d->loadedDictionaryList.clear();
    for (QMultiHash<QString, QString>::const_iterator i = loadedDictionaryList.begin(); i != loadedDictionaryList.end(); ++i)
    {
        if (dictionaries.keys().contains(i.key()) && dictionaries.value(i.key()).contains(i.value()))
            d->loadedDictionaryList.insert(i.key(), i.value());
    }
}

void
DictionaryManager::saveDictionarySettings()
{
    QStringList rawDictionaryList;

    for (QMultiHash<QString, QString>::const_iterator i = d->loadedDictionaryList.begin(); i != d->loadedDictionaryList.end(); ++i)
    {
        rawDictionaryList.append(i.key());
        rawDictionaryList.append(i.value());
    }

    QSettings settings;
    settings.setValue("DictionaryManager/loadedDictionaryList", rawDictionaryList);
}

void
DictionaryManager::loadDictionarySettings()
{
    QSettings settings;
    QStringList rawDictionaryList = settings.value("DictionaryManager/loadedDictionaryList").toStringList();

    if (rawDictionaryList.isEmpty())
    {
        setLoadedDictionaryList(availableDictionaryList());
    }
    else
    {
        QMultiHash<QString, QString> dictionaries;
        for (QStringList::const_iterator i = rawDictionaryList.begin(); i != rawDictionaryList.end(); i += 2)
            dictionaries.insert(*i, *(i + 1));

        setLoadedDictionaryList(dictionaries);
    }
}

void
DictionaryManager::reloadDictionaryList()
{
    QMultiHash<QString, QString> loadedDictionaryList;
    // for (QHash<QString, QPluginLoader*>::const_iterator i = d->plugins.begin(); i != d->plugins.end(); ++i)
    // {
        // DictionaryPlugin *plugin = qobject_cast<DictionaryPlugin*>((*i)->instance());
        // plugin->setLoadedDictionaryList(plugin->loadedDictionaryList());

        // foreach(const QString& dictionaryName, plugin->loadedDictionaryList())
            // loadedDictionaryList.append(DictionaryDataItem(i.key(), dictionaryName));
    // }

    QMultiHash<QString, QString> oldDictionaryList = d->loadedDictionaryList;
    d->loadedDictionaryList.clear();

    for (QMultiHash<QString, QString>::const_iterator i = oldDictionaryList.begin(); i != oldDictionaryList.end(); ++i)
    {
        if (loadedDictionaryList.contains(i.key(), i.value()))
            d->loadedDictionaryList.insert(i.key(), i.value());
    }
}

#include "dictionarymanager.moc"
<commit_msg>Fill in the dictionary plugin class with the dictionary list properly<commit_after>/******************************************************************************
 * This file is part of the Mula project
 * Copyright (c) 2011 Laszlo Papp <lpapp@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.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
 */

#include "dictionarymanager.h"

#include "pluginmanager.h"

#include <QtCore/QFileInfoList>
#include <QtCore/QDir>
#include <QtCore/QSettings>
#include <QtCore/QPluginLoader>

using namespace MulaCore;

MULA_DEFINE_SINGLETON( DictionaryManager )

class DictionaryManager::Private
{
    public:
        Private()
        {
        }

        ~Private()
        {
        }

        QMultiHash<QString, QString> loadedDictionaryList;
};

DictionaryManager::DictionaryManager(QObject *parent)
    : MulaCore::Singleton< MulaCore::DictionaryManager >( parent )
    , d(new Private)
{
    loadDictionarySettings();
}

DictionaryManager::~DictionaryManager()
{
    saveDictionarySettings();
}

bool
DictionaryManager::isTranslatable(const QString &word)
{
    for (QMultiHash<QString, QString>::const_iterator i = d->loadedDictionaryList.begin(); i != d->loadedDictionaryList.end(); ++i)
    {
        MulaCore::DictionaryPlugin* dictionaryPlugin = MulaCore::PluginManager::instance()->plugin(i.key());
        if (!dictionaryPlugin)
            continue;

        if (dictionaryPlugin->isTranslatable(i.value(), word))
            return true;
    }

    return false;
}

QString
DictionaryManager::translate(const QString &word)
{
    QString simplifiedWord = word.simplified();
    QString translatedWord;

    for (QMultiHash<QString, QString>::const_iterator i = d->loadedDictionaryList.begin(); i != d->loadedDictionaryList.end(); ++i)
    {
        MulaCore::DictionaryPlugin* dictionaryPlugin = MulaCore::PluginManager::instance()->plugin(i.key());
        if (!dictionaryPlugin)
            continue;

        if (!dictionaryPlugin->isTranslatable(i.key(), simplifiedWord))
            continue;

        MulaCore::Translation translation = dictionaryPlugin->translate(i.key(), simplifiedWord);
        translatedWord.append(QString("
\n")
            + "" + translation.dictionaryName() + "
\n"
            + "" + translation.title() + "
\n"
            + translation.translation() + "
\n");
    }

    return translatedWord;
}

QStringList
DictionaryManager::findSimilarWords(const QString &word)
{
    QString simplifiedWord = word.simplified();
    QStringList similarWords;

    for (QMultiHash<QString, QString>::const_iterator i = d->loadedDictionaryList.begin(); i != d->loadedDictionaryList.end(); ++i)
    {
        MulaCore::DictionaryPlugin* dictionaryPlugin = MulaCore::PluginManager::instance()->plugin(i.key());
        if (!dictionaryPlugin)
            continue;

        if (!dictionaryPlugin->features().testFlag(DictionaryPlugin::SearchSimilar))
            continue;

        QStringList similarWords = dictionaryPlugin->findSimilarWords(i.value(), simplifiedWord);
        foreach (const QString& similarWord, similarWords)
        {
            if (!similarWords.contains(similarWord, Qt::CaseSensitive))
                similarWords.append(similarWord);
        }
    }

    return similarWords;
}

QMultiHash<QString, QString>
DictionaryManager::availableDictionaryList() const
{
    QMultiHash<QString, QString> availableDictionaryList;

    // for (QHash<QString, QPluginLoader*>::const_iterator i = m_plugins.begin(); i != m_plugins.end(); ++i)
    // {
        // DictionaryPlugin *plugin = qobject_cast<DictionaryPlugin*>((*i)->instance());
        // QStringList dictionaries = plugin->availableDictionaryList();
        // foreach (const QString& dictionary, dictionaries)
            // availableDictionaryList.append(DictionaryDataItem(i.key(), dictionary));
    // }

    return availableDictionaryList;
}

void
DictionaryManager::setLoadedDictionaryList(const QMultiHash<QString, QString> &loadedDictionaryList)
{
    QMultiHash<QString, QString> dictionaries = loadedDictionaryList;

    foreach (const QString& pluginName, dictionaries.keys())
    {
        MulaCore::DictionaryPlugin* dictionaryPlugin = MulaCore::PluginManager::instance()->plugin(pluginName);
        if (!dictionaryPlugin)
            continue;

        dictionaryPlugin->setLoadedDictionaryList(dictionaries.values());
        foreach (const QString& dictionaryName, dictionaryPlugin->loadedDictionaryList())
                dictionaries.insert(pluginName, dictionaryName);
    }

    d->loadedDictionaryList.clear();
    for (QMultiHash<QString, QString>::const_iterator i = loadedDictionaryList.begin(); i != loadedDictionaryList.end(); ++i)
    {
        if (dictionaries.keys().contains(i.key()) && dictionaries.value(i.key()).contains(i.value()))
            d->loadedDictionaryList.insert(i.key(), i.value());
    }
}

void
DictionaryManager::saveDictionarySettings()
{
    QStringList rawDictionaryList;

    for (QMultiHash<QString, QString>::const_iterator i = d->loadedDictionaryList.begin(); i != d->loadedDictionaryList.end(); ++i)
    {
        rawDictionaryList.append(i.key());
        rawDictionaryList.append(i.value());
    }

    QSettings settings;
    settings.setValue("DictionaryManager/loadedDictionaryList", rawDictionaryList);
}

void
DictionaryManager::loadDictionarySettings()
{
    QSettings settings;
    QStringList rawDictionaryList = settings.value("DictionaryManager/loadedDictionaryList").toStringList();

    if (rawDictionaryList.isEmpty())
    {
        setLoadedDictionaryList(availableDictionaryList());
    }
    else
    {
        QMultiHash<QString, QString> dictionaries;
        for (QStringList::const_iterator i = rawDictionaryList.begin(); i != rawDictionaryList.end(); i += 2)
            dictionaries.insert(*i, *(i + 1));

        setLoadedDictionaryList(dictionaries);
    }
}

void
DictionaryManager::reloadDictionaryList()
{
    QMultiHash<QString, QString> loadedDictionaryList;
    // for (QHash<QString, QPluginLoader*>::const_iterator i = d->plugins.begin(); i != d->plugins.end(); ++i)
    // {
        // DictionaryPlugin *plugin = qobject_cast<DictionaryPlugin*>((*i)->instance());
        // plugin->setLoadedDictionaryList(plugin->loadedDictionaryList());

        // foreach(const QString& dictionaryName, plugin->loadedDictionaryList())
            // loadedDictionaryList.append(DictionaryDataItem(i.key(), dictionaryName));
    // }

    QMultiHash<QString, QString> oldDictionaryList = d->loadedDictionaryList;
    d->loadedDictionaryList.clear();

    for (QMultiHash<QString, QString>::const_iterator i = oldDictionaryList.begin(); i != oldDictionaryList.end(); ++i)
    {
        if (loadedDictionaryList.contains(i.key(), i.value()))
            d->loadedDictionaryList.insert(i.key(), i.value());
    }
}

#include "dictionarymanager.moc"
<|endoftext|>


<commit_before>// Copyright (c) 2012-2015 Dano Pernis
// See LICENSE for details

#include <gtk/gtk.h>
#include <glib.h>
#include <fstream>
#include <iostream>
#include <stdexcept>
#include <cassert>
#include <vector>
#include "CPU.h"

struct ROM : public hcc::IROM {
    ROM() : data(0x8000, 0) { }

    bool load(const char *filename)
    {
        std::ifstream input(filename);
        std::string line;
        auto it = begin(data);
        while (input.good() && it != end(data)) {
            getline(input, line);
            if (line.size() == 0) {
                continue;
            }
            if (line.size() != 16) {
                return false;
            }

            unsigned int instruction = 0;
            for (unsigned int i = 0; i<16; ++i) {
                instruction <<= 1;
                switch (line[i]) {
                case '0':
                    break;
                case '1':
                    instruction |= 1;
                    break;
                default:
                    return false;
                }
            }
            *it++ = instruction;
        }

        // clear the rest
        while (it != end(data)) {
            *it++ = 0;
        }

        return true;
    }

    unsigned short get(unsigned int address) const override
    { return data.at(address); }

private:
    std::vector<unsigned short> data;
};

gboolean on_draw(GtkWidget*, cairo_t* cr, gpointer data)
{
    GdkPixbuf* pixbuf = reinterpret_cast<GdkPixbuf*>(data);
    gdk_cairo_set_source_pixbuf(cr, pixbuf, 0, 0);
    cairo_paint(cr);
    return FALSE;
}

struct RAM : public hcc::IRAM {
    static const unsigned int CHANNELS = 3;
    static const unsigned int SCREEN_WIDTH = 512;
    static const unsigned int SCREEN_HEIGHT = 256;

    std::vector<unsigned short> data;
    GdkPixbuf *pixbuf;
    GtkWidget *screen;

    void putpixel(unsigned short x, unsigned short y, bool black) {
        int color = black ? 0x00 : 0xff;

        int n_channels = gdk_pixbuf_get_n_channels (pixbuf);
        int rowstride = gdk_pixbuf_get_rowstride (pixbuf);
        guchar* pixels = gdk_pixbuf_get_pixels(pixbuf);
        guchar* p = pixels + y * rowstride + x * n_channels;
        p[0] = color;
        p[1] = color;
        p[2] = color;
    }
public:
    RAM() : data(0x6001, 0)
    {
        pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, SCREEN_WIDTH, SCREEN_HEIGHT);
        gdk_pixbuf_fill(pixbuf, 0x0000000);

        screen = gtk_drawing_area_new();
        gtk_widget_set_size_request(screen, SCREEN_WIDTH, SCREEN_HEIGHT);
        g_signal_connect(screen, "draw", G_CALLBACK(on_draw), pixbuf);
    }

    void keyboard(unsigned short value) {
        data[0x6000] = value;
    }

    GtkWidget* getScreenWidget() {
        return screen;
    }

    void set(unsigned int address, unsigned short value) override
    {
        data.at(address) = value;

        // check if we are writing to video RAM
        if (0x4000 <= address && address <0x6000) {
            address -= 0x4000;

            unsigned short y = address / 32;
            unsigned short x = 16*(address % 32);
            for (int bit = 0; bit<16; ++bit) {
                putpixel(x + bit, y, value & 1);
                value = value >> 1;
            }
            gdk_threads_enter();
            gtk_widget_queue_draw(screen);
            gdk_threads_leave();
        }
    }

    unsigned short get(unsigned int address) const override
    { return data.at(address); }
};

struct emulator {
    emulator();
    void load_clicked();
    void run_clicked();
    void pause_clicked();
    gboolean keyboard_callback(GdkEventKey* event);
    void run_thread();
    GtkToolItem* create_button(const gchar* stock_id, const gchar* text, GCallback callback);

    ROM rom;
    RAM ram;
    hcc::CPU cpu;

    bool running = false;

    GtkWidget* window;
    GtkWidget* load_dialog;
    GtkWidget* error_dialog;
    GtkToolItem* button_load;
    GtkToolItem* button_run;
    GtkToolItem* button_pause;
};

gboolean c_keyboard_callback(GtkWidget*, GdkEventKey *event, gpointer user_data)
{ return reinterpret_cast<emulator*>(user_data)->keyboard_callback(event); }

void c_load_clicked(GtkButton*, gpointer user_data)
{ reinterpret_cast<emulator*>(user_data)->load_clicked(); }

void c_run_clicked(GtkButton*, gpointer user_data)
{ reinterpret_cast<emulator*>(user_data)->run_clicked(); }

void c_pause_clicked(GtkButton*, gpointer user_data)
{ reinterpret_cast<emulator*>(user_data)->pause_clicked(); }

gpointer c_run_thread(gpointer user_data)
{
    reinterpret_cast<emulator*>(user_data)->run_thread();
    return NULL;
}

// Translate special keys. See Figure 5.6 in TECS book.
unsigned short translate(guint keyval)
{
    switch (keyval) {
    case GDK_KEY_Return:    return 128;
    case GDK_KEY_BackSpace: return 129;
    case GDK_KEY_Left:      return 130;
    case GDK_KEY_Up:        return 131;
    case GDK_KEY_Right:     return 132;
    case GDK_KEY_Down:      return 133;
    case GDK_KEY_Home:      return 134;
    case GDK_KEY_End:       return 135;
    case GDK_KEY_Page_Up:   return 136;
    case GDK_KEY_Page_Down: return 137;
    case GDK_KEY_Insert:    return 138;
    case GDK_KEY_Delete:    return 139;
    case GDK_KEY_Escape:    return 140;
    case GDK_KEY_F1:        return 141;
    case GDK_KEY_F2:        return 142;
    case GDK_KEY_F3:        return 143;
    case GDK_KEY_F4:        return 144;
    case GDK_KEY_F5:        return 145;
    case GDK_KEY_F6:        return 146;
    case GDK_KEY_F7:        return 147;
    case GDK_KEY_F8:        return 148;
    case GDK_KEY_F9:        return 149;
    case GDK_KEY_F10:       return 150;
    case GDK_KEY_F11:       return 151;
    case GDK_KEY_F12:       return 152;
    }
    return keyval;
}

emulator::emulator()
{
    /* toolbar buttons */
    button_load    = create_button("document-open",        "Load...", G_CALLBACK(c_load_clicked));
    button_run     = create_button("media-playback-start", "Run",     G_CALLBACK(c_run_clicked));
    button_pause   = create_button("media-playback-pause", "Pause",   G_CALLBACK(c_pause_clicked));

    GtkToolItem *separator1 = gtk_separator_tool_item_new();

    gtk_widget_set_sensitive(GTK_WIDGET(button_run), FALSE);
    gtk_widget_set_sensitive(GTK_WIDGET(button_pause), FALSE);

    /* toolbar itself */
    GtkWidget *toolbar = gtk_toolbar_new();
    gtk_widget_set_hexpand(toolbar, TRUE);
    gtk_toolbar_set_style(GTK_TOOLBAR(toolbar), GTK_TOOLBAR_ICONS);
    gtk_toolbar_insert(GTK_TOOLBAR(toolbar), button_load,  -1);
    gtk_toolbar_insert(GTK_TOOLBAR(toolbar), separator1,   -1);
    gtk_toolbar_insert(GTK_TOOLBAR(toolbar), button_run,   -1);
    gtk_toolbar_insert(GTK_TOOLBAR(toolbar), button_pause, -1);

    /* keyboard */
    GtkWidget *keyboard = gtk_toggle_button_new_with_label("Grab keyboard focus");
    gtk_widget_add_events(keyboard, GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK);
    g_signal_connect(keyboard, "key-press-event",   G_CALLBACK(c_keyboard_callback), this);
    g_signal_connect(keyboard, "key-release-event", G_CALLBACK(c_keyboard_callback), this);

    /* main layout */
    GtkWidget *grid = gtk_grid_new();
    gtk_grid_attach(GTK_GRID(grid), toolbar, 0, 0, 1, 1);
    gtk_grid_attach(GTK_GRID(grid), ram.getScreenWidget(), 0, 1, 1, 1);
    gtk_grid_attach(GTK_GRID(grid), keyboard, 0, 2, 1, 1);

    /* main window */
    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_window_set_title(GTK_WINDOW(window), "HACK emulator");
    gtk_window_set_resizable(GTK_WINDOW(window), FALSE);
    gtk_window_set_focus(GTK_WINDOW(window), NULL);
    g_signal_connect(window, "destroy", G_CALLBACK (gtk_main_quit), NULL);
    gtk_container_add(GTK_CONTAINER(window), grid);
    gtk_widget_show_all(window);
    gtk_widget_set_visible(GTK_WIDGET(button_pause), FALSE);

    load_dialog = gtk_file_chooser_dialog_new(
        "Load ROM", GTK_WINDOW(window), GTK_FILE_CHOOSER_ACTION_OPEN,
        "gtk-cancel", GTK_RESPONSE_CANCEL,
        "gtk-open", GTK_RESPONSE_ACCEPT,
        NULL);

    error_dialog = gtk_message_dialog_new(GTK_WINDOW(window),
        GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE,
        "Error loading program");
}

GtkToolItem* emulator::create_button(const gchar* stock_id, const gchar* text, GCallback callback)
{
    GtkToolItem *button = gtk_tool_button_new(NULL, text);
    gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(button), stock_id);
    gtk_tool_item_set_tooltip_text(button, text);
    g_signal_connect(button, "clicked", callback, this);
    return button;
}

void emulator::load_clicked()
{
    const gint result = gtk_dialog_run(GTK_DIALOG(load_dialog));
    gtk_widget_hide(load_dialog);

    if (result != GTK_RESPONSE_ACCEPT) {
        return;
    }

    char *filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(load_dialog));
    const bool loaded = rom.load(filename);
    g_free(filename);

    if (!loaded) {
        gtk_dialog_run(GTK_DIALOG(error_dialog));
        gtk_widget_hide(error_dialog);
        return;
    }

    cpu.reset();
    gtk_widget_set_sensitive(GTK_WIDGET(button_run), TRUE);
}

void emulator::run_clicked()
{
    assert(!running);

    running = true;
    gtk_widget_set_sensitive(GTK_WIDGET(button_run), FALSE);
    gtk_widget_set_visible(GTK_WIDGET(button_run), FALSE);
    gtk_widget_set_sensitive(GTK_WIDGET(button_pause), TRUE);
    gtk_widget_set_visible(GTK_WIDGET(button_pause), TRUE);

    g_thread_create(c_run_thread, this, FALSE, NULL);
}

void emulator::pause_clicked()
{
    assert(running);

    running = false;
    gtk_widget_set_sensitive(GTK_WIDGET(button_pause), FALSE);
    gtk_widget_set_visible(GTK_WIDGET(button_pause), FALSE);
    gtk_widget_set_sensitive(GTK_WIDGET(button_run), TRUE);
    gtk_widget_set_visible(GTK_WIDGET(button_run), TRUE);
}

gboolean emulator::keyboard_callback(GdkEventKey* event)
{
    if (event->type == GDK_KEY_RELEASE) {
        ram.keyboard(0);
    } else {
        ram.keyboard(translate(event->keyval));
    }
    return TRUE;
}

void emulator::run_thread()
{
    int steps = 0;
    while (running) {
        cpu.step(&rom, &ram);
        if (steps>100) {
            g_usleep(10);
            steps = 0;
        }
        ++steps;
    }
}

int main(int argc, char *argv[])
{
    gtk_init(&argc, &argv);
    emulator e;
    gtk_main();
    return 0;
}
<commit_msg>Got rid of last deprecated functions<commit_after>// Copyright (c) 2012-2015 Dano Pernis
// See LICENSE for details

#include <gtk/gtk.h>
#include <glib.h>
#include <fstream>
#include <iostream>
#include <stdexcept>
#include <cassert>
#include <vector>
#include "CPU.h"

struct ROM : public hcc::IROM {
    ROM() : data(0x8000, 0) { }

    bool load(const char *filename)
    {
        std::ifstream input(filename);
        std::string line;
        auto it = begin(data);
        while (input.good() && it != end(data)) {
            getline(input, line);
            if (line.size() == 0) {
                continue;
            }
            if (line.size() != 16) {
                return false;
            }

            unsigned int instruction = 0;
            for (unsigned int i = 0; i<16; ++i) {
                instruction <<= 1;
                switch (line[i]) {
                case '0':
                    break;
                case '1':
                    instruction |= 1;
                    break;
                default:
                    return false;
                }
            }
            *it++ = instruction;
        }

        // clear the rest
        while (it != end(data)) {
            *it++ = 0;
        }

        return true;
    }

    unsigned short get(unsigned int address) const override
    { return data.at(address); }

private:
    std::vector<unsigned short> data;
};

gboolean on_draw(GtkWidget*, cairo_t* cr, gpointer data)
{
    GdkPixbuf* pixbuf = reinterpret_cast<GdkPixbuf*>(data);
    gdk_cairo_set_source_pixbuf(cr, pixbuf, 0, 0);
    cairo_paint(cr);
    return FALSE;
}

gboolean queue_redraw(gpointer widget)
{
    gtk_widget_queue_draw(GTK_WIDGET(widget));
    return FALSE;
}

struct RAM : public hcc::IRAM {
    static const unsigned int CHANNELS = 3;
    static const unsigned int SCREEN_WIDTH = 512;
    static const unsigned int SCREEN_HEIGHT = 256;

    std::vector<unsigned short> data;
    GdkPixbuf *pixbuf;
    GtkWidget *screen;

    void putpixel(unsigned short x, unsigned short y, bool black) {
        int color = black ? 0x00 : 0xff;

        int n_channels = gdk_pixbuf_get_n_channels (pixbuf);
        int rowstride = gdk_pixbuf_get_rowstride (pixbuf);
        guchar* pixels = gdk_pixbuf_get_pixels(pixbuf);
        guchar* p = pixels + y * rowstride + x * n_channels;
        p[0] = color;
        p[1] = color;
        p[2] = color;
    }
public:
    RAM() : data(0x6001, 0)
    {
        pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, SCREEN_WIDTH, SCREEN_HEIGHT);
        gdk_pixbuf_fill(pixbuf, 0x0000000);

        screen = gtk_drawing_area_new();
        gtk_widget_set_size_request(screen, SCREEN_WIDTH, SCREEN_HEIGHT);
        g_signal_connect(screen, "draw", G_CALLBACK(on_draw), pixbuf);
    }

    void keyboard(unsigned short value) {
        data[0x6000] = value;
    }

    GtkWidget* getScreenWidget() {
        return screen;
    }

    void set(unsigned int address, unsigned short value) override
    {
        data.at(address) = value;

        // check if we are writing to video RAM
        if (0x4000 <= address && address <0x6000) {
            address -= 0x4000;

            unsigned short y = address / 32;
            unsigned short x = 16*(address % 32);
            for (int bit = 0; bit<16; ++bit) {
                putpixel(x + bit, y, value & 1);
                value = value >> 1;
            }
            gdk_threads_add_idle(queue_redraw, screen);
        }
    }

    unsigned short get(unsigned int address) const override
    { return data.at(address); }
};

struct emulator {
    emulator();
    void load_clicked();
    void run_clicked();
    void pause_clicked();
    gboolean keyboard_callback(GdkEventKey* event);
    void run_thread();
    GtkToolItem* create_button(const gchar* stock_id, const gchar* text, GCallback callback);

    ROM rom;
    RAM ram;
    hcc::CPU cpu;

    bool running = false;

    GtkWidget* window;
    GtkWidget* load_dialog;
    GtkWidget* error_dialog;
    GtkToolItem* button_load;
    GtkToolItem* button_run;
    GtkToolItem* button_pause;
};

gboolean c_keyboard_callback(GtkWidget*, GdkEventKey *event, gpointer user_data)
{ return reinterpret_cast<emulator*>(user_data)->keyboard_callback(event); }

void c_load_clicked(GtkButton*, gpointer user_data)
{ reinterpret_cast<emulator*>(user_data)->load_clicked(); }

void c_run_clicked(GtkButton*, gpointer user_data)
{ reinterpret_cast<emulator*>(user_data)->run_clicked(); }

void c_pause_clicked(GtkButton*, gpointer user_data)
{ reinterpret_cast<emulator*>(user_data)->pause_clicked(); }

gpointer c_run_thread(gpointer user_data)
{
    reinterpret_cast<emulator*>(user_data)->run_thread();
    return NULL;
}

// Translate special keys. See Figure 5.6 in TECS book.
unsigned short translate(guint keyval)
{
    switch (keyval) {
    case GDK_KEY_Return:    return 128;
    case GDK_KEY_BackSpace: return 129;
    case GDK_KEY_Left:      return 130;
    case GDK_KEY_Up:        return 131;
    case GDK_KEY_Right:     return 132;
    case GDK_KEY_Down:      return 133;
    case GDK_KEY_Home:      return 134;
    case GDK_KEY_End:       return 135;
    case GDK_KEY_Page_Up:   return 136;
    case GDK_KEY_Page_Down: return 137;
    case GDK_KEY_Insert:    return 138;
    case GDK_KEY_Delete:    return 139;
    case GDK_KEY_Escape:    return 140;
    case GDK_KEY_F1:        return 141;
    case GDK_KEY_F2:        return 142;
    case GDK_KEY_F3:        return 143;
    case GDK_KEY_F4:        return 144;
    case GDK_KEY_F5:        return 145;
    case GDK_KEY_F6:        return 146;
    case GDK_KEY_F7:        return 147;
    case GDK_KEY_F8:        return 148;
    case GDK_KEY_F9:        return 149;
    case GDK_KEY_F10:       return 150;
    case GDK_KEY_F11:       return 151;
    case GDK_KEY_F12:       return 152;
    }
    return keyval;
}

emulator::emulator()
{
    /* toolbar buttons */
    button_load    = create_button("document-open",        "Load...", G_CALLBACK(c_load_clicked));
    button_run     = create_button("media-playback-start", "Run",     G_CALLBACK(c_run_clicked));
    button_pause   = create_button("media-playback-pause", "Pause",   G_CALLBACK(c_pause_clicked));

    GtkToolItem *separator1 = gtk_separator_tool_item_new();

    gtk_widget_set_sensitive(GTK_WIDGET(button_run), FALSE);
    gtk_widget_set_sensitive(GTK_WIDGET(button_pause), FALSE);

    /* toolbar itself */
    GtkWidget *toolbar = gtk_toolbar_new();
    gtk_widget_set_hexpand(toolbar, TRUE);
    gtk_toolbar_set_style(GTK_TOOLBAR(toolbar), GTK_TOOLBAR_ICONS);
    gtk_toolbar_insert(GTK_TOOLBAR(toolbar), button_load,  -1);
    gtk_toolbar_insert(GTK_TOOLBAR(toolbar), separator1,   -1);
    gtk_toolbar_insert(GTK_TOOLBAR(toolbar), button_run,   -1);
    gtk_toolbar_insert(GTK_TOOLBAR(toolbar), button_pause, -1);

    /* keyboard */
    GtkWidget *keyboard = gtk_toggle_button_new_with_label("Grab keyboard focus");
    gtk_widget_add_events(keyboard, GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK);
    g_signal_connect(keyboard, "key-press-event",   G_CALLBACK(c_keyboard_callback), this);
    g_signal_connect(keyboard, "key-release-event", G_CALLBACK(c_keyboard_callback), this);

    /* main layout */
    GtkWidget *grid = gtk_grid_new();
    gtk_grid_attach(GTK_GRID(grid), toolbar, 0, 0, 1, 1);
    gtk_grid_attach(GTK_GRID(grid), ram.getScreenWidget(), 0, 1, 1, 1);
    gtk_grid_attach(GTK_GRID(grid), keyboard, 0, 2, 1, 1);

    /* main window */
    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_window_set_title(GTK_WINDOW(window), "HACK emulator");
    gtk_window_set_resizable(GTK_WINDOW(window), FALSE);
    gtk_window_set_focus(GTK_WINDOW(window), NULL);
    g_signal_connect(window, "destroy", G_CALLBACK (gtk_main_quit), NULL);
    gtk_container_add(GTK_CONTAINER(window), grid);
    gtk_widget_show_all(window);
    gtk_widget_set_visible(GTK_WIDGET(button_pause), FALSE);

    load_dialog = gtk_file_chooser_dialog_new(
        "Load ROM", GTK_WINDOW(window), GTK_FILE_CHOOSER_ACTION_OPEN,
        "gtk-cancel", GTK_RESPONSE_CANCEL,
        "gtk-open", GTK_RESPONSE_ACCEPT,
        NULL);

    error_dialog = gtk_message_dialog_new(GTK_WINDOW(window),
        GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE,
        "Error loading program");
}

GtkToolItem* emulator::create_button(const gchar* stock_id, const gchar* text, GCallback callback)
{
    GtkToolItem *button = gtk_tool_button_new(NULL, text);
    gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(button), stock_id);
    gtk_tool_item_set_tooltip_text(button, text);
    g_signal_connect(button, "clicked", callback, this);
    return button;
}

void emulator::load_clicked()
{
    const gint result = gtk_dialog_run(GTK_DIALOG(load_dialog));
    gtk_widget_hide(load_dialog);

    if (result != GTK_RESPONSE_ACCEPT) {
        return;
    }

    char *filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(load_dialog));
    const bool loaded = rom.load(filename);
    g_free(filename);

    if (!loaded) {
        gtk_dialog_run(GTK_DIALOG(error_dialog));
        gtk_widget_hide(error_dialog);
        return;
    }

    cpu.reset();
    gtk_widget_set_sensitive(GTK_WIDGET(button_run), TRUE);
}

void emulator::run_clicked()
{
    assert(!running);

    running = true;
    gtk_widget_set_sensitive(GTK_WIDGET(button_run), FALSE);
    gtk_widget_set_visible(GTK_WIDGET(button_run), FALSE);
    gtk_widget_set_sensitive(GTK_WIDGET(button_pause), TRUE);
    gtk_widget_set_visible(GTK_WIDGET(button_pause), TRUE);

    g_thread_new("c_run_thread", c_run_thread, this);
}

void emulator::pause_clicked()
{
    assert(running);

    running = false;
    gtk_widget_set_sensitive(GTK_WIDGET(button_pause), FALSE);
    gtk_widget_set_visible(GTK_WIDGET(button_pause), FALSE);
    gtk_widget_set_sensitive(GTK_WIDGET(button_run), TRUE);
    gtk_widget_set_visible(GTK_WIDGET(button_run), TRUE);
}

gboolean emulator::keyboard_callback(GdkEventKey* event)
{
    if (event->type == GDK_KEY_RELEASE) {
        ram.keyboard(0);
    } else {
        ram.keyboard(translate(event->keyval));
    }
    return TRUE;
}

void emulator::run_thread()
{
    int steps = 0;
    while (running) {
        cpu.step(&rom, &ram);
        if (steps>100) {
            g_usleep(10);
            steps = 0;
        }
        ++steps;
    }
}

int main(int argc, char *argv[])
{
    gtk_init(&argc, &argv);
    emulator e;
    gtk_main();
    return 0;
}
<|endoftext|>