
// DisasmDlg.cpp : implementation file
//

#include "pch.h"
#include "DisasmDlg.h"
#include "afxdialogex.h"
#include "Debugger.h"
#include "Platform.h"

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

/////////////////////////////////////////////////////////////////////////////
// CDisasmDlg dialog

CDisasmDlg::CDisasmDlg(CWnd *pParent /*=nullptr*/)
	: CDialogEx(CDisasmDlg::IDD, pParent)
	, m_hAccelTable(nullptr)
	, m_strDisasmAddr(_T("0"))
{
}

CDisasmDlg::~CDisasmDlg()
{
	m_hFont.DeleteObject();
}

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

void CDisasmDlg::DoDataExchange(CDataExchange *pDX)
{
	CDialogEx::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_LIST_DA_DISASM, m_ListDisasm);
	DDX_Control(pDX, IDC_EDIT_DA_DBGADDR, m_EditAddr);
	DDX_Text(pDX, IDC_EDIT_DA_DBGADDR, m_strDisasmAddr);
}


BEGIN_MESSAGE_MAP(CDisasmDlg, CDialogEx)
	ON_WM_SIZE()
	ON_WM_GETMINMAXINFO()
	ON_WM_SETFOCUS()
	ON_MESSAGE(WM_DBG_TOP_ADDRESS_UPDATE, &CDisasmDlg::OnDisasmTopAddressUpdate)
	ON_MESSAGE(WM_DBG_TOP_ADDRESS_SET, &CDisasmDlg::OnDisasmTopAddressSet)
	ON_MESSAGE(WM_DBG_CURRENT_ADDRESS_CHANGE, &CDisasmDlg::OnDisasmCurrentAddressChange)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CDisasmDlg message handlers

BOOL CDisasmDlg::OnInitDialog()
{
	CDialogEx::OnInitDialog();
	m_hAccelTable = LoadAccelerators(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDR_MAINFRAME));
	m_Resizer.Init(this);
	m_Resizer.AddCtrl(IDC_LIST_DA_DISASM, DT_LEFT | DT_TOP | DT_RIGHT | DT_BOTTOM, FALSE, FALSE);
	m_Resizer.AddCtrl(IDC_EDIT_DA_DBGADDR, DT_LEFT | DT_TOP, TRUE, TRUE);
	m_EditAddr.SetLimitText(6);
	LOGFONT lf;
	::GetObject((HGDIOBJ)::SendMessage(GetSafeHwnd(), WM_GETFONT, 0, 0), sizeof(LOGFONT), &lf);
	_tcscpy_s(lf.lfFaceName, LF_FACESIZE, _T("Courier New\0"));

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

	m_ListDisasm.SetFont(&m_hFont, FALSE);
	m_ListDisasm.Init();
	return TRUE; // return TRUE unless you set the focus to a control
	// EXCEPTION: OCX Property Pages should return FALSE
}

void CDisasmDlg::InitDebugger()
{
	m_ListDisasm.AttachDebugger(g_Platform.GetDebuggerPtr());
	g_Platform.GetDebuggerPtr()->AttachWnd(this);
	SetDisasmAddr(g_Config.m_nDisasmAddr);
	m_ListDisasm.Invalidate(FALSE); // перерисуем дизассемблер
}

void CDisasmDlg::SetDisasmAddr(uint16_t addr)
{
	m_strDisasmAddr = ::WordToOctString(addr);
	UpdateData(FALSE);
}

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

void CDisasmDlg::OnCancel()
{
}


void CDisasmDlg::OnSize(UINT nType, int cx, int cy)
{
	CDialogEx::OnSize(nType, cx, cy);
	m_Resizer.OnSize(cx, cy);
}

void CDisasmDlg::OnGetMinMaxInfo(MINMAXINFO *lpMMI)
{
	m_Resizer.GetMinMaxInfo(lpMMI);
}

void CDisasmDlg::OnSetFocus(CWnd *pOldWnd)
{
	CDialogEx::OnSetFocus(pOldWnd);
	m_ListDisasm.SetFocus();
}


LRESULT CDisasmDlg::OnDisasmTopAddressUpdate(WPARAM, LPARAM)
{
	UpdateData(TRUE);
	uint16_t nAddr = ::OctStringToWord(m_strDisasmAddr);
	g_Config.m_nDisasmAddr = nAddr;
	// обновим значение, чтобы оно было всегда 6 значным
	SetDisasmAddr(nAddr);  // обновим адрес в поле адреса.
	m_ListDisasm.Invalidate(FALSE); // перерисуем дизассемблер
	return S_OK;
}

LRESULT CDisasmDlg::OnDisasmCurrentAddressChange(WPARAM wp, LPARAM)
{
	SetDisasmAddr(uint16_t(wp));
	m_ListDisasm.Invalidate(FALSE); // перерисуем дизассемблер
	return S_OK;
}

LRESULT CDisasmDlg::OnDisasmTopAddressSet(WPARAM wp, LPARAM)
{
	SetDisasmAddr(uint16_t(wp));
	return S_OK;
}

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

	return CDialogEx::PreTranslateMessage(pMsg);
}
