// RegDumpFDDDlg.cpp : implementation file
//

#include "stdafx.h"
#include "RegDumpFDDDlg.h"
#include "afxdialogex.h"
#include "Board.h"
#include "Debugger.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CRegDumpDlg dialog
constexpr auto COLUMN_WIDTH = 60;
constexpr auto COLUMN_WIDTH_PRT = 78;
constexpr auto COLUMN_WIDTH_REG = 38;
constexpr auto COLUMN_WIDTH_TXT = 70;

CRegDumpFDDDlg::CRegDumpFDDDlg(CWnd *pParent /*=NULL*/)
	: CDialogEx(CRegDumpFDDDlg::IDD, pParent)
	, m_pDebugger(nullptr)
	, m_hAccelTable(nullptr)
{
}

CRegDumpFDDDlg::~CRegDumpFDDDlg()
{
	hFont.DeleteObject();
}

void CRegDumpFDDDlg::DoDataExchange(CDataExchange *pDX)
{
	CDialogEx::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_MD_FDD_DATA, m_listFDD);
	DDX_Control(pDX, IDC_MD_HDD_REGISTERS, m_listHDD);
}


BEGIN_MESSAGE_MAP(CRegDumpFDDDlg, CDialogEx)
	ON_WM_SIZE()
	ON_NOTIFY(LVN_ITEMCHANGED, IDC_MD_FDD_DATA, &OnLvnItemchangedMdFddData)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CRegDumpDlg message handlers
const UINT CRegDumpFDDDlg::m_pLISTFDDIDs[4] =
{
	IDS_MEMORY_177130IN, IDS_MEMORY_177130OUT,
	IDS_MEMORY_177132IN, IDS_MEMORY_177132OUT
};
const CString CRegDumpFDDDlg::m_plistHDDHDrs[10] =
{
	_T("1F0"),
	_T("1F1"),
	_T("1F2"),
	_T("1F3"),
	_T("1F4"),
	_T("1F5"),
	_T("1F6"),
	_T("1F7"),
	_T("3F6"),
	_T("3F7"),
};

void CRegDumpFDDDlg::ResizeList(CMultiEditListCtrl *list, int height)
{
	CRect rect, itemRect;
	list->GetWindowRect(&rect);
	ScreenToClient(&rect);

	if (list->GetItemRect(0, itemRect, LVIR_BOUNDS))
	{
		register int cx = itemRect.Width() + GetSystemMetrics(SM_CXDLGFRAME);
		register int cy = itemRect.Height() * height + GetSystemMetrics(SM_CYDLGFRAME);
		list->SetWindowPos(nullptr, rect.left, rect.top, cx, cy, SWP_SHOWWINDOW);
	}
}

