GCodeLine GCodeInterpreter::AssignGFuncParams(map<char, vector<float>>& data, GFunction& fun, size_t line)
{
	GCodeLine func;
	func.function = fun;
	func.line = line;
	FunctionArguments args = functionPrototypes[fun];
	if(args.size() == 0)
	{
		//Function with no parameters
		if(fun.second == -1)
			func.data[fun.first] = data[fun.first][0];
		else
			func.data[fun.first] = fun.second;
		return func;
	}
	auto iterator = find_if(args.begin(), args.end(), [&] (vector<char>& a)->bool
	{
		return MatchesArgumentList(a, data);//there are no arguments
	});
	if(iterator == args.end())//Match didn't found, use  previous arguments
		iterator = find_if(args.begin(), args.end(), [&] (vector<char>& a)->bool
		{
			return MatchesArgumentListWithOldVariables(a, data);
		});
	if(iterator == args.end())
		throw exception("Funkci nebyly pøedány správné argumenty");
	//Copy arguments
	if(fun.second == -1)
		func.data[fun.first] = data[fun.first][0];
	else
		func.data[fun.first] = fun.second;
	for_each(iterator->begin(), iterator->end(), [&](char c)
	{
		auto argIter = data.find(c);
		if(argIter != data.end())
		{
			if(argIter->second.size() > 1)
				throw exception("Vícenásobný argument");
			func.data[c] = data[c][0];
			return;
		}
		auto argIter2 = lastValue.find(c);
		if(argIter2 != lastValue.end())
		{
			if(coordType == INC && IsAxis(c))
			{
				func.data[c] = 0;
			}
			else
				func.data[c] = lastValue[c];
			return;
		}
		throw exception("Nebyly pøedány všechny argumenty");
	});
	return func;
}
void ScreenMapControllers::Input( const DeviceInput& DeviceI, const InputEventType type, const GameInput &GameI, const MenuInput &MenuI, const StyleInput &StyleI )
{
	if( type != IET_FIRST_PRESS && type != IET_SLOW_REPEAT )
		return;	// ignore

	LOG->Trace( "ScreenMapControllers::Input():  device: %d, button: %d", 
		DeviceI.device, DeviceI.button );

	int button = DeviceI.button;

#ifdef _XBOX
	if(!m_iWaitingForPress && DeviceI.device == DEVICE_JOY1)
	{
		// map the xbox controller buttons to the keyboard equivalents
		if(DeviceI.button == JOY_HAT_LEFT)
			button = KEY_LEFT;
		else if(DeviceI.button == JOY_HAT_RIGHT)
			button = KEY_RIGHT;
		else if(DeviceI.button == JOY_HAT_UP)
			button = KEY_UP;
		else if(DeviceI.button == JOY_HAT_DOWN)
			button = KEY_DOWN;
		else if(DeviceI.button == JOY_AUX_1)
			button = KEY_ENTER;
		else if(DeviceI.button == JOY_AUX_2)
			button = KEY_ESC;
		else if(DeviceI.button == JOY_1 || DeviceI.button == JOY_2 ||
				DeviceI.button == JOY_3 || DeviceI.button == JOY_4)
			button = KEY_DEL;
	}
#endif

	//
	// TRICKY:  Some adapters map the PlayStation digital d-pad to both axes and
	// buttons.  We want buttons to be used for any mappings where possible because
	// presses of buttons aren't mutually exclusive and presses of axes are (e.g.
	// can't read presses of both Left and Right simultaneously).  So, when the user
	// presses a button, we'll wait until the next Update before adding a mapping so
	// that we get a chance to see all input events the user's press of a panel.
	// Prefer non-axis events over axis events. 
	//
	if( m_iWaitingForPress )
	{
		/* Don't allow function keys to be mapped. */
		if ( DeviceI.device == DEVICE_KEYBOARD && (DeviceI.button >= KEY_F1 && DeviceI.button <= KEY_F12) )
		{
			m_textError.SetText( "That key can not be mapped." );
			SCREENMAN->PlayInvalidSound();
			m_textError.StopTweening();
			m_textError.SetDiffuse( RageColor(0,1,0,1) );
			m_textError.BeginTweening( 3 );
			m_textError.BeginTweening( 1 );
			m_textError.SetDiffuse( RageColor(0,1,0,0) );
		}
		else
		{
			if( m_DeviceIToMap.IsValid() &&
				!IsAxis(m_DeviceIToMap) &&
				IsAxis(DeviceI) )
			{
				LOG->Trace("Ignored input; non-axis event already received");
				return;	// ignore this press
			}

			m_DeviceIToMap = DeviceI;
		}
	}
#ifdef _XBOX
	else if( DeviceI.device == DEVICE_JOY1 )
#else
	else if( DeviceI.device == DEVICE_KEYBOARD )
#endif
	{
		switch( button )
		{
		/* We only advertise space as doing this, but most games
		 * use either backspace or delete, and I find them more
		 * intuitive, so allow them, too. -gm */

		/* XXX: For some reason that eludes me, this function gets sent an
		 * KEY_SPACE button press every time the JOY_HAT_UP button is pressed.
		 * Had to put this in to prevent mappings being erased everytime the user
		 * pressed up on the joypad. */

		case KEY_DEL:
#ifndef _XBOX
		case KEY_SPACE:
		case KEY_BACK: /* Clear the selected input mapping. */
#endif
			{
				GameInput curGameI( (GameController)m_iCurController, (GameButton)m_iCurButton );
				INPUTMAPPER->ClearFromInputMap( curGameI, m_iCurSlot );
				INPUTMAPPER->AddDefaultMappingsForCurrentGameIfUnmapped();
		
				// commit to disk after each change
				INPUTMAPPER->SaveMappingsToDisk();
			}
			break;
		case KEY_LEFT: /* Move the selection left, wrapping up. */
			if( m_iCurSlot == 0 && m_iCurController == 0 )
				break;	// can't go left any more
			m_iCurSlot--;
			if( m_iCurSlot < 0 )
			{
				m_iCurSlot = NUM_CHANGABLE_SLOTS-1;
				m_iCurController--;
			}

			break;
		case KEY_RIGHT:	/* Move the selection right, wrapping down. */
			if( m_iCurSlot == NUM_CHANGABLE_SLOTS-1 && m_iCurController == MAX_GAME_CONTROLLERS-1 )
				break;	// can't go right any more
			m_iCurSlot++;
			if( m_iCurSlot > NUM_CHANGABLE_SLOTS-1 )
			{
				m_iCurSlot = 0;
				m_iCurController++;
			}
			break;
		case KEY_UP: /* Move the selection up. */
			if( m_iCurButton == 0 )
				break;	// can't go up any more
			m_iCurButton--;
			break;
		case KEY_DOWN: /* Move the selection down. */
			if( m_iCurButton == GAMESTATE->GetCurrentGame()->m_iButtonsPerController-1 )
				break;	// can't go down any more
			m_iCurButton++;
			break;
		case KEY_ESC: /* Quit the screen. */
			if( !IsTransitioning() )
			{
				SCREENMAN->PlayStartSound();

				INPUTMAPPER->SaveMappingsToDisk();	// save changes

				StartTransitioning( SM_GoToNextScreen );		
				for( int b=0; b<GAMESTATE->GetCurrentGame()->m_iButtonsPerController; b++ )
					m_Line[b].RunCommands( (b%2)? ODD_LINE_OUT:EVEN_LINE_OUT );
			}
			break;
		case KEY_ENTER: /* Change the selection. */
		case KEY_KP_ENTER:
			m_iWaitingForPress = FramesToWaitForInput;
			m_DeviceIToMap.MakeInvalid();
			break;
		}
	}

//	Screen::Input( DeviceI, type, GameI, MenuI, StyleI );	// default handler

	LOG->Trace( "m_iCurSlot: %d m_iCurController: %d m_iCurButton: %d", m_iCurSlot, m_iCurController, m_iCurButton );

	Refresh();
}