1
0
mirror of https://git.code.sf.net/p/fuse-emulator/fuse synced 2026-01-27 01:41:34 +03:00
Files
fuse/ui/win32/memorybrowser.c
Fredrick Meunier ba77c2ab67 Move memory.[ch] to memory_pages.[ch]
To avoid clashes with any similarly named system files (thanks,
BogDan Vatra and Sergio Baldoví).
2016-12-10 20:27:03 +11:00

382 lines
10 KiB
C

/* memorybrowser.c: the Win32 memory browser
Copyright (c) 2008 Marek Januszewski
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Author contact information:
E-mail: philip-fuse@shadowmagic.org.uk
*/
#include <config.h>
#include <libspectrum.h>
#include <tchar.h>
#include <windows.h>
#include "compat.h"
#include "fuse.h"
#include "memory_pages.h"
#include "win32internals.h"
#include "memorybrowser.h"
static INT_PTR CALLBACK
memorybrowser_proc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam );
static LRESULT CALLBACK
memory_listview_proc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam );
static void
memorybrowser_init( HWND hwndDlg );
void
menu_machine_memorybrowser( int action );
/* helper constants for memory listview's scrollbar */
static const int memorysb_min = 0x0000;
static const int memorysb_max = 0x10000;
static const int memorysb_step = 0x10;
/* Visual styles could change visible rows */
static int memorysb_page_inc = 0xa0;
static int memorysb_page_size = 0x140;
static int memorysb_page_rows = 20;
/* Address of first visible row */
static libspectrum_word memaddr = 0x0000;
static void
update_display( HWND hwndDlg, libspectrum_word base )
{
int i, j;
TCHAR buffer[ 8 + 64 + 20 ];
TCHAR *text[] = { &buffer[0], &buffer[ 8 ], &buffer[ 8 + 64 ] };
TCHAR buffer2[ 8 ];
memaddr = base;
SendDlgItemMessage( hwndDlg, IDC_MEM_LV, LVM_DELETEALLITEMS, 0, 0 );
LV_ITEM lvi;
lvi.mask = LVIF_TEXT;
for( i = 0; i < memorysb_page_rows; i++ ) {
_sntprintf( text[0], 8, TEXT( "%04X" ), base );
text[1][0] = '\0';
for( j = 0; j < memorysb_step; j++, base++ ) {
libspectrum_byte b = readbyte_internal( base );
_sntprintf( buffer2, 4, TEXT( "%02X " ), b );
_tcsncat( text[1], buffer2, 4 );
text[2][j] = ( b >= 32 && b < 127 ) ? b : '.';
}
text[2][ 0x10 ] = '\0';
/* append the item */
lvi.iItem = SendDlgItemMessage( hwndDlg, IDC_MEM_LV,
LVM_GETITEMCOUNT, 0, 0 );
lvi.iSubItem = 0;
lvi.pszText = text[0];
SendDlgItemMessage( hwndDlg, IDC_MEM_LV, LVM_INSERTITEM, 0,
( LPARAM ) &lvi );
lvi.iSubItem = 1;
lvi.pszText = text[1];
SendDlgItemMessage( hwndDlg, IDC_MEM_LV, LVM_SETITEM, 0,
( LPARAM ) &lvi );
lvi.iSubItem = 2;
lvi.pszText = text[2];
SendDlgItemMessage( hwndDlg, IDC_MEM_LV, LVM_SETITEM, 0,
( LPARAM ) &lvi );
}
}
static int
scroller( HWND hwndDlg, WPARAM scroll_command )
{
libspectrum_word base;
SCROLLINFO si;
memset( &si, 0, sizeof( si ) );
si.cbSize = sizeof(si);
si.fMask = SIF_POS;
GetScrollInfo( GetDlgItem( hwndDlg, IDC_MEM_SB ), SB_CTL, &si );
int value = si.nPos;
int selected = 0;
/* in Windows we have to read the command and scroll the scrollbar manually */
switch( LOWORD( scroll_command ) ) {
case SB_BOTTOM:
value = memorysb_max;
selected = memorysb_page_rows - 1;
break;
case SB_TOP:
value = memorysb_min;
break;
case SB_LINEDOWN:
value += memorysb_step;
selected = 1;
break;
case SB_LINEUP:
value -= memorysb_step;
break;
case SB_PAGEUP:
value -= memorysb_page_inc;
break;
case SB_PAGEDOWN:
value += memorysb_page_inc;
selected = memorysb_page_rows - 1;
break;
case SB_THUMBPOSITION:
case SB_THUMBTRACK:
value = HIWORD( scroll_command );
break;
default:
return 1;
}
if( value > memorysb_max - memorysb_page_size )
value = memorysb_max - memorysb_page_size;
if( value < memorysb_min ) value = memorysb_min;
/* Drop the low bits before displaying anything */
base = value; base &= 0xfff0;
if( base != memaddr ) {
/* set the new scrollbar position */
memset( &si, 0, sizeof(si) );
si.cbSize = sizeof(si);
si.fMask = SIF_POS;
si.nPos = base;
SetScrollInfo( GetDlgItem( hwndDlg, IDC_MEM_SB ), SB_CTL, &si, TRUE );
update_display( hwndDlg, base );
}
/* Select row according to last scroll command */
ListView_SetItemState( GetDlgItem( hwndDlg, IDC_MEM_LV ), selected,
LVIS_SELECTED, LVIS_SELECTED );
return 0;
}
void
menu_machine_memorybrowser( int action GCC_UNUSED )
{
fuse_emulation_pause();
DialogBox( fuse_hInstance, MAKEINTRESOURCE( IDD_MEM ),
fuse_hWnd, (DLGPROC) memorybrowser_proc );
fuse_emulation_unpause();
return;
}
static INT_PTR CALLBACK
memorybrowser_proc( HWND hwndDlg, UINT uMsg, WPARAM wParam,
LPARAM lParam GCC_UNUSED )
{
switch( uMsg )
{
case WM_INITDIALOG:
memorybrowser_init( hwndDlg );
return TRUE;
case WM_COMMAND:
if( LOWORD( wParam ) == IDCLOSE ||
LOWORD( wParam ) == IDCANCEL ) {
EndDialog( hwndDlg, 0 );
return TRUE;
}
break;
case WM_CLOSE: {
EndDialog( hwndDlg, 0 );
return TRUE;
}
case WM_VSCROLL:
/* Accept vertical scroll from listview too */
scroller( hwndDlg, wParam );
return TRUE;
case WM_MOUSEWHEEL:
{
/* get current position */
SCROLLINFO si;
memset( &si, 0, sizeof(si) );
si.cbSize = sizeof(si);
si.fMask = SIF_POS;
GetScrollInfo( GetDlgItem( hwndDlg, IDC_MEM_SB ), SB_CTL, &si );
/* convert delta displacement to memory displacement */
short delta = (short) HIWORD( wParam ) / WHEEL_DELTA;
int value = si.nPos - delta * memorysb_step;
if( value > memorysb_max - memorysb_page_size )
value = memorysb_max - memorysb_page_size;
if( value < memorysb_min ) value = memorysb_min;
/* scroll to new position */
scroller( hwndDlg, MAKEWPARAM( SB_THUMBPOSITION, value ) );
return TRUE;
}
}
return FALSE;
}
static LRESULT CALLBACK
memory_listview_proc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
switch( msg ) {
case WM_DESTROY:
{
WNDPROC orig_proc = (WNDPROC) GetProp( hWnd, "original_proc" );
SetWindowLongPtr( hWnd, GWLP_WNDPROC, (LONG_PTR) orig_proc );
RemoveProp( hWnd, "original_proc" );
break;
}
case WM_KEYDOWN:
{
WORD scroll_notify = 0xffff;
switch( wParam )
{
case VK_UP:
scroll_notify = SB_LINEUP;
break;
case VK_PRIOR:
scroll_notify = SB_PAGEUP;
break;
case VK_NEXT:
scroll_notify = SB_PAGEDOWN;
break;
case VK_DOWN:
scroll_notify = SB_LINEDOWN;
break;
case VK_HOME:
scroll_notify = SB_TOP;
break;
case VK_END:
scroll_notify = SB_BOTTOM;
break;
}
/* Inform parent window about key scrolling */
if( scroll_notify != 0xffff ) {
SendMessage( GetParent( hWnd ), WM_VSCROLL,
MAKEWPARAM( scroll_notify, 0 ), (LPARAM) NULL );
return 0;
}
break;
}
case WM_MOUSEWHEEL:
{
/* Inform parent window about mouse scrolling */
SendMessage( GetParent( hWnd ), WM_MOUSEWHEEL, wParam, lParam );
return 0;
}
}
WNDPROC orig_proc = (WNDPROC) GetProp( hWnd, "original_proc" );
return CallWindowProc( orig_proc, hWnd, msg, wParam, lParam );
}
static void
memorybrowser_init( HWND hwndDlg )
{
size_t i;
int error;
HFONT font;
const TCHAR *titles[] = { "Address", "Hex", "Data" };
int column_widths[] = { 62, 348, 124 };
error = win32ui_get_monospaced_font( &font ); if( error ) return;
/* subclass listview to catch keydown and mousewheel messages */
HWND hwnd_list = GetDlgItem( hwndDlg, IDC_MEM_LV );
WNDPROC orig_proc = (WNDPROC) GetWindowLongPtr( hwnd_list, GWLP_WNDPROC );
SetProp( hwnd_list, "original_proc", (HANDLE) orig_proc );
SetWindowLongPtr( hwnd_list, GWLP_WNDPROC,
(LONG_PTR) (WNDPROC) memory_listview_proc );
/* set extended listview style to select full row, when an item is selected */
DWORD lv_ext_style;
lv_ext_style = SendDlgItemMessage( hwndDlg, IDC_MEM_LV,
LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0 );
lv_ext_style |= LVS_EX_FULLROWSELECT;
lv_ext_style |= LVS_EX_DOUBLEBUFFER;
SendDlgItemMessage( hwndDlg, IDC_MEM_LV,
LVM_SETEXTENDEDLISTVIEWSTYLE, 0, lv_ext_style );
/* create columns */
LVCOLUMN lvc;
lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT ;
lvc.fmt = LVCFMT_LEFT;
for( i = 0; i < 3; i++ ) {
if( i != 0 )
lvc.mask |= LVCF_SUBITEM;
lvc.cx = column_widths[i];
lvc.pszText = (TCHAR *)titles[i];
SendDlgItemMessage( hwndDlg, IDC_MEM_LV, LVM_INSERTCOLUMN, i,
( LPARAM ) &lvc );
}
/* set font of the listview to monospaced one */
SendDlgItemMessage( hwndDlg, IDC_MEM_LV , WM_SETFONT,
(WPARAM) font, FALSE );
/* Recalculate visible rows, Visual Styles could change rows height */
memorysb_page_rows = SendDlgItemMessage( hwndDlg, IDC_MEM_LV,
LVM_GETCOUNTPERPAGE, 0, 0 );
memorysb_page_size = memorysb_page_rows * memorysb_step;
memorysb_page_inc = memorysb_page_size / 2;
/* set the scrollbar parameters */
SCROLLINFO si;
si.cbSize = sizeof(si);
si.fMask = SIF_POS | SIF_RANGE | SIF_PAGE;
si.nPos = memaddr;
si.nMin = memorysb_min;
si.nMax = memorysb_max;
si.nPage = memorysb_page_size;
SetScrollInfo( GetDlgItem( hwndDlg, IDC_MEM_SB ), SB_CTL, &si, TRUE );
update_display( hwndDlg, memaddr );
/* Recalculate columns width, high DPI resolutions have larger sizes */
ListView_SetColumnWidth( hwnd_list, 0, LVSCW_AUTOSIZE_USEHEADER );
ListView_SetColumnWidth( hwnd_list, 1, LVSCW_AUTOSIZE );
ListView_SetColumnWidth( hwnd_list, 2, LVSCW_AUTOSIZE_USEHEADER );
}