BOOL CRegDumpFDDDlg::OnInitDialog()
{
	CDialogEx::OnInitDialog();
	m_hAccelTable = LoadAccelerators(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDR_MAINFRAME));
	LOGFONT lf;
	::GetObject((HGDIOBJ)::SendMessage(GetSafeHwnd(), WM_GETFONT, 0, 0), sizeof(LOGFONT), &lf);
	_tcscpy_s(lf.lfFaceName, LF_FACESIZE, _T("Courier New\0"));

	if (!hFont.CreateFontIndirect(&lf))
	{
		_tcscpy_s(lf.lfFaceName, LF_FACESIZE, _T("Lucida Console\0"));
		hFont.CreateFontIndirect(&lf);
	}

	int nPixelW = GetDeviceCaps(GetDC()->GetSafeHdc(), LOGPIXELSX);
	// Подсказки
	m_ToolTip.Create(this, WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP/* | TTS_BALLOON*/);
	m_ToolTip.SetDelayTime(TTDT_AUTOPOP, 20000);
	//*** you could change the defualt settings ***
	//m_ToolTip.SetTipBkColor(RGB(255, 255, 255));
	//m_ToolTip.SetTipTextColor(RGB(255, 0, 0));
	CString strHeader;
	// Создадим список регистров FDD
	// 2 колонки, 1-я - имя регистра, 2-я - его значение
	m_listFDD.SetFont(&hFont, FALSE);
	m_listFDD.SetExtendedStyle(LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | LVS_EX_DOUBLEBUFFER | LVS_EX_SNAPTOGRID);
	m_listFDD.InsertColumn(LISTFDD_NAME_COL, LPSTR_TEXTCALLBACK, LVCFMT_LEFT, MulDiv(COLUMN_WIDTH_PRT, nPixelW, 96));
	m_listFDD.InsertColumn(LISTFDD_VALUE_COL, LPSTR_TEXTCALLBACK, LVCFMT_LEFT, MulDiv(COLUMN_WIDTH, nPixelW, 96));

	for (int i = FDDREG177130IN_LINE; i <= FDDREG177132OUT_LINE; ++i)
	{
		strHeader.LoadString(m_pLISTFDDIDs[i]);
		m_listFDD.InsertItem(i, strHeader);
		m_listFDD.SetItem(i, LISTFDD_VALUE_COL, LVIF_TEXT, nullptr, 0, 0, 0, 0);
	}

	m_listFDD.SetColumnBkColor(GetSysColor(COLOR_BTNFACE), LISTFDD_NAME_COL);
	m_listFDD.EnableColumnEdit(false, LISTFDD_NAME_COL);
	m_listFDD.EnableColumnEdit(false, LISTFDD_VALUE_COL); //запретим редактировать. только для просмотра
	ResizeList(&m_listFDD, FDDREG177132OUT_LINE + 1);
	// Создадим список регистров HDD
	// 6 колонок, 1-я и 4-я - адрес порта/регистра, 2-я и 5-я - их значения по чтению, 3-я и 6-я - их значения по записи
	m_listHDD.SetFont(&hFont, FALSE);
	m_listHDD.SetExtendedStyle(LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | LVS_EX_DOUBLEBUFFER | LVS_EX_SNAPTOGRID);
	m_listHDD.InsertColumn(LISTHDD_NAME1_COL, LPSTR_TEXTCALLBACK, LVCFMT_LEFT, MulDiv(COLUMN_WIDTH_REG, nPixelW, 96));
	m_listHDD.InsertColumn(LISTHDD_VALUE11_COL, LPSTR_TEXTCALLBACK, LVCFMT_LEFT, MulDiv(COLUMN_WIDTH, nPixelW, 96));
	m_listHDD.InsertColumn(LISTHDD_VALUE12_COL, LPSTR_TEXTCALLBACK, LVCFMT_LEFT, MulDiv(COLUMN_WIDTH, nPixelW, 96));
	m_listHDD.InsertColumn(LISTHDD_NAME2_COL, LPSTR_TEXTCALLBACK, LVCFMT_LEFT, MulDiv(COLUMN_WIDTH_REG, nPixelW, 96));
	m_listHDD.InsertColumn(LISTHDD_VALUE21_COL, LPSTR_TEXTCALLBACK, LVCFMT_LEFT, MulDiv(COLUMN_WIDTH, nPixelW, 96));
	m_listHDD.InsertColumn(LISTHDD_VALUE22_COL, LPSTR_TEXTCALLBACK, LVCFMT_LEFT, MulDiv(COLUMN_WIDTH, nPixelW, 96));

	for (int i = R1F0_LINE; i <= R3F7_LINE; ++i)
	{
		strHeader = m_plistHDDHDrs[i];
		m_listHDD.InsertItem(i, strHeader);
		m_listHDD.SetItem(i, LISTHDD_VALUE11_COL, LVIF_TEXT, LPSTR_TEXTCALLBACK, 0, 0, 0, 0);
		m_listHDD.SetItem(i, LISTHDD_VALUE12_COL, LVIF_TEXT, LPSTR_TEXTCALLBACK, 0, 0, 0, 0);
		m_listHDD.SetItem(i, LISTHDD_NAME2_COL, LVIF_TEXT, strHeader, 0, 0, 0, 0);
		m_listHDD.SetItem(i, LISTHDD_VALUE21_COL, LVIF_TEXT, LPSTR_TEXTCALLBACK, 0, 0, 0, 0);
		m_listHDD.SetItem(i, LISTHDD_VALUE22_COL, LVIF_TEXT, LPSTR_TEXTCALLBACK, 0, 0, 0, 0);
	}

	m_listHDD.SetColumnBkColor(GetSysColor(COLOR_BTNFACE), LISTHDD_NAME1_COL);
	m_listHDD.EnableColumnEdit(false, LISTHDD_NAME1_COL);
	m_listHDD.EnableColumnEdit(false, LISTHDD_VALUE11_COL); //значения редактировать тоже запрещаем
	m_listHDD.EnableColumnEdit(false, LISTHDD_VALUE12_COL); //значения редактировать тоже запрещаем
	m_listHDD.SetColumnBkColor(GetSysColor(COLOR_BTNFACE), LISTHDD_NAME2_COL);
	m_listHDD.EnableColumnEdit(false, LISTHDD_NAME2_COL);
	m_listHDD.EnableColumnEdit(false, LISTHDD_VALUE21_COL); //значения редактировать тоже запрещаем
	m_listHDD.EnableColumnEdit(false, LISTHDD_VALUE22_COL); //значения редактировать тоже запрещаем
	ResizeList(&m_listHDD, R3F7_LINE + 1);
	// Create layout
	m_Resizer.Init(this);
	m_Resizer.AddCtrl(IDC_MD_HDD_REGISTERS, DT_LEFT | DT_TOP, TRUE, TRUE);
	m_Resizer.AddCtrl(IDC_MD_FDD_DATA, DT_LEFT | DT_TOP, TRUE, TRUE);
	return TRUE; // return TRUE unless you set the focus to a control
	// EXCEPTION: OCX Property Pages should return FALSE
}

