#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <commctrl.h>
#include "resource.h"
#include "TypesOfExec.h"
#include "WinABC.h"

HINSTANCE g_hInstance;
HWND g_hWnd;
HWND g_hwndStatusBar;
HWND g_hToolbar;
HWND hwndOutput;
HWND hwndFavourite;
WNDPROC oldEditMainProc;
const TCHAR szJmenoAplikace[] = TEXT("WinABC");
HANDLE g_hThreadInit = NULL;

void * pAbc;
char * pFileName;
char Command[COMMAND_SIZE];
UINT elapsedSeconds;
int showWindowStatus = SW_NORMAL;

BOOL isWorking = FALSE;
/* Je potreba, pri initu se nesmi ukoncit program */
BOOL isInitAbc = FALSE;

BOOL labelsInToolbar;
BOOL timeInStatusbar;
BOOL loadAbcrc;
BOOL confirmExit;

FILE * outStream;

HWND hEditMain;
HWND hEditPrint[MAX_OUTPUTS];
HWND hCheckPrint[MAX_OUTPUTS];
BOOL zalohaCheck[MAX_OUTPUTS];

HFONT hfCourier;
LOGFONT logEditFont;

extern char command[MAX_OUTPUTS][COMMAND_SIZE];
extern int numEdits;
extern BOOL wrapText;

extern void Abc_Start();
extern void Abc_Stop();
extern void * Abc_FrameGetGlobalFrame();

