562 lines
17 KiB
C#
562 lines
17 KiB
C#
|
using System;
|
|||
|
using System.Collections.Generic;
|
|||
|
using System.ComponentModel;
|
|||
|
using System.Drawing;
|
|||
|
using System.Data;
|
|||
|
using System.Linq;
|
|||
|
using System.Text;
|
|||
|
using System.Threading.Tasks;
|
|||
|
using System.Windows.Forms;
|
|||
|
using Mesen.GUI.Config;
|
|||
|
using System.Globalization;
|
|||
|
|
|||
|
namespace Mesen.GUI.Debugger.Controls
|
|||
|
{
|
|||
|
public partial class CodeViewerActions : UserControl
|
|||
|
{
|
|||
|
public event SetNextStatementEventHandler OnSetNextStatement;
|
|||
|
public event ShowInSplitViewEventHandler OnShowInSplitView;
|
|||
|
public event SwitchToSourceEventHandler OnSwitchView;
|
|||
|
|
|||
|
private int _lastClickedAddress = Int32.MaxValue;
|
|||
|
private string _newWatchValue = string.Empty;
|
|||
|
private string _lastWord = string.Empty;
|
|||
|
private Point _lastLocation = Point.Empty;
|
|||
|
private DebugViewInfo _config;
|
|||
|
|
|||
|
public ICodeViewer Viewer { get; set; }
|
|||
|
public bool SourceView { get; set; }
|
|||
|
|
|||
|
public CodeViewerActions()
|
|||
|
{
|
|||
|
InitializeComponent();
|
|||
|
}
|
|||
|
|
|||
|
public CodeViewerActions(ICodeViewer viewer, bool isSourceView) : this()
|
|||
|
{
|
|||
|
Viewer = viewer;
|
|||
|
SourceView = isSourceView;
|
|||
|
|
|||
|
this.InitShortcuts();
|
|||
|
}
|
|||
|
|
|||
|
private void InitShortcuts()
|
|||
|
{
|
|||
|
mnuEditInMemoryViewer.InitShortcut(this, nameof(DebuggerShortcutsConfig.CodeWindow_EditInMemoryViewer));
|
|||
|
mnuEditLabel.InitShortcut(this, nameof(DebuggerShortcutsConfig.CodeWindow_EditLabel));
|
|||
|
mnuSetNextStatement.InitShortcut(this, nameof(DebuggerShortcutsConfig.CodeWindow_SetNextStatement));
|
|||
|
mnuShowNextStatement.InitShortcut(this, nameof(DebuggerShortcutsConfig.GoToProgramCounter));
|
|||
|
mnuToggleBreakpoint.InitShortcut(this, nameof(DebuggerShortcutsConfig.CodeWindow_ToggleBreakpoint));
|
|||
|
|
|||
|
mnuUndoPrgChrEdit.InitShortcut(this, nameof(DebuggerShortcutsConfig.Undo));
|
|||
|
mnuCopySelection.InitShortcut(this, nameof(DebuggerShortcutsConfig.Copy));
|
|||
|
|
|||
|
mnuSwitchView.InitShortcut(this, nameof(DebuggerShortcutsConfig.CodeWindow_SwitchView));
|
|||
|
|
|||
|
if(!SourceView) {
|
|||
|
mnuNavigateBackward.InitShortcut(this, nameof(DebuggerShortcutsConfig.CodeWindow_NavigateBack));
|
|||
|
mnuNavigateForward.InitShortcut(this, nameof(DebuggerShortcutsConfig.CodeWindow_NavigateForward));
|
|||
|
|
|||
|
mnuEditSelectedCode.InitShortcut(this, nameof(DebuggerShortcutsConfig.CodeWindow_EditSelectedCode));
|
|||
|
mnuEditSubroutine.InitShortcut(this, nameof(DebuggerShortcutsConfig.CodeWindow_EditSubroutine));
|
|||
|
|
|||
|
mnuMarkAsCode.InitShortcut(this, nameof(DebuggerShortcutsConfig.MarkAsCode));
|
|||
|
mnuMarkAsData.InitShortcut(this, nameof(DebuggerShortcutsConfig.MarkAsData));
|
|||
|
mnuMarkAsUnidentifiedData.InitShortcut(this, nameof(DebuggerShortcutsConfig.MarkAsUnidentified));
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public void InitMenu(DebugViewInfo config)
|
|||
|
{
|
|||
|
_config = config;
|
|||
|
mnuPrgShowInline.Checked = false;
|
|||
|
mnuPrgAddressReplace.Checked = false;
|
|||
|
mnuPrgAddressBelow.Checked = false;
|
|||
|
mnuHidePrgAddresses.Checked = false;
|
|||
|
|
|||
|
mnuShowByteCodeOnLeft.Checked = false;
|
|||
|
mnuShowByteCodeBelow.Checked = false;
|
|||
|
mnuHideByteCode.Checked = false;
|
|||
|
|
|||
|
mnuShowSourceAsComments.Checked = config.ShowSourceAsComments;
|
|||
|
|
|||
|
switch(config.ByteCodePosition) {
|
|||
|
case ByteCodePosition.Left:
|
|||
|
Viewer.CodeViewer.ShowContentNotes = true;
|
|||
|
Viewer.CodeViewer.ShowSingleContentLineNotes = true;
|
|||
|
this.mnuShowByteCodeOnLeft.Checked = true;
|
|||
|
break;
|
|||
|
|
|||
|
case ByteCodePosition.Below:
|
|||
|
Viewer.CodeViewer.ShowContentNotes = true;
|
|||
|
Viewer.CodeViewer.ShowSingleContentLineNotes = false;
|
|||
|
this.mnuShowByteCodeBelow.Checked = true;
|
|||
|
break;
|
|||
|
|
|||
|
case ByteCodePosition.Hidden:
|
|||
|
Viewer.CodeViewer.ShowContentNotes = false;
|
|||
|
Viewer.CodeViewer.ShowSingleContentLineNotes = false;
|
|||
|
this.mnuHideByteCode.Checked = true;
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
switch(config.PrgAddressPosition) {
|
|||
|
case PrgAddressPosition.Inline:
|
|||
|
Viewer.CodeViewer.ShowCompactPrgAddresses = true;
|
|||
|
Viewer.CodeViewer.ShowLineNumberNotes = false;
|
|||
|
Viewer.CodeViewer.ShowSingleLineLineNumberNotes = false;
|
|||
|
this.mnuPrgShowInline.Checked = true;
|
|||
|
break;
|
|||
|
|
|||
|
case PrgAddressPosition.Replace:
|
|||
|
Viewer.CodeViewer.ShowCompactPrgAddresses = false;
|
|||
|
Viewer.CodeViewer.ShowLineNumberNotes = true;
|
|||
|
Viewer.CodeViewer.ShowSingleLineLineNumberNotes = true;
|
|||
|
this.mnuPrgAddressReplace.Checked = true;
|
|||
|
break;
|
|||
|
|
|||
|
case PrgAddressPosition.Below:
|
|||
|
Viewer.CodeViewer.ShowCompactPrgAddresses = false;
|
|||
|
Viewer.CodeViewer.ShowLineNumberNotes = true;
|
|||
|
Viewer.CodeViewer.ShowSingleLineLineNumberNotes = false;
|
|||
|
this.mnuPrgAddressBelow.Checked = true;
|
|||
|
break;
|
|||
|
|
|||
|
case PrgAddressPosition.Hidden:
|
|||
|
Viewer.CodeViewer.ShowCompactPrgAddresses = false;
|
|||
|
Viewer.CodeViewer.ShowLineNumberNotes = false;
|
|||
|
Viewer.CodeViewer.ShowSingleLineLineNumberNotes = false;
|
|||
|
this.mnuHidePrgAddresses.Checked = true;
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private void UpdateConfig()
|
|||
|
{
|
|||
|
this.InitMenu(_config);
|
|||
|
ConfigManager.ApplyChanges();
|
|||
|
}
|
|||
|
|
|||
|
private void contextMenuCode_Opening(object sender, CancelEventArgs e)
|
|||
|
{
|
|||
|
UpdateContextMenuItemVisibility(true);
|
|||
|
|
|||
|
int startAddress, endAddress;
|
|||
|
string range;
|
|||
|
GetSelectedAddressRange(out startAddress, out endAddress, out range);
|
|||
|
mnuMarkSelectionAs.Enabled = startAddress >= 0 && endAddress >= 0 && startAddress <= endAddress;
|
|||
|
if(mnuMarkSelectionAs.Enabled) {
|
|||
|
mnuMarkSelectionAs.Text = "Mark selection as... (" + range + ")";
|
|||
|
} else {
|
|||
|
mnuMarkSelectionAs.Text = "Mark selection as...";
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private void GetSelectedAddressRange(out int start, out int end, out string range)
|
|||
|
{
|
|||
|
int firstLineOfSelection = Viewer.CodeViewer.SelectionStart;
|
|||
|
while(Viewer.CodeViewer.GetLineNumber(firstLineOfSelection) < 0) {
|
|||
|
firstLineOfSelection++;
|
|||
|
}
|
|||
|
int firstLineAfterSelection = Viewer.CodeViewer.SelectionStart + Viewer.CodeViewer.SelectionLength + 1;
|
|||
|
while(Viewer.CodeViewer.GetLineNumber(firstLineAfterSelection) < 0) {
|
|||
|
firstLineAfterSelection++;
|
|||
|
}
|
|||
|
start = Viewer.CodeViewer.GetLineNumber(firstLineOfSelection);
|
|||
|
end = Viewer.CodeViewer.GetLineNumber(firstLineAfterSelection) - 1;
|
|||
|
|
|||
|
range = "";
|
|||
|
if(start >= 0 && end >= 0) {
|
|||
|
range = $"${start.ToString("X4")} - ${end.ToString("X4")}";
|
|||
|
start = InteropEmu.DebugGetAbsoluteAddress((UInt32)start);
|
|||
|
end = InteropEmu.DebugGetAbsoluteAddress((UInt32)end);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private void MarkSelectionAs(CdlPrgFlags type)
|
|||
|
{
|
|||
|
int startAddress, endAddress;
|
|||
|
string range;
|
|||
|
GetSelectedAddressRange(out startAddress, out endAddress, out range);
|
|||
|
|
|||
|
if(startAddress >= 0 && endAddress >= 0 && startAddress <= endAddress) {
|
|||
|
InteropEmu.DebugMarkPrgBytesAs((UInt32)startAddress, (UInt32)endAddress, type);
|
|||
|
|
|||
|
frmDebugger debugger = DebugWindowManager.GetDebugger();
|
|||
|
if(debugger != null) {
|
|||
|
debugger.UpdateDebugger(false);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private void mnuMarkAsCode_Click(object sender, EventArgs e)
|
|||
|
{
|
|||
|
this.MarkSelectionAs(CdlPrgFlags.Code);
|
|||
|
}
|
|||
|
|
|||
|
private void mnuMarkAsData_Click(object sender, EventArgs e)
|
|||
|
{
|
|||
|
this.MarkSelectionAs(CdlPrgFlags.Data);
|
|||
|
}
|
|||
|
|
|||
|
private void mnuMarkAsUnidentifiedData_Click(object sender, EventArgs e)
|
|||
|
{
|
|||
|
this.MarkSelectionAs(CdlPrgFlags.None);
|
|||
|
}
|
|||
|
|
|||
|
private void mnuGoToLocation_Click(object sender, EventArgs e)
|
|||
|
{
|
|||
|
GoToLocation();
|
|||
|
}
|
|||
|
|
|||
|
private void GoToLocation()
|
|||
|
{
|
|||
|
Viewer.ScrollToLineNumber((int)_lastClickedAddress);
|
|||
|
}
|
|||
|
|
|||
|
private void mnuAddToWatch_Click(object sender, EventArgs e)
|
|||
|
{
|
|||
|
AddWatch();
|
|||
|
}
|
|||
|
|
|||
|
private void AddWatch()
|
|||
|
{
|
|||
|
WatchManager.AddWatch(_newWatchValue);
|
|||
|
}
|
|||
|
|
|||
|
private void mnuShowInSplitView_Click(object sender, EventArgs e)
|
|||
|
{
|
|||
|
ShowInSplitView();
|
|||
|
}
|
|||
|
|
|||
|
private void ShowInSplitView()
|
|||
|
{
|
|||
|
this.OnShowInSplitView?.Invoke(Viewer, new AddressEventArgs() { Address = (UInt32)_lastClickedAddress });
|
|||
|
}
|
|||
|
|
|||
|
private void mnuEditLabel_Click(object sender, EventArgs e)
|
|||
|
{
|
|||
|
if(UpdateContextMenu(_lastLocation)) {
|
|||
|
AddressTypeInfo info = new AddressTypeInfo();
|
|||
|
InteropEmu.DebugGetAbsoluteAddressAndType((UInt32)_lastClickedAddress, ref info);
|
|||
|
if(info.Address >= 0) {
|
|||
|
ctrlLabelList.EditLabel((UInt32)info.Address, info.Type);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private void mnuNavigateForward_Click(object sender, EventArgs e)
|
|||
|
{
|
|||
|
Viewer.CodeViewer.NavigateForward();
|
|||
|
}
|
|||
|
|
|||
|
private void mnuNavigateBackward_Click(object sender, EventArgs e)
|
|||
|
{
|
|||
|
Viewer.CodeViewer.NavigateBackward();
|
|||
|
}
|
|||
|
|
|||
|
private void mnuToggleBreakpoint_Click(object sender, EventArgs e)
|
|||
|
{
|
|||
|
this.ToggleBreakpoint(false);
|
|||
|
}
|
|||
|
|
|||
|
public void ToggleBreakpoint(bool toggleEnabledFlag)
|
|||
|
{
|
|||
|
int relativeAddress = Viewer.CodeViewer.CurrentLine;
|
|||
|
AddressTypeInfo info = Viewer.GetAddressInfo(Viewer.CodeViewer.SelectedLine);
|
|||
|
|
|||
|
BreakpointManager.ToggleBreakpoint(relativeAddress, info, toggleEnabledFlag);
|
|||
|
}
|
|||
|
|
|||
|
private void mnuShowByteCodeOnLeft_Click(object sender, EventArgs e)
|
|||
|
{
|
|||
|
_config.ByteCodePosition = ByteCodePosition.Left;
|
|||
|
this.UpdateConfig();
|
|||
|
}
|
|||
|
|
|||
|
private void mnuShowByteCodeBelow_Click(object sender, EventArgs e)
|
|||
|
{
|
|||
|
_config.ByteCodePosition = ByteCodePosition.Below;
|
|||
|
this.UpdateConfig();
|
|||
|
}
|
|||
|
|
|||
|
private void mnuHideByteCode_Click(object sender, EventArgs e)
|
|||
|
{
|
|||
|
_config.ByteCodePosition = ByteCodePosition.Hidden;
|
|||
|
this.UpdateConfig();
|
|||
|
}
|
|||
|
|
|||
|
private void mnuShowSourceAsComments_Click(object sender, EventArgs e)
|
|||
|
{
|
|||
|
_config.ShowSourceAsComments = mnuShowSourceAsComments.Checked;
|
|||
|
this.UpdateConfig();
|
|||
|
}
|
|||
|
|
|||
|
private void mnuShowInlineCompactDisplay_Click(object sender, EventArgs e)
|
|||
|
{
|
|||
|
_config.PrgAddressPosition = PrgAddressPosition.Inline;
|
|||
|
this.UpdateConfig();
|
|||
|
}
|
|||
|
|
|||
|
private void mnuReplaceCpuAddress_Click(object sender, EventArgs e)
|
|||
|
{
|
|||
|
_config.PrgAddressPosition = PrgAddressPosition.Replace;
|
|||
|
this.UpdateConfig();
|
|||
|
}
|
|||
|
|
|||
|
private void mnuBelowCpuAddress_Click(object sender, EventArgs e)
|
|||
|
{
|
|||
|
_config.PrgAddressPosition = PrgAddressPosition.Below;
|
|||
|
this.UpdateConfig();
|
|||
|
}
|
|||
|
|
|||
|
private void mnuHidePrgAddresses_Click(object sender, EventArgs e)
|
|||
|
{
|
|||
|
_config.PrgAddressPosition = PrgAddressPosition.Hidden;
|
|||
|
this.UpdateConfig();
|
|||
|
}
|
|||
|
|
|||
|
private void mnuCopySelection_Click(object sender, EventArgs e)
|
|||
|
{
|
|||
|
Viewer.CodeViewer.CopySelection(ConfigManager.Config.DebugInfo.CopyAddresses, ConfigManager.Config.DebugInfo.CopyByteCode);
|
|||
|
}
|
|||
|
|
|||
|
private void mnuShowNextStatement_Click(object sender, EventArgs e)
|
|||
|
{
|
|||
|
this.ScrollToActiveAddress();
|
|||
|
}
|
|||
|
|
|||
|
public void ScrollToActiveAddress()
|
|||
|
{
|
|||
|
if(Viewer.ActiveAddress.HasValue) {
|
|||
|
Viewer.ScrollToLineNumber((int)Viewer.ActiveAddress.Value);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private void mnuShowLineNotes_Click(object sender, EventArgs e)
|
|||
|
{
|
|||
|
Viewer.CodeViewer.ShowLineNumberNotes = this.mnuShowLineNotes.Checked;
|
|||
|
this.UpdateConfig();
|
|||
|
}
|
|||
|
|
|||
|
private void mnuFindOccurrences_Click(object sender, EventArgs e)
|
|||
|
{
|
|||
|
Viewer.FindAllOccurrences(_lastWord, true, true);
|
|||
|
}
|
|||
|
|
|||
|
private void mnuUndoPrgChrEdit_Click(object sender, EventArgs e)
|
|||
|
{
|
|||
|
if(InteropEmu.DebugHasUndoHistory()) {
|
|||
|
InteropEmu.DebugPerformUndo();
|
|||
|
frmDebugger debugger = DebugWindowManager.GetDebugger();
|
|||
|
if(debugger != null) {
|
|||
|
debugger.UpdateDebugger(false);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private void mnuSetNextStatement_Click(object sender, EventArgs e)
|
|||
|
{
|
|||
|
this.OnSetNextStatement?.Invoke(new AddressEventArgs() { Address = (UInt32)Viewer.CodeViewer.CurrentLine });
|
|||
|
}
|
|||
|
|
|||
|
private void mnuEditSubroutine_Click(object sender, EventArgs e)
|
|||
|
{
|
|||
|
Viewer.EditSubroutine();
|
|||
|
}
|
|||
|
|
|||
|
private void mnuEditSelectedCode_Click(object sender, EventArgs e)
|
|||
|
{
|
|||
|
Viewer.EditSelectedCode();
|
|||
|
}
|
|||
|
|
|||
|
private void mnuEditInMemoryViewer_Click(object sender, EventArgs e)
|
|||
|
{
|
|||
|
if(UpdateContextMenu(_lastLocation)) {
|
|||
|
DebugWindowManager.OpenMemoryViewer(_lastClickedAddress, false);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private void mnuSwitchView_Click(object sender, EventArgs e)
|
|||
|
{
|
|||
|
if(Viewer.SymbolProvider != null) {
|
|||
|
this.OnSwitchView?.Invoke(Viewer);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public void ProcessMouseUp(Point location, MouseButtons button)
|
|||
|
{
|
|||
|
if(UpdateContextMenu(location)) {
|
|||
|
if(button == MouseButtons.Left) {
|
|||
|
if(ModifierKeys.HasFlag(Keys.Control) && ModifierKeys.HasFlag(Keys.Alt)) {
|
|||
|
ShowInSplitView();
|
|||
|
} else if(ModifierKeys.HasFlag(Keys.Control)) {
|
|||
|
AddWatch();
|
|||
|
} else if(ModifierKeys.HasFlag(Keys.Alt)) {
|
|||
|
Viewer.FindAllOccurrences(_lastWord, true, true);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public void ProcessMouseDoubleClick(Point location)
|
|||
|
{
|
|||
|
if(UpdateContextMenu(location) && mnuGoToLocation.Enabled) {
|
|||
|
GoToLocation();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private void contextMenuCode_Closed(object sender, ToolStripDropDownClosedEventArgs e)
|
|||
|
{
|
|||
|
mnuEditSelectedCode.Enabled = true;
|
|||
|
mnuEditSubroutine.Enabled = true;
|
|||
|
}
|
|||
|
|
|||
|
public void UpdateContextMenuItemVisibility(bool? visible = null)
|
|||
|
{
|
|||
|
mnuUndoPrgChrEdit.Enabled = InteropEmu.DebugHasUndoHistory();
|
|||
|
mnuShowNextStatement.Enabled = Viewer.ActiveAddress.HasValue;
|
|||
|
mnuSetNextStatement.Enabled = Viewer.ActiveAddress.HasValue;
|
|||
|
mnuEditSelectedCode.Enabled = mnuEditSubroutine.Enabled = InteropEmu.DebugIsExecutionStopped() && Viewer.CodeViewer.CurrentLine >= 0;
|
|||
|
|
|||
|
if(visible.HasValue) {
|
|||
|
mnuAddToWatch.Visible = visible.Value;
|
|||
|
mnuEditLabel.Visible = visible.Value;
|
|||
|
mnuGoToLocation.Visible = visible.Value;
|
|||
|
mnuToggleBreakpoint.Visible = visible.Value;
|
|||
|
sepAddToWatch.Visible = visible.Value;
|
|||
|
sepEditLabel.Visible = visible.Value;
|
|||
|
mnuFindOccurrences.Visible = visible.Value;
|
|||
|
}
|
|||
|
|
|||
|
if(SourceView) {
|
|||
|
mnuMarkSelectionAs.Visible = false;
|
|||
|
mnuShowCodeNotes.Visible = false;
|
|||
|
|
|||
|
mnuFindOccurrences.Visible = false;
|
|||
|
mnuEditSubroutine.Visible = false;
|
|||
|
mnuEditSelectedCode.Visible = false;
|
|||
|
mnuNavigateForward.Visible = false;
|
|||
|
mnuNavigateBackward.Visible = false;
|
|||
|
mnuEditLabel.Visible = false;
|
|||
|
sepNavigation.Visible = false;
|
|||
|
mnuShowSourceAsComments.Visible = false;
|
|||
|
}
|
|||
|
|
|||
|
if(Viewer.SymbolProvider == null) {
|
|||
|
mnuShowSourceAsComments.Visible = false;
|
|||
|
mnuSwitchView.Visible = false;
|
|||
|
sepSwitchView.Visible = false;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private bool UpdateContextMenu(Point mouseLocation)
|
|||
|
{
|
|||
|
_lastLocation = mouseLocation;
|
|||
|
|
|||
|
UpdateContextMenuItemVisibility(true);
|
|||
|
|
|||
|
mnuSwitchView.Text = SourceView ? "Switch to Disassembly View" : "Switch to Source View";
|
|||
|
|
|||
|
string word = Viewer.CodeViewer.GetWordUnderLocation(mouseLocation);
|
|||
|
Ld65DbgImporter.SymbolInfo symbol = null;
|
|||
|
CodeLabel codeLabel = null;
|
|||
|
|
|||
|
if(!word.StartsWith("$")) {
|
|||
|
codeLabel = LabelManager.GetLabel(word);
|
|||
|
|
|||
|
if(Viewer.SymbolProvider != null) {
|
|||
|
int rangeStart, rangeEnd;
|
|||
|
if(Viewer.CodeViewer.GetNoteRangeAtLocation(mouseLocation.Y, out rangeStart, out rangeEnd)) {
|
|||
|
symbol = Viewer.SymbolProvider.GetSymbol(word, rangeStart, rangeEnd);
|
|||
|
if(symbol?.SegmentID == null) {
|
|||
|
symbol = null;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if(word.StartsWith("$") || codeLabel != null || symbol != null) {
|
|||
|
//Cursor is on a numeric value or label
|
|||
|
_lastWord = word;
|
|||
|
|
|||
|
if(word.StartsWith("$")) {
|
|||
|
//CPU Address
|
|||
|
_lastClickedAddress = Int32.Parse(word.Substring(1), NumberStyles.AllowHexSpecifier);
|
|||
|
_newWatchValue = "[$" + _lastClickedAddress.ToString("X") + "]";
|
|||
|
} else if(symbol != null) {
|
|||
|
//Symbol
|
|||
|
AddressTypeInfo addressInfo = (AddressTypeInfo)Viewer.SymbolProvider.GetSymbolAddressInfo(symbol);
|
|||
|
_lastClickedAddress = (Int32)InteropEmu.DebugGetRelativeAddress((uint)addressInfo.Address, addressInfo.Type);
|
|||
|
bool matchingLabelExists = codeLabel != null && codeLabel.Label == symbol.Name;
|
|||
|
_newWatchValue = matchingLabelExists ? $"[{word}]" : $"[${_lastClickedAddress.ToString("X2")}]";
|
|||
|
} else if(codeLabel != null) {
|
|||
|
//Label
|
|||
|
_lastClickedAddress = (Int32)InteropEmu.DebugGetRelativeAddress(codeLabel.Address, codeLabel.AddressType);
|
|||
|
_newWatchValue = "[" + word + "]";
|
|||
|
}
|
|||
|
|
|||
|
mnuGoToLocation.Enabled = true;
|
|||
|
mnuGoToLocation.Text = $"Go to Location ({word})";
|
|||
|
|
|||
|
mnuShowInSplitView.Enabled = true;
|
|||
|
mnuShowInSplitView.Text = $"Show in Split View ({word})";
|
|||
|
|
|||
|
mnuAddToWatch.Enabled = true;
|
|||
|
mnuAddToWatch.Text = $"Add to Watch ({word})";
|
|||
|
|
|||
|
mnuFindOccurrences.Enabled = true;
|
|||
|
mnuFindOccurrences.Text = $"Find Occurrences ({word})";
|
|||
|
|
|||
|
mnuEditLabel.Enabled = true;
|
|||
|
mnuEditLabel.Text = $"Edit Label ({word})";
|
|||
|
|
|||
|
mnuEditInMemoryViewer.Enabled = true;
|
|||
|
mnuEditInMemoryViewer.Text = $"Edit in Memory Viewer ({word})";
|
|||
|
|
|||
|
return true;
|
|||
|
} else {
|
|||
|
mnuGoToLocation.Enabled = false;
|
|||
|
mnuGoToLocation.Text = "Go to Location";
|
|||
|
mnuShowInSplitView.Enabled = false;
|
|||
|
mnuShowInSplitView.Text = "Show in Split View";
|
|||
|
mnuAddToWatch.Enabled = false;
|
|||
|
mnuAddToWatch.Text = "Add to Watch";
|
|||
|
mnuFindOccurrences.Enabled = false;
|
|||
|
mnuFindOccurrences.Text = "Find Occurrences";
|
|||
|
mnuEditLabel.Enabled = false;
|
|||
|
mnuEditLabel.Text = "Edit Label";
|
|||
|
mnuEditInMemoryViewer.Enabled = false;
|
|||
|
mnuEditInMemoryViewer.Text = $"Edit in Memory Viewer";
|
|||
|
|
|||
|
if(mouseLocation.X < Viewer.CodeViewer.CodeMargin) {
|
|||
|
_lastClickedAddress = Viewer.CodeViewer.GetLineNumberAtPosition(mouseLocation.Y);
|
|||
|
} else {
|
|||
|
_lastClickedAddress = Viewer.CodeViewer.LastSelectedLine;
|
|||
|
}
|
|||
|
|
|||
|
if(_lastClickedAddress >= 0) {
|
|||
|
//Cursor is in the margin, over an address label
|
|||
|
string address = $"${_lastClickedAddress.ToString("X4")}";
|
|||
|
_newWatchValue = $"[{address}]";
|
|||
|
_lastWord = address;
|
|||
|
|
|||
|
mnuShowInSplitView.Enabled = true;
|
|||
|
mnuShowInSplitView.Text = $"Show in Split View ({address})";
|
|||
|
mnuAddToWatch.Enabled = true;
|
|||
|
mnuAddToWatch.Text = $"Add to Watch ({address})";
|
|||
|
mnuFindOccurrences.Enabled = true;
|
|||
|
mnuFindOccurrences.Text = $"Find Occurrences ({address})";
|
|||
|
mnuEditLabel.Enabled = true;
|
|||
|
mnuEditLabel.Text = $"Edit Label ({address})";
|
|||
|
mnuEditInMemoryViewer.Enabled = true;
|
|||
|
mnuEditInMemoryViewer.Text = $"Edit in Memory Viewer ({address})";
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
return false;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|