/* * 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.Runtime.CompilerServices; using System.Windows; using System.Windows.Controls; using System.Windows.Input; using Asm65; namespace SourceGen.WpfGui { /// /// Go to line dialog. /// public partial class GotoBox : Window, INotifyPropertyChanged { /// /// On success, this will hold the target offset. /// public int TargetOffset { get; private set; } /// /// Reference to project. /// private DisasmProject mProject; /// /// Initial offset, used for finding the best match among non-unique labels. /// private int mInitialOffset; /// /// Reference to formatter. This determines how values are displayed. /// private Formatter mFormatter; /// /// Set to true when input is valid. Controls whether the "Go" button is enabled. /// public bool IsValid { get { return mIsValid; } set { mIsValid = value; OnPropertyChanged(); } } private bool mIsValid; public string OffsetValueStr { get { return mOffsetValueStr; } set { mOffsetValueStr = value; OnPropertyChanged(); } } private string mOffsetValueStr; public string AddressValueStr { get { return mAddressValueStr; } set { mAddressValueStr = value; OnPropertyChanged(); } } private string mAddressValueStr; public string LabelValueStr { get { return mLabelValueStr; } set { mLabelValueStr = value; OnPropertyChanged(); } } private string mLabelValueStr; // INotifyPropertyChanged implementation public event PropertyChangedEventHandler PropertyChanged; private void OnPropertyChanged([CallerMemberName] string propertyName = "") { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } public GotoBox(Window owner, DisasmProject proj, int initialOffset, Formatter formatter) { InitializeComponent(); Owner = owner; DataContext = this; mProject = proj; mInitialOffset = initialOffset; mFormatter = formatter; TargetOffset = -1; } private void Window_Loaded(object sender, RoutedEventArgs e) { UpdateDisplay(); targetTextBox.Focus(); } // Catch ESC key. private void Window_KeyEventHandler(object sender, KeyEventArgs e) { if (e.Key == Key.Escape) { DialogResult = false; } } private void GoButton_Click(object sender, RoutedEventArgs e) { DialogResult = true; } private void TargetTextBox_TextChanged(object sender, TextChangedEventArgs e) { ProcessInput(); UpdateDisplay(); IsValid = (TargetOffset >= 0); } private void ProcessInput() { TargetOffset = -1; string input = targetTextBox.Text.Trim(); if (string.IsNullOrEmpty(input)) { return; } if (input[0] == '+') { // this can only be an offset; convert as hexadecimal number try { int offset = Convert.ToInt32(input.Substring(1), 16); if (offset >= 0 && offset < mProject.FileDataLength) { TargetOffset = offset; } } catch (Exception) { } return; } // Try it as a label. If they give the label a hex name (e.g. "A001") they // can prefix it with '$' to disambiguate the address. int labelOffset = -1; string trimLabel = Symbol.TrimAndValidateLabel(input, mFormatter.NonUniqueLabelPrefix, out bool isValid, out bool unused1, out bool unused2, out bool hasNonUniquePrefix, out Symbol.LabelAnnotation unused3); if (isValid) { // Could be a label. See if there's a match. if (hasNonUniquePrefix) { Symbol sym = mProject.FindBestNonUniqueLabel(trimLabel, mInitialOffset); if (sym != null) { labelOffset = mProject.FindLabelOffsetByName(sym.Label); } } else { labelOffset = mProject.FindLabelOffsetByName(trimLabel); } } if (labelOffset >= 0) { TargetOffset = labelOffset; } else if (Address.ParseAddress(input, 1 << 24, out int addr)) { // could be a valid address; check against address map int offset = mProject.AddrMap.AddressToOffset(0, addr); if (offset >= 0) { TargetOffset = offset; } } } private void UpdateDisplay() { string offsetStr = string.Empty; string addressStr = string.Empty; string labelStr = string.Empty; if (TargetOffset >= 0) { offsetStr = mFormatter.FormatOffset24(TargetOffset); int addr = mProject.GetAnattrib(TargetOffset).Address; addressStr = "$" + mFormatter.FormatAddress(addr, addr > 0xffff); Symbol sym = mProject.GetAnattrib(TargetOffset).Symbol; if (sym != null) { labelStr = sym.GenerateDisplayLabel(mFormatter); } } OffsetValueStr = offsetStr; AddressValueStr = addressStr; LabelValueStr = labelStr; } } }