2019-09-01 23:40:54 +00:00
|
|
|
|
/*
|
|
|
|
|
* 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;
|
|
|
|
|
|
2019-11-27 02:54:42 +00:00
|
|
|
|
// Dialog label text color.
|
|
|
|
|
private Brush mDefaultLabelColor = SystemColors.WindowTextBrush;
|
2019-09-01 23:40:54 +00:00
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|