/*	Renegade Scripts.dll
	Keys.cfg editor
	Copyright 2006 Jonathan Wilson

	This file is part of the Renegade scripts.dll
	The Renegade scripts.dll is free software; you can redistribute it and/or modify it under
	the terms of the GNU General Public License as published by the Free
	Software Foundation; either version 2, or (at your option) any later
	version. See the file COPYING for more details.
	In addition, an exemption is given to allow Run Time Dynamic Linking of this code with any closed source module that does not contain code covered by this licence.
	Only the source code to the module(s) containing the licenced code has to be released.
*/
#if (_MSC_VER >= 1400)
#define _CRT_SECURE_NO_DEPRECATE 1
#define _CRT_NONSTDC_NO_DEPRECATE 1
#endif
#include <windows.h>
#include <stdio.h>
#include "resource.h"
template <class T> class SimpleVecClass {
protected:
	T *Vector;
	int VectorMax;
public:
	SimpleVecClass(unsigned int size)
	{
		Vector = 0;
		VectorMax = 0;
		if (size > 0)
		{
			Resize(size);
		}
	}
	virtual bool Uninitialised_Grow(int newsize)
	{
		if ((newsize > 0) && (newsize > VectorMax))
		{
			delete Vector;
			T *vec = new T[newsize*4];
			Vector = vec;
			VectorMax = newsize;
		}
		return true;
	}
	SimpleVecClass(const SimpleVecClass<T> &cl)
	{
		Uninitialised_Grow(cl.VectorMax);
		memcpy(Vector,cl.Vector,VectorMax);
	}
	int Length()
	{
		return VectorMax;
	}
	T &operator[](int index)
	{
		return Vector[index];
	}
	virtual ~SimpleVecClass()
	{
		if (Vector)
		{
			delete Vector;
			Vector = 0;
		}
	}
	virtual bool Resize(int newsize)
	{
		T *vec;
		if (VectorMax == newsize)
		{
			return true;
		}
		if (newsize > 0)
		{
			vec = new T[newsize*4];
			if (Vector)
			{
				int count;
				count = VectorMax;
				if (newsize < count)
				{
					count = newsize;
				}
				memcpy(vec,Vector,count*4);
				delete Vector;
				Vector = 0;
			}
			Vector = vec;
			VectorMax = newsize;
		}
		else
		{
			VectorMax = 0;
			if (Vector)
			{
				delete Vector;
				Vector = 0;
			}
		}
		return true;
	}
};
template <class T> class SimpleDynVecClass : public SimpleVecClass<T> {
protected:
	int ActiveCount;
public:
	SimpleDynVecClass(int size) : SimpleVecClass<T>(size)
	{
		ActiveCount = 0;
	}
	SimpleDynVecClass(const SimpleDynVecClass<T> &cl) : SimpleVecClass<T>(cl)
	{
		ActiveCount = cl.ActiveCount;
	}
	int Count()
	{
		return ActiveCount;
	}
	virtual ~SimpleDynVecClass()
	{
		if (Vector)
		{
			delete Vector;
			Vector = 0;
		}
	}
	virtual bool Resize(int newsize)
	{
		if (SimpleVecClass<T>::Resize(newsize))
		{
			if (VectorMax < ActiveCount)
			{
				ActiveCount = VectorMax;
			}
			return true;
		}
		return false;
	}
	int Add(T& data)
	{
		for (int i = 0;i < VectorMax;i++)
		{
			if (!Vector[i])
			{
				Vector[i] = data;
				ActiveCount++;
				return i;
			}
		}
		Resize(VectorMax+1);
		Vector[VectorMax-1] = data;
		ActiveCount++;
		return VectorMax-1;
	}
	void Delete(int position)
	{
		Vector[position] = 0;
		ActiveCount--;
	}
};
struct Key {
	char *LogicalKeyName;
	int KeyNumber;
};
SimpleDynVecClass<Key *> KeyList = SimpleDynVecClass<Key *>(0);
struct keynames {
	const char *translatedkeyname;
	const char *keyname;
};
const keynames keynamearr[111] = {
{"None","None_Key"},
{"F1","F1_Key"},
{"F2","F2_Key"},
{"F3","F3_Key"},
{"F4","F4_Key"},
{"F5","F5_Key"},
{"F6","F6_Key"},
{"F7","F7_Key"},
{"F8","F8_Key"},
{"F9","F9_Key"},
{"F10","F10_Key"},
{"F11","F11_Key"},
{"F12","F12_Key"},
{"0","0_Key"},
{"1","1_Key"},
{"2","2_Key"},
{"3","3_Key"},
{"4","4_Key"},
{"5","5_Key"},
{"6","6_Key"},
{"7","7_Key"},
{"8","8_Key"},
{"9","9_Key"},
{"A","A_Key"},
{"B","B_Key"},
{"C","C_Key"},
{"D","D_Key"},
{"E","E_Key"},
{"F","F_Key"},
{"G","G_Key"},
{"H","H_Key"},
{"I","I_Key"},
{"J","J_Key"},
{"K","K_Key"},
{"L","L_Key"},
{"M","M_Key"},
{"N","N_Key"},
{"O","O_Key"},
{"P","P_Key"},
{"Q","Q_Key"},
{"R","R_Key"},
{"S","S_Key"},
{"T","T_Key"},
{"U","U_Key"},
{"V","V_Key"},
{"W","W_Key"},
{"X","X_Key"},
{"Y","Y_Key"},
{"Z","Z_Key"},
{"MINUS","Minus_Key"},
{"EQUALS","Equals_Key"},
{"BACK","Backspace_Key"},
{"TAB","Tab_Key"},
{"LBRACKET","Left_Bracket_Key"},
{"RBRACKET","Right_Bracket_Key"},
{"RETURN","Enter_Key"},
{"SEMICOLON","Semicolon_Key"},
{"'","Apostrophe_Key"},
{"GRAVE/~","Grave_Key"},
{"BACKSLASH","Backslash_Key"},
{"COMMA","Comma_Key"},
{"PERIOD","Period_Key"},
{"SLASH","Slash_Key"},
{"SPACE","Space_Bar_Key"},
{"CAPS LOCK","Caps_Lock_Key"},
{"NUM LOCK","Num_Lock_Key"},
{"SCROLL LOCK","Scroll_Lock_Key"},
{"ESCAPE","Escape_Key"},
{"NUMPAD0","Keypad_0_Key"},
{"NUMPAD1","Keypad_1_Key"},
{"NUMPAD2","Keypad_2_Key"},
{"NUMPAD3","Keypad_3_Key"},
{"NUMPAD4","Keypad_4_Key"},
{"NUMPAD5","Keypad_5_Key"},
{"NUMPAD6","Keypad_6_Key"},
{"NUMPAD7","Keypad_7_Key"},
{"NUMPAD8","Keypad_8_Key"},
{"NUMPAD9","Keypad_9_Key"},
{"NUMPAD MINUS","Keypad_Minus_Key"},
{"NUMPAD MULTIPLY","Keypad_Star_Key"},
{"NUMPAD PLUS","Keypad_Plus_Key"},
{"NUMPAD DECIMAL","Keypad_Period_Key"},
{"NUMPAD ENTER","Keypad_Enter_Key"},
{"NUMPAD DIVIDE","Keypad_Slash_Key"},
{"HOME","Home_Key"},
{"PAGE UP","Page_Up_Key"},
{"END","End_Key"},
{"PAGE DOWN","Page_Down_Key"},
{"INSERT","Insert_Key"},
{"DELETE","Delete_Key"},
{"ARROW UP","Up_Key"},
{"ARROW DOWN","Down_Key"},
{"ARROW LEFT","Left_Key"},
{"ARROW RIGHT","Right_Key"},
{"SYSRQ","Sys_Req_Key"},
{"CONTROL","Control_Key"},
{"LEFT CONTROL","Left_Control_Key"},
{"RIGHT CONTROL","Right_Control_Key"},
{"SHIFT","Shift_Key"},
{"LEFT SHIFT","Left_Shift_Key"},
{"RIGHT SHIFT","Right_Shift_Key"},
{"ALT","Alt_Key"},
{"LEFT ALT","Left_Alt_Key"},
{"RIGHT ALT","Right_Alt_Key"},
{"WIN","Windows_Key"},
{"LEFT WIN","Left_Windows_Key"},
{"RIGHT WIN","Right_Windows_Key"},
{"APPS","App_Menu_Key"},
{"MOUSE LEFT BUTTON","Left_Mouse_Button"},
{"MOUSE RIGHT BUTTON","Right_Mouse_Button"},
{"MOUSE CENTER BUTTON","Center_Mouse_Button"}};
int getkey(const char *key)
{
	for (int i = 0;i < 110; i++)
	{
		if (!stricmp(key,keynamearr[i].keyname))
		{
			return i;
		}
	}
	return -1;
}
BOOL CALLBACK DlgProc(HWND hwnd,UINT Message,WPARAM wParam,LPARAM lParam)
{
	switch(Message)
	{
		case WM_INITDIALOG:
			{
				SendMessage(hwnd,WM_SETICON,ICON_SMALL,(LPARAM)LoadImage(GetModuleHandle(NULL),MAKEINTRESOURCE(IDI_APP),IMAGE_ICON,32,32,LR_DEFAULTCOLOR));
				SendMessage(hwnd,WM_SETICON,ICON_BIG,(LPARAM)LoadImage(GetModuleHandle(NULL),MAKEINTRESOURCE(IDI_APP),IMAGE_ICON,32,32,LR_DEFAULTCOLOR));
				for (int i = 0;i < 110; i++)
				{
					SendDlgItemMessage(hwnd,IDC_PHYSICAL,LB_ADDSTRING,0,(LPARAM)keynamearr[i].translatedkeyname);
				}
				SendDlgItemMessage(hwnd,IDC_PHYSICAL,LB_SETCURSEL,(WPARAM)0,(LPARAM)0);
				FILE *f = fopen("data\\keys.cfg","rt");
				if (f)
				{
					char data[100];
					while (fgets(data,100,f))
					{
						Key *k = new Key;
						char *a = strtok(data,"=");
						char *b = strtok(NULL,"=");
						k->LogicalKeyName = strdup(a);
						b[strlen(b)-1] = 0;
						k->KeyNumber = getkey(b);
						KeyList.Add(k);
						SendDlgItemMessage(hwnd,IDC_LOGICAL,LB_ADDSTRING,0,(LPARAM)k->LogicalKeyName);
					}
					fclose(f);
					SendDlgItemMessage(hwnd,IDC_LOGICAL,LB_SETCURSEL,(WPARAM)0,(LPARAM)0);
					int pos = KeyList[0]->KeyNumber;
					SendDlgItemMessage(hwnd,IDC_PHYSICAL,LB_SETCURSEL,pos,0);
				}
				break;
			}
		case WM_CLOSE:
			EndDialog(hwnd,0);
		break;
		case WM_COMMAND:
			switch(LOWORD(wParam))
			{
				case IDC_LOGICAL:
					switch(HIWORD(wParam))
					{
						case LBN_SELCHANGE:
						{
							int index = SendDlgItemMessage(hwnd,IDC_LOGICAL,LB_GETCURSEL,(WPARAM)0,(LPARAM)0);
							int pos = KeyList[index]->KeyNumber;
							SendDlgItemMessage(hwnd,IDC_PHYSICAL,LB_SETCURSEL,pos,0);
						}
					}
				break;
				case IDC_PHYSICAL:
					switch(HIWORD(wParam))
					{
						case LBN_SELCHANGE:
						{
							int index = SendDlgItemMessage(hwnd,IDC_LOGICAL,LB_GETCURSEL,(WPARAM)0,(LPARAM)0);
							if (index != -1)
							{
								int num = SendDlgItemMessage(hwnd,IDC_PHYSICAL,LB_GETCURSEL,(WPARAM)0,(LPARAM)0);
								KeyList[index]->KeyNumber = num;
							}
						}
					}
				break;
				case IDC_ADD:
					switch(HIWORD(wParam))
					{
						case BN_CLICKED:
						{
							int len = SendDlgItemMessage(hwnd,IDC_NEWKEY,WM_GETTEXTLENGTH,0,0);
							char *a = new char[len+1];
							SendDlgItemMessage(hwnd,IDC_NEWKEY,WM_GETTEXT,(WPARAM)len+1,(LPARAM)a);
							Key *k = new Key;
							k->LogicalKeyName = strdup(a);
							k->KeyNumber = 0;
							KeyList.Add(k);
							int index = SendDlgItemMessage(hwnd,IDC_LOGICAL,LB_ADDSTRING,0,(LPARAM)k->LogicalKeyName);
							SendDlgItemMessage(hwnd,IDC_LOGICAL,LB_SETCURSEL,(WPARAM)index,(LPARAM)0);
							SendDlgItemMessage(hwnd,IDC_PHYSICAL,LB_SETCURSEL,(WPARAM)0,(LPARAM)0);
						}
					}
				break;
				case IDC_QUIT:
					switch(HIWORD(wParam))
					{
						case BN_CLICKED:
						{
							EndDialog(hwnd,0);
						}
					}
				break;
				case IDC_SAVE:
					switch(HIWORD(wParam))
					{
						case BN_CLICKED:
						{
							FILE *f = fopen("data\\keys.cfg","wt");
							if (f)
							{
								int x = KeyList.Count();
								for (int i = 0;i < x;i++)
								{
									fprintf(f,"%s=%s\n",KeyList[i]->LogicalKeyName,keynamearr[KeyList[i]->KeyNumber].keyname);
								}
								fclose(f);
							}
							else
							{
								MessageBox(hwnd,"Cannot save keys.cfg, make sure keycfg.exe is in your renegade folder","Error",MB_OK);
							}
							EndDialog(hwnd,0);
						}
					}
				break;
			}
		default:
			return FALSE;
	}
	return TRUE;
}

int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,
	LPSTR lpCmdLine,int nCmdShow)
{
	return DialogBox(hInstance,MAKEINTRESOURCE(IDD_MAIN),NULL,DlgProc);
}
