mame/src/osd/modules/debugger/win/memorywininfo.cpp

303 lines
9.2 KiB
C++

// license:BSD-3-Clause
// copyright-holders:Aaron Giles, Vas Crabb
//============================================================
//
// memorywininfo.c - Win32 debug window handling
//
//============================================================
#include "emu.h"
#include "memorywininfo.h"
#include "debugviewinfo.h"
#include "memoryviewinfo.h"
#include "uimetrics.h"
#include "winutf8.h"
memorywin_info::memorywin_info(debugger_windows_interface &debugger) :
editwin_info(debugger, false, "Memory", nullptr),
m_combownd(nullptr)
{
if (!window())
return;
m_views[0].reset(new memoryview_info(debugger, *this, window()));
if ((m_views[0] == nullptr) || !m_views[0]->is_valid())
{
m_views[0].reset();
return;
}
// create the options menu
HMENU const optionsmenu = CreatePopupMenu();
AppendMenu(optionsmenu, MF_ENABLED, ID_1_BYTE_CHUNKS, TEXT("1-byte chunks\tCtrl+1"));
AppendMenu(optionsmenu, MF_ENABLED, ID_2_BYTE_CHUNKS, TEXT("2-byte chunks\tCtrl+2"));
AppendMenu(optionsmenu, MF_ENABLED, ID_4_BYTE_CHUNKS, TEXT("4-byte chunks\tCtrl+4"));
AppendMenu(optionsmenu, MF_ENABLED, ID_8_BYTE_CHUNKS, TEXT("8-byte chunks\tCtrl+8"));
AppendMenu(optionsmenu, MF_ENABLED, ID_FLOATING_POINT_32BIT, TEXT("32 bit floating point\tCtrl+9"));
AppendMenu(optionsmenu, MF_ENABLED, ID_FLOATING_POINT_64BIT, TEXT("64 bit floating point"));
AppendMenu(optionsmenu, MF_ENABLED, ID_FLOATING_POINT_80BIT, TEXT("80 bit floating point"));
AppendMenu(optionsmenu, MF_DISABLED | MF_SEPARATOR, 0, TEXT(""));
AppendMenu(optionsmenu, MF_ENABLED, ID_LOGICAL_ADDRESSES, TEXT("Logical Addresses\tCtrl+L"));
AppendMenu(optionsmenu, MF_ENABLED, ID_PHYSICAL_ADDRESSES, TEXT("Physical Addresses\tCtrl+Y"));
AppendMenu(optionsmenu, MF_DISABLED | MF_SEPARATOR, 0, TEXT(""));
AppendMenu(optionsmenu, MF_ENABLED, ID_REVERSE_VIEW, TEXT("Reverse View\tCtrl+R"));
AppendMenu(optionsmenu, MF_DISABLED | MF_SEPARATOR, 0, TEXT(""));
AppendMenu(optionsmenu, MF_ENABLED, ID_INCREASE_MEM_WIDTH, TEXT("Increase bytes per line\tCtrl+P"));
AppendMenu(optionsmenu, MF_ENABLED, ID_DECREASE_MEM_WIDTH, TEXT("Decrease bytes per line\tCtrl+O"));
AppendMenu(GetMenu(window()), MF_ENABLED | MF_POPUP, (UINT_PTR)optionsmenu, TEXT("Options"));
// set up the view to track the initial expression
downcast<memoryview_info *>(m_views[0].get())->set_expression("0");
set_edit_defstr("0");
set_editwnd_text("0");
editwnd_select_all();
// create a combo box
m_views[0]->set_source_for_visible_cpu();
m_combownd = m_views[0]->create_source_combobox(window(), (LONG_PTR)this);
// set the caption
update_caption();
// recompute the children once to get the maxwidth
memorywin_info::recompute_children();
// position the window and recompute children again
SetWindowPos(window(), HWND_TOP, 100, 100, maxwidth(), 200, SWP_SHOWWINDOW);
memorywin_info::recompute_children();
// mark the edit box as the default focus and set it
editwin_info::set_default_focus();
}
memorywin_info::~memorywin_info()
{
}
bool memorywin_info::handle_key(WPARAM wparam, LPARAM lparam)
{
if (GetAsyncKeyState(VK_CONTROL) & 0x8000)
{
switch (wparam)
{
case '1':
SendMessage(window(), WM_COMMAND, ID_1_BYTE_CHUNKS, 0);
return true;
case '2':
SendMessage(window(), WM_COMMAND, ID_2_BYTE_CHUNKS, 0);
return true;
case '4':
SendMessage(window(), WM_COMMAND, ID_4_BYTE_CHUNKS, 0);
return true;
case '8':
SendMessage(window(), WM_COMMAND, ID_8_BYTE_CHUNKS, 0);
return true;
case '9':
SendMessage(window(), WM_COMMAND, ID_FLOATING_POINT_32BIT, 0);
return true;
case 'L':
SendMessage(window(), WM_COMMAND, ID_LOGICAL_ADDRESSES, 0);
return true;
case 'Y':
SendMessage(window(), WM_COMMAND, ID_PHYSICAL_ADDRESSES, 0);
return true;
case 'R':
SendMessage(window(), WM_COMMAND, ID_REVERSE_VIEW, 0);
return true;
case 'P':
SendMessage(window(), WM_COMMAND, ID_INCREASE_MEM_WIDTH, 0);
return true;
case 'O':
SendMessage(window(), WM_COMMAND, ID_DECREASE_MEM_WIDTH, 0);
return true;
}
}
return editwin_info::handle_key(wparam, lparam);
}
void memorywin_info::recompute_children()
{
// compute a client rect
RECT bounds;
bounds.top = bounds.left = 0;
bounds.right = m_views[0]->prefwidth() + (2 * EDGE_WIDTH);
bounds.bottom = 200;
AdjustWindowRectEx(&bounds, DEBUG_WINDOW_STYLE, FALSE, DEBUG_WINDOW_STYLE_EX);
// clamp the min/max size
set_maxwidth(bounds.right - bounds.left);
// get the parent's dimensions
RECT parent;
GetClientRect(window(), &parent);
// edit box gets half of the width
RECT editrect;
editrect.top = parent.top + EDGE_WIDTH;
editrect.bottom = editrect.top + metrics().debug_font_height() + 4;
editrect.left = parent.left + EDGE_WIDTH;
editrect.right = parent.left + ((parent.right - parent.left) / 2) - EDGE_WIDTH;
// combo box gets the other half of the width
RECT comborect;
comborect.top = editrect.top;
comborect.bottom = editrect.bottom;
comborect.left = editrect.right + (2 * EDGE_WIDTH);
comborect.right = parent.right - EDGE_WIDTH;
// memory view gets the rest
RECT memrect;
memrect.top = editrect.bottom + (2 * EDGE_WIDTH);
memrect.bottom = parent.bottom - EDGE_WIDTH;
memrect.left = parent.left + EDGE_WIDTH;
memrect.right = parent.right - EDGE_WIDTH;
// set the bounds of things
m_views[0]->set_bounds(memrect);
set_editwnd_bounds(editrect);
smart_set_window_bounds(m_combownd, window(), comborect);
}
void memorywin_info::update_menu()
{
editwin_info::update_menu();
auto *const memview = downcast<memoryview_info *>(m_views[0].get());
HMENU const menu = GetMenu(window());
CheckMenuItem(menu, ID_1_BYTE_CHUNKS, MF_BYCOMMAND | (memview->data_format() == debug_view_memory::data_format::HEX_8BIT ? MF_CHECKED : MF_UNCHECKED));
CheckMenuItem(menu, ID_2_BYTE_CHUNKS, MF_BYCOMMAND | (memview->data_format() == debug_view_memory::data_format::HEX_16BIT ? MF_CHECKED : MF_UNCHECKED));
CheckMenuItem(menu, ID_4_BYTE_CHUNKS, MF_BYCOMMAND | (memview->data_format() == debug_view_memory::data_format::HEX_32BIT ? MF_CHECKED : MF_UNCHECKED));
CheckMenuItem(menu, ID_8_BYTE_CHUNKS, MF_BYCOMMAND | (memview->data_format() == debug_view_memory::data_format::HEX_64BIT ? MF_CHECKED : MF_UNCHECKED));
CheckMenuItem(menu, ID_FLOATING_POINT_32BIT, MF_BYCOMMAND | (memview->data_format() == debug_view_memory::data_format::FLOAT_32BIT ? MF_CHECKED : MF_UNCHECKED));
CheckMenuItem(menu, ID_FLOATING_POINT_64BIT, MF_BYCOMMAND | (memview->data_format() == debug_view_memory::data_format::FLOAT_64BIT ? MF_CHECKED : MF_UNCHECKED));
CheckMenuItem(menu, ID_FLOATING_POINT_80BIT, MF_BYCOMMAND | (memview->data_format() == debug_view_memory::data_format::FLOAT_80BIT ? MF_CHECKED : MF_UNCHECKED));
CheckMenuItem(menu, ID_LOGICAL_ADDRESSES, MF_BYCOMMAND | (memview->physical() ? MF_UNCHECKED : MF_CHECKED));
CheckMenuItem(menu, ID_PHYSICAL_ADDRESSES, MF_BYCOMMAND | (memview->physical() ? MF_CHECKED : MF_UNCHECKED));
CheckMenuItem(menu, ID_REVERSE_VIEW, MF_BYCOMMAND | (memview->reverse() ? MF_CHECKED : MF_UNCHECKED));
EnableMenuItem(menu, ID_DECREASE_MEM_WIDTH, MF_BYCOMMAND | ((memview->chunks_per_row() > 1) ? MF_ENABLED : MF_GRAYED));
}
bool memorywin_info::handle_command(WPARAM wparam, LPARAM lparam)
{
auto *const memview = downcast<memoryview_info *>(m_views[0].get());
switch (HIWORD(wparam))
{
// combo box selection changed
case CBN_SELCHANGE:
{
int const sel = SendMessage((HWND)lparam, CB_GETCURSEL, 0, 0);
if (sel != CB_ERR)
{
memview->set_source_index(sel);
update_caption();
// reset the focus
set_default_focus();
return true;
}
break;
}
// menu selections
case 0:
switch (LOWORD(wparam))
{
case ID_1_BYTE_CHUNKS:
memview->set_data_format(1);
return true;
case ID_2_BYTE_CHUNKS:
memview->set_data_format(2);
return true;
case ID_4_BYTE_CHUNKS:
memview->set_data_format(4);
return true;
case ID_8_BYTE_CHUNKS:
memview->set_data_format(8);
return true;
case ID_FLOATING_POINT_32BIT:
memview->set_data_format(9);
return true;
case ID_FLOATING_POINT_64BIT:
memview->set_data_format(10);
return true;
case ID_FLOATING_POINT_80BIT:
memview->set_data_format(11);
return true;
case ID_LOGICAL_ADDRESSES:
memview->set_physical(false);
return true;
case ID_PHYSICAL_ADDRESSES:
memview->set_physical(true);
return true;
case ID_REVERSE_VIEW:
memview->set_reverse(!memview->reverse());
return true;
case ID_INCREASE_MEM_WIDTH:
memview->set_chunks_per_row(memview->chunks_per_row() + 1);
recompute_children();
return true;
case ID_DECREASE_MEM_WIDTH:
memview->set_chunks_per_row(memview->chunks_per_row() - 1);
recompute_children();
return true;
}
break;
}
return editwin_info::handle_command(wparam, lparam);
}
void memorywin_info::draw_contents(HDC dc)
{
editwin_info::draw_contents(dc);
if (m_combownd)
draw_border(dc, m_combownd);
}
void memorywin_info::process_string(const std::string &string)
{
// set the string to the memory view
downcast<memoryview_info *>(m_views[0].get())->set_expression(string);
// select everything in the edit text box
editwnd_select_all();
// update the default string to match
set_edit_defstr(string);
}
void memorywin_info::update_caption()
{
win_set_window_text_utf8(window(), std::string("Memory: ").append(m_views[0]->source_name()).c_str());
}