#include "stdafx.h"

#include "CEditAnyChars.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

namespace ALX1153
{

	CEditAnyChars::CEditAnyChars()
	{
		ChooseCharsSet(e_CharsOfAny);
	}

	void CEditAnyChars::ChooseCharsSet(ee_chars ch,BYTE* pAddSpec,DWORD dwdAddArrayLen,BYTE* pDelSpec,DWORD dwdDelArrayLen)
	{
		switch(ch)
		{
			case e_CharsOfAddSpec:
			{
				if(pAddSpec && dwdAddArrayLen)
				{
					for(DWORD dwd=0;dwd<dwdAddArrayLen;dwd++)
					{
						m_LettersToAllow.set(pAddSpec[dwd]);
					}
				}
			}
			break;

			case e_CharsOfDelSpec:
			{
				if(pDelSpec && dwdDelArrayLen)
				{
					for(DWORD dwd=0;dwd<dwdDelArrayLen;dwd++)
					{
						m_LettersToAllow.reset(pDelSpec[dwd]);
					}
				}
			}
			break;

			case e_CharsOfAny:
			{
				m_LettersToAllow.set();
			}
			break;

			case e_CharsOfNothing:
			{
				m_LettersToAllow.reset();
			}
			break;

			case e_CharsOfHex:
			{
				m_LettersToAllow.reset();
				m_LettersToAllow.set('0');
				m_LettersToAllow.set('1');
				m_LettersToAllow.set('2');
				m_LettersToAllow.set('3');
				m_LettersToAllow.set('4');
				m_LettersToAllow.set('5');
				m_LettersToAllow.set('6');
				m_LettersToAllow.set('7');
				m_LettersToAllow.set('8');
				m_LettersToAllow.set('9');
				m_LettersToAllow.set('a');
				m_LettersToAllow.set('b');
				m_LettersToAllow.set('c');
				m_LettersToAllow.set('d');
				m_LettersToAllow.set('e');
				m_LettersToAllow.set('f');
				m_LettersToAllow.set('A');
				m_LettersToAllow.set('B');
				m_LettersToAllow.set('C');
				m_LettersToAllow.set('D');
				m_LettersToAllow.set('E');
				m_LettersToAllow.set('F');
			}
			break;

			case e_CharsOfDec:
			{
				m_LettersToAllow.reset();
				m_LettersToAllow.set('0');
				m_LettersToAllow.set('1');
				m_LettersToAllow.set('2');
				m_LettersToAllow.set('3');
				m_LettersToAllow.set('4');
				m_LettersToAllow.set('5');
				m_LettersToAllow.set('6');
				m_LettersToAllow.set('7');
				m_LettersToAllow.set('8');
				m_LettersToAllow.set('9');
			}
			break;
		}

		m_LettersToAllow.set(VK_BACK);
		m_LastChoosen=ch;

	}

	bool CEditAnyChars::TestSymbolAndCorrectIfNeed(WPARAM* pWP)
	{
		return TestSymbolAndCorrectIfNeed((BYTE*)pWP);
	}

	bool CEditAnyChars::TestSymbolAndCorrectIfNeed(BYTE* pCH)
	{
		if(!m_LettersToAllow.test(*pCH))return false;

		switch(m_LastChoosen)
		{
			case e_CharsOfHex:
			{
				switch(*pCH)
				{
					case 'a':*pCH='A';break;
					case 'b':*pCH='B';break;
					case 'c':*pCH='C';break;
					case 'd':*pCH='D';break;
					case 'e':*pCH='E';break;
					case 'f':*pCH='F';break;
				}
			}
			break;

			case e_CharsOfDec:
			{
			}
			break;

		}

		return true;
	}

	//перевод строки "XX" в BYTE
	unsigned __int64 CEditAnyChars::atoQWORD(const char* pText)
	{
		unsigned __int64 res=0;
		const char* pBeg=pText;
		const char* pEnd=pBeg+min( sizeof(res)*2,::strlen(pText) );
		for(const char* p=pEnd-1;p>=pBeg && p<pEnd;p--)
		{
			res<<=4;
			switch(*p)
			{
				case '0':res|=0x0;break;
				case '1':res|=0x1;break;
				case '2':res|=0x2;break;
				case '3':res|=0x3;break;
				case '4':res|=0x4;break;
				case '5':res|=0x5;break;
				case '6':res|=0x6;break;
				case '7':res|=0x7;break;
				case '8':res|=0x8;break;
				case '9':res|=0x9;break;
				case 'a':
				case 'A':res|=0xa;break;
				case 'b':
				case 'B':res|=0xb;break;
				case 'c':
				case 'C':res|=0xc;break;
				case 'd':
				case 'D':res|=0xd;break;
				case 'e':
				case 'E':res|=0xe;break;
				case 'f':
				case 'F':res|=0xf;break;
			}
		}

		return res;
	}

	unsigned __int64 CEditAnyChars::GetTextLikeDecValue_nosign()
	{
		CString txt;
		GetWindowText(txt);
		return _atoi64(txt);
	}

	unsigned __int64 CEditAnyChars::GetTextLikeHexValue()
	{
		CString txt;
		GetWindowText(txt);
		return atoQWORD(txt);
	}

	LRESULT CEditAnyChars::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
	{
		switch(message)
		{

	//		WM_SYSDEADCHAR
	//		WM_UNICHAR
	//		WM_DEADCHAR

			case WM_CHAR:
			{
				if(!TestSymbolAndCorrectIfNeed(&wParam))return 0;
			}
			break;

			case WM_PASTE:
			{
				if(::OpenClipboard(0))
				{
					if(::IsClipboardFormatAvailable(CF_TEXT))
					{

						HANDLE h=::GetClipboardData(CF_TEXT);
						if(h)
						{
							const BYTE* pch=(const BYTE*)::GlobalLock(h);
							DWORD dwdSize=::GlobalSize(h);
							if(pch)
							{
								try
								{
									if(dwdSize && pch[dwdSize-1]==0)
									{
										std::vector<BYTE> ToInsert;

										for(DWORD dwd=0;dwd<dwdSize && pch[dwd]!=0;dwd++)
										{
											BYTE CH=pch[dwd];
											if(TestSymbolAndCorrectIfNeed(&CH))
											{
												ToInsert.push_back(CH);
											}
										}

										ToInsert.push_back(0);
										ReplaceSel((char*)&ToInsert[0],1);
									}
								}
								catch(...)
								{
								}

								::GlobalUnlock(h);
							}
						}

					}
					::CloseClipboard();
				}

				return 0;
			}
			break;

		}

		return CEdit::WindowProc(message, wParam, lParam);
	}
}