void CRegDumpFDDDlg::AttachDebugger(CDebugger *pDbgr)
{
	m_pDebugger = pDbgr;
}


//отменяем действие кнопок enter и esc в диалоге
void CRegDumpFDDDlg::OnOK()
{
}

void CRegDumpFDDDlg::OnCancel()
{
}


void CRegDumpFDDDlg::OnSize(UINT nType, int cx, int cy)
{
	CDialogEx::OnSize(nType, cx, cy);
	// Resize layout to current window size
	m_Resizer.OnSize(cx, cy);
}

CSize CRegDumpFDDDlg::GetMinSize()
{
	CSize size;
	MINMAXINFO mmi;
	m_Resizer.GetMinMaxInfo(&mmi);
	size.cx = mmi.ptMinTrackSize.x;
	size.cy = mmi.ptMinTrackSize.y;
	return size;
}



void CRegDumpFDDDlg::DisplayFDDData()
{
	if (m_pDebugger)
	{
		for (int i = FDDREG177130IN_LINE; i <= FDDREG177132OUT_LINE; ++i)
		{
			m_listFDD.SetItemWithModified(m_pDebugger->GetFDDData(i), i, LISTFDD_VALUE_COL);
		}
	}
}

void CRegDumpFDDDlg::DisplayHDDData()
{
	if (m_pDebugger)
	{
		for (int i = R1F0_LINE; i <= R3F7_LINE; ++i)
		{
			m_listHDD.SetItemWithModified(m_pDebugger->GetDebugHDDRegs(0, i, true), i, LISTHDD_VALUE11_COL);
			m_listHDD.SetItemWithModified(m_pDebugger->GetDebugHDDRegs(0, i, false), i, LISTHDD_VALUE12_COL);
			m_listHDD.SetItemWithModified(m_pDebugger->GetDebugHDDRegs(1, i, true), i, LISTHDD_VALUE21_COL);
			m_listHDD.SetItemWithModified(m_pDebugger->GetDebugHDDRegs(1, i, false), i, LISTHDD_VALUE22_COL);
		}
	}
}





void CRegDumpFDDDlg::OnLvnItemchangedMdFddData(NMHDR *pNMHDR, LRESULT *pResult)
{
	auto pNMLV = reinterpret_cast<LPNMLISTVIEW >(pNMHDR);
	// TODO: добавьте свой код обработчика уведомлений
	*pResult = S_OK;
}

//для того, чтобы акселераторы работали, их надо загрузить и в этот диалог
//и передавать главному фрейму.
// способа проще найти не получилось.
BOOL CRegDumpFDDDlg::PreTranslateMessage(MSG *pMsg)
{
	if (m_hAccelTable)
	{
		if (::TranslateAccelerator(AfxGetMainWnd()->GetSafeHwnd(), m_hAccelTable, pMsg))
		{
			return TRUE;
		}
	}

	m_ToolTip.RelayEvent(pMsg);
	return CDialogEx::PreTranslateMessage(pMsg);
}