extern INT_PTR CALLBACK DialogSettings(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
extern INT_PTR CALLBACK DialogFavourite(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
extern INT_PTR CALLBACK DialogAbout(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
extern INT_PTR CALLBACK DialogOutput(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
extern INT_PTR CALLBACK DialogPrintSettings(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
extern INT_PTR CALLBACK DialogWizard(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
extern BOOL OtevritSoubor(HWND hWnd, LPTSTR lpFile);
extern BOOL UlozitSoubor(HWND hWnd, LPTSTR lpFile);
extern BOOL LoadSettings(HWND hWnd);
extern void StartExecute(char *prikaz, int withOutputs);
extern BOOL Execute(char *prikaz, int typeOfExec);
extern BOOL SaveSettings(HWND hWnd);
extern void StartPrintOutputs(HWND hWnd);
extern void WithAppPath(char *fileName, char *fullFileName);

void CenterWindow(HWND hWnd)
{
	int sirkaPlochy, vyskaPlochy;
	HDC hdc;
	RECT rect;
	hdc = GetDC(g_hWnd);
	sirkaPlochy = GetDeviceCaps(hdc, HORZRES);
	vyskaPlochy = GetDeviceCaps(hdc, VERTRES);

	GetClientRect(hWnd, &rect);
	SetWindowPos(hWnd, NULL, (sirkaPlochy - rect.right + rect.left)/2,(vyskaPlochy - rect.bottom + rect.top)/2, 0, 0, SWP_NOSIZE | SWP_NOZORDER);

	ReleaseDC(g_hWnd, hdc);
}

LRESULT CALLBACK WindowProcEdit(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	switch (uMsg)
	{
		case WM_GETDLGCODE:
			return DLGC_WANTALLKEYS;
		case WM_KEYDOWN:
			SendMessage(g_hWnd, UM_KEY_IN_CONTROL, wParam /*kod klávesy*/, (LPARAM)GetMenu(hWnd));
		break;
	}
	return CallWindowProc(oldEditMainProc, hWnd, uMsg, wParam, lParam);
}

void DisableInputs()
{
	HMENU hMenu;
	isWorking = TRUE;
	hMenu = GetMenu(g_hWnd);
	EnableMenuItem(hMenu, ID_SHOWSTATISTICS, MF_DISABLED | MF_GRAYED | MF_BYCOMMAND);
	EnableMenuItem(hMenu, ID_SHOWCOMMANDSLIST, MF_DISABLED | MF_GRAYED | MF_BYCOMMAND);
	EnableMenuItem(hMenu, ID_OPEN, MF_DISABLED | MF_GRAYED | MF_BYCOMMAND);
	EnableMenuItem(hMenu, ID_SAVE, MF_DISABLED | MF_GRAYED | MF_BYCOMMAND);
	EnableMenuItem(hMenu, ID_UNDO, MF_DISABLED | MF_GRAYED | MF_BYCOMMAND);
	EnableMenuItem(hMenu, ID_EMPTY, MF_DISABLED | MF_GRAYED | MF_BYCOMMAND);
	EnableMenuItem(hMenu, ID_HISTORY, MF_DISABLED | MF_GRAYED | MF_BYCOMMAND);
	EnableMenuItem(hMenu, ID_COMWIZARD, MF_DISABLED | MF_GRAYED | MF_BYCOMMAND);
	EnableMenuItem(hMenu, ID_PRINTSETTINGS, MF_DISABLED | MF_GRAYED | MF_BYCOMMAND);

	EnableMenuItem(hMenu, ID_SHOWAIGER, MF_DISABLED | MF_GRAYED | MF_BYCOMMAND);
	EnableMenuItem(hMenu, ID_SHOWBENCH, MF_DISABLED | MF_GRAYED | MF_BYCOMMAND);
	EnableMenuItem(hMenu, ID_SHOWBLIF, MF_DISABLED | MF_GRAYED | MF_BYCOMMAND);
	EnableMenuItem(hMenu, ID_SHOWBLIFMV, MF_DISABLED | MF_GRAYED | MF_BYCOMMAND);
	EnableMenuItem(hMenu, ID_SHOWCELLNET, MF_DISABLED | MF_GRAYED | MF_BYCOMMAND);
	EnableMenuItem(hMenu, ID_SHOWCOUNTER, MF_DISABLED | MF_GRAYED | MF_BYCOMMAND);
	EnableMenuItem(hMenu, ID_SHOWDOT, MF_DISABLED | MF_GRAYED | MF_BYCOMMAND);
	EnableMenuItem(hMenu, ID_SHOWEQN, MF_DISABLED | MF_GRAYED | MF_BYCOMMAND);
	EnableMenuItem(hMenu, ID_SHOWGML, MF_DISABLED | MF_GRAYED | MF_BYCOMMAND);
	EnableMenuItem(hMenu, ID_SHOWPLA, MF_DISABLED | MF_GRAYED | MF_BYCOMMAND);
	EnableMenuItem(hMenu, ID_SHOWVERILOG, MF_DISABLED | MF_GRAYED | MF_BYCOMMAND);

	SendMessage(g_hToolbar, TB_ENABLEBUTTON, ID_OPEN, MAKELONG(FALSE, 0));
	SendMessage(g_hToolbar, TB_ENABLEBUTTON, ID_SAVE, MAKELONG(FALSE, 0));
	SendMessage(g_hToolbar, TB_ENABLEBUTTON, ID_UNDO, MAKELONG(FALSE, 0));
	SendMessage(g_hToolbar, TB_ENABLEBUTTON, ID_SHOWSTATISTICS, MAKELONG(FALSE, 0));
	SendMessage(g_hToolbar, TB_ENABLEBUTTON, ID_COMWIZARD, MAKELONG(FALSE, 0));
	SendMessage(g_hToolbar, TB_ENABLEBUTTON, ID_HISTORY, MAKELONG(FALSE, 0));
	SendMessage(g_hToolbar, TB_ENABLEBUTTON, ID_SHOWCOMMANDSLIST, MAKELONG(FALSE, 0));

	EnableWindow(hEditMain, FALSE);
}

void EnableInputs()
{
	HMENU hMenu;
	hMenu = GetMenu(g_hWnd);
	EnableMenuItem(hMenu, ID_SHOWSTATISTICS, MF_ENABLED | MF_BYCOMMAND);
	EnableMenuItem(hMenu, ID_SHOWCOMMANDSLIST, MF_ENABLED | MF_BYCOMMAND);
	EnableMenuItem(hMenu, ID_OPEN, MF_ENABLED | MF_BYCOMMAND);
	EnableMenuItem(hMenu, ID_SAVE, MF_ENABLED | MF_BYCOMMAND);
	EnableMenuItem(hMenu, ID_UNDO, MF_ENABLED | MF_BYCOMMAND);
	EnableMenuItem(hMenu, ID_EMPTY, MF_ENABLED | MF_BYCOMMAND);
	EnableMenuItem(hMenu, ID_HISTORY, MF_ENABLED | MF_BYCOMMAND);
	EnableMenuItem(hMenu, ID_COMWIZARD, MF_ENABLED | MF_BYCOMMAND);
	EnableMenuItem(hMenu, ID_PRINTSETTINGS, MF_ENABLED | MF_BYCOMMAND);

	EnableMenuItem(hMenu, ID_SHOWAIGER, MF_ENABLED | MF_BYCOMMAND);
	EnableMenuItem(hMenu, ID_SHOWBENCH, MF_ENABLED | MF_BYCOMMAND);
	EnableMenuItem(hMenu, ID_SHOWBLIF, MF_ENABLED | MF_BYCOMMAND);
	EnableMenuItem(hMenu, ID_SHOWBLIFMV, MF_ENABLED | MF_BYCOMMAND);
	EnableMenuItem(hMenu, ID_SHOWCELLNET, MF_ENABLED | MF_BYCOMMAND);
	EnableMenuItem(hMenu, ID_SHOWCOUNTER, MF_ENABLED | MF_BYCOMMAND);
	EnableMenuItem(hMenu, ID_SHOWDOT, MF_ENABLED | MF_BYCOMMAND);
	EnableMenuItem(hMenu, ID_SHOWEQN, MF_ENABLED | MF_BYCOMMAND);
	EnableMenuItem(hMenu, ID_SHOWGML, MF_ENABLED | MF_BYCOMMAND);
	EnableMenuItem(hMenu, ID_SHOWPLA, MF_ENABLED | MF_BYCOMMAND);
	EnableMenuItem(hMenu, ID_SHOWVERILOG, MF_ENABLED | MF_BYCOMMAND);


	SendMessage(g_hToolbar, TB_ENABLEBUTTON, ID_OPEN, MAKELONG(TRUE, 0));
	SendMessage(g_hToolbar, TB_ENABLEBUTTON, ID_SAVE, MAKELONG(TRUE, 0));
	SendMessage(g_hToolbar, TB_ENABLEBUTTON, ID_UNDO, MAKELONG(TRUE, 0));
	SendMessage(g_hToolbar, TB_ENABLEBUTTON, ID_SHOWSTATISTICS, MAKELONG(TRUE, 0));
	SendMessage(g_hToolbar, TB_ENABLEBUTTON, ID_COMWIZARD, MAKELONG(TRUE, 0));
	SendMessage(g_hToolbar, TB_ENABLEBUTTON, ID_HISTORY, MAKELONG(TRUE, 0));
	SendMessage(g_hToolbar, TB_ENABLEBUTTON, ID_SHOWCOMMANDSLIST, MAKELONG(TRUE, 0));

	EnableWindow(hEditMain, TRUE);
	isWorking = FALSE;
}

void ResizeWindow(int width, int height)
{
	int i;
	RECT rect;
	int statBarH;
	int toolBarH;
	int comboBoxH;
	#define COMBODROP 128
	#define CHECKBOXH 16
	int casti1[1] = {-1};
	int casti2[2] = {width*2/3, -1};
	GetWindowRect(g_hwndStatusBar, &rect);
	statBarH = rect.bottom - rect.top;
	GetWindowRect(g_hToolbar, &rect);
	toolBarH = rect.bottom - rect.top;
	GetWindowRect(GetWindow(hEditMain, GW_CHILD), &rect);
	comboBoxH = rect.bottom - rect.top + 8;
	MoveWindow(hEditMain, 0, toolBarH, width, COMBODROP, TRUE);
	//SetWindowPos(hEditMain, NULL, 0, 0, (rectTB.bottom - rectTB.top)
	for (i = 0; i < numEdits; i++)
	{
		MoveWindow(hCheckPrint[i], 0 + (i%2)*(width/2), toolBarH + comboBoxH + ((height-toolBarH-comboBoxH-statBarH)/((numEdits+1)/2))*((i - (i%2))/2),
								width/2, CHECKBOXH, TRUE);
		MoveWindow(hEditPrint[i], 0 + (i%2)*(width/2), toolBarH + comboBoxH + CHECKBOXH + ((height-toolBarH-comboBoxH-statBarH)/((numEdits+1)/2))*((i - (i%2))/2),
								width/2, (height-toolBarH-comboBoxH-statBarH)/((numEdits+1)/2)-CHECKBOXH, TRUE);
	}

	if (timeInStatusbar)
		SendMessage(g_hwndStatusBar, SB_SETPARTS, 2, (LPARAM)casti2);
	else
		SendMessage(g_hwndStatusBar, SB_SETPARTS, 1, (LPARAM)casti1);

}

void VytvorEdity()
{
	RECT rect;
	int i;

	hfCourier = CreateFontIndirect(&logEditFont);

	for (i = 0; i < numEdits; i++)
	{
		if (wrapText)
		{
			hEditPrint[i] = CreateWindowEx(WS_EX_RIGHTSCROLLBAR,
				TEXT("EDIT"), TEXT(""),
				WS_CHILD | WS_VSCROLL | WS_VISIBLE |
				ES_MULTILINE | ES_WANTRETURN | ES_READONLY | WS_BORDER | 
				ES_AUTOVSCROLL | WS_TABSTOP,
				0, 0, 0, 0,	g_hWnd, NULL, g_hInstance, NULL);
		}
		else
		{
			hEditPrint[i] = CreateWindowEx(WS_EX_RIGHTSCROLLBAR,
				TEXT("EDIT"), TEXT(""),
				WS_CHILD | WS_HSCROLL | WS_VSCROLL | WS_VISIBLE |
				ES_MULTILINE | ES_WANTRETURN | ES_READONLY | WS_BORDER | 
				ES_AUTOVSCROLL | ES_AUTOHSCROLL | WS_TABSTOP,
				0, 0, 0, 0,	g_hWnd, NULL, g_hInstance, NULL);
		}		
		hCheckPrint[i] = CreateWindowEx(0, TEXT("BUTTON"), command[i],
				WS_CHILD | WS_VISIBLE |	BS_AUTOCHECKBOX | WS_TABSTOP,
				0, 0, 0, 0, g_hWnd, NULL, g_hInstance, NULL);
		SendMessage(hEditPrint[i], WM_SETFONT, (WPARAM)hfCourier, (LPARAM)TRUE);
		SendMessage(hCheckPrint[i], BM_SETCHECK, zalohaCheck[i], 0);
	}
	GetClientRect(g_hWnd, &rect);
	ResizeWindow(rect.right, rect.bottom);
}

void CheckAllOutputs(BOOL stav)
{
	int i;
	for (i = 0; i < numEdits ; i++)
		SendMessage(hCheckPrint[i], BM_SETCHECK, stav, 0);
}

void ShowFormat(WORD typ)
{
	char prikaz[COMMAND_SIZE];
	char lpFile[MAX_PATH + 64];
	FILE *f;

	WithAppPath("temp.tmp", lpFile);

	f = fopen(lpFile, "w");
	if (f <= 0)
	{
		MessageBox(g_hWnd, TEXT("Can't open file!"), TEXT("Error"), MB_ICONERROR);
		return;
	}
	fprintf(f, "This format is not available now. See instructions in output window!");
	fclose(f);

	switch (typ)
	{
		case ID_SHOWAIGER:
			sprintf(prikaz, "write_aiger \"%s\"", lpFile);
			break;
		case ID_SHOWBENCH:
			sprintf(prikaz, "write_bench \"%s\"", lpFile);
			break;
		case ID_SHOWBLIF:
			sprintf(prikaz, "write_blif \"%s\"", lpFile);
			break;
		case ID_SHOWBLIFMV:
			sprintf(prikaz, "write_blif_mv \"%s\"", lpFile);
			break;
		case ID_SHOWCELLNET:
			sprintf(prikaz, "write_cellnet \"%s\"", lpFile);
			break;
		case ID_SHOWCOUNTER:
			sprintf(prikaz, "write_counter \"%s\"", lpFile);
			break;
		case ID_SHOWDOT:
			sprintf(prikaz, "write_dot \"%s\"", lpFile);
			break;
		case ID_SHOWEQN:
			sprintf(prikaz, "write_eqn \"%s\"", lpFile);
			break;
		case ID_SHOWGML:
			sprintf(prikaz, "write_gml \"%s\"", lpFile);
			break;
		case ID_SHOWPLA:
			sprintf(prikaz, "write_pla \"%s\"", lpFile);
			break;
		case ID_SHOWVERILOG:
			sprintf(prikaz, "write_verilog \"%s\"", lpFile);
			break;
	}
	StartExecute(prikaz, EX_OPENNOTEPAD);
}

/* Procedura okna */
LRESULT CALLBACK WindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	RECT rect;
	char prikaz[COMMAND_SIZE];
	char lpFile[MAX_PATH];
	INT_PTR dlgResult;

	switch (msg)
	{
		case WM_DESTROY:
			PostQuitMessage(0);
			break;
		case WM_CLOSE:
			if (isInitAbc)
				return 0;
			if (confirmExit && MessageBox(hWnd, TEXT("Do you really want to exit?"), TEXT("Exit"), MB_YESNO | MB_ICONQUESTION) != IDYES)
				return 0;
			SaveSettings(hWnd);
			break;
		case WM_TIMER:
			elapsedSeconds++;
			sprintf(prikaz, "Elapsed: %u seconds", elapsedSeconds);
			SendMessage(g_hwndStatusBar, SB_SETTEXT, 1, (LPARAM)prikaz);
			break;
		case WM_COMMAND:
			switch (LOWORD(wParam))
			{
				case ID_EXIT:
					SendMessage(hWnd, WM_CLOSE, wParam, lParam);
					break;
				case ID_ABOUT:
					dlgResult = DialogBox(g_hInstance, MAKEINTRESOURCE(IDD_DIALOG_ABOUT), hWnd, (DLGPROC)DialogAbout);
					break;
				case ID_SHOWCOMMANDSLIST:
					StartExecute("help", EX_NOOUTPUTS);
					break;
				case ID_OPEN:
					if (OtevritSoubor(hWnd, lpFile))
					{
						sprintf(prikaz, "read \"%s\"", lpFile);
						StartExecute(prikaz, EX_WITHOUTPUTS);
					}
					break;
				case ID_SAVE:
					if (UlozitSoubor(hWnd, lpFile))
					{
						sprintf(prikaz, "write \"%s\"", lpFile);
						StartExecute(prikaz, EX_WITHOUTPUTS);
					}
					break;
				case ID_UNDO:
					StartExecute("undo", EX_WITHOUTPUTS);
					break;
				case ID_HISTORY:
					StartExecute("history", EX_NOOUTPUTS);
					break;
				case ID_EMPTY:
					if (MessageBox(hWnd, TEXT("Do you really want to erase current net?"), TEXT("Empty net"), MB_YESNO | MB_ICONQUESTION) == IDYES)
					{
						StartExecute("empty", EX_WITHOUTPUTS);
					}
					break;
				case ID_COMWIZARD:
					dlgResult = DialogBox(g_hInstance, MAKEINTRESOURCE(IDD_DIALOG_WIZARD), hWnd, (DLGPROC)DialogWizard);
					break;
				case ID_SHOWFAVOURITE:
					ShowWindow(hwndFavourite, SW_SHOW);
					SendMessage(g_hToolbar, TB_CHECKBUTTON, ID_FAVCHECK, MAKELONG(TRUE, 0));
					break;
				case ID_HIDEFAVOURITE:
					SendMessage(g_hToolbar, TB_CHECKBUTTON, ID_FAVCHECK, MAKELONG(FALSE, 0));
					ShowWindow(hwndFavourite, SW_HIDE);
					break;
				case ID_SHOWOUTPUT:
					ShowWindow(hwndOutput, SW_SHOW);
					SendMessage(g_hToolbar, TB_CHECKBUTTON, ID_OUTCHECK, MAKELONG(TRUE, 0));
					break;
				case ID_HIDEOUTPUT:
					SendMessage(g_hToolbar, TB_CHECKBUTTON, ID_OUTCHECK, MAKELONG(FALSE, 0));
					ShowWindow(hwndOutput, SW_HIDE);
					break;
				case ID_FAVCHECK:
					if (SendMessage(g_hToolbar, TB_ISBUTTONCHECKED, ID_FAVCHECK, (LPARAM)0))
						SendMessage(g_hWnd, WM_COMMAND, ID_SHOWFAVOURITE, 0);
					else 
						SendMessage(g_hWnd, WM_COMMAND, ID_HIDEFAVOURITE, 0);
					break;
				case ID_OUTCHECK:
					if (SendMessage(g_hToolbar, TB_ISBUTTONCHECKED, ID_OUTCHECK, (LPARAM)0))
						SendMessage(g_hWnd, WM_COMMAND, ID_SHOWOUTPUT, 0);
					else 
						SendMessage(g_hWnd, WM_COMMAND, ID_HIDEOUTPUT, 0);
					break;
				case ID_SETTINGS:
					dlgResult = DialogBox(g_hInstance, MAKEINTRESOURCE(IDD_DIALOG_SETTINGS), hWnd, (DLGPROC)DialogSettings);
					GetClientRect(g_hWnd, &rect);
					ResizeWindow(rect.right, rect.bottom);
					break;
				case ID_PRINTSETTINGS:
					dlgResult = DialogBox(g_hInstance, MAKEINTRESOURCE(IDD_DIALOG_PRINT_SETTINGS), hWnd, (DLGPROC)DialogPrintSettings);
					if (dlgResult == IDOK)
						SendMessage(hWnd, WM_COMMAND, ID_SHOWSTATISTICS, 0);
					break;
				case ID_SHOWSTATISTICS:
					StartPrintOutputs(hWnd);
					break;
				case ID_CHECKALL:
					CheckAllOutputs(TRUE);
					break;
				case ID_UNCHECKALL:
					CheckAllOutputs(FALSE);
					break;
				case ID_SHOWAIGER:
				case ID_SHOWBENCH:
				case ID_SHOWBLIF:
				case ID_SHOWBLIFMV:
				case ID_SHOWCELLNET:
				case ID_SHOWCOUNTER:
				case ID_SHOWDOT:
				case ID_SHOWEQN:
				case ID_SHOWGML:
				case ID_SHOWPLA:
				case ID_SHOWVERILOG:
					ShowFormat(LOWORD(wParam));
					break;
			}
			break;
		case WM_SIZE:
			SendMessage(g_hwndStatusBar, WM_SIZE, wParam, lParam);
			SendMessage(g_hToolbar, WM_SIZE, wParam, lParam);
			ResizeWindow(LOWORD(lParam), HIWORD(lParam));
			break;
		case WM_NOTIFY:
			{
				LPNMTTDISPINFO lpTTDISPINFO;
				LPNMHDR lpNMHDR = (LPNMHDR)lParam;
				if (lpNMHDR->code == TTN_GETDISPINFO)
				{
					lpTTDISPINFO = (LPNMTTDISPINFO)lParam;
					lpTTDISPINFO->hinst = g_hInstance;
					lpTTDISPINFO->lpszText = MAKEINTRESOURCE(lpTTDISPINFO->hdr.idFrom);
				}
			}
			break;
		case UM_KEY_IN_CONTROL:
			if (wParam == VK_RETURN)
			{
				GetWindowText(hEditMain, prikaz, COMMAND_SIZE - 1);
				SendMessage(hEditMain, CB_INSERTSTRING, 0, (LPARAM)prikaz);
				SetFocus(g_hwndStatusBar);	/* hEditMain musi ztratit focus */
				StartExecute(prikaz, EX_WITHOUTPUTS);
			}
			break;
		case UM_SETFOCUS_COMBO:
			SetFocus(hEditMain);
			break;
	}
	return DefWindowProc(hWnd, msg, wParam, lParam);
}

BOOL ToolBar_AddButton(int nBitmapa, int nPrikaz, LPCTSTR pString, BYTE bState, BYTE bStyle, ULONG dwData)
{
	TBBUTTON tbb;
	ZeroMemory(&tbb, sizeof (TBBUTTON));
	tbb.iBitmap  = nBitmapa;
	tbb.idCommand = nPrikaz;
	tbb.fsState = bState;
	tbb.fsStyle = bStyle;
	tbb.dwData = dwData;
	tbb.iString = labelsInToolbar ? (INT_PTR)pString : (INT_PTR)NULL;
	return SendMessage(g_hToolbar, TB_INSERTBUTTON, -1, (LPARAM)&tbb);
}

BOOL ToolBar_AddSeparator()
{
	return ToolBar_AddButton(0, 0, TEXT(""), TBSTATE_ENABLED, (BYTE)TBSTYLE_SEP, 0);
}

BOOL CreateToolbar()
{
	TBADDBITMAP tbab;

	/* Toolbar */
	g_hToolbar = CreateWindowEx(0,
		TOOLBARCLASSNAME,
		(LPCTSTR)NULL,
		WS_CHILD | WS_VISIBLE | CCS_ADJUSTABLE | TBSTYLE_TOOLTIPS | TBSTYLE_FLAT,
		0, 0, 0, 0,
		g_hWnd,
		(HMENU)IDR_TOOLBAR1,
		g_hInstance,
		NULL);
	if (!IsWindow(g_hToolbar))
		return FALSE;
	SendMessage(g_hToolbar, TB_BUTTONSTRUCTSIZE, (WPARAM) sizeof (TBBUTTON), 0);
	tbab.hInst = g_hInstance;
	tbab.nID = IDR_TOOLBAR1;
	if (SendMessage(g_hToolbar, TB_ADDBITMAP, (WPARAM) 13, (LPARAM) &tbab) == -1)
	{
		MessageBox(g_hWnd, TEXT("Chyba pri vytvareni toolbaru!"), TEXT("ERROR"), MB_ICONERROR);
		return FALSE;
	}

	ToolBar_AddButton(0, ID_OPEN, "Open", TBSTATE_ENABLED, (BYTE)(TBSTYLE_BUTTON | TBSTYLE_TOOLTIPS), 0);
	ToolBar_AddButton(1, ID_SAVE, "Save", TBSTATE_ENABLED, (BYTE)(TBSTYLE_BUTTON | TBSTYLE_TOOLTIPS), 0);
	ToolBar_AddSeparator();
	/*
	ToolBar_AddButton(2, 0, "Print", TBSTATE_ENABLED, (BYTE)(TBSTYLE_BUTTON | TBSTYLE_TOOLTIPS), 0);
	ToolBar_AddSeparator();
	ToolBar_AddButton(3, 0, "Copy", TBSTATE_ENABLED, (BYTE)(TBSTYLE_BUTTON | TBSTYLE_TOOLTIPS), 0);
	ToolBar_AddButton(4, 0, "Paste", TBSTATE_ENABLED, (BYTE)(TBSTYLE_BUTTON | TBSTYLE_TOOLTIPS), 0);
	ToolBar_AddSeparator();
	ToolBar_AddButton(5, ID_UNDO, "Undo", TBSTATE_ENABLED, (BYTE)(TBSTYLE_BUTTON | TBSTYLE_TOOLTIPS), 0);
	ToolBar_AddButton(6, ID_REDO, "Redo", TBSTATE_ENABLED, (BYTE)(TBSTYLE_BUTTON | TBSTYLE_TOOLTIPS), 0);
	ToolBar_AddSeparator();*/
	ToolBar_AddButton(7, ID_SHOWSTATISTICS, "Refresh", TBSTATE_ENABLED, (BYTE)(TBSTYLE_BUTTON | TBSTYLE_TOOLTIPS), 0);
	ToolBar_AddButton(8, ID_COMWIZARD, "Command", TBSTATE_ENABLED, (BYTE)(TBSTYLE_BUTTON | TBSTYLE_TOOLTIPS), 0);
	ToolBar_AddSeparator();
	ToolBar_AddButton(9, ID_FAVCHECK, "Favourite", TBSTATE_ENABLED, (BYTE)(TBSTYLE_CHECK | TBSTYLE_TOOLTIPS), 0);
	ToolBar_AddButton(10, ID_OUTCHECK, "Output", TBSTATE_ENABLED, (BYTE)(TBSTYLE_CHECK | TBSTYLE_TOOLTIPS), 0);
	ToolBar_AddButton(11, ID_HISTORY, "History", TBSTATE_ENABLED, (BYTE)(TBSTYLE_BUTTON | TBSTYLE_TOOLTIPS), 0);
	ToolBar_AddButton(12, ID_SHOWCOMMANDSLIST, "Commands", TBSTATE_ENABLED, (BYTE)(TBSTYLE_BUTTON | TBSTYLE_TOOLTIPS), 0);
	return TRUE;
}

BOOL CreateStatusbar()
{
	/* Stavovy radek */
	g_hwndStatusBar = CreateWindowEx(0,
		STATUSCLASSNAME,
		TEXT("Inicializace..."),
		WS_CHILD | WS_VISIBLE,
		0, 0, 0, 0,
		g_hWnd,
		(HMENU)NULL,
		g_hInstance,
		NULL);
	if (!IsWindow(g_hwndStatusBar))
		return FALSE;
	return TRUE;
}


/* Inicializace */
BOOL Inicializace()
{
	//HFONT hFont;
	WNDCLASSEX wcex;
	INITCOMMONCONTROLSEX icc;
	icc.dwSize = sizeof (INITCOMMONCONTROLSEX);
	icc.dwICC = ICC_WIN95_CLASSES;
	if (!InitCommonControlsEx(&icc))
		return FALSE;
	wcex.cbSize = sizeof (WNDCLASSEX); 
	wcex.style = CS_HREDRAW | CS_VREDRAW;
	wcex.lpfnWndProc = (WNDPROC)WindowProc;
	wcex.cbClsExtra = 0;
	wcex.cbWndExtra = 0;
	wcex.hInstance = g_hInstance;
	wcex.hIcon = LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_MAINICON));
	wcex.hIconSm = LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_MAINICON_SMALL));
	wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
	wcex.hbrBackground = GetSysColorBrush(COLOR_MENU);
	wcex.lpszMenuName = MAKEINTRESOURCE(IDR_MAINMENU);
	wcex.lpszClassName = szJmenoAplikace;
	if (!RegisterClassEx(&wcex))
		return FALSE;
	g_hWnd = CreateWindowEx(0, szJmenoAplikace, TEXT("WinABC"),
		WS_OVERLAPPEDWINDOW,
		100, 50, 640, 480,
		(HWND)NULL,
		(HMENU)NULL,
		g_hInstance,
		NULL);
	if (!g_hWnd)
		return FALSE;

	/* Edit pro zadavani prikazu */
	hEditMain = CreateWindowEx(WS_EX_RIGHTSCROLLBAR | WS_EX_STATICEDGE,
		TEXT("COMBOBOX"), TEXT(""),
		WS_CHILD | WS_VISIBLE |	WS_BORDER | CBS_DROPDOWN | CBS_AUTOHSCROLL,
		0, 0, 200, 240,
		g_hWnd, NULL,
		g_hInstance, NULL);
	if (!IsWindow(hEditMain))
		return FALSE;

	/* Nastaveni fontu */
	//hFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
	//SendMessage(hEditMain, WM_SETFONT, (WPARAM)hFont, (LPARAM)TRUE);

	return TRUE;
}

DWORD WINAPI AbcInit(LPVOID lpParameter)
{	
	char fullFileName[MAX_PATH];
	char text[COMMAND_SIZE];
	isInitAbc = TRUE;
	Abc_Start();
	pAbc = Abc_FrameGetGlobalFrame();
	isInitAbc = FALSE;
	EnableInputs();

	if (loadAbcrc)
	{
		WithAppPath("abc.rc", fullFileName);
		sprintf(text, "source \"%s\"", fullFileName);
		if (Execute(text, EX_NOOUTPUTS))
		{
			EnableInputs();
			SetWindowText(g_hwndStatusBar, "abc.rc loaded");
			Execute("unset progressbar", EX_NOOUTPUTS);
			EnableInputs();
		}
		else
		{
			EnableInputs();
			SetWindowText(g_hwndStatusBar, "abc.rc not loaded");
		}
	}

	SendMessage(g_hWnd, WM_COMMAND, ID_SHOWSTATISTICS, 0);
	CloseHandle(g_hThreadInit);
	return 0;
}

int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
	MSG msg;
	DWORD dwThreadId;

	g_hInstance = hInstance;
	if (!Inicializace())
		return -1;

	hwndFavourite = CreateDialog(g_hInstance, MAKEINTRESOURCE(IDD_DIALOG_FAVOURITE), g_hWnd, (DLGPROC)DialogFavourite);

	if (!LoadSettings(g_hWnd))
	{
		MessageBox(g_hWnd, TEXT("WinABC must NOT be in write protected folder!\nFor correct function, copy the application on your local disk."), TEXT("Error"), MB_ICONERROR);
		return 1;
	}
	
	CreateStatusbar();
	CreateToolbar();
	ShowWindow(g_hWnd, showWindowStatus);

	VytvorEdity();
	
	hwndOutput = CreateDialog(g_hInstance, MAKEINTRESOURCE(IDD_DIALOG_OUTPUT), g_hWnd, (DLGPROC)DialogOutput);
	CenterWindow(hwndOutput);
	SendDlgItemMessage(hwndOutput, IDC_EDIT_OUTPUT, WM_SETFONT, (WPARAM)hfCourier, (LPARAM)TRUE);

	DisableInputs();
	SetWindowText(g_hwndStatusBar, TEXT("Initializing ABC framework..."));

	g_hThreadInit = CreateThread(NULL, 0, AbcInit, (LPVOID)NULL, 0, &dwThreadId);
	if (!g_hThreadInit)
		MessageBox(g_hWnd, TEXT("Nepodarilo se vytvorit vlakno pro inicializaci ABC"), TEXT("Error"), MB_ICONERROR);

	oldEditMainProc = (WNDPROC)SetWindowLong(GetWindow(hEditMain, GW_CHILD), GWL_WNDPROC, (LONG)WindowProcEdit);

	while (GetMessage(&msg, NULL, 0, 0)) 
	{
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}

	Abc_Stop();
	return 0;
}
