void FundingState::btnOkClick(Action *)
{
	_game->popState();
}

/*
 *
 * This file is part of OpenXcom.
 *
 */
#include "FundingState.h"
#include <sstream>
#include "../Engine/Game.h"
#include "../Mod/Mod.h"
#include "../Engine/LocalizedText.h"
#include "../Engine/Unicode.h"
#include "../Interface/TextButton.h"
#include "../Interface/Window.h"
#include "../Interface/Text.h"
#include "../Interface/TextList.h"
#include "../Savegame/Country.h"
#include "../Mod/RuleCountry.h"
#include "../Savegame/SavedGame.h"
#include "../Engine/Options.h"

namespace OpenXcom
{

/**
 * Initializes all the elements in the Funding screen.
 * @param game Pointer to the core game.
 */
FundingState::FundingState()
{
	_screen = false;

	// Create objects
	_window = new Window(this, 320, 200, 0, 0, POPUP_BOTH);
	_btnOk = new TextButton(50, 12, 135, 180);
	_txtTitle = new Text(320, 17, 0, 8);
	_txtCountry = new Text(100, 9, 32, 30);
	_txtFunding = new Text(100, 9, 140, 30);
	_txtChange = new Text(72, 9, 240, 30);
	_lstCountries = new TextList(260, 136, 32, 40);

	// Set palette
	setInterface("fundingWindow");

	add(_window, "window", "fundingWindow");
	add(_btnOk, "button", "fundingWindow");
	add(_txtTitle, "text1", "fundingWindow");
	add(_txtCountry, "text2", "fundingWindow");
	add(_txtFunding, "text2", "fundingWindow");
	add(_txtChange, "text2", "fundingWindow");
	add(_lstCountries, "list", "fundingWindow");

	centerAllSurfaces();

	// Set up objects
	_window->setBackground(_game->getMod()->getSurface("BACK13.SCR"));

	_btnOk->setText(tr("STR_OK"));
	_btnOk->onMouseClick((ActionHandler)&FundingState::btnOkClick);
	_btnOk->onKeyboardPress((ActionHandler)&FundingState::btnOkClick, Options::keyOk);
	_btnOk->onKeyboardPress((ActionHandler)&FundingState::btnOkClick, Options::keyCancel);
	_btnOk->onKeyboardPress((ActionHandler)&FundingState::btnOkClick, Options::keyGeoFunding);

	_txtTitle->setAlign(ALIGN_CENTER);
	_txtTitle->setBig();
	_txtTitle->setText(tr("STR_INTERNATIONAL_RELATIONS"));

	_txtCountry->setText(tr("STR_COUNTRY"));

	_txtFunding->setText(tr("STR_FUNDING"));

	_txtChange->setText(tr("STR_CHANGE"));

	_lstCountries->setColumns(3, 108, 100, 52);
	_lstCountries->setDot(true);
	for (std::vector<Country*>::iterator i = _game->getSavedGame()->getCountries()->begin(); i != _game->getSavedGame()->getCountries()->end(); ++i)
	{
		std::ostringstream ss, ss2;
		ss << Unicode::TOK_COLOR_FLIP << Unicode::formatFunding((*i)->getFunding().at((*i)->getFunding().size()-1)) << Unicode::TOK_COLOR_FLIP;
		if ((*i)->getFunding().size() > 1)
		{
			ss2 << Unicode::TOK_COLOR_FLIP;
			int change = (*i)->getFunding().back() - (*i)->getFunding().at((*i)->getFunding().size()-2);
			if (change > 0)
				ss2 << '+';
			ss2 << Unicode::formatFunding(change);
			ss2 << Unicode::TOK_COLOR_FLIP;
		}
		else
		{
			ss2 << Unicode::formatFunding(0);
		}
		_lstCountries->addRow(3, tr((*i)->getRules()->getType()).c_str(), ss.str().c_str(), ss2.str().c_str());
	}
	_lstCountries->addRow(2, tr("STR_TOTAL_UC").c_str(), Unicode::formatFunding(_game->getSavedGame()->getCountryFunding()).c_str());
	_lstCountries->setRowColor(_game->getSavedGame()->getCountries()->size(), _txtCountry->getColor());
}

/**
 *
 */
FundingState::~FundingState()
{

}

/**
 * Returns to the previous screen.
 * @param action Pointer to an action.
 */


bool cOAL_WAVSample::CreateFromFile(const wstring &asFilename)
{
	FILE *fileHandle = OpenFileW(asFilename, L"rb");
	fseek(fileHandle, 0, SEEK_END);
	size_t pos = ftell(fileHandle);
	fseek(fileHandle, 0, SEEK_SET);

	void *buffer = malloc(pos);

	fread(buffer, pos, 1, fileHandle);
	fclose(fileHandle);
	bool result = CreateFromBuffer(buffer, pos);
	free(buffer);

	return result;
}

/*
 *
 * This file is part of OALWrapper
 *
 */
/**
	@file OAL_WAVSample.cpp
	@author Luis Rodero
	@date 2006-10-02
	@version 0.1
	Derived class for containing WAV Sample data
*/

#include "OALWrapper/OAL_WAVSample.h"
#include "OALWrapper/OAL_Buffer.h"
#include "OALWrapper/OAL_Helper.h"
#include "OALWrapper/OAL_Device.h"

// Pull in for OAL Types
#include <ogg/ogg.h>
#include <cstdlib>
#include <cstdio>
#include <cstring>

using namespace std;

//	-	Loads sample data from a WAV file

struct RIFF_Header {
	char chunkID[4];
	ogg_int32_t chunkSize;
	char format[4];
};

struct WAVE_Format {
	char subChunkID[4];
	ogg_int32_t subChunkSize;
	ogg_int16_t audioFormat;
	ogg_int16_t numChannels;
	ogg_int32_t sampleRate;
	ogg_int32_t byteRate;
	ogg_int16_t blockAlign;
	ogg_int16_t bitsPerSample;
};

struct WAVE_Data {
  char subChunkID[4]; //should contain the word data
  ogg_int32_t subChunkSize; //Stores the size of the data block
};

struct RIFF_SubChunk {
  char subChunkID[4]; //should contain the word data
  ogg_int32_t subChunkSize; //Stores the size of the data block
};

static const char* find_chunk(const char* start, const char* end, const char* chunkID)
{
	RIFF_SubChunk chunk;
	const char* ptr = start;
	while (ptr < (end - sizeof(RIFF_SubChunk)))
	{
		memcpy(&chunk, ptr, sizeof(RIFF_SubChunk));

		if (chunk.subChunkID[0] == chunkID[0] &&
			chunk.subChunkID[1] == chunkID[1] &&
			chunk.subChunkID[2] == chunkID[2] &&
			chunk.subChunkID[3] == chunkID[3])
		{
			return ptr;
		}
		ptr += sizeof(RIFF_SubChunk) + chunk.subChunkSize;
	}
	return 0;
}

template<typename T>
inline const char*readStruct(T& dest, const char*& ptr)
{
	const char* ret;
	memcpy(&dest, ptr, sizeof(T));
	ptr += sizeof(RIFF_SubChunk);
	ret = ptr;
	ptr += dest.subChunkSize;
	return ret;
}

bool cOAL_WAVSample::CreateFromBuffer(const void* apBuffer, size_t aSize)
{
	const char* start = (const char*)apBuffer;
	const char* end = start + aSize;
	const char* ptr = start;
	RIFF_Header riff_header;
	WAVE_Format wave_format;
	WAVE_Data wave_data;

	memcpy(&riff_header, ptr, sizeof(RIFF_Header));
	ptr += sizeof(RIFF_Header);

	if (riff_header.chunkID[0] != 'R' ||
		riff_header.chunkID[1] != 'I' ||
		riff_header.chunkID[2] != 'F' ||
		riff_header.chunkID[3] != 'F' ||
		riff_header.format[0] != 'W' ||
		riff_header.format[1] != 'A' ||
		riff_header.format[2] != 'V' ||
		riff_header.format[3] != 'E')
	{
		return false;
	}

	ptr = find_chunk(ptr, end, "fmt ");
	if (!ptr) {
		return false;
	}
	readStruct(wave_format, ptr);

	if (wave_format.audioFormat != 1) {
		return false;
	}

	ptr = find_chunk(ptr, end, "data");
	if (!ptr) {
		return false;
	}

	const char* base = readStruct(wave_data, ptr);

	size_t size = wave_data.subChunkSize;
	if (size > (end - base)) {
		return false;
	}

	mlChannels = wave_format.numChannels;
	if (mlChannels == 2)
	{
		if (wave_format.bitsPerSample == 8)
		{
			mFormat = AL_FORMAT_STEREO8;
			mlSamples = size / 2;
		}
		else //if (wave_format.bitsPerSample == 16)
		{
			mlSamples = size / 4;
			mFormat = AL_FORMAT_STEREO16;
		}
	} else //if (mlChannels == 1)
	{
		if (wave_format.bitsPerSample == 8)
		{
			mlSamples = size;
			mFormat = AL_FORMAT_MONO8;
		}
		else //if (wave_format.bitsPerSample == 16)
		{
			mlSamples = size / 2;
			mFormat = AL_FORMAT_MONO16;
		}
	}
	mlFrequency = wave_format.sampleRate;
	mfTotalTime = float(mlSamples) / float(mlFrequency);

	cOAL_Buffer* pBuffer = mvBuffers[0];
	mbStatus = pBuffer->Feed((ALvoid*)base, size);

	return true;
}


while (ptr < (end - sizeof(RIFF_SubChunk)))
	{
		memcpy(&chunk, ptr, sizeof(RIFF_SubChunk));

		if (chunk.subChunkID[0] == chunkID[0] &&
			chunk.subChunkID[1] == chunkID[1] &&
			chunk.subChunkID[2] == chunkID[2] &&
			chunk.subChunkID[3] == chunkID[3])
		{
			return ptr;
		}
		ptr += sizeof(RIFF_SubChunk) + chunk.subChunkSize;
	}

/*
 *
 * This file is part of OALWrapper
 *
 */
/**
	@file OAL_WAVSample.cpp
	@author Luis Rodero
	@date 2006-10-02
	@version 0.1
	Derived class for containing WAV Sample data
*/

#include "OALWrapper/OAL_WAVSample.h"
#include "OALWrapper/OAL_Buffer.h"
#include "OALWrapper/OAL_Helper.h"
#include "OALWrapper/OAL_Device.h"

// Pull in for OAL Types
#include <ogg/ogg.h>
#include <cstdlib>
#include <cstdio>
#include <cstring>

using namespace std;

//	-	Loads sample data from a WAV file

bool cOAL_WAVSample::CreateFromFile(const wstring &asFilename)
{
	FILE *fileHandle = OpenFileW(asFilename, L"rb");
	fseek(fileHandle, 0, SEEK_END);
	size_t pos = ftell(fileHandle);
	fseek(fileHandle, 0, SEEK_SET);

	void *buffer = malloc(pos);

	fread(buffer, pos, 1, fileHandle);
	fclose(fileHandle);
	bool result = CreateFromBuffer(buffer, pos);
	free(buffer);

	return result;
}

struct RIFF_Header {
	char chunkID[4];
	ogg_int32_t chunkSize;
	char format[4];
};

struct WAVE_Format {
	char subChunkID[4];
	ogg_int32_t subChunkSize;
	ogg_int16_t audioFormat;
	ogg_int16_t numChannels;
	ogg_int32_t sampleRate;
	ogg_int32_t byteRate;
	ogg_int16_t blockAlign;
	ogg_int16_t bitsPerSample;
};

struct WAVE_Data {
  char subChunkID[4]; //should contain the word data
  ogg_int32_t subChunkSize; //Stores the size of the data block
};

struct RIFF_SubChunk {
  char subChunkID[4]; //should contain the word data
  ogg_int32_t subChunkSize; //Stores the size of the data block
};

static const char* find_chunk(const char* start, const char* end, const char* chunkID)
{
	RIFF_SubChunk chunk;
	const char* ptr = start;

	return 0;
}

template<typename T>
inline const char*readStruct(T& dest, const char*& ptr)
{
	const char* ret;
	memcpy(&dest, ptr, sizeof(T));
	ptr += sizeof(RIFF_SubChunk);
	ret = ptr;
	ptr += dest.subChunkSize;
	return ret;
}

bool cOAL_WAVSample::CreateFromBuffer(const void* apBuffer, size_t aSize)
{
	const char* start = (const char*)apBuffer;
	const char* end = start + aSize;
	const char* ptr = start;
	RIFF_Header riff_header;
	WAVE_Format wave_format;
	WAVE_Data wave_data;

	memcpy(&riff_header, ptr, sizeof(RIFF_Header));
	ptr += sizeof(RIFF_Header);

	if (riff_header.chunkID[0] != 'R' ||
		riff_header.chunkID[1] != 'I' ||
		riff_header.chunkID[2] != 'F' ||
		riff_header.chunkID[3] != 'F' ||
		riff_header.format[0] != 'W' ||
		riff_header.format[1] != 'A' ||
		riff_header.format[2] != 'V' ||
		riff_header.format[3] != 'E')
	{
		return false;
	}

	ptr = find_chunk(ptr, end, "fmt ");
	if (!ptr) {
		return false;
	}
	readStruct(wave_format, ptr);

	if (wave_format.audioFormat != 1) {
		return false;
	}

	ptr = find_chunk(ptr, end, "data");
	if (!ptr) {
		return false;
	}

	const char* base = readStruct(wave_data, ptr);

	size_t size = wave_data.subChunkSize;
	if (size > (end - base)) {
		return false;
	}

	mlChannels = wave_format.numChannels;
	if (mlChannels == 2)
	{
		if (wave_format.bitsPerSample == 8)
		{
			mFormat = AL_FORMAT_STEREO8;
			mlSamples = size / 2;
		}
		else //if (wave_format.bitsPerSample == 16)
		{
			mlSamples = size / 4;
			mFormat = AL_FORMAT_STEREO16;
		}
	} else //if (mlChannels == 1)
	{
		if (wave_format.bitsPerSample == 8)
		{
			mlSamples = size;
			mFormat = AL_FORMAT_MONO8;
		}
		else //if (wave_format.bitsPerSample == 16)
		{
			mlSamples = size / 2;
			mFormat = AL_FORMAT_MONO16;
		}
	}
	mlFrequency = wave_format.sampleRate;
	mfTotalTime = float(mlSamples) / float(mlFrequency);

	cOAL_Buffer* pBuffer = mvBuffers[0];
	mbStatus = pBuffer->Feed((ALvoid*)base, size);

	return true;
}


switch (value) {
  case 1: return X(value);
  case 2: return X(value, value);
  case 3: return (X)value;
  default: break;
  }

// Test is line- and column-sensitive. Run lines are below.

struct X {
  X();
  X(int);
  X(int, int);
  X(const X&);
};

X getX(int value) {

  return X();
}

struct Y {
  int member;

