1
0
mirror of https://github.com/fadden/6502bench.git synced 2024-11-29 10:50:28 +00:00

Add a "move table" button

A simple if slightly awkward way to reposition a local variable
table.
This commit is contained in:
Andy McFadden 2019-09-01 16:40:54 -07:00
parent d542a809f8
commit 9a61a852ad
7 changed files with 341 additions and 19 deletions

View File

@ -104,6 +104,8 @@ namespace SourceGen {
/// up in the symbol table, and the uniquifier isn't able to tell that the entry in the
/// symbol table is itself. The logic is simpler if we just rename the label before
/// the uniquifier ever sees it.
///
/// I feel like there has to be a simpler way to do this. This'll do for now.
/// </remarks>
private Dictionary<string, string> mDupRemap;

View File

@ -1324,6 +1324,7 @@ namespace SourceGen {
case LineListGen.Line.Type.EquDirective:
case LineListGen.Line.Type.RegWidthDirective:
case LineListGen.Line.Type.OrgDirective:
case LineListGen.Line.Type.LocalVariableTable:
if (format == ClipLineFormat.Disassembly) {
if (!string.IsNullOrEmpty(parts.Addr)) {
sb.Append(parts.Addr);
@ -1706,21 +1707,37 @@ namespace SourceGen {
public void EditLocalVariableTable() {
int selIndex = mMainWin.CodeListView_GetFirstSelectedIndex();
int offset = CodeLineList[selIndex].FileOffset;
// Get existing table, if any.
mProject.LvTables.TryGetValue(offset, out LocalVariableTable oldLvt);
EditLocalVariableTable dlg = new EditLocalVariableTable(mMainWin, mProject.SymbolTable,
mOutputFormatter, oldLvt);
EditLocalVariableTable dlg = new EditLocalVariableTable(mMainWin, mProject,
mOutputFormatter, oldLvt, offset);
if (dlg.ShowDialog() != true) {
return;
}
if (oldLvt == dlg.NewTable) {
if (offset != dlg.NewOffset) {
// Table moved. We create two changes, one to delete the current table, one
// to create a new table.
Debug.Assert(!mProject.LvTables.TryGetValue(dlg.NewOffset,
out LocalVariableTable unused));
UndoableChange rem = UndoableChange.CreateLocalVariableTableChange(offset,
oldLvt, null);
UndoableChange add = UndoableChange.CreateLocalVariableTableChange(dlg.NewOffset,
null, dlg.NewTable);
ChangeSet cs = new ChangeSet(2);
cs.Add(rem);
cs.Add(add);
ApplyUndoableChanges(cs);
} else if (oldLvt != dlg.NewTable) {
// New table, edited in place, or deleted.
UndoableChange uc = UndoableChange.CreateLocalVariableTableChange(offset,
oldLvt, dlg.NewTable);
ChangeSet cs = new ChangeSet(uc);
ApplyUndoableChanges(cs);
} else {
Debug.WriteLine("LvTable unchanged");
return;
}
UndoableChange uc = UndoableChange.CreateLocalVariableTableChange(offset,
oldLvt, dlg.NewTable);
ChangeSet cs = new ChangeSet(uc);
ApplyUndoableChanges(cs);
}
public bool CanEditLongComment() {

View File

@ -118,6 +118,9 @@
<Compile Include="WpfGui\EditLongComment.xaml.cs">
<DependentUpon>EditLongComment.xaml</DependentUpon>
</Compile>
<Compile Include="WpfGui\EditLvTableLocation.xaml.cs">
<DependentUpon>EditLvTableLocation.xaml</DependentUpon>
</Compile>
<Compile Include="WpfGui\EditNote.xaml.cs">
<DependentUpon>EditNote.xaml</DependentUpon>
</Compile>
@ -275,6 +278,10 @@
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="WpfGui\EditLvTableLocation.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="WpfGui\EditNote.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>

View File

@ -83,8 +83,10 @@ limitations under the License.
Content="Clear values from previous tables"/>
<DockPanel Grid.Column="0" Grid.Row="3" Grid.ColumnSpan="2" Margin="0,8,0,0" LastChildFill="False">
<Button DockPanel.Dock="Left" Content="Delete Table" Width="120" IsEnabled="{Binding IsNotNewTable}"
Click="DeleteTableButton_Click"/>
<Button DockPanel.Dock="Left" Content="Delete Table" Width="120"
IsEnabled="{Binding IsNotNewTable}" Click="DeleteTableButton_Click"/>
<Button DockPanel.Dock="Left" Content="Move Table" Width="120" Margin="8,0,0,0"
IsEnabled="{Binding IsNotNewTable}" Click="MoveTableButton_Click"/>
<Button DockPanel.Dock="Right" Content="Cancel" Width="70" Margin="8,0,0,0" IsCancel="True"/>
<Button DockPanel.Dock="Right" Grid.Column="1" Content="OK" Width="70"
IsDefault="True" Click="OkButton_Click"/>

View File

@ -14,7 +14,6 @@
* limitations under the License.
*/
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
@ -22,7 +21,6 @@ using System.Runtime.CompilerServices;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using Asm65;
using CommonWPF;
@ -31,13 +29,18 @@ namespace SourceGen.WpfGui {
/// <summary>
/// Edit a LocalVariableTable.
/// </summary>
public partial class EditLocalVariableTable : Window {
public partial class EditLocalVariableTable : Window, INotifyPropertyChanged {
/// <summary>
/// Result. Will be null if the table was deleted, or if cancel was hit while
/// Output. Will be null if the table was deleted, or if cancel was hit while
/// creating a new table.
/// </summary>
public LocalVariableTable NewTable { get; private set; }
/// <summary>
/// Output. If the table was moved, the new offset will be different from the old.
/// </summary>
public int NewOffset { get; private set; }
// Item for the symbol list view ItemsSource.
public class FormattedSymbol {
public string Label { get; private set; }
@ -82,15 +85,25 @@ namespace SourceGen.WpfGui {
private LocalVariableTable mWorkTable;
/// <summary>
/// Symbol table for uniqueness check.
/// Project reference.
/// </summary>
private SymbolTable mSymbolTable;
private DisasmProject mProject;
/// <summary>
/// Format object to use when formatting addresses and constants.
/// </summary>
private Formatter mFormatter;
/// <summary>
/// Symbol table for uniqueness check.
/// </summary>
private SymbolTable mSymbolTable;
/// <summary>
/// Table offset, for move ops.
/// </summary>
private int mOffset;
// INotifyPropertyChanged implementation
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged([CallerMemberName] string propertyName = "") {
@ -101,14 +114,16 @@ namespace SourceGen.WpfGui {
/// <summary>
/// Constructor. lvt will be null when creating a new entry.
/// </summary>
public EditLocalVariableTable(Window owner, SymbolTable symbolTable, Formatter formatter,
LocalVariableTable lvt) {
public EditLocalVariableTable(Window owner, DisasmProject project, Formatter formatter,
LocalVariableTable lvt, int offset) {
InitializeComponent();
Owner = owner;
DataContext = this;
mSymbolTable = symbolTable;
mProject = project;
mFormatter = formatter;
mSymbolTable = project.SymbolTable;
mOffset = NewOffset = offset;
if (lvt != null) {
mWorkTable = new LocalVariableTable(lvt);
@ -173,6 +188,13 @@ namespace SourceGen.WpfGui {
}
}
private void MoveTableButton_Click(object sender, RoutedEventArgs e) {
EditLvTableLocation dlg = new EditLvTableLocation(this, mProject, mOffset, NewOffset);
if (dlg.ShowDialog() == true) {
NewOffset = dlg.NewOffset;
}
}
private void SymbolsListView_SelectionChanged(object sender, SelectionChangedEventArgs e) {
UpdateControls();
}

View File

@ -0,0 +1,76 @@
<!--
Copyright 2019 faddenSoft
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<Window x:Class="SourceGen.WpfGui.EditLvTableLocation"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:SourceGen.WpfGui"
mc:Ignorable="d"
Title="Edit Local Variable Table Location"
SizeToContent="WidthAndHeight" ResizeMode="NoResize"
ShowInTaskbar="False" WindowStartupLocation="CenterOwner"
ContentRendered="Window_ContentRendered">
<Window.Resources>
<BooleanToVisibilityConverter x:Key="BoolToVis"/>
</Window.Resources>
<DockPanel LastChildFill="False" Margin="8">
<TextBlock DockPanel.Dock="Top" Text="Select new location for table" Margin="0,0,75,8"/>
<StackPanel DockPanel.Dock="Top" Orientation="Horizontal">
<TextBlock Text="File offset (hex): +"/>
<!-- up/down control, inspired by https://stackoverflow.com/a/5321605/294248 -->
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBox Name="offsetTextBox" Grid.Column="0" Grid.Row="0" Grid.RowSpan="2" Width="50" MaxLength="6"
Text="{Binding OffsetStr, UpdateSourceTrigger=PropertyChanged, FallbackValue=012345}"/>
<RepeatButton Grid.Column="1" Grid.Row="0" Content="5" FontSize="8" FontFamily="Marlett"
VerticalContentAlignment="Center" HorizontalContentAlignment="Center"
Click="OffsetUp_Click"/>
<RepeatButton Grid.Column="1" Grid.Row="1" Content="6" FontSize="8" FontFamily="Marlett"
VerticalContentAlignment="Center" HorizontalContentAlignment="Center"
Click="OffsetDown_Click"/>
</Grid>
</StackPanel>
<DockPanel DockPanel.Dock="Bottom" LastChildFill="False" Margin="0,16,0,0">
<Button DockPanel.Dock="Right" Content="Cancel" Width="70" Margin="8,0,0,0" IsCancel="True"/>
<Button DockPanel.Dock="Right" Grid.Column="1" Content="OK" Width="70"
IsDefault="True" IsEnabled="{Binding IsValid}" Click="OkButton_Click"/>
</DockPanel>
<TextBlock DockPanel.Dock="Bottom" Margin="0,4,0,0"
Text="• Offset must not already have a local variable table"
Foreground="{Binding TableAlreadyPresentBrush}"/>
<TextBlock DockPanel.Dock="Bottom" Margin="0,4,0,0"
Text="• Offset must be the start of an instruction"
Foreground="{Binding NotInstructionBrush}"/>
<TextBlock DockPanel.Dock="Bottom" Margin="0,4,0,0"
Text="• Offset value must be valid"
Foreground="{Binding InvalidOffsetBrush}"/>
</DockPanel>
</Window>

View File

@ -0,0 +1,196 @@
/*
* Copyright 2019 faddenSoft
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Windows;
using System.Windows.Media;
namespace SourceGen.WpfGui {
/// <summary>
/// Allows repositioning of a local variable table.
/// </summary>
/// <remarks>
/// This would be better implemented as cut/copy/paste, allowing parts of tables to be
/// freely duplicated and copied around, but that's a bunch of work for something that
/// I'm not yet convinced is important. (It might not be that much more work in and of
/// itself, but once the action is possible people will expect it to work for comments
/// and notes, and maybe want to paste operand formatting.)
/// </remarks>
public partial class EditLvTableLocation : Window, INotifyPropertyChanged {
/// <summary>
/// After a successful move, this will hold the new offset.
/// </summary>
public int NewOffset { get; private set; }
/// <summary>
/// Project reference.
/// </summary>
private DisasmProject mProject;
/// <summary>
/// File offset at which we are initially positioned.
/// </summary>
private int mCurrentOffset;
// Dialog label text color, saved off at dialog load time.
private Brush mDefaultLabelColor = Brushes.Black;
private Brush mErrorLabelColor = Brushes.Red;
public string OffsetStr {
get { return mOffsetStr; }
set { mOffsetStr = value; OnPropertyChanged(); ValidateOffset(); }
}
private string mOffsetStr;
public bool IsValid {
get { return mIsValid; }
set { mIsValid = value; OnPropertyChanged(); }
}
private bool mIsValid;
public Brush InvalidOffsetBrush {
get { return mInvalidOffsetBrush; }
set { mInvalidOffsetBrush = value; OnPropertyChanged(); }
}
private Brush mInvalidOffsetBrush;
public Brush NotInstructionBrush {
get { return mNotInstructionBrush; }
set { mNotInstructionBrush = value; OnPropertyChanged(); }
}
private Brush mNotInstructionBrush;
public Brush TableAlreadyPresentBrush {
get { return mTableAlreadyPresentBrush; }
set { mTableAlreadyPresentBrush = value; OnPropertyChanged(); }
}
private Brush mTableAlreadyPresentBrush;
// INotifyPropertyChanged implementation
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged([CallerMemberName] string propertyName = "") {
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public EditLvTableLocation(Window owner, DisasmProject project, int curOffset,
int initialOffset) {
InitializeComponent();
Owner = owner;
DataContext = this;
mProject = project;
mCurrentOffset = curOffset;
// curOffset is where the table actually is. initialOffset reflects changes
// made on a previous invocation of this dialog.
OffsetStr = initialOffset.ToString("x6");
}
private void Window_ContentRendered(object sender, EventArgs e) {
offsetTextBox.SelectAll();
offsetTextBox.Focus();
}
private void OkButton_Click(object sender, RoutedEventArgs e) {
NewOffset = Convert.ToInt32(OffsetStr, 16);
DialogResult = true;
}
private void OffsetUp_Click(object sender, RoutedEventArgs e) {
AdjustOffset(-1);
}
private void OffsetDown_Click(object sender, RoutedEventArgs e) {
AdjustOffset(1);
}
/// <summary>
/// Adjusts the offset up or down enough to get it to the next instruction start that
/// doesn't already have a local variable table.
/// </summary>
/// <param name="adj">Adjustment, should be +1 or -1.</param>
private void AdjustOffset(int adj) {
int offset;
try {
offset = Convert.ToInt32(OffsetStr, 16);
} catch (Exception) {
// string is garbage, just put the initial offset back in
OffsetStr = mCurrentOffset.ToString("x6");
return;
}
offset += adj;
while (offset >= 0 && offset < mProject.FileDataLength) {
if (mProject.GetAnattrib(offset).IsInstructionStart && !HasTableNotSelf(offset)) {
// found a winner
OffsetStr = offset.ToString("x6");
return;
}
offset += adj;
}
}
private void ValidateOffset() {
InvalidOffsetBrush = NotInstructionBrush = TableAlreadyPresentBrush =
mDefaultLabelColor;
if (string.IsNullOrEmpty(OffsetStr)) {
InvalidOffsetBrush = mErrorLabelColor;
IsValid = false;
return;
}
int offset;
try {
offset = Convert.ToInt32(OffsetStr, 16);
} catch (Exception) {
InvalidOffsetBrush = mErrorLabelColor;
IsValid = false;
return;
}
if (offset < 0 || offset >= mProject.FileDataLength) {
InvalidOffsetBrush = mErrorLabelColor;
IsValid = false;
return;
}
Anattrib attr = mProject.GetAnattrib(offset);
if (!attr.IsInstructionStart) {
NotInstructionBrush = mErrorLabelColor;
IsValid = false;
return;
}
if (HasTableNotSelf(offset)) {
TableAlreadyPresentBrush = mErrorLabelColor;
IsValid = false;
return;
}
IsValid = true;
}
/// <summary>
/// Returns true if the specified offset is the start of an instruction, and doesn't
/// have a local variable table unless the table is us.
/// </summary>
private bool HasTableNotSelf(int offset) {
return offset != mCurrentOffset &&
mProject.LvTables.TryGetValue(offset, out LocalVariableTable unused);
}
}
}