#include "global.h"
#include "cdatalogwin.h"
#include "cdatalog.h"
#include <stdlib.h>
#include <richedit.h>
#include <commdlg.h>

void CDatalogWindow::ShowWindow(bool show)
{
	::ShowWindow(hwnd, show ? SW_SHOW : SW_HIDE);
}

void CDatalogWindow::NewFile()
{
	if (contentChanged)
	{
		int res = MessageBox(app.mainWindow->GetHandle(), "Chcete uložiť aktuálny program?", "Nový program",
			MB_ICONQUESTION|MB_YESNOCANCEL);
		switch (res)
		{
		case IDYES:
			if (!SaveToFile())//podarilo sa ulozit?
				return;
			break;
		case IDCANCEL:
			return;
		}
	}

	::ZeroMemory(fileName, 1024);
	fileNameOfs = 0;
	::SetWindowText(hwnd, "");//vymaz obsah
	::SetWindowText(app.mainWindow->GetHandle(), "InLog");
	contentChanged = false;
}


void CDatalogWindow::LoadFromFile()
{
	if (contentChanged)
	{
		int res = MessageBox(app.mainWindow->GetHandle(), "Chcete uložiť aktuálny program?", "Otvoriť nový program",
			MB_ICONQUESTION|MB_YESNOCANCEL);
		switch (res)
		{
		case IDYES:
			if (!SaveToFile())//podarilo sa ulozit?
				return;
			break;
		case IDCANCEL:
			return;
		}
	}

	OPENFILENAME ofn;
	::ZeroMemory(&ofn, sizeof(ofn));
	ofn.lStructSize = sizeof(ofn);
	ofn.hwndOwner = app.mainWindow->GetHandle();
	ofn.lpstrFilter = "Textové súbory\0*.txt\0\0";
	ofn.lpstrCustomFilter = NULL;
	ofn.nFilterIndex = 1;
	ofn.lpstrFile = fileName;
	ofn.nMaxFile = 1023;
	ofn.lpstrFileTitle = NULL;
	ofn.lpstrInitialDir = NULL;
	ofn.lpstrTitle = NULL;
	ofn.Flags = OFN_FILEMUSTEXIST;
	ofn.lpstrDefExt = "txt";
	if (::GetOpenFileName(&ofn))
	{
		HANDLE h = ::CreateFile(fileName, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, 0);
		if (h == INVALID_HANDLE_VALUE)
		{
			char *tmp = CMemory::printstr("Súbor %s sa nepodarilo otvoriť!", &fileName[ofn.nFileOffset]);
			::MessageBox(app.mainWindow->GetHandle(), tmp, "Pozor!", MB_ICONWARNING|MB_OK); _DELETE(tmp);
			return;
		}
		//alokuj potrebnu pamat
		DWORD len = ::GetFileSize(h, NULL);
		char *data = (char*)::mallocx(len+1);

		//nacitaj data zo suboru
		DWORD i;
		::ReadFile(h, data, len, &i, 0);
		::CloseHandle(h);

		if (i!=len)
		{
			char *tmp = CMemory::printstr("Súbor %s sa nepodarilo načítať!", &fileName[ofn.nFileOffset]);
			::MessageBox(app.mainWindow->GetHandle(), tmp, "Pozor!", MB_ICONWARNING|MB_OK); _DELETE(tmp);
		}
		//nastav text do editora
		stopNotify = true;
		data[i] = 0;
		::SetWindowText(hwnd, data);
		::freex(data);
		stopNotify = false;
		//ofarbi
		ColorizeIDBAtoms();

		fileNameOfs = ofn.nFileOffset;
		char *tmp = CMemory::printstr("InLog [%s]", &fileName[ofn.nFileOffset]);
		::SetWindowText(app.mainWindow->GetHandle(), tmp); _DELETE(tmp);

		contentChanged = false;
	}

//#endif

}

DWORD CDatalogWindow::GetNumOfLines()
{
	return ::SendMessage(hwnd, EM_GETLINECOUNT, 0, 0);
}