  X getX();
};

X Y::getX() {
  return member;
}

struct YDerived : Y {
  X getAnotherX() { return member; }
};

void test() {
  X foo;

  try {
  } catch (X e) {
    X x;
  }

  struct LocalS {
    void meth() {
      int x;
      ++x;
    }
  };
}

// RUN: c-index-test -test-load-source-usrs local %s | FileCheck -check-prefix=CHECK-USR %s
// CHECK-USR: get-cursor.cpp c:get-cursor.cpp@472@F@test#@e Extent=[38:12 - 38:15]
// CHECK-USR: get-cursor.cpp c:get-cursor.cpp@483@F@test#@x Extent=[39:5 - 39:8]


// Test is line- and column-sensitive. Run lines are below.

struct X {
  X();
  X(int);
  X(int, int);
  X(const X&);
};

X getX(int value) {
  switch (value) {
  case 1: return X(value);
  case 2: return X(value, value);
  case 3: return (X)value;
  default: break;
  }
  return X();
}

struct Y {
  int member;

  X getX();
};

X Y::getX() {
  return member;
}

struct YDerived : Y {
  X getAnotherX() { return member; }
};

void test() {
  X foo;

  struct LocalS {
    void meth() {
      int x;
      ++x;
    }
  };
}

// RUN: c-index-test -test-load-source-usrs local %s | FileCheck -check-prefix=CHECK-USR %s
// CHECK-USR: get-cursor.cpp c:get-cursor.cpp@472@F@test#@e Extent=[38:12 - 38:15]
// CHECK-USR: get-cursor.cpp c:get-cursor.cpp@483@F@test#@x Extent=[39:5 - 39:8]


void Window::setDX(int dx)
{
	_dx = dx;
}

/*
 *
 * This file is part of OpenXcom.
 *
 */
#include "Window.h"
#include <SDL.h>
#include <SDL_mixer.h>
#include "../fmath.h"
#include "../Engine/Timer.h"
#include "../Engine/Sound.h"
#include "../Engine/RNG.h"

namespace OpenXcom
{

const double Window::POPUP_SPEED = 0.05;

Sound *Window::soundPopup[3];

/**
 * Sets up a blank window with the specified size and position.
 * @param state Pointer to state the window belongs to.
 * @param width Width in pixels.
 * @param height Height in pixels.
 * @param x X position in pixels.
 * @param y Y position in pixels.
 * @param popup Popup animation.
 */
Window::Window(State *state, int width, int height, int x, int y, WindowPopup popup) : Surface(width, height, x, y), _dx(-x), _dy(-y), _bg(0), _color(0), _popup(popup), _popupStep(0.0), _state(state), _contrast(false), _screen(false), _thinBorder(false)
{
	_timer = new Timer(10);
	_timer->onTimer((SurfaceHandler)&Window::popup);

	if (_popup == POPUP_NONE)
	{
		_popupStep = 1.0;
	}
	else
	{
		setHidden(true);
		_timer->start();
		if (_state != 0)
		{
			_screen = state->isScreen();
			if (_screen)
				_state->toggleScreen();
		}
	}
}

/**
 * Deletes timers.
 */
Window::~Window()
{
	delete _timer;
}

/**
 * Changes the surface used to draw the background of the window.
 * @param bg New background.
 */
void Window::setBackground(Surface *bg)
{
	_bg = bg;
	_redraw = true;
}

/**
 * Changes the color used to draw the shaded border.
 * @param color Color value.
 */
void Window::setColor(Uint8 color)
{
	_color = color;
	_redraw = true;
}

/**
 * Returns the color used to draw the shaded border.
 * @return Color value.
 */
Uint8 Window::getColor() const
{
	return _color;
}

/**
 * Enables/disables high contrast color. Mostly used for
 * Battlescape UI.
 * @param contrast High contrast setting.
 */
void Window::setHighContrast(bool contrast)
{
	_contrast = contrast;
	_redraw = true;
}

/**
 * Keeps the animation timers running.
 */
void Window::think()
{
	if (_hidden && _popupStep < 1.0)
	{
		_state->hideAll();
		setHidden(false);
	}

	_timer->think(0, this);
}

/**
 * Plays the window popup animation.
 */
void Window::popup()
{
	if (AreSame(_popupStep, 0.0))
	{
		int sound = RNG::seedless(0,2);
		if (soundPopup[sound] != 0)
		{
			soundPopup[sound]->play(Mix_GroupAvailable(0));
		}
	}
	if (_popupStep < 1.0)
	{
		_popupStep += POPUP_SPEED;
	}
	else
	{
		if (_screen)
		{
			_state->toggleScreen();
		}
		_state->showAll();
		_popupStep = 1.0;
		_timer->stop();
	}
	_redraw = true;
}

/**
 * Draws the bordered window with a graphic background.
 * The background never moves with the window, it's
 * always aligned to the top-left corner of the screen
 * and cropped to fit the inside area.
 */
void Window::draw()
{
	Surface::draw();
	SDL_Rect square;

	if (_popup == POPUP_HORIZONTAL || _popup == POPUP_BOTH)
	{
		square.x = (int)((getWidth() - getWidth() * _popupStep) / 2);
		square.w = (int)(getWidth() * _popupStep);
	}
	else
	{
		square.x = 0;
		square.w = getWidth();
	}
	if (_popup == POPUP_VERTICAL || _popup == POPUP_BOTH)
	{
		square.y = (int)((getHeight() - getHeight() * _popupStep) / 2);
		square.h = (int)(getHeight() * _popupStep);
	}
	else
	{
		square.y = 0;
		square.h = getHeight();
	}

	int mul = 1;
	if (_contrast)
	{
		mul = 2;
	}
	Uint8 color = _color + 3 * mul;

	if (_thinBorder)
	{
		color = _color + 1 * mul;
		for (int i = 0; i < 5; ++i)
		{
			drawRect(&square, color);

			if (i % 2 == 0)
			{
				square.x++;
				square.y++;
			}
			square.w--;
			square.h--;

			switch (i)
			{
			case 0:
				color = _color + 5 * mul;
				setPixel(square.w, 0, color);
				break;
			case 1:
				color = _color + 2 * mul;
				break;
			case 2:
				color = _color + 4 * mul;
				setPixel(square.w+1, 1, color);
				break;
			case 3:
				color = _color + 3 * mul;
				break;
			}
		}
	}
	else
	{
		for (int i = 0; i < 5; ++i)
		{
			drawRect(&square, color);
			if (i < 2)
				color -= 1 * mul;
			else
				color += 1 * mul;
			square.x++;
			square.y++;
			if (square.w >= 2)
				square.w -= 2;
			else
				square.w = 1;

			if (square.h >= 2)
				square.h -= 2;
			else
				square.h = 1;
		}
	}

	if (_bg != 0)
	{
		_bg->getCrop()->x = square.x - _dx;
		_bg->getCrop()->y = square.y - _dy;
		_bg->getCrop()->w = square.w ;
		_bg->getCrop()->h = square.h ;
		_bg->setX(square.x);
		_bg->setY(square.y);
		_bg->blit(this);
	}
}

/**
 * Changes the horizontal offset of the surface in the X axis.
 * @param dx X position in pixels.
 */

/**
 * Changes the vertical offset of the surface in the Y axis.
 * @param dy Y position in pixels.
 */
void Window::setDY(int dy)
{
	_dy = dy;
}

/**
 * Changes the window to have a thin border.
 */
void Window::setThinBorder()
{
	_thinBorder = true;
}

}


switch (i)
			{
			case 0:
				color = _color + 5 * mul;
				setPixel(square.w, 0, color);
				break;
			case 1:
				color = _color + 2 * mul;
				break;
			case 2:
				color = _color + 4 * mul;
				setPixel(square.w+1, 1, color);
				break;
			case 3:
				color = _color + 3 * mul;
				break;
			}

/*
 *
 * This file is part of OpenXcom.
 *
 */
#include "Window.h"
#include <SDL.h>
#include <SDL_mixer.h>
#include "../fmath.h"
#include "../Engine/Timer.h"
#include "../Engine/Sound.h"
#include "../Engine/RNG.h"

namespace OpenXcom
{

const double Window::POPUP_SPEED = 0.05;

Sound *Window::soundPopup[3];

/**
 * Sets up a blank window with the specified size and position.
 * @param state Pointer to state the window belongs to.
 * @param width Width in pixels.
 * @param height Height in pixels.
 * @param x X position in pixels.
 * @param y Y position in pixels.
 * @param popup Popup animation.
 */
Window::Window(State *state, int width, int height, int x, int y, WindowPopup popup) : Surface(width, height, x, y), _dx(-x), _dy(-y), _bg(0), _color(0), _popup(popup), _popupStep(0.0), _state(state), _contrast(false), _screen(false), _thinBorder(false)
{
	_timer = new Timer(10);
	_timer->onTimer((SurfaceHandler)&Window::popup);

	if (_popup == POPUP_NONE)
	{
		_popupStep = 1.0;
	}
	else
	{
		setHidden(true);
		_timer->start();
		if (_state != 0)
		{
			_screen = state->isScreen();
			if (_screen)
				_state->toggleScreen();
		}
	}
}

/**
 * Deletes timers.
 */
Window::~Window()
{
	delete _timer;
}

/**
 * Changes the surface used to draw the background of the window.
 * @param bg New background.
 */
void Window::setBackground(Surface *bg)
{
	_bg = bg;
	_redraw = true;
}

/**
 * Changes the color used to draw the shaded border.
 * @param color Color value.
 */
void Window::setColor(Uint8 color)
{
	_color = color;
	_redraw = true;
}

/**
 * Returns the color used to draw the shaded border.
 * @return Color value.
 */
Uint8 Window::getColor() const
{
	return _color;
}

/**
 * Enables/disables high contrast color. Mostly used for
 * Battlescape UI.
 * @param contrast High contrast setting.
 */
void Window::setHighContrast(bool contrast)
{
	_contrast = contrast;
	_redraw = true;
}

/**
 * Keeps the animation timers running.
 */
void Window::think()
{
	if (_hidden && _popupStep < 1.0)
	{
		_state->hideAll();
		setHidden(false);
	}

	_timer->think(0, this);
}

/**
 * Plays the window popup animation.
 */
void Window::popup()
{
	if (AreSame(_popupStep, 0.0))
	{
		int sound = RNG::seedless(0,2);
		if (soundPopup[sound] != 0)
		{
			soundPopup[sound]->play(Mix_GroupAvailable(0));
		}
	}
	if (_popupStep < 1.0)
	{
		_popupStep += POPUP_SPEED;
	}
	else
	{
		if (_screen)
		{
			_state->toggleScreen();
		}
		_state->showAll();
		_popupStep = 1.0;
		_timer->stop();
	}
	_redraw = true;
}

/**
 * Draws the bordered window with a graphic background.
 * The background never moves with the window, it's
 * always aligned to the top-left corner of the screen
 * and cropped to fit the inside area.
 */
void Window::draw()
{
	Surface::draw();
	SDL_Rect square;

	if (_popup == POPUP_HORIZONTAL || _popup == POPUP_BOTH)
	{
		square.x = (int)((getWidth() - getWidth() * _popupStep) / 2);
		square.w = (int)(getWidth() * _popupStep);
	}
	else
	{
		square.x = 0;
		square.w = getWidth();
	}
	if (_popup == POPUP_VERTICAL || _popup == POPUP_BOTH)
	{
		square.y = (int)((getHeight() - getHeight() * _popupStep) / 2);
		square.h = (int)(getHeight() * _popupStep);
	}
	else
	{
		square.y = 0;
		square.h = getHeight();
	}

	int mul = 1;
	if (_contrast)
	{
		mul = 2;
	}
	Uint8 color = _color + 3 * mul;

	if (_thinBorder)
	{
		color = _color + 1 * mul;
		for (int i = 0; i < 5; ++i)
		{
			drawRect(&square, color);

			if (i % 2 == 0)
			{
				square.x++;
				square.y++;
			}
			square.w--;
			square.h--;

		}
	}
	else
	{
		for (int i = 0; i < 5; ++i)
		{
			drawRect(&square, color);
			if (i < 2)
				color -= 1 * mul;
			else
				color += 1 * mul;
			square.x++;
			square.y++;
			if (square.w >= 2)
				square.w -= 2;
			else
				square.w = 1;

			if (square.h >= 2)
				square.h -= 2;
			else
				square.h = 1;
		}
	}

	if (_bg != 0)
	{
		_bg->getCrop()->x = square.x - _dx;
		_bg->getCrop()->y = square.y - _dy;
		_bg->getCrop()->w = square.w ;
		_bg->getCrop()->h = square.h ;
		_bg->setX(square.x);
		_bg->setY(square.y);
		_bg->blit(this);
	}
}

/**
 * Changes the horizontal offset of the surface in the X axis.
 * @param dx X position in pixels.
 */
void Window::setDX(int dx)
{
	_dx = dx;
}

/**
 * Changes the vertical offset of the surface in the Y axis.
 * @param dy Y position in pixels.
 */
void Window::setDY(int dy)
{
	_dy = dy;
}

/**
 * Changes the window to have a thin border.
 */
void Window::setThinBorder()
{
	_thinBorder = true;
}

}


int CQRCode::ProcessQRFile(const QString &szFile, QString &szText)
{
    QImage img(szFile);
    if(img.isNull())
    {
        LOG_MODEL_ERROR("CQRCode", "This isn't image file:%s",
                        szFile.toStdString().c_str());
        return 1;
    }
    return ProcessQImage(img, szText);
}

#include "QRCode.h"
#include <QDesktopServices>
#include <QMessageBox>
#include <QPainter>
#include "MainWindow.h"

#ifdef RABBITIM_USE_LIBQRENCODE
#include "qrencode.h"
#endif

#ifdef RABBITIM_USE_QZXING
    #include "QZXing.h"
#endif

#define RABBITIM_ID "rabbitim://id/"
#define RABBITIM_USERINFO "rabbitim://userinfo/"

CQRCode::CQRCode() : QObject()
{
}

QImage CQRCode::QRcodeEncodeString(const QString &szData, const QImage &inImage, const QSize &size)
{
#ifdef RABBITIM_USE_LIBQRENCODE
    QImage image(size, QImage::Format_RGB32);
    QPainter painter(&image);

    //NOTE: I have hardcoded some parameters here that would make more sense as variables.
    // ECLEVEL_M is much faster recognizable by barcodescanner any any other type
    // any mode other than QR_MODE_8 or QR_MODE_KANJI results in EINVAL. First 1 is version, second is case sensitivity
    QRcode* qr = QRcode_encodeString(szData.toStdString().c_str(), 1, QR_ECLEVEL_M, QR_MODE_8, 1);
    if (qr != nullptr)
    {
        QColor fg("black");
        QColor bg("white");
        painter.setBrush(bg);
        painter.setPen(Qt::NoPen);
        painter.drawRect(0, 0, size.width(), size.height());
        painter.setBrush(fg);
        const int s = qr->width > 0 ? qr->width : 1;
        const double w = size.width();
        const double h = size.height();
        const double aspect = w / h;
        const double scale = ((aspect > 1.0) ? h : w) / s;

        for (int y = 0; y < s; y++)
        {
            const int yy = y * s;
            for (int x = 0; x < s; x++)
            {
                const int xx = yy + x;
                const unsigned char b = qr->data[xx];
                if (b & 0x01)
                {
                    const double rx1 = x * scale,
                                 ry1 = y * scale;
                    QRectF r(rx1, ry1, scale, scale);
                    painter.drawRects(&r, 1);
                }
            }
        }
        QRcode_free(qr);

        //在二维码上画图片
        if(!inImage.isNull())
        {
            qreal x = (size.width() >> 1) - (size.width() / 10);
            qreal y = (size.height() >> 1) - (size.height() / 10);
            qreal w = size.width() / 5;
            qreal h = size.height() / 5;
            LOG_MODEL_DEBUG("CQRCode", "x:%f, y:%f", x, y);
            int penw = 3;
            painter.setBrush(QBrush(QColor(255, 255, 255)));
            painter.drawRect(x - penw, y - penw, w + (penw << 1), h + (penw << 1));
            painter.setPen(QPen(Qt::NoPen));
            painter.setBrush(QBrush(Qt::NoBrush));
            QRectF rect(x, y, w, h);
            painter.drawImage(rect, inImage);
        }
    }
    else
    {
        QColor error("red");
        painter.setBrush(error);
        painter.drawRect(0, 0, size.width(), size.height());
        LOG_MODEL_ERROR("CTool", "QR FAIL");
    }

    qr = nullptr;
    return image;
#endif //RABBITIM_USE_LIBQRENCODE

#ifdef RABBITIM_USE_QZXING
    try{
        QZXing encoder;
        QImage image = encoder.encodeData(szData);
        image = image.scaled(size);
        QPainter painter(&image);

        //在二维码上画图片
        if(!inImage.isNull())
        {
            qreal x = (size.width() >> 1) - (size.width() / 10);
            qreal y = (size.height() >> 1) - (size.height() / 10);
            qreal w = size.width() / 5;
            qreal h = size.height() / 5;
            LOG_MODEL_DEBUG("CQRCode", "x:%f, y:%f", x, y);
            int penw = 3;
            painter.setBrush(QBrush(QColor(255, 255, 255)));
            painter.drawRect(x - penw, y - penw, w + (penw << 1), h + (penw << 1));
            painter.setPen(QPen(Qt::NoPen));
            painter.setBrush(QBrush(Qt::NoBrush));
            QRectF rect(x, y, w, h);
            painter.drawImage(rect, inImage);
        }
        return image;
    }catch(...){
        ;
    }
#endif

    return QImage();
}

int CQRCode::ProcessQImage(QImage image, QString &szText)
{
    QString szMessage;
#ifdef RABBITIM_USE_QZXING
    try{
        QZXing decoder;
        decoder.setDecoder(QZXing::DecoderFormat_QR_CODE |
                           QZXing::DecoderFormat_DATA_MATRIX |
                           QZXing::DecoderFormat_UPC_E |
                           QZXing::DecoderFormat_UPC_A |
                           QZXing::DecoderFormat_EAN_8 |
                           QZXing::DecoderFormat_EAN_13 |
                           QZXing::DecoderFormat_CODE_128 |
                           QZXing::DecoderFormat_CODE_93 |
                           QZXing::DecoderFormat_CODE_39 |
                           QZXing::DecoderFormat_ITF |
                           QZXing::DecoderFormat_Aztec |
                           QZXing::DecoderFormat_CODABAR |
                           QZXing::DecoderFormat_MAXICODE |
                           QZXing::DecoderFormat_PDF_417 |
                           QZXing::DecoderFormat_RSS_14 |
                           QZXing::DecoderFormat_RSS_EXPANDED |
                           QZXing::DecoderFormat_UPC_EAN_EXTENSION |
                           QZXing::DecoderFormat_CODE_128_GS1
                           );
        szMessage = decoder.decodeImage(image);
        if(szMessage.isEmpty())
        {
            LOG_MODEL_ERROR("CQRCode", "Scan image fail.");
            return 1;
        }
        LOG_MODEL_DEBUG("CQRCode", "Decode:%s", szMessage.toStdString().c_str());
    }catch(...){
        LOG_MODEL_ERROR("CQRCode", "Exception:Scan image fail.");
        return 1;
    }
#endif

    szText = szMessage;
    return ProcessMessage(szMessage);
}
/*
int CQRCode::ProcessQImage(const std::shared_ptr<CVideoFrame> &frame, QString &szText)
{
    if(VIDEO_FORMAT_NONE == frame->m_VideoInfo.Format)
        return -1;
    std::shared_ptr<CVideoFrame> outFrame;
    if (VIDEO_FORMAT_RGB32 != frame->m_VideoInfo.Format)
    {
#ifdef RABBITIM_USE_FFMPEG
        CTool::ConvertFormat(frame, outFrame,
                             frame->m_VideoInfo.nWidth,
                             frame->m_VideoInfo.nHeight,
                             VIDEO_FORMAT_RGB32);
#else
    #error "Must use ffmpeg library"
#endif
    }
    else
    {
        outFrame = frame;
    }
    QImage img((const uchar*)outFrame->GetData(),
               outFrame->m_VideoInfo.nWidth,
               outFrame->m_VideoInfo.nHeight,
               QImage::Format_RGB32);
    if(img.isNull())
    {
        LOG_MODEL_ERROR("CQRCode", "Image is null");
        return -1;
    }
    return ProcessQImage(img, szText);
}*/

QImage CQRCode::QRcodeEncodeUserInfo(const QString &szInfo,
                                     const QImage &inImage)
{
    QString szData = RABBITIM_USERINFO + szInfo;
    return QRcodeEncodeString(szData, inImage);
}

QImage CQRCode::QRcodeEncodeUserId(const QString &szId, const QImage &inImage)
{
    QString szData = RABBITIM_ID + szId;
    return QRcodeEncodeString(szData, inImage);
}

/* > 0 ：
 * = 0 ：成功处理
 * < 0 : 错误
 */
int CQRCode::ProcessMessage(const QString &szMessage)
{
    QUrl url(szMessage);
    if("rabbitim" == url.scheme())
    {
        QString szId;
        if("id" == url.host()) //增加好友
        {
            szId = szMessage.right(szMessage.size()
                                   - QString(RABBITIM_ID).size());
        } else if("userinfo" == url.host()) {
            int nId = szMessage.indexOf("Id:",
                                        szMessage.indexOf(RABBITIM_USERINFO),
                                        Qt::CaseInsensitive) + 3;
            int nRight = szMessage.indexOf(";", nId);
            szId = szMessage.mid(nId, nRight - nId);
        }
        LOG_MODEL_DEBUG("CQRCode", "ID:%s", szId.toStdString().c_str());
        if(szId.isEmpty())
            return -1;
        if(USER_INFO_LOCALE.isNull())
            return -2;
        if(USER_INFO_LOCALE->GetInfo()->GetId() == szId)
        {
            LOG_MODEL_ERROR("CQRCode", "Roster[%s] is self.",
                            szId.toStdString().c_str());
            return 0;
        }
        QSharedPointer<CUser> user = GLOBAL_USER->GetUserInfoRoster(szId);
        if(user.isNull())
        {
            QMessageBox msg(QMessageBox::Question, "",
                            tr("Do you add roster ") + szId + "?",
                            QMessageBox::Yes | QMessageBox::No,
                            nullptr, Qt::Dialog | Qt::MSWindowsFixedSizeDialogHint |Qt::WindowStaysOnTopHint);
            if(QMessageBox::Ok == msg.exec())
            {
                GET_CLIENT->RosterAdd(szId);
            }
        } else  {
            LOG_MODEL_ERROR("CQRCode", "Roster[%s] has exist.",
                            szId.toStdString().c_str());
        }
        return 0;
    } else {
        if(url.scheme() == "http"
                || url.scheme() == "https"
                || url.scheme() == "ftp"
                || url.scheme() == "mailto")
        {
            QMessageBox msg(QMessageBox::Question, "",
                            tr("Do open ") + szMessage + "?",
                            QMessageBox::Ok | QMessageBox::No,
                            nullptr, Qt::Dialog | Qt::MSWindowsFixedSizeDialogHint |Qt::WindowStaysOnTopHint);
            if(QMessageBox::Ok == msg.exec())
            {
                if(QDesktopServices::openUrl(url))
                    return 0;
            }
            else
                return 0;
        }
    }
    return -4;
}


switch (OpSize) {
    case 4: {
      cmpxchg8b(dword [MemReg]);
      // EDX:EAX now contains the result
      mov(Dst.first.cvt32(), eax);
      mov(Dst.second.cvt32(), edx);
    break;
    }
    case 8: {
      cmpxchg16b(qword [MemReg]);
      // RDX:RAX now contains the result
      mov(Dst.first, rax);
      mov(Dst.second, rdx);
    break;
    }
    default: LOGMAN_MSG_A_FMT("Unsupported: {}", OpSize);
  }

/*
$info$
tags: backend|x86-64
$end_info$
*/

#include "Interface/Core/JIT/x86_64/JITClass.h"

#include <FEXCore/IR/IR.h>
#include <FEXCore/Utils/LogManager.h>

#include <array>
#include <stdint.h>
#include <utility>
#include <xbyak/xbyak.h>

namespace FEXCore::CPU {
#define DEF_OP(x) void X86JITCore::Op_##x(FEXCore::IR::IROp_Header *IROp, uint32_t Node)
DEF_OP(CASPair) {
  auto Op = IROp->C<IR::IROp_CAS>();
  uint8_t OpSize = IROp->Size;

  // This will write to memory! Careful!
  // Third operand must be a calculated guest memory address
  auto Dst = GetSrcPair<RA_64>(Node);
  auto Expected = GetSrcPair<RA_64>(Op->Header.Args[0].ID());
  auto Desired = GetSrcPair<RA_64>(Op->Header.Args[1].ID());
  auto MemSrc = GetSrc<RA_64>(Op->Header.Args[2].ID());

  Xbyak::Reg MemReg = MemSrc;

  mov(rax, Expected.first);
  mov(rdx, Expected.second);

  mov(rbx, Desired.first);
  mov(rcx, Desired.second);

  // RDI(Or Source) now contains pointer
  // RDX:RAX contains our expected value
  // RCX:RBX contains our desired

  lock();

}

DEF_OP(CAS) {
  auto Op = IROp->C<IR::IROp_CAS>();
  uint8_t OpSize = IROp->Size;

  // This will write to memory! Careful!
  // Third operand must be a calculated guest memory address

  Xbyak::Reg MemReg = GetSrc<RA_64>(Op->Header.Args[2].ID());

  mov(rax, GetSrc<RA_64>(Op->Header.Args[0].ID()));

  // RCX now contains pointer
  // RAX contains our expected value
  // RDX contains our desired

  lock();
  switch (OpSize) {
  case 1: {
    cmpxchg(byte [MemReg], GetSrc<RA_8>(Op->Header.Args[1].ID()));
    movzx(GetDst<RA_64>(Node), al);
  break;
  }
  case 2: {
    cmpxchg(word [MemReg], GetSrc<RA_16>(Op->Header.Args[1].ID()));
    movzx(GetDst<RA_64>(Node), ax);
  break;
  }
  case 4: {
    cmpxchg(dword [MemReg], GetSrc<RA_32>(Op->Header.Args[1].ID()));
    // RAX now contains the result
    mov (GetDst<RA_64>(Node), eax);
  break;
  }
  case 8: {
    cmpxchg(qword [MemReg], GetSrc<RA_64>(Op->Header.Args[1].ID()));
    // RAX now contains the result
    mov (GetDst<RA_64>(Node), rax);
  break;
  }
  default: LOGMAN_MSG_A_FMT("Unsupported: {}", OpSize);
  }
}

DEF_OP(AtomicAdd) {
  auto Op = IROp->C<IR::IROp_AtomicAdd>();

  Xbyak::Reg MemReg = GetSrc<RA_64>(Op->Header.Args[0].ID());

  lock();
  switch (IROp->Size) {
    case 1:
      add(byte [MemReg], GetSrc<RA_8>(Op->Header.Args[1].ID()));
      break;
    case 2:
      add(word [MemReg], GetSrc<RA_16>(Op->Header.Args[1].ID()));
      break;
    case 4:
      add(dword [MemReg], GetSrc<RA_32>(Op->Header.Args[1].ID()));
      break;
    case 8:
      add(qword [MemReg], GetSrc<RA_64>(Op->Header.Args[1].ID()));
      break;
    default:  LOGMAN_MSG_A_FMT("Unhandled AtomicAdd size: {}", IROp->Size);
  }
}

DEF_OP(AtomicSub) {
  auto Op = IROp->C<IR::IROp_AtomicSub>();

  Xbyak::Reg MemReg = GetSrc<RA_64>(Op->Header.Args[0].ID());
  lock();
  switch (IROp->Size) {
    case 1:
      sub(byte [MemReg], GetSrc<RA_8>(Op->Header.Args[1].ID()));
      break;
    case 2:
      sub(word [MemReg], GetSrc<RA_16>(Op->Header.Args[1].ID()));
      break;
    case 4:
      sub(dword [MemReg], GetSrc<RA_32>(Op->Header.Args[1].ID()));
      break;
    case 8:
      sub(qword [MemReg], GetSrc<RA_64>(Op->Header.Args[1].ID()));
      break;
    default:  LOGMAN_MSG_A_FMT("Unhandled AtomicAdd size: {}", IROp->Size);
  }
}

DEF_OP(AtomicAnd) {
  auto Op = IROp->C<IR::IROp_AtomicAnd>();

  Xbyak::Reg MemReg = GetSrc<RA_64>(Op->Header.Args[0].ID());
  lock();
  switch (IROp->Size) {
    case 1:
      and_(byte [MemReg], GetSrc<RA_8>(Op->Header.Args[1].ID()));
      break;
    case 2:
      and_(word [MemReg], GetSrc<RA_16>(Op->Header.Args[1].ID()));
      break;
    case 4:
      and_(dword [MemReg], GetSrc<RA_32>(Op->Header.Args[1].ID()));
      break;
    case 8:
      and_(qword [MemReg], GetSrc<RA_64>(Op->Header.Args[1].ID()));
      break;
    default:  LOGMAN_MSG_A_FMT("Unhandled AtomicAdd size: {}", IROp->Size);
  }
}

DEF_OP(AtomicOr) {
  auto Op = IROp->C<IR::IROp_AtomicOr>();

  Xbyak::Reg MemReg = GetSrc<RA_64>(Op->Header.Args[0].ID());
  lock();
  switch (IROp->Size) {
    case 1:
      or_(byte [MemReg], GetSrc<RA_8>(Op->Header.Args[1].ID()));
      break;
    case 2:
      or_(word [MemReg], GetSrc<RA_16>(Op->Header.Args[1].ID()));
      break;
    case 4:
      or_(dword [MemReg], GetSrc<RA_32>(Op->Header.Args[1].ID()));
      break;
    case 8:
      or_(qword [MemReg], GetSrc<RA_64>(Op->Header.Args[1].ID()));
      break;
    default:  LOGMAN_MSG_A_FMT("Unhandled AtomicAdd size: {}", IROp->Size);
  }
}

DEF_OP(AtomicXor) {
  auto Op = IROp->C<IR::IROp_AtomicXor>();

  Xbyak::Reg MemReg = GetSrc<RA_64>(Op->Header.Args[0].ID());
  lock();
  switch (IROp->Size) {
    case 1:
      xor_(byte [MemReg], GetSrc<RA_8>(Op->Header.Args[1].ID()));
      break;
    case 2:
      xor_(word [MemReg], GetSrc<RA_16>(Op->Header.Args[1].ID()));
      break;
    case 4:
      xor_(dword [MemReg], GetSrc<RA_32>(Op->Header.Args[1].ID()));
      break;
    case 8:
      xor_(qword [MemReg], GetSrc<RA_64>(Op->Header.Args[1].ID()));
      break;
    default:  LOGMAN_MSG_A_FMT("Unhandled AtomicAdd size: {}", IROp->Size);
  }
}

DEF_OP(AtomicSwap) {
  auto Op = IROp->C<IR::IROp_AtomicSwap>();

  Xbyak::Reg MemReg = rax;
  mov(MemReg, GetSrc<RA_64>(Op->Header.Args[0].ID()));

  switch (IROp->Size) {
    case 1:
      movzx(GetDst<RA_64>(Node), GetSrc<RA_8>(Op->Header.Args[1].ID()));
      lock();
      xchg(byte [MemReg], GetDst<RA_8>(Node));
      break;
    case 2:
      movzx(GetDst<RA_64>(Node), GetSrc<RA_16>(Op->Header.Args[1].ID()));
      lock();
      xchg(word [MemReg], GetDst<RA_16>(Node));
      break;
    case 4:
      mov(GetDst<RA_64>(Node), GetSrc<RA_32>(Op->Header.Args[1].ID()));
      lock();
      xchg(dword [MemReg], GetDst<RA_32>(Node));
      break;
    case 8:
      mov(GetDst<RA_64>(Node), GetSrc<RA_64>(Op->Header.Args[1].ID()));
      lock();
      xchg(qword [MemReg], GetDst<RA_64>(Node));
      break;
    default:  LOGMAN_MSG_A_FMT("Unhandled AtomicSwap size: {}", IROp->Size);
  }
}

DEF_OP(AtomicFetchAdd) {
  auto Op = IROp->C<IR::IROp_AtomicFetchAdd>();

  Xbyak::Reg MemReg = GetSrc<RA_64>(Op->Header.Args[0].ID());
  switch (IROp->Size) {
    case 1:
      movzx(rcx, GetSrc<RA_8>(Op->Header.Args[1].ID()));
      lock();
      xadd(byte [MemReg], cl);
      movzx(GetDst<RA_32>(Node), cl);
      break;
    case 2:
      movzx(rcx, GetSrc<RA_16>(Op->Header.Args[1].ID()));
      lock();
      xadd(word [MemReg], cx);
      movzx(GetDst<RA_32>(Node), cx);
      break;
    case 4:
      mov(ecx, GetSrc<RA_32>(Op->Header.Args[1].ID()));
      lock();
      xadd(dword [MemReg], ecx);
      mov(GetDst<RA_64>(Node), ecx);
      break;
    case 8:
      mov(rcx, GetSrc<RA_64>(Op->Header.Args[1].ID()));
      lock();
      xadd(qword [MemReg], rcx);
      mov(GetDst<RA_64>(Node), rcx);
      break;
    default:  LOGMAN_MSG_A_FMT("Unhandled AtomicFetchAdd size: {}", IROp->Size);
  }
}

DEF_OP(AtomicFetchSub) {
  auto Op = IROp->C<IR::IROp_AtomicFetchSub>();

  Xbyak::Reg MemReg = GetSrc<RA_64>(Op->Header.Args[0].ID());
  switch (IROp->Size) {
    case 1:
      mov(cl, GetSrc<RA_8>(Op->Header.Args[1].ID()));
      neg(cl);
      lock();
      xadd(byte [MemReg], cl);
      movzx(GetDst<RA_32>(Node), cl);
      break;
    case 2:
      mov(cx, GetSrc<RA_16>(Op->Header.Args[1].ID()));
      neg(cx);
      lock();
      xadd(word [MemReg], cx);
      movzx(GetDst<RA_32>(Node), cx);
      break;
    case 4:
      mov(ecx, GetSrc<RA_32>(Op->Header.Args[1].ID()));
      neg(ecx);
      lock();
      xadd(dword [MemReg], ecx);
      mov(GetDst<RA_32>(Node), ecx);
      break;
    case 8:
      mov(rcx, GetSrc<RA_64>(Op->Header.Args[1].ID()));
      neg(rcx);
      lock();
      xadd(qword [MemReg], rcx);
      mov(GetDst<RA_64>(Node), rcx);
      break;
    default:  LOGMAN_MSG_A_FMT("Unhandled AtomicFetchSub size: {}", IROp->Size);
  }
}

DEF_OP(AtomicFetchAnd) {
  auto Op = IROp->C<IR::IROp_AtomicFetchAnd>();

  // TMP1 = rax
  Xbyak::Reg MemReg = GetSrc<RA_64>(Op->Header.Args[0].ID());

  switch (IROp->Size) {
    case 1: {
      mov(TMP1.cvt8(), byte [MemReg]);

      Label Loop;
      L(Loop);
      mov(TMP2.cvt8(), TMP1.cvt8());
      mov(TMP3.cvt8(), TMP1.cvt8());
      and_(TMP2.cvt8(), GetSrc<RA_8>(Op->Header.Args[1].ID()));

      // Updates RAX with the value from memory
      lock(); cmpxchg(byte [MemReg], TMP2.cvt8());
      jne(Loop);
      // Result is the previous value from memory, which is currently in TMP3
      movzx(GetDst<RA_64>(Node), TMP3.cvt8());
      break;
    }
    case 2: {
      mov(TMP1.cvt16(), word [MemReg]);

      Label Loop;
      L(Loop);
      mov(TMP2.cvt16(), TMP1.cvt16());
      mov(TMP3.cvt16(), TMP1.cvt16());
      and_(TMP2.cvt16(), GetSrc<RA_16>(Op->Header.Args[1].ID()));

      // Updates RAX with the value from memory
      lock(); cmpxchg(word [MemReg], TMP2.cvt16());
      jne(Loop);

      // Result is the previous value from memory, which is currently in TMP3
      movzx(GetDst<RA_64>(Node), TMP3.cvt16());
      break;
    }
    case 4: {
      mov(TMP1.cvt32(), dword [MemReg]);

      Label Loop;
      L(Loop);
      mov(TMP2.cvt32(), TMP1.cvt32());
      mov(TMP3.cvt32(), TMP1.cvt32());
      and_(TMP2.cvt32(), GetSrc<RA_32>(Op->Header.Args[1].ID()));

      // Updates RAX with the value from memory
      lock(); cmpxchg(dword [MemReg], TMP2.cvt32());
      jne(Loop);

      // Result is the previous value from memory, which is currently in TMP3
      mov(GetDst<RA_32>(Node), TMP3.cvt32());
      break;
    }
    case 8: {
      mov(TMP1.cvt64(), qword [MemReg]);

      Label Loop;
      L(Loop);
      mov(TMP2.cvt64(), TMP1.cvt64());
      mov(TMP3.cvt64(), TMP1.cvt64());
      and_(TMP2.cvt64(), GetSrc<RA_64>(Op->Header.Args[1].ID()));

      // Updates RAX with the value from memory
      lock(); cmpxchg(qword [MemReg], TMP2.cvt64());
      jne(Loop);

      // Result is the previous value from memory, which is currently in TMP3
      mov(GetDst<RA_64>(Node), TMP3.cvt64());
      break;
    }
    default:  LOGMAN_MSG_A_FMT("Unhandled AtomicFetchAnd size: {}", IROp->Size);
  }
}

DEF_OP(AtomicFetchOr) {
  auto Op = IROp->C<IR::IROp_AtomicFetchOr>();

  // TMP1 = rax
  Xbyak::Reg MemReg = GetSrc<RA_64>(Op->Header.Args[0].ID());
  switch (IROp->Size) {
    case 1: {
      mov(TMP1.cvt8(), byte [MemReg]);

      Label Loop;
      L(Loop);
      mov(TMP2.cvt8(), TMP1.cvt8());
      mov(TMP3.cvt8(), TMP1.cvt8());
      or_(TMP2.cvt8(), GetSrc<RA_8>(Op->Header.Args[1].ID()));

      // Updates RAX with the value from memory
      lock(); cmpxchg(byte [MemReg], TMP2.cvt8());
      jne(Loop);
      // Result is the previous value from memory, which is currently in TMP3
      movzx(GetDst<RA_64>(Node), TMP3.cvt8());
      break;
    }
    case 2: {
      mov(TMP1.cvt16(), word [MemReg]);

      Label Loop;
      L(Loop);
      mov(TMP2.cvt16(), TMP1.cvt16());
      mov(TMP3.cvt16(), TMP1.cvt16());
      or_(TMP2.cvt16(), GetSrc<RA_16>(Op->Header.Args[1].ID()));

      // Updates RAX with the value from memory
      lock(); cmpxchg(word [MemReg], TMP2.cvt16());
      jne(Loop);

      // Result is the previous value from memory, which is currently in TMP3
      movzx(GetDst<RA_64>(Node), TMP3.cvt16());
      break;
    }
    case 4: {
      mov(TMP1.cvt32(), dword [MemReg]);

      Label Loop;
      L(Loop);
      mov(TMP2.cvt32(), TMP1.cvt32());
      mov(TMP3.cvt32(), TMP1.cvt32());
      or_(TMP2.cvt32(), GetSrc<RA_32>(Op->Header.Args[1].ID()));

      // Updates RAX with the value from memory
      lock(); cmpxchg(dword [MemReg], TMP2.cvt32());
      jne(Loop);

      // Result is the previous value from memory, which is currently in TMP3
      mov(GetDst<RA_32>(Node), TMP3.cvt32());
      break;
    }
    case 8: {
      mov(TMP1.cvt64(), qword [MemReg]);

      Label Loop;
      L(Loop);
      mov(TMP2.cvt64(), TMP1.cvt64());
      mov(TMP3.cvt64(), TMP1.cvt64());
      or_(TMP2.cvt64(), GetSrc<RA_64>(Op->Header.Args[1].ID()));

      // Updates RAX with the value from memory
      lock(); cmpxchg(qword [MemReg], TMP2.cvt64());
      jne(Loop);

      // Result is the previous value from memory, which is currently in TMP3
      mov(GetDst<RA_64>(Node), TMP3.cvt64());
      break;
    }
    default:  LOGMAN_MSG_A_FMT("Unhandled AtomicFetchOr size: {}", IROp->Size);
  }
}

DEF_OP(AtomicFetchXor) {
  auto Op = IROp->C<IR::IROp_AtomicFetchXor>();

  // TMP1 = rax
  Xbyak::Reg MemReg = GetSrc<RA_64>(Op->Header.Args[0].ID());
  switch (IROp->Size) {
    case 1: {
      mov(TMP1.cvt8(), byte [MemReg]);

      Label Loop;
      L(Loop);
      mov(TMP2.cvt8(), TMP1.cvt8());
      mov(TMP3.cvt8(), TMP1.cvt8());
      xor_(TMP2.cvt8(), GetSrc<RA_8>(Op->Header.Args[1].ID()));

      // Updates RAX with the value from memory
      lock(); cmpxchg(byte [MemReg], TMP2.cvt8());
      jne(Loop);
      // Result is the previous value from memory, which is currently in TMP3
      movzx(GetDst<RA_64>(Node), TMP3.cvt8());
      break;
    }
    case 2: {
      mov(TMP1.cvt16(), word [MemReg]);

      Label Loop;
      L(Loop);
      mov(TMP2.cvt16(), TMP1.cvt16());
      mov(TMP3.cvt16(), TMP1.cvt16());
      xor_(TMP2.cvt16(), GetSrc<RA_16>(Op->Header.Args[1].ID()));

      // Updates RAX with the value from memory
      lock(); cmpxchg(word [MemReg], TMP2.cvt16());
      jne(Loop);

      // Result is the previous value from memory, which is currently in TMP3
      movzx(GetDst<RA_64>(Node), TMP3.cvt16());
      break;
    }
    case 4: {
      mov(TMP1.cvt32(), dword [MemReg]);

      Label Loop;
      L(Loop);
      mov(TMP2.cvt32(), TMP1.cvt32());
      mov(TMP3.cvt32(), TMP1.cvt32());
      xor_(TMP2.cvt32(), GetSrc<RA_32>(Op->Header.Args[1].ID()));

      // Updates RAX with the value from memory
      lock(); cmpxchg(dword [MemReg], TMP2.cvt32());
      jne(Loop);

      // Result is the previous value from memory, which is currently in TMP3
      mov(GetDst<RA_32>(Node), TMP3.cvt32());
      break;
    }
    case 8: {
      mov(TMP1.cvt64(), qword [MemReg]);

      Label Loop;
      L(Loop);
      mov(TMP2.cvt64(), TMP1.cvt64());
      mov(TMP3.cvt64(), TMP1.cvt64());
      xor_(TMP2.cvt64(), GetSrc<RA_64>(Op->Header.Args[1].ID()));

      // Updates RAX with the value from memory
      lock(); cmpxchg(qword [MemReg], TMP2.cvt64());
      jne(Loop);

      // Result is the previous value from memory, which is currently in TMP3
      mov(GetDst<RA_64>(Node), TMP3.cvt64());
      break;
    }
    default:  LOGMAN_MSG_A_FMT("Unhandled AtomicFetchXor size: {}", IROp->Size);
  }
}

DEF_OP(AtomicFetchNeg) {
  auto Op = IROp->C<IR::IROp_AtomicFetchNeg>();

  Xbyak::Reg MemReg = GetSrc<RA_64>(Op->Header.Args[0].ID());
  switch (IROp->Size) {
    case 1: {
      mov(TMP1.cvt8(), byte [MemReg]);

      Label Loop;
      L(Loop);
      mov(TMP2.cvt8(), TMP1.cvt8());
      mov(TMP3.cvt8(), TMP1.cvt8());
      neg(TMP2.cvt8());

      // Updates RAX with the value from memory
      lock(); cmpxchg(byte [MemReg], TMP2.cvt8());
      jne(Loop);
      // Result is the previous value from memory, which is currently in TMP3
      movzx(GetDst<RA_64>(Node), TMP3.cvt8());
      break;
    }
    case 2: {
      mov(TMP1.cvt16(), word [MemReg]);

      Label Loop;
      L(Loop);
      mov(TMP2.cvt16(), TMP1.cvt16());
      mov(TMP3.cvt16(), TMP1.cvt16());
      neg(TMP2.cvt16());

      // Updates RAX with the value from memory
      lock(); cmpxchg(word [MemReg], TMP2.cvt16());
      jne(Loop);

      // Result is the previous value from memory, which is currently in TMP3
      movzx(GetDst<RA_64>(Node), TMP3.cvt16());
      break;
    }
    case 4: {
      mov(TMP1.cvt32(), dword [MemReg]);

      Label Loop;
      L(Loop);
      mov(TMP2.cvt32(), TMP1.cvt32());
      mov(TMP3.cvt32(), TMP1.cvt32());
      neg(TMP2.cvt32());

      // Updates RAX with the value from memory
      lock(); cmpxchg(dword [MemReg], TMP2.cvt32());
      jne(Loop);

      // Result is the previous value from memory, which is currently in TMP3
      mov(GetDst<RA_32>(Node), TMP3.cvt32());
      break;
    }
    case 8: {
      mov(TMP1.cvt64(), qword [MemReg]);

      Label Loop;
      L(Loop);
      mov(TMP2.cvt64(), TMP1.cvt64());
      mov(TMP3.cvt64(), TMP1.cvt64());
      neg(TMP2.cvt64());

      // Updates RAX with the value from memory
      lock(); cmpxchg(qword [MemReg], TMP2.cvt64());
      jne(Loop);

      // Result is the previous value from memory, which is currently in TMP3
      mov(GetDst<RA_64>(Node), TMP3.cvt64());
      break;
    }
    default:  LOGMAN_MSG_A_FMT("Unhandled AtomicFetchNeg size: {}", IROp->Size);
  }
}

#undef DEF_OP
void X86JITCore::RegisterAtomicHandlers() {
#define REGISTER_OP(op, x) OpHandlers[FEXCore::IR::IROps::OP_##op] = &X86JITCore::Op_##x
  REGISTER_OP(CASPAIR,        CASPair);
  REGISTER_OP(CAS,            CAS);
  REGISTER_OP(ATOMICADD,      AtomicAdd);
  REGISTER_OP(ATOMICSUB,      AtomicSub);
  REGISTER_OP(ATOMICAND,      AtomicAnd);
  REGISTER_OP(ATOMICOR,       AtomicOr);
  REGISTER_OP(ATOMICXOR,      AtomicXor);
  REGISTER_OP(ATOMICSWAP,     AtomicSwap);
  REGISTER_OP(ATOMICFETCHADD, AtomicFetchAdd);
  REGISTER_OP(ATOMICFETCHSUB, AtomicFetchSub);
  REGISTER_OP(ATOMICFETCHAND, AtomicFetchAnd);
  REGISTER_OP(ATOMICFETCHOR,  AtomicFetchOr);
  REGISTER_OP(ATOMICFETCHXOR, AtomicFetchXor);
  REGISTER_OP(ATOMICFETCHNEG, AtomicFetchNeg);
#undef REGISTER_OP
}
}


void	CListenerUser::setPos( const NLMISC::CVector& pos )
{
	// Change position
	_DrvListener->setPos( pos );

	// Select environment effect
	CAudioMixerUser::instance()->applyListenerMove( pos );
}

// This source file has been modified by the following contributors:

#include "stdsound.h"

#include "nel/sound/listener_user.h"
#include "nel/sound/audio_mixer_user.h"

namespace NLSOUND {

/*
 * Set the position vector (default: (0,0,0)) (3D mode only)
 */


int iStereoChorusBPlugin::get_param(int ndx, kxparam_t *value)
{
	*value = _params[ndx]; return 0;
}

// kX Driver / kX Driver Interface / kX Driver Effects Library
// All rights reserved

/*
 */

#include "stdafx.h"

// --------------- the above should be a 'standard' beginning of any .cpp file

#include "stchorus.h"
// effect source
#include "da_stchorus.cpp"

inline kxparam_t kabs(kxparam_t v)
{
        if(v<0) return -v; else return v;
}

// _params
typedef enum {
	LEVEL_ID,
	INWIDTH_ID,
	OUTWIDTH_ID,
	FEEDBACK_ID,
	DELAY_ID,
	MODDEPTH_ID,
	MODPHASE_ID,
	MODFREQ_ID,
	FEEDINVERT_ID
};

// default plugin _params
static kxparam_t stchorus_default_params[STCHORUS_PARAMS_COUNT] = {80, 0, 50, 16, 60, 20, -120, 150, 0}; //temporarely

/* Plugin Implemenation */

int iStereoChorusBPlugin::set_param(int ndx, kxparam_t value) // calculates effect _params
{
	_params[ndx] = value;

	switch (ndx)
	{
	case LEVEL_ID:
		set_dsp_register(_R_LEVEL, itodspr_scl(100, value));
		break;

	case INWIDTH_ID:
		set_dsp_register(_R_INWIDTH, itodspr_scl(100, kabs(value)));
		write_instr_opcode(_IN_PHASE_INSTR, (word)((value>0)?MACS1:MACS));
		write_instr_opcode(_IN_PHASE_INSTR + 1, (word)((value>0)?MACS1:MACS));
		break;

	case OUTWIDTH_ID:
		set_dsp_register(_R_OUTWIDTH, itodspr_scl(100, 50 - value));
		break;

	case FEEDBACK_ID:
	case FEEDINVERT_ID:
		value = _params[FEEDBACK_ID];
		if (_params[FEEDINVERT_ID]) value = - value;
		set_dsp_register(_R_FEEDBACK, itodspr_scl(100, value));
		break;

	case DELAY_ID:
		set_dsp_register(_R_DELAY, (dword)((value * SAMPLES_PER_MSEC / 10 + 2) << 0xc));
		// or less precise: set_dsp_register(_R_DELAY, value * 0x4CCD + 0x2000);
		break;

	case MODDEPTH_ID:
		set_dsp_register(_R_MODDEPTH, itodspr_scl(200, value)); // 0...100 -> 0.0...0.5
		break;

	case MODPHASE_ID:
		set_dsp_register(_R_MODPHASE, itodspr_scl(180, value));
		break;

	case MODFREQ_ID:
		set_dsp_register(_R_MODFREQ, itodspr_scl(100 * (SAMPLES_PER_SEC / 2), value));
		break;
	}

	if (cp) ((iStereoChorusBPluginDlg*) cp)->sync(ndx);

	return 0;
}

int iStereoChorusBPlugin::set_defaults()
{
	set_all_params(stchorus_default_params); return 0;
}

int iStereoChorusBPlugin::set_all_params(kxparam_t* values)
{
	kxparam_t value;

	memcpy(_params, values, STCHORUS_PARAMS_COUNT*sizeof(dword));

		set_dsp_register(_R_LEVEL, itodspr_scl(100, _params[LEVEL_ID]));

		value = (int)_params[INWIDTH_ID];
		set_dsp_register(_R_INWIDTH, itodspr_scl(100, kabs(value)));
		write_instr_opcode(_IN_PHASE_INSTR, (word)((value>0)?MACS1:MACS));
		write_instr_opcode(_IN_PHASE_INSTR + 1, (word)((value>0)?MACS1:MACS));

		set_dsp_register(_R_OUTWIDTH, itodspr_scl(100, 50 - _params[OUTWIDTH_ID]));

		value = (int)_params[FEEDBACK_ID];
		if (_params[FEEDINVERT_ID]) value = - value;
		set_dsp_register(_R_FEEDBACK, itodspr_scl(100, value));

		set_dsp_register(_R_DELAY, (dword)((_params[DELAY_ID] * SAMPLES_PER_MSEC / 10 + 2) << 0xc));

		set_dsp_register(_R_MODDEPTH, itodspr_scl(200, _params[MODDEPTH_ID]));

		set_dsp_register(_R_MODPHASE, itodspr_scl(180, _params[MODPHASE_ID]));

		set_dsp_register(_R_MODFREQ, itodspr_scl(100 * (SAMPLES_PER_SEC / 2), _params[MODFREQ_ID]));

	if (cp) ((iStereoChorusBPluginDlg*) cp)->sync(EVERYPM_ID);

	return 0;
}

int iStereoChorusBPlugin::request_microcode() // generally is called after init()
{
	publish_microcode(stchorus);

	// you should free code and info massives in ::close() if allocated dynamically
	return 0;
}

const char *iStereoChorusBPlugin::get_plugin_description(int id)
{
	plugin_description(stchorus);
}

iKXPluginGUI *iStereoChorusBPlugin::create_cp(kDialog *parent,kFile *mf)
{
	iStereoChorusBPluginDlg *tmp;
	tmp = new iStereoChorusBPluginDlg(this, parent, mf);
	tmp->create();
	return tmp;
}

int iStereoChorusBPlugin::get_user_interface()
{
	return IKXPLUGIN_OWNER;
}

static kx_fxparam_descr _param_descr[STCHORUS_PARAMS_COUNT] = {
	{"Level", KX_FXPARAM_LEVEL, 0, 100},
	{"InWidth", KX_FXPARAM_PERCENT, -50, 50},
	{"OutWidth", KX_FXPARAM_PERCENT, -50, 50},
	{"Feedback", KX_FXPARAM_PERCENT, 0, 99},
	{"Delay", KX_FXPARAM_MS, 0, 200},
	{"Mod Depth", KX_FXPARAM_PERCENT, 0, 100},
	{"Phase", KX_FXPARAM_ANGLE, -180, 180},
	{"Mod Rate", KX_FXPARAM_HZ, 0, 1000},
	{"Invert Feedback", KX_FXPARAM_SWITCH, 0, 1}};

int iStereoChorusBPlugin::describe_param(int ndx, kx_fxparam_descr *descr)
{
	memcpy(descr, &_param_descr[ndx], sizeof kx_fxparam_descr); return 0;
}

/* Plugin UI Implementation */

void iStereoChorusBPluginDlg::init()
{
	CKXPluginGUI::init();
	// custom dialog initialization here...

	create_dialog(stchorus_name, 535, 200);

	// add all GUI controls

	create_vfader(fdrLevel, LEVEL_ID, "Level", 0, 100,             5, 12, 55, 170);
	create_vfader(fdrInWidth, INWIDTH_ID, "InWidth", -50, 50,      65, 12, 55, 170);
	create_vfader(fdrOutWidth, OUTWIDTH_ID, "OutWidth", -50, 50,   125, 12, 55, 170);
	create_vfader(fdrFeedback, FEEDBACK_ID, "Feedback", 0, 99,     185, 12, 55, 170);

	create_hfader(fdrDelay, DELAY_ID, "Delay (ms)", 0, 200,          245, 47, 280, 80);
	create_hfader(fdrModDepth, MODDEPTH_ID, "Mod Depth (%)", 0, 100, 245, 82, 280, 80);
	create_hfader(fdrModPhase, MODPHASE_ID, "Phase (°)", -180, 180,  245, 117, 280, 80);
	create_hfader(fdrModFreq, MODFREQ_ID, "Mod Rate (Hz)",  0, 1000, 245, 152, 280, 80);

	create_checkbox(chkFeedInvert, FEEDINVERT_ID, "Invert Feedback", 255, 20, 120);

	controls_enabled = TRUE;

	sync(EVERYPM_ID); // Synchronize UI Controls with Plugin _params

        redraw();
}

void iStereoChorusBPluginDlg::sync(int ndx)
{
	char c[MAX_LABEL_STRING];
	kxparam_t v;

	switch (ndx)
	{
	case EVERYPM_ID: // update all controls
	case LEVEL_ID:
		v = plugin->_params[LEVEL_ID];
		if (controls_enabled) {VSSETPOS(fdrLevel.slider, (int)v); fdrLevel.slider.redraw();}
		sprintf(c, "%i " "%%", v);
		fdrLevel.svalue.SetWindowText(c);
		if (ndx != EVERYPM_ID) break;

	case INWIDTH_ID:
		v = plugin->_params[INWIDTH_ID];
		if (controls_enabled) {VSSETPOS(fdrInWidth.slider, (int)v); fdrInWidth.slider.redraw();}
		sprintf(c, "%i " "%%", v);
		fdrInWidth.svalue.SetWindowText(c);
		if (ndx != EVERYPM_ID) break;

	case OUTWIDTH_ID:
		v = plugin->_params[OUTWIDTH_ID];
		if (controls_enabled) {VSSETPOS(fdrOutWidth.slider, (int)v); fdrOutWidth.slider.redraw();}
		sprintf(c, "%i " "%%", v);
		fdrOutWidth.svalue.SetWindowText(c);
		if (ndx != EVERYPM_ID) break;

	case FEEDINVERT_ID:
		v = plugin->_params[FEEDINVERT_ID];
		if (controls_enabled) {chkFeedInvert.set_check((int)v); chkFeedInvert.redraw();}
		if (ndx != EVERYPM_ID) break;

	case FEEDBACK_ID:
		v = plugin->_params[FEEDBACK_ID];
		if (controls_enabled) {VSSETPOS(fdrFeedback.slider, (int)v); fdrFeedback.slider.redraw();}
		sprintf(c, "%i " "%%", v);
		fdrFeedback.svalue.SetWindowText(c);
		if (ndx != EVERYPM_ID) break;

	case DELAY_ID:
		v = plugin->_params[DELAY_ID];
		if (controls_enabled) {fdrDelay.slider.set_pos((int)v); fdrDelay.slider.redraw();}
		sprintf(c, "%i.%i", v/10, v%10);
		fdrDelay.svalue.SetWindowText(c);
		if (ndx != EVERYPM_ID) break;

	case MODPHASE_ID:
		v = plugin->_params[MODPHASE_ID];
		if (controls_enabled) {fdrModPhase.slider.set_pos((int)v); fdrModPhase.slider.redraw();}
		sprintf(c, "%i", v);
		fdrModPhase.svalue.SetWindowText(c);
		if (ndx != EVERYPM_ID) break;

	case MODFREQ_ID:
		v = plugin->_params[MODFREQ_ID];
		if (controls_enabled) {fdrModFreq.slider.set_pos((int)v); fdrModFreq.slider.redraw();}
		sprintf(c, "%i.%02i", v/100, v%100);
		fdrModFreq.svalue.SetWindowText(c);
		if (ndx != EVERYPM_ID) break;

	case MODDEPTH_ID:
		v = plugin->_params[MODDEPTH_ID];
		if (controls_enabled) {fdrModDepth.slider.set_pos((int)v); fdrModDepth.slider.redraw();}
		sprintf(c, "%i", v);
		fdrModDepth.svalue.SetWindowText(c);
		if (ndx != EVERYPM_ID) break;
	}
}


while (fgets(info, sizeof(info), fp) != NULL);

#include <stdio.h>
#include <time.h>
#include <string.h>
#include <assert.h>

extern "C" char* getDeviceInfo()
{
    static char info[128];
    static FILE *fp;

    if (fp != NULL)
    {
        return info;
    }

    fp = popen("uname -s -n -m ", "r");
    if (NULL == fp)
    {
        perror("popen failed");
        return NULL;
    }

    info[strcspn(info, "\n")] = 0;//remove '\r' for json requirment
    info[strcspn(info, "\r")] = 0;//remove '\n' for json requirment

    pclose(fp);
    return info;
}

extern "C" char* getCurrentUtcTime()
{
    static char time_str[128];
    time_t currentTime = time(NULL);
    assert(strftime(time_str, sizeof(time_str), "%Y-%m-%dT%H:%M:%SZ", gmtime(&currentTime)));
    return time_str;
}


switch (command) {
   case Cancel::command:
      return cancel(args);
   case AcquireNexServiceToken::command:
      return acquireNexServiceToken(args);
   default:
      return nn::ResultSuccess;
   }

#include "ios_fpd_act_serverstandardservice.h"

#include "ios/nn/ios_nn_ipc_server_command.h"
#include "nn/act/nn_act_result.h"

using namespace nn::ipc;
using namespace nn::act;

namespace ios::fpd::internal
{

static nn::Result
acquireNexServiceToken(CommandHandlerArgs &args)
{
   return ResultUcError;
};

static nn::Result
cancel(CommandHandlerArgs &args)
{
   auto command = ServerCommand<ActServerStandardService::Cancel> { args };
   return nn::ResultSuccess;
}

nn::Result
ActServerStandardService::commandHandler(uint32_t unk1,
                                         CommandId command,
                                         CommandHandlerArgs &args)
{


while(true) {
            wxString name =
                ::wxGetTextFromUser(_("Set a name to the compiler"), _("New compiler found!"), cmp->GetName());
            if(name.IsEmpty()) {
                return;
            }
            // Add the compiler
            if(BuildSettingsConfigST::Get()->IsCompilerExist(name)) {
                continue;
            }
            cmp->SetName(name);
            break;
        }

// file name            : advanced_settings.cpp
// A
//              _____           _      _     _ _
//              \____/\___/ \__,_|\___\_____/_|\__\___|
//                                                  F i l e
// C++ code generated with wxFormBuilder (version May  5 2007)
// PLEASE DO "NOT" EDIT THIS FILE!

#include "CompilersFoundDlg.h"
#include "NewCompilerDlg.h"
#include "advance_settings_base.h"
#include "advanced_settings.h"
#include "build_page.h"
#include "build_settings_config.h"
#include "buildsettingstab.h"
#include "editor_config.h"
#include "frame.h"
#include "globals.h"
#include "macros.h"
#include "manager.h"
#include "windowattrmanager.h"
#include <CompilersDetectorManager.h>
#include <cl_aui_notebook_art.h>
#include <wx/textdlg.h>
#include <wx/xrc/xmlres.h>

BuildSettingsDialog::BuildSettingsDialog(wxWindow* parent, size_t selected_page, int id, wxString title, wxPoint pos,
                                         wxSize size, int style)
    : AdvancedDlgBase(parent)
    , m_rightclickMenu(NULL)
{
    m_compilersPage = new CompilerMainPage(m_notebook);
    m_notebook->AddPage(m_compilersPage, _("Compilers"), true);
    m_buildSettings = new BuildTabSetting(m_notebook);
    m_notebook->AddPage(m_buildSettings, _("Build Output Appearance"), false);

    m_buildPage = new BuildPage(m_notebook);
    m_notebook->AddPage(m_buildPage, _("Build Systems"), false);
    m_rightclickMenu = wxXmlResource::Get()->LoadMenu(wxT("delete_compiler_menu"));
    LoadCompilers();
    clSetDialogBestSizeAndPosition(this);
}

void BuildSettingsDialog::LoadCompilers() { m_compilersPage->LoadCompilers(); }

BuildSettingsDialog::~BuildSettingsDialog() { wxDELETE(m_rightclickMenu); }

void BuildSettingsDialog::OnButtonNewClicked()
{
    NewCompilerDlg dlg(this);
    if(dlg.ShowModal() == wxID_OK) {
        CreateNewCompiler(dlg.GetCompilerName(), dlg.GetMasterCompiler());
        LoadCompilers();
    }
}

void BuildSettingsDialog::OnButtonOKClicked(wxCommandEvent& event)
{
    OnApply(event);
    EndModal(wxID_OK);
}

bool BuildSettingsDialog::CreateNewCompiler(const wxString& name, const wxString& copyFrom)
{
    if(BuildSettingsConfigST::Get()->IsCompilerExist(name)) {
        wxMessageBox(_("A compiler with this name already exists"), _("Error"), wxOK | wxICON_HAND);
        return false;
    }

    CompilerPtr cmp;
    if(!copyFrom.IsEmpty()) {
        cmp = BuildSettingsConfigST::Get()->GetCompiler(copyFrom);
    } else {
        cmp = BuildSettingsConfigST::Get()->GetCompiler(name);
    }
    cmp->SetName(name);
    BuildSettingsConfigST::Get()->SetCompiler(cmp);
    return true;
}

bool BuildSettingsDialog::DeleteCompiler(const wxString& name)
{
    if(wxMessageBox(_("Remove Compiler?"), _("Confirm"), wxYES_NO | wxICON_QUESTION) == wxYES) {
        BuildSettingsConfigST::Get()->DeleteCompiler(name);
        return true;
    }
    return false;
}

void BuildSettingsDialog::OnContextMenu(wxContextMenuEvent& e)
{
    //    // only compilers have children
}

#define ID_MENU_AUTO_DETECT_COMPILERS 1001
#define ID_MENU_ADD_COMPILER_BY_PATH 1002
#define ID_MENU_CLONE_COMPILER 1003

void BuildSettingsDialog::OnAutoDetectCompilers(wxButton* btn)
{
    // Launch the auto detect compilers code

    wxMenu menu;
    menu.Append(ID_MENU_ADD_COMPILER_BY_PATH, _("Add an existing compiler"));
    menu.Append(ID_MENU_CLONE_COMPILER, _("Clone a compiler"));
    menu.AppendSeparator();
    menu.Append(ID_MENU_AUTO_DETECT_COMPILERS, _("Scan computer for installed compilers"));

    // Menu will be shown in client coordinates
    wxRect size = btn->GetSize();
    wxPoint menuPos(0, size.GetHeight());

    int res = btn->GetPopupMenuSelectionFromUser(menu, menuPos);
    if(res == ID_MENU_AUTO_DETECT_COMPILERS) {
        if(m_compilersDetector.Locate()) {
            CallAfter(&BuildSettingsDialog::OnCompilersDetected, m_compilersDetector.GetCompilersFound());
        }

    } else if(res == ID_MENU_CLONE_COMPILER) {
        CallAfter(&BuildSettingsDialog::OnButtonNewClicked);

    } else if(res == ID_MENU_ADD_COMPILER_BY_PATH) {
        CallAfter(&BuildSettingsDialog::OnAddExistingCompiler);
    }
}

void BuildSettingsDialog::OnCompilersDetected(const ICompilerLocator::CompilerVec_t& compilers)
{
    CompilersFoundDlg dlg(this, compilers);
    if(dlg.ShowModal() == wxID_OK) {
        ICompilerLocator::CompilerVec_t selected_compilers;
        if(dlg.GetSelectedCompilers(selected_compilers) == 0) {
            return;
        }

        auto conf = BuildSettingsConfigST::Get();
        conf->BeginBatch();
        for(auto compiler : selected_compilers) {
            if(conf->IsCompilerExist(compiler->GetName())) {
                conf->DeleteCompiler(compiler->GetName());
            }
            conf->SetCompiler(compiler);
        }
        conf->Flush();

        // update the code completion search paths
        clMainFrame::Get()->CallAfter(&clMainFrame::UpdateParserSearchPathsFromDefaultCompiler);

        // update the compilers view
        LoadCompilers();
    }
}

void BuildSettingsDialog::OnApply(wxCommandEvent& event)
{
    // save the build page
    BuildSettingsConfigST::Get()->BeginBatch();
    m_compilersPage->Save();
    m_buildPage->Save();
    m_buildSettings->Save();
    // mark all the projects as dirty
    wxArrayString projects;
    clCxxWorkspaceST::Get()->GetProjectList(projects);
    for(size_t i = 0; i < projects.size(); i++) {
        ProjectPtr proj = ManagerST::Get()->GetProject(projects.Item(i));
        if(proj) {
            proj->SetModified(true);
        }
    }
    // Now do the actual save
    BuildSettingsConfigST::Get()->Flush();
}

void BuildSettingsDialog::OnApplyUI(wxUpdateUIEvent& event)
{
    event.Enable(m_compilersPage->IsDirty() || m_buildSettings->IsModified());
}

void BuildSettingsDialog::OnAddExistingCompiler()
{
    wxString folder = ::wxDirSelector(_("Select the compiler folder"));
    if(folder.IsEmpty()) {
        return;
    }

    CompilerPtr cmp = m_compilersDetector.Locate(folder);
    if(cmp) {
        // We found new compiler
        // Prompt the user to give it a name

        // Save the new compiler
        BuildSettingsConfigST::Get()->SetCompiler(cmp);

        // Reload the dialog
        LoadCompilers();
    }
}

void BuildSettingsDialog::OnScanAndSuggestCompilers()
{
    if(m_compilersDetector.Locate()) {
        CallAfter(&BuildSettingsDialog::OnCompilersDetected, m_compilersDetector.GetCompilersFound());
    }
}