2019-09-11 00:43:31 +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;
|
2019-09-12 20:57:52 +00:00
|
|
|
|
using System.IO;
|
2019-09-11 00:43:31 +00:00
|
|
|
|
using System.Runtime.CompilerServices;
|
|
|
|
|
using System.Windows;
|
|
|
|
|
using System.Windows.Controls;
|
|
|
|
|
|
2019-09-12 20:57:52 +00:00
|
|
|
|
using CommonUtil;
|
|
|
|
|
using Microsoft.Win32;
|
|
|
|
|
|
2019-09-11 00:43:31 +00:00
|
|
|
|
namespace SourceGen.WpfGui {
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Export selection dialog.
|
|
|
|
|
/// </summary>
|
|
|
|
|
public partial class Export : Window, INotifyPropertyChanged {
|
2019-09-12 20:57:52 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Indicates which type of file the user wants to generate.
|
|
|
|
|
/// </summary>
|
|
|
|
|
public enum GenerateFileType {
|
|
|
|
|
Unknown = 0,
|
|
|
|
|
Text,
|
|
|
|
|
Html
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Result: type of file to generate.
|
|
|
|
|
/// </summary>
|
|
|
|
|
public GenerateFileType GenType { get; private set; }
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Result: full pathname of output file.
|
|
|
|
|
/// </summary>
|
|
|
|
|
public string PathName { get; private set; }
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Result: flags indicating which of the optional columns should be shown.
|
|
|
|
|
/// </summary>
|
|
|
|
|
public Exporter.ActiveColumnFlags ColFlags { get; private set; }
|
|
|
|
|
|
|
|
|
|
private bool mIncludeNotes;
|
|
|
|
|
public bool IncludeNotes {
|
|
|
|
|
get { return mIncludeNotes; }
|
|
|
|
|
set { mIncludeNotes = value; OnPropertyChanged(); }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private bool mShowOffset;
|
|
|
|
|
public bool ShowOffset {
|
|
|
|
|
get { return mShowOffset; }
|
|
|
|
|
set { mShowOffset = value; OnPropertyChanged(); }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private bool mShowAddress;
|
|
|
|
|
public bool ShowAddress {
|
|
|
|
|
get { return mShowAddress; }
|
|
|
|
|
set { mShowAddress = value; OnPropertyChanged(); }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private bool mShowBytes;
|
|
|
|
|
public bool ShowBytes {
|
|
|
|
|
get { return mShowBytes; }
|
|
|
|
|
set { mShowBytes = value; OnPropertyChanged(); }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private bool mShowFlags;
|
|
|
|
|
public bool ShowFlags {
|
|
|
|
|
get { return mShowFlags; }
|
|
|
|
|
set { mShowFlags = value; OnPropertyChanged(); }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private bool mShowAttrs;
|
|
|
|
|
public bool ShowAttr {
|
|
|
|
|
get { return mShowAttrs; }
|
|
|
|
|
set { mShowAttrs = value; OnPropertyChanged(); }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private bool mSelectionOnly;
|
|
|
|
|
public bool SelectionOnly {
|
|
|
|
|
get { return mSelectionOnly; }
|
|
|
|
|
set { mSelectionOnly = value; OnPropertyChanged(); }
|
|
|
|
|
}
|
|
|
|
|
|
2019-09-18 18:05:52 +00:00
|
|
|
|
private bool mLongLabelNewLine;
|
|
|
|
|
public bool LongLabelNewLine {
|
|
|
|
|
get { return mLongLabelNewLine; }
|
|
|
|
|
set { mLongLabelNewLine = value; OnPropertyChanged(); }
|
|
|
|
|
}
|
|
|
|
|
|
2019-09-11 00:43:31 +00:00
|
|
|
|
//
|
|
|
|
|
// Numeric input fields, bound directly to TextBox.Text. These rely on a TextChanged
|
|
|
|
|
// field to update the IsValid flag, because the "set" method is only called when the
|
|
|
|
|
// field contains a valid integer.
|
|
|
|
|
//
|
|
|
|
|
private int mAsmLabelColWidth;
|
|
|
|
|
public int AsmLabelColWidth {
|
|
|
|
|
get { return mAsmLabelColWidth; }
|
|
|
|
|
set {
|
|
|
|
|
if (mAsmLabelColWidth != value) {
|
|
|
|
|
mAsmLabelColWidth = value;
|
|
|
|
|
OnPropertyChanged();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
private int mAsmOpcodeColWidth;
|
|
|
|
|
public int AsmOpcodeColWidth {
|
|
|
|
|
get { return mAsmOpcodeColWidth; }
|
|
|
|
|
set {
|
|
|
|
|
if (mAsmOpcodeColWidth != value) {
|
|
|
|
|
mAsmOpcodeColWidth = value;
|
|
|
|
|
OnPropertyChanged();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
private int mAsmOperandColWidth;
|
|
|
|
|
public int AsmOperandColWidth {
|
|
|
|
|
get { return mAsmOperandColWidth; }
|
|
|
|
|
set {
|
|
|
|
|
if (mAsmOperandColWidth != value) {
|
|
|
|
|
mAsmOperandColWidth = value;
|
|
|
|
|
OnPropertyChanged();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
private int mAsmCommentColWidth;
|
|
|
|
|
public int AsmCommentColWidth {
|
|
|
|
|
get { return mAsmCommentColWidth; }
|
|
|
|
|
set {
|
|
|
|
|
if (mAsmCommentColWidth != value) {
|
|
|
|
|
mAsmCommentColWidth = value;
|
|
|
|
|
OnPropertyChanged();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-09-12 20:57:52 +00:00
|
|
|
|
private bool mTextModePlain;
|
|
|
|
|
public bool TextModePlain {
|
|
|
|
|
get { return mTextModePlain; }
|
|
|
|
|
set { mTextModePlain = value; OnPropertyChanged(); }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private bool mTextModeCsv;
|
|
|
|
|
public bool TextModeCsv {
|
|
|
|
|
get { return mTextModeCsv; }
|
|
|
|
|
set { mTextModeCsv = value; OnPropertyChanged(); }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private bool mOverwriteCss;
|
|
|
|
|
public bool OverwriteCss {
|
|
|
|
|
get { return mOverwriteCss; }
|
|
|
|
|
set { mOverwriteCss = value; OnPropertyChanged(); }
|
|
|
|
|
}
|
|
|
|
|
|
2019-12-14 00:52:50 +00:00
|
|
|
|
private bool mGenerateImageFiles;
|
|
|
|
|
public bool GenerateImageFiles {
|
|
|
|
|
get { return mGenerateImageFiles; }
|
|
|
|
|
set { mGenerateImageFiles = value; OnPropertyChanged(); }
|
|
|
|
|
}
|
|
|
|
|
|
2019-09-12 20:57:52 +00:00
|
|
|
|
private enum TextMode {
|
|
|
|
|
Unknown = 0,
|
|
|
|
|
PlainText,
|
|
|
|
|
Csv
|
|
|
|
|
}
|
|
|
|
|
|
2019-09-11 00:43:31 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Valid flag, used to enable the "generate" buttons.
|
|
|
|
|
/// </summary>
|
|
|
|
|
public bool IsValid {
|
|
|
|
|
get { return mIsValid; }
|
|
|
|
|
set { mIsValid = value; OnPropertyChanged(); }
|
|
|
|
|
}
|
|
|
|
|
private bool mIsValid;
|
|
|
|
|
|
|
|
|
|
// INotifyPropertyChanged implementation
|
|
|
|
|
public event PropertyChangedEventHandler PropertyChanged;
|
|
|
|
|
private void OnPropertyChanged([CallerMemberName] string propertyName = "") {
|
|
|
|
|
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
|
|
|
|
}
|
|
|
|
|
|
2019-09-12 20:57:52 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Filename of project file.
|
|
|
|
|
/// </summary>
|
|
|
|
|
string mProjectFileName;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public Export(Window owner, string projectFileName) {
|
2019-09-11 00:43:31 +00:00
|
|
|
|
InitializeComponent();
|
|
|
|
|
Owner = owner;
|
|
|
|
|
DataContext = this;
|
2019-09-12 20:57:52 +00:00
|
|
|
|
|
|
|
|
|
mProjectFileName = projectFileName;
|
2019-09-11 00:43:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void Window_Loaded(object sender, RoutedEventArgs e) {
|
2019-09-12 20:57:52 +00:00
|
|
|
|
IncludeNotes = AppSettings.Global.GetBool(AppSettings.EXPORT_INCLUDE_NOTES, false);
|
|
|
|
|
ShowOffset = AppSettings.Global.GetBool(AppSettings.EXPORT_SHOW_OFFSET, false);
|
|
|
|
|
ShowAddress = AppSettings.Global.GetBool(AppSettings.EXPORT_SHOW_ADDR, false);
|
|
|
|
|
ShowBytes = AppSettings.Global.GetBool(AppSettings.EXPORT_SHOW_BYTES, false);
|
|
|
|
|
ShowFlags = AppSettings.Global.GetBool(AppSettings.EXPORT_SHOW_FLAGS, false);
|
|
|
|
|
ShowAttr = AppSettings.Global.GetBool(AppSettings.EXPORT_SHOW_ATTR, false);
|
|
|
|
|
SelectionOnly = AppSettings.Global.GetBool(AppSettings.EXPORT_SELECTION_ONLY, false);
|
2019-09-18 18:05:52 +00:00
|
|
|
|
LongLabelNewLine =
|
|
|
|
|
AppSettings.Global.GetBool(AppSettings.EXPORT_LONG_LABEL_NEW_LINE, false);
|
2019-12-14 00:52:50 +00:00
|
|
|
|
GenerateImageFiles =
|
|
|
|
|
AppSettings.Global.GetBool(AppSettings.EXPORT_GENERATE_IMAGE_FILES, true);
|
2019-09-12 20:57:52 +00:00
|
|
|
|
|
2020-07-16 17:48:03 +00:00
|
|
|
|
int[] colWidths = new int[] { 16, 8, 18, 100 }; // wide output
|
2019-09-12 20:57:52 +00:00
|
|
|
|
string colStr = AppSettings.Global.GetString(AppSettings.EXPORT_COL_WIDTHS, null);
|
|
|
|
|
try {
|
|
|
|
|
if (!string.IsNullOrEmpty(colStr)) {
|
|
|
|
|
colWidths = TextUtil.DeserializeIntArray(colStr);
|
|
|
|
|
if (colWidths.Length != 4) {
|
|
|
|
|
throw new InvalidOperationException("Bad length " + colWidths.Length);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} finally {
|
|
|
|
|
AsmLabelColWidth = colWidths[0];
|
|
|
|
|
AsmOpcodeColWidth = colWidths[1];
|
|
|
|
|
AsmOperandColWidth = colWidths[2];
|
|
|
|
|
AsmCommentColWidth = colWidths[3];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TextMode mode = (TextMode)AppSettings.Global.GetEnum(AppSettings.EXPORT_TEXT_MODE,
|
|
|
|
|
typeof(TextMode), (int)TextMode.PlainText);
|
|
|
|
|
if (mode == TextMode.PlainText) {
|
|
|
|
|
TextModePlain = true;
|
|
|
|
|
} else {
|
|
|
|
|
TextModeCsv = true;
|
|
|
|
|
}
|
2019-09-11 00:43:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
2019-09-12 20:57:52 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Saves the settings to the global settings object.
|
|
|
|
|
/// </summary>
|
|
|
|
|
private void SaveSettings() {
|
|
|
|
|
AppSettings.Global.SetBool(AppSettings.EXPORT_INCLUDE_NOTES, IncludeNotes);
|
|
|
|
|
AppSettings.Global.SetBool(AppSettings.EXPORT_SHOW_OFFSET, ShowOffset);
|
|
|
|
|
AppSettings.Global.SetBool(AppSettings.EXPORT_SHOW_ADDR, ShowAddress);
|
|
|
|
|
AppSettings.Global.SetBool(AppSettings.EXPORT_SHOW_BYTES, ShowBytes);
|
|
|
|
|
AppSettings.Global.SetBool(AppSettings.EXPORT_SHOW_FLAGS, ShowFlags);
|
|
|
|
|
AppSettings.Global.SetBool(AppSettings.EXPORT_SHOW_ATTR, ShowAttr);
|
|
|
|
|
AppSettings.Global.SetBool(AppSettings.EXPORT_SELECTION_ONLY, SelectionOnly);
|
2019-09-18 18:05:52 +00:00
|
|
|
|
AppSettings.Global.SetBool(AppSettings.EXPORT_LONG_LABEL_NEW_LINE, LongLabelNewLine);
|
2019-12-14 00:52:50 +00:00
|
|
|
|
AppSettings.Global.SetBool(AppSettings.EXPORT_GENERATE_IMAGE_FILES,GenerateImageFiles);
|
2019-09-12 20:57:52 +00:00
|
|
|
|
int[] colWidths = new int[] {
|
|
|
|
|
AsmLabelColWidth, AsmOpcodeColWidth, AsmOperandColWidth, AsmCommentColWidth
|
|
|
|
|
};
|
|
|
|
|
string cereal = TextUtil.SerializeIntArray(colWidths);
|
|
|
|
|
AppSettings.Global.SetString(AppSettings.EXPORT_COL_WIDTHS, cereal);
|
|
|
|
|
// OverwriteCss is not saved, since there's generally no reason to replace it.
|
|
|
|
|
// Forcing the user to check it every time is essentially the same as popping
|
|
|
|
|
// up an "are you sure you want to overwrite" dialog, but less annoying for the
|
|
|
|
|
// common case.
|
|
|
|
|
|
|
|
|
|
TextMode mode;
|
|
|
|
|
if (TextModePlain) {
|
|
|
|
|
mode = TextMode.PlainText;
|
|
|
|
|
} else {
|
|
|
|
|
mode = TextMode.Csv;
|
|
|
|
|
}
|
|
|
|
|
AppSettings.Global.SetEnum(AppSettings.EXPORT_TEXT_MODE, typeof(TextMode), (int)mode);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Updates the state of the UI.
|
|
|
|
|
/// </summary>
|
2019-09-11 00:43:31 +00:00
|
|
|
|
private void UpdateControls() {
|
|
|
|
|
bool isValid = true;
|
|
|
|
|
|
|
|
|
|
isValid &= !Validation.GetHasError(asmLabelColWidthTextBox);
|
|
|
|
|
isValid &= !Validation.GetHasError(asmOpcodeColWidthTextBox);
|
|
|
|
|
isValid &= !Validation.GetHasError(asmOperandColWidthTextBox);
|
|
|
|
|
isValid &= !Validation.GetHasError(asmCommentColWidthTextBox);
|
|
|
|
|
|
|
|
|
|
IsValid = isValid;
|
|
|
|
|
}
|
|
|
|
|
|
2019-09-12 20:57:52 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Called whenever something is typed in one of the column width entry boxes.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <remarks>
|
|
|
|
|
/// We need this because we're using validated int fields rather than strings. The
|
|
|
|
|
/// "set" call doesn't fire if the user types garbage.
|
|
|
|
|
/// </remarks>
|
2019-09-11 00:43:31 +00:00
|
|
|
|
private void AsmColWidthTextBox_TextChanged(object sender, TextChangedEventArgs e) {
|
|
|
|
|
UpdateControls();
|
|
|
|
|
}
|
2019-09-12 20:57:52 +00:00
|
|
|
|
|
|
|
|
|
private void GenerateHtmlButton_Click(object sender, RoutedEventArgs e) {
|
|
|
|
|
GenType = GenerateFileType.Html;
|
|
|
|
|
Finish(Res.Strings.FILE_FILTER_HTML, ".html");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void GenerateTextButton_Click(object sender, RoutedEventArgs e) {
|
|
|
|
|
GenType = GenerateFileType.Text;
|
|
|
|
|
if (TextModeCsv) {
|
|
|
|
|
Finish(Res.Strings.FILE_FILTER_CSV, ".csv");
|
|
|
|
|
} else {
|
|
|
|
|
Finish(Res.Strings.FILE_FILTER_TEXT, ".txt");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Handles a click on one of the "generate" buttons.
|
|
|
|
|
/// </summary>
|
|
|
|
|
private void Finish(string fileFilter, string fileExt) {
|
|
|
|
|
Debug.Assert(mProjectFileName == Path.GetFileName(mProjectFileName));
|
|
|
|
|
string initialName = Path.GetFileNameWithoutExtension(mProjectFileName) + fileExt;
|
2019-10-10 21:00:52 +00:00
|
|
|
|
if (GenType == GenerateFileType.Html) {
|
|
|
|
|
// Can't link to a file with an unescaped '#' -- the browser will think
|
|
|
|
|
// it's an anchor.
|
|
|
|
|
initialName = initialName.Replace('#', '_');
|
|
|
|
|
}
|
2019-09-12 20:57:52 +00:00
|
|
|
|
|
|
|
|
|
SaveFileDialog fileDlg = new SaveFileDialog() {
|
|
|
|
|
Filter = fileFilter + "|" + Res.Strings.FILE_FILTER_ALL,
|
|
|
|
|
FilterIndex = 1,
|
|
|
|
|
ValidateNames = true,
|
|
|
|
|
AddExtension = true, // doesn't add extension if non-ext file exists
|
|
|
|
|
FileName = initialName
|
|
|
|
|
};
|
|
|
|
|
if (fileDlg.ShowDialog() != true) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
PathName = Path.GetFullPath(fileDlg.FileName);
|
|
|
|
|
|
|
|
|
|
ColFlags = Exporter.ActiveColumnFlags.None;
|
|
|
|
|
if (ShowOffset) {
|
|
|
|
|
ColFlags |= Exporter.ActiveColumnFlags.Offset;
|
|
|
|
|
}
|
|
|
|
|
if (ShowAddress) {
|
|
|
|
|
ColFlags |= Exporter.ActiveColumnFlags.Address;
|
|
|
|
|
}
|
|
|
|
|
if (ShowBytes) {
|
|
|
|
|
ColFlags |= Exporter.ActiveColumnFlags.Bytes;
|
|
|
|
|
}
|
|
|
|
|
if (ShowFlags) {
|
|
|
|
|
ColFlags |= Exporter.ActiveColumnFlags.Flags;
|
|
|
|
|
}
|
|
|
|
|
if (ShowAttr) {
|
|
|
|
|
ColFlags |= Exporter.ActiveColumnFlags.Attr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SaveSettings();
|
|
|
|
|
DialogResult = true;
|
|
|
|
|
}
|
2019-09-11 00:43:31 +00:00
|
|
|
|
}
|
|
|
|
|
}
|