void CDatalogWindow::SaveToFileAs()
{
	char *oldName = _NEW(char[1024]); ::CopyMemory(oldName, fileName, strlen(fileName)+1);
	::ZeroMemory(fileName, 1024);//vymazeme aktualny nazov, takze SaveToFile si bude mysliet, ze chceme ulozit este neulozeny
	//subor a preto nam ponukne vybratie nazvu
	if (!SaveToFile())
	{
		//ak sa neulozil, vratime sa k povodnemu nazvu
		::CopyMemory(fileName, oldName, strlen(oldName)+1);
	}
	_DELETE(oldName);
}

bool CDatalogWindow::SaveToFile()
{
	bool emptyFile = false;

	DWORD fnOfs = fileNameOfs;
	char *fn = fileName;

	if (!fileName[0])
	{
		emptyFile = true;
		fn = _NEW(char[1024]); ::ZeroMemory(fn, 1024);
		//este nie je vybraty ziaden subor
		OPENFILENAME ofn;
		::ZeroMemory(&ofn, sizeof(ofn));
		ofn.lStructSize = sizeof(ofn);
		ofn.hwndOwner = app.mainWindow->GetHandle();
		ofn.lpstrFilter = "Textové súbory\0*.txt\0\0";
		ofn.lpstrCustomFilter = NULL;
		ofn.nFilterIndex = 1;
		ofn.lpstrFile = fn;
		ofn.nMaxFile = 1023;
		ofn.lpstrFileTitle = NULL;
		ofn.lpstrInitialDir = NULL;
		ofn.lpstrTitle = NULL;
		ofn.Flags = OFN_PATHMUSTEXIST|OFN_OVERWRITEPROMPT;
		ofn.lpstrDefExt = "txt";
		if (::GetSaveFileName(&ofn))
		{
			fnOfs = ofn.nFileOffset;
		}
		else
		{
			_DELETE(fn);
			return false;
		}
	}

	HANDLE h = ::CreateFile(fn, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
	if (h == INVALID_HANDLE_VALUE)
	{
		char *tmp = CMemory::printstr("Súbor %s sa nepodarilo otvoriť pre zápis!", &fn[fnOfs]);
		::MessageBox(app.mainWindow->GetHandle(), tmp, "Pozor!", MB_ICONWARNING|MB_OK); _DELETE(tmp);

		if (emptyFile)
		{
			_DELETE(fn);
		}
		return false;
	}

	if (emptyFile)
	{
		::CopyMemory(fileName, fn, strlen(fn));
		fileNameOfs = fnOfs;
		_DELETE(fn);
	}

	//uloz data do suboru
	DWORD len;
	char *_data = (char*)ReadInput(&len);

	//nahrad 0x0d (13) za 0x0d 0x0a (enter v textovych suboroch)
	DWORD nLines = GetNumOfLines();
	char *data = _NEW(char[len+nLines]);//na kazdy 13 pocitaj este 0x0a

	DWORD j=0;
	for (DWORD i=0; i<len; i++)
	{
		data[j++] = _data[i];
		if (_data[i]==0x0d)
			data[j++] = 0x0a;
	}

	DWORD written;
	::WriteFile(h, data, j, &written, 0); _DELETE(data);
	::CloseHandle(h);
	freex(_data);

	if (written!=j)
	{
		char *tmp = CMemory::printstr("Dáta sa nepodarilo uložiť do súboru %s!", &fn[fnOfs]);
		::MessageBox(app.mainWindow->GetHandle(), tmp, "Pozor!", MB_ICONWARNING|MB_OK); _DELETE(tmp);
	}

	char *tmp = CMemory::printstr("InLog [%s]", &fileName[fileNameOfs]);
	::SetWindowText(app.mainWindow->GetHandle(), tmp); _DELETE(tmp);

	contentChanged = false;

	return true;
}
/*
bool CDatalogWindow::SaveToFileAs()
{
	DWORD len = strlen(fileName);
	TCHAR *oldFileName = _NEW(char[len+1]);
	::CopyMemory(oldFileName, fileName, len);

	OPENFILENAME ofn;
	::ZeroMemory(&ofn, sizeof(ofn));
	ofn.lStructSize = sizeof(ofn);
	ofn.hwndOwner = app.mainWindow->GetHandle();
	ofn.lpstrFilter = "Textové súbory\0*.txt\0\0";
	ofn.lpstrCustomFilter = NULL;
	ofn.nFilterIndex = 1;
	ofn.lpstrFile = fileName;
	ofn.nMaxFile = 1024;
	ofn.lpstrFileTitle = NULL;
	ofn.lpstrInitialDir = NULL;
	ofn.lpstrTitle = NULL;
	ofn.Flags = OFN_PATHMUSTEXIST|OFN_OVERWRITEPROMPT;
	ofn.lpstrDefExt = "txt";
	if (::GetSaveFileName(&ofn))
	{
		fileNameOfs = ofn.nFileOffset;
		return SaveToFile();
	}
	else
		return false;
}
*/
/*#ifdef _DEBUG
	char *name ="c:\\datalog";
	TEXTRANGE tr;
	tr.chrg.cpMin = 0;
	tr.chrg.cpMax = -1;//vsetko (cely obsah richedit)
	
	GETTEXTLENGTHEX gtle;
	gtle.codepage = 0;
	gtle.flags = GTL_DEFAULT;
	DWORD len = ::SendMessage(hwnd, EM_GETTEXTLENGTHEX, (WPARAM)&gtle, 0);//zisti dlzku textu

	tr.lpstrText = (char*)::mallocx(len+1);

	::SendMessage(hwnd, EM_GETTEXTRANGE, 0, (LPARAM)&tr);//zisti text

	DWORD i;
	HANDLE h = ::CreateFile(name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);//vytvor subor
	::WriteFile(h, tr.lpstrText, len, &i, 0);
	if (i != len)
	{
		//chyba
		//TODO
		//...
		//...
		//...
	}
	::CloseHandle(h);
	::freex(tr.lpstrText);
#endif
}
*/

DWORD CDatalogWindow::GetFontHeight(DWORD size)
{
	DWORD ret;
	HDC hdc = ::GetDC(NULL);
	ret = -::MulDiv(size, ::GetDeviceCaps(hdc, LOGPIXELSY), 72);
	::ReleaseDC(NULL, hdc);
	return ret;
}


void CDatalogWindow::RefreshFont()
{
	hFont = (HFONT)::CreateFont(GetFontHeight(app.options->editor.fontSize), 0, 0, 0, FW_DONTCARE, FALSE, FALSE, FALSE, ANSI_CHARSET, OUT_CHARACTER_PRECIS, CLIP_CHARACTER_PRECIS,
		DEFAULT_QUALITY, 0, app.options->editor.fontName);
	::SendMessage(hwnd, WM_SETFONT, (LPARAM)hFont, 0);
	::DeleteObject(hFont);
	//v debugu mame nejake vypisi, output este nemusi byt
	if (app.mainWindow->GetOutputWindow())
		ColorizeIDBAtoms();
}

CDatalogWindow::CDatalogWindow(HWND parent)
{
	idbAtoms = _NEW(CStringTable());

	::LoadLibrary("RICHED20.DLL");
	hwnd = ::CreateWindowEx(WS_EX_CLIENTEDGE, RICHEDIT_CLASS, NULL, WS_CHILD|ES_MULTILINE|WS_VSCROLL|WS_HSCROLL, 0, 0, 0, 0, parent, 0, app.hInstance, 0);

	RefreshFont();

	::SendMessage(hwnd, EM_SETEVENTMASK, 0, (LPARAM)ENM_SELCHANGE|ENM_DRAGDROPDONE|ENM_CHANGE);
	::SendMessage(hwnd, EM_SETUNDOLIMIT, 1,0);//kvoli sprostemu selektovaniu pri ofarbovani musime vypnut undo
			//ale ked sa vypne (0), tak nefunguje drag&drop, hadze chybu(???)
			//takze undo ponechame aspon 1 a odignorujeme to pri stlaceni ctrl+z

	RECT rc;
	::GetClientRect(parent,&rc);

	::SetWindowPos(hwnd, 0, 202, 0, rc.right-202, 300, 0);

	stopNotify = false;
	ctrlFlag = false;
	contentChanged = false;

	//asociuj okno s jeho instanciou
	::SetWindowLong(hwnd,GWL_USERDATA,(DWORD)this);
	oldWindowProc = (WNDPROC)::GetWindowLong(hwnd, GWL_WNDPROC);
	::SetWindowLong(hwnd, GWL_WNDPROC, (LONG)StaticWindowProc);

	fileName = _NEW(char[1024]);
	::ZeroMemory(fileName, 1024);

}

CDatalogWindow::~CDatalogWindow()
{
	_DELETE(idbAtoms);
	_DELETE(fileName);
	DestroyWindow(hwnd);
	::SetWindowText(app.mainWindow->GetHandle(), "InLog");
}

void CDatalogWindow::wmCOMMANDfromParent(WPARAM wp)
{
	if (stopNotify || contentChanged)
		return;

	if (HIWORD(wp) == EN_CHANGE)
	{
		//zmena obsahu okna
		contentChanged = true;
		char *tmp = _NEW(char[100]); ::ZeroMemory(tmp, 100);
		HWND h = app.mainWindow->GetHandle();
		::GetWindowText(h, tmp, 98);
		tmp[strlen(tmp)] = '*';
		::SetWindowText(h, tmp);
		_DELETE(tmp);
	}
}

void CDatalogWindow::wmNOTIFYfromParent(NMHDR*nmh)
{
	if (stopNotify)
		return;

	switch (nmh->code)
	{
	case EN_SELCHANGE:
		{
			DWORD min = ((SELCHANGE*)nmh)->chrg.cpMin;
			DWORD max = ((SELCHANGE*)nmh)->chrg.cpMax;

			
			//zmena selektnutia
			if (min !=  max) //nieco selektnute
				return;//nebudeme prefarbovat, aby sa zachovalo farbenie

			Colorize(notifyAction);
		}
		break;
	case EN_DRAGDROPDONE:
//		notifyAction = DATALOGWINDOW_COLORIZE_SELECTION;
		Colorize(DATALOGWINDOW_COLORIZE_SELECTION);
		break;
	}
}

/*
void CDatalogWindow::wmCHAR(char c)
{
	if (lessOperator && (c == '-') )
	{
		//prepis <- na jeden znak

		::SendMessage(hwnd, EM_HIDESELECTION, TRUE, 0);

		CHARRANGE chr;
		::SendMessage(hwnd, EM_EXGETSEL, 0, (LPARAM)&chr);

		//vrat spat seleknutie
		chr.cpMin++;
		::SendMessage(hwnd, EM_EXSETSEL, 0, (LPARAM)&chr);
		//vrat spat prekreslovanie a prekresli okno
		::SendMessage(hwnd, EM_HIDESELECTION, FALSE, 0);

		lessOperator = false;
	}
	else
	if (c == '<')
		lessOperator = true;
	else
		lessOperator = false;
}*/

void CDatalogWindow::wmKEYUP(int key)
{
	if (key == VK_CONTROL)
		ctrlFlag = false;
}

bool CDatalogWindow::wmKEYDOWN(int key)
{
	if (ctrlFlag)
	{
		switch (key)
		{
		case 'V'://paste
			//zisti aktualnu poziciu (aby sme vedeli, kde zacina pastnuty text
			indexBeforePaste = ::SendMessage(hwnd, EM_LINEINDEX, -1, 0);
			notifyAction = DATALOGWINDOW_COLORIZE_PASTE;
			return true;
		case 'A'://select all
		case 'X'://cut
		case 'C'://copy
			return true;
		default:
			return false;
		}
	}
	else
	{
		if (key == VK_CONTROL)
			ctrlFlag = true;
		else
		{
			switch (key)
			{
				case VK_RETURN:
					notifyAction = DATALOGWINDOW_COLORIZE_ENTER;

					//prekresli aktualny riadok
					//okrem sipok, home, end, to nemusime
				case VK_END:
				case VK_HOME:
				case VK_LEFT:
				case VK_RIGHT:
				case VK_UP:
				case VK_DOWN:
					notifyAction = 0;
					break;
				default:
					notifyAction = DATALOGWINDOW_COLORIZE_LINE;
					break;
			}
		}
	}
	return true;
}

void CDatalogWindow::SetIDBAtoms(CStringTable *a)
{
	_DELETE(idbAtoms);
	idbAtoms = _NEW(CStringTable);
	for (DWORD i=0; i<a->GetCount(); i++)
		idbAtoms->Insert((char*)a->Get(i));
}

void CDatalogWindow::Colorize()
{
	Colorize(DATALOGWINDOW_COLORIZE_ALL);
}

void CDatalogWindow::ColorizeIDBAtoms()
{
	void* mem = ReadInput(NULL);
	CSyntacticAnalyzer *sa = _NEW(CSyntacticAnalyzer(mem));
		sa->output = false;
		sa->ReadRules();
		sa->output = true;
	_DELETE(sa);
	freex(mem);
}

void CDatalogWindow::Colorize(DWORD flag)
{
	//ak paste = true, zisti atomy v texte, ktory sa skopiroval z clipboardu
	TEXTRANGE tr;

	if (!flag)
		return;

	stopNotify = true;

	//urci zaciatok a koniec textu, ktory sa spracuva
	switch (flag)
	{
		case DATALOGWINDOW_COLORIZE_PASTE:
		{
			tr.chrg.cpMin = indexBeforePaste;
			DWORD index = ::SendMessage(hwnd, EM_LINEINDEX, -1, 0);//aktualny riadok
			DWORD length = ::SendMessage(hwnd, EM_LINELENGTH, index, 0);//jeho dlzka
			tr.chrg.cpMax = index + length;
			break;
		}
		case DATALOGWINDOW_COLORIZE_LINE:
		{
			DWORD index = tr.chrg.cpMin = ::SendMessage(hwnd, EM_LINEINDEX, -1, 0);
			tr.chrg.cpMax = index + ::SendMessage(hwnd, EM_LINELENGTH, index, 0);//dlzka aktualneho riadku
			break;
		}
		case DATALOGWINDOW_COLORIZE_ENTER:
		{
			//treba spracovat aj predchadzajuci riadok
			DWORD line = ::SendMessage(hwnd, EM_LINEFROMCHAR, -1, 0);//aktualny riadok
			DWORD index = ::SendMessage(hwnd, EM_LINEINDEX, -1, 0); //aktualny riadok
			tr.chrg.cpMax = ::SendMessage(hwnd, EM_LINELENGTH, index, 0);//dlzka aktualneho riadku
			index = tr.chrg.cpMin = ::SendMessage(hwnd, EM_LINEINDEX, line-1, 0); //predchadzajuci riadok je ako pociatocny
			tr.chrg.cpMax += (index + ::SendMessage(hwnd, EM_LINELENGTH, index, 0) + 1);//+dlzka predchadzajuceho riadku + 1 na enter
			break;
		}
		case DATALOGWINDOW_COLORIZE_ALL:
		{
			tr.chrg.cpMin = 0;
			tr.chrg.cpMax = -1;
			break;
		}
		case DATALOGWINDOW_COLORIZE_SELECTION:
			{
				CHARRANGE chr;
				//chceme len selektnutu cast + riadok, kde zacina a riadok, kde konci
				::SendMessage(hwnd, EM_EXGETSEL, 0, (LPARAM)&chr);
				DWORD startLine = ::SendMessage(hwnd, EM_EXLINEFROMCHAR, 0, chr.cpMin);
				DWORD endLine = ::SendMessage(hwnd, EM_EXLINEFROMCHAR, 0, chr.cpMax);

				tr.chrg.cpMin = ::SendMessage(hwnd, EM_LINEINDEX, startLine, 0);
				tr.chrg.cpMax = ::SendMessage(hwnd, EM_LINEINDEX, endLine, 0);
				DWORD length = ::SendMessage(hwnd, EM_LINELENGTH, tr.chrg.cpMax, 0);//jeho dlzka
				tr.chrg.cpMax += length;
			}
			break;
		case 0:
			stopNotify = false;
			return;
	}
	if (tr.chrg.cpMin == tr.chrg.cpMax)
	{
		stopNotify = false;
		return;
	}

	if (flag == DATALOGWINDOW_COLORIZE_ALL)
	{
		GETTEXTLENGTHEX gtle;
		gtle.codepage = 0;
		gtle.flags = GTL_DEFAULT;
		DWORD len = ::SendMessage(hwnd, EM_GETTEXTLENGTHEX, (WPARAM)&gtle, 0);
		tr.lpstrText = _NEW(char[len+1]);
	}
	else
	{
		tr.lpstrText = _NEW(char[tr.chrg.cpMax - tr.chrg.cpMin + 1]);
	}

	::SendMessage(hwnd, EM_GETTEXTRANGE, 0, (LPARAM)&tr);

	CLexicalAnalyzer* la = _NEW(CLexicalAnalyzer(tr.lpstrText));
	if (!la)
		{ _DELETE(tr.lpstrText); stopNotify = false; return; }

	LEXICAL_HILIGHTED_ATOMS *ha = la->HilightsWords(idbAtoms);

	//preformatuj najdene atomy v aktualnom riadku

	::SendMessage(hwnd, WM_SETREDRAW, FALSE, 0);//zatial neprekresluj okno
	//::SendMessage(hwnd, EM_HIDESELECTION, TRUE, 0);
	//::SendMessage(hwnd, WM_SETREDRAW, FALSE, 0);//zatial neprekresluj okno

	CHARRANGE chrOld;

	//zisti selekciu
	::SendMessage(hwnd, EM_EXGETSEL, 0, (LPARAM)&chrOld);
	//vyselektuj riadok
	::SendMessage(hwnd, EM_EXSETSEL, 0, (LPARAM)&tr.chrg);

	CHARFORMAT chf;
	chf.cbSize = sizeof(chf);
	chf.dwMask = CFM_COLOR;
	chf.dwEffects = 0;

	//najskor preformatujeme text
	if (flag == DATALOGWINDOW_COLORIZE_PASTE)
	{
		//text v schranke moze byt rozneho formatovania, nastav nase formatovanie (pismo)
		CHARFORMAT chf;
		chf.cbSize = sizeof(chf);
		chf.dwMask = CFM_SIZE|CFM_FACE|CFM_COLOR;
		chf.yHeight = app.options->editor.fontSize*20;
		strcpy(chf.szFaceName, app.options->editor.fontName);
		chf.crTextColor = RGB(0,0,0);
		::SendMessage(hwnd, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&chf);
	}
	else
	{
		//obycajny text (nie je pastnuty, je len napisany) -> daj len na cierno
		chf.crTextColor = RGB(0,0,0);
		::SendMessage(hwnd, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&chf);
	}


	DWORD start = tr.chrg.cpMin;

	//ofarbi jednotlive atomy
	for (DWORD i=0; i<ha->count; i++)
	{
		//nastav novu
		tr.chrg.cpMin = ha->item[i].pos_begin-1 + start;
		tr.chrg.cpMax = ha->item[i].pos_end-1 + start;

		::SendMessage(hwnd, EM_EXSETSEL, 0, (LPARAM)&tr.chrg);

		switch (ha->item[i].type)
		{
			case LEXICAL_HILIGHT_EDBATOM:
				chf.crTextColor = RGB(0,120,0);
				break;
			case LEXICAL_HILIGHT_IDBATOM:
				chf.crTextColor = RGB(255,120,40);
				break;
			case LEXICAL_HILIGHT_NUMBER:
				chf.crTextColor = RGB(200,0,0);
				break;
			case LEXICAL_HILIGHT_KEYWORD:
				chf.crTextColor = RGB(0,0,255);
				break;
			case LEXICAL_HILIGHT_ANSWER:
				chf.crTextColor = RGB(255,0,0);
				break;
			case LEXICAL_HILIGHT_STRING:
				chf.crTextColor = RGB(0,120,255);
				break;
		}
		::SendMessage(hwnd, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&chf);
	}

	//vrat povodne selektnutie
	::SendMessage(hwnd, EM_EXSETSEL, 0, (LPARAM)&chrOld);

	//nastav cierne pismo
	if (flag != DATALOGWINDOW_COLORIZE_SELECTION)
	{
		chf.crTextColor = RGB(0,0,0);
		::SendMessage(hwnd, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&chf);
	}

	//::SendMessage(hwnd, EM_HIDESELECTION, FALSE, 0);
	::SendMessage(hwnd, WM_SETREDRAW, TRUE, 0);
	::InvalidateRect(hwnd, NULL, TRUE);
	//::UpdateWindow(hwnd);


	_DELETE(la);
	_DELETE(tr.lpstrText);

	freex(ha);

	stopNotify = false;

	notifyAction = 0;
}

//static
LRESULT CALLBACK CDatalogWindow::StaticWindowProc(HWND hwnd,UINT msg,WPARAM wp,LPARAM lp)
{
	DWORD p = ::GetWindowLong(hwnd,GWL_USERDATA);
	return ((CDatalogWindow*)p)->WindowProc(hwnd,msg,wp,lp);
}

bool CDatalogWindow::Close()
{
	if (contentChanged)
	{
		int res = MessageBox(app.mainWindow->GetHandle(), "Chcete pred ukončením uložiť program?", "InLog",
			MB_ICONQUESTION|MB_YESNOCANCEL);
		switch (res)
		{
		case IDYES:
			return SaveToFile();
		case IDCANCEL:
			return false;
		case IDNO:
			return true;
		}
	}
	return true;
}

LRESULT CALLBACK CDatalogWindow::WindowProc(HWND hwnd,UINT msg,WPARAM wp,LPARAM lp)
{
	switch (msg)
	{
	case WM_KEYDOWN:
		if (!wmKEYDOWN((int)wp))
			return 0;
		break;
	case WM_KEYUP:
		wmKEYUP((int)wp);
		break;
	case WM_KILLFOCUS:
		ctrlFlag = false;//ak stratime focus, uz nemame ani stlacene ctrl
		break;
	}

	int res = ::CallWindowProc(oldWindowProc, hwnd,msg,wp,lp);

	return res;
}

void* CDatalogWindow::ReadInput(DWORD* sz)
{
	//alokuj pamat pre vsetky riadky
	DWORD pocet = ::SendMessage(hwnd, EM_GETLINECOUNT, 0, 0);
	//spocitaj kolko pamate treba
	DWORD size = ::SendMessage(hwnd, EM_LINEINDEX, pocet-1, 0);//velkost do posledneho riadku
	size+= ::SendMessage(hwnd, EM_LINELENGTH, size, 0);//dlzka posledneho riadku
	size+= 4;//pri uvolneni to hadze exception, neviem preco.. tak trosku viac pamate mu dam
	char* mem = (char*)::mallocx(size);
	if (sz)
		*sz = (size-4);

	//skopiruj, riadok po riadku, pridaj zariadkovanie
	DWORD j=0,i;
	for (i=0; i<pocet; i++)
	{
		((PWORD)((DWORD)mem+j))[0] = (WORD)size;
		DWORD k = ::SendMessage(hwnd, EM_GETLINE, i, (LPARAM)&mem[j]);
		j+=k;
	}
	mem[j-1] = 0;

	return mem;
}



void CDatalogWindow::Evaluate()
{
	void* mem = ReadInput(NULL);
	app.mainWindow->GetOutputWindow()->Clear();
	CDatalog *datalog = _NEW(CDatalog(mem));
	datalog->Evaluate();
	_DELETE(datalog);
	freex(mem);
	::SetFocus(hwnd);
}

void CDatalogWindow::DoResize()
{
	RECT rcParent, rcAtom;
	::GetClientRect(::GetParent(hwnd), &rcParent);
	::GetWindowRect(app.mainWindow->GetAtomsWindow()->GetHandle(), &rcAtom);
	::SetWindowPos(hwnd, 0, 0, 0,
		rcParent.right-(rcAtom.right-rcAtom.left)-2, rcParent.bottom-200-3, SWP_NOMOVE | SWP_NOZORDER);
}

HWND CDatalogWindow::GetHandle()
{
	return hwnd;
}