mirror of
https://github.com/fadden/6502bench.git
synced 2025-02-18 08:30:28 +00:00
Implement HTML export
Pretty straightforward formatted-text dump, with links for internal labels, and a table of exported symbols at the end.
This commit is contained in:
parent
1631cd77f6
commit
d3ff1f6eff
@ -135,9 +135,8 @@ namespace SourceGen {
|
||||
/// </summary>
|
||||
public string ProjectPathName { get; set; }
|
||||
|
||||
// Name of data file. This is used for debugging and when naming DLLs for
|
||||
// project-local extension scripts. Just the filename, not the path.
|
||||
private string mDataFileName;
|
||||
// Filename only of data file. This is used for debugging and text export.
|
||||
public string DataFileName { get; private set; }
|
||||
|
||||
// This holds working state for the code and data analyzers. Some of the state
|
||||
// is presented directly to the user, e.g. status flags. All of the data here
|
||||
@ -258,7 +257,7 @@ namespace SourceGen {
|
||||
Debug.Assert(fileData.Length == FileDataLength);
|
||||
|
||||
mFileData = fileData;
|
||||
mDataFileName = dataFileName;
|
||||
DataFileName = dataFileName;
|
||||
FileDataCrc32 = CommonUtil.CRC32.OnWholeBuffer(0, mFileData);
|
||||
#if DATA_PRESCAN
|
||||
ScanFileData();
|
||||
@ -343,7 +342,7 @@ namespace SourceGen {
|
||||
Debug.Assert(fileData.Length == FileDataLength);
|
||||
Debug.Assert(CRC32.OnWholeBuffer(0, fileData) == FileDataCrc32);
|
||||
mFileData = fileData;
|
||||
mDataFileName = dataFileName;
|
||||
DataFileName = dataFileName;
|
||||
|
||||
FixAndValidate(ref report);
|
||||
|
||||
|
@ -17,6 +17,8 @@ using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Windows;
|
||||
using System.Windows.Media;
|
||||
|
||||
using Asm65;
|
||||
using CommonUtil;
|
||||
@ -350,8 +352,302 @@ namespace SourceGen {
|
||||
}
|
||||
}
|
||||
|
||||
#region HTML
|
||||
|
||||
private const string HTML_EXPORT_TEMPLATE = "ExportTemplate.html";
|
||||
private const string HTML_EXPORT_CSS_FILE = "SGStyle.css";
|
||||
private const string LABEL_LINK_PREFIX = "Sym";
|
||||
|
||||
public void OutputToHtml(string pathName, bool overwriteCss) {
|
||||
Debug.WriteLine("HTML"); // TODO
|
||||
string exportTemplate = RuntimeDataAccess.GetPathName(HTML_EXPORT_TEMPLATE);
|
||||
string tmplStr;
|
||||
try {
|
||||
// exportTemplate will be null if Runtime access failed
|
||||
tmplStr = File.ReadAllText(exportTemplate);
|
||||
} catch (Exception ex) {
|
||||
string msg = string.Format(Res.Strings.ERR_FILE_READ_FAILED_FMT,
|
||||
pathName, ex.Message);
|
||||
MessageBox.Show(msg, Res.Strings.ERR_FILE_GENERIC_CAPTION,
|
||||
MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
return;
|
||||
}
|
||||
|
||||
// Perform some quick substitutions.
|
||||
tmplStr = tmplStr.Replace("$ProjectName$", mProject.DataFileName);
|
||||
tmplStr = tmplStr.Replace("$AppVersion$", App.ProgramVersion.ToString());
|
||||
|
||||
// Generate and substitute the symbol table. This should be small enough that
|
||||
// we won't break the world by doing it with string.Replace().
|
||||
string symTabStr = GenerateHtmlSymbolTable();
|
||||
tmplStr = tmplStr.Replace("$SymbolTable$", symTabStr);
|
||||
|
||||
// For the main event we split the template in half, and generate the code lines
|
||||
// directly into the stream writer.
|
||||
const string CodeLinesStr = "$CodeLines$";
|
||||
int splitPoint = tmplStr.IndexOf(CodeLinesStr);
|
||||
if (splitPoint < 0) {
|
||||
Debug.WriteLine("No place to put code");
|
||||
return;
|
||||
}
|
||||
string template1 = tmplStr.Substring(0, splitPoint);
|
||||
string template2 = tmplStr.Substring(splitPoint + CodeLinesStr.Length);
|
||||
|
||||
|
||||
// Generate UTF-8 text, without a byte-order mark.
|
||||
using (StreamWriter sw = new StreamWriter(pathName, false, new UTF8Encoding(false))) {
|
||||
sw.Write(template1);
|
||||
|
||||
// With the style "code { white-space: pre; }", leading spaces and EOL markers
|
||||
// are preserved.
|
||||
sw.Write("<code style=\"white-space: pre;\">");
|
||||
StringBuilder sb = new StringBuilder(128);
|
||||
for (int lineIndex = 0; lineIndex < mCodeLineList.Count; lineIndex++) {
|
||||
if (Selection != null && !Selection[lineIndex]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (GenerateHtmlLine(lineIndex, sb)) {
|
||||
sw.WriteLine(sb.ToString());
|
||||
//sw.WriteLine("<br/>");
|
||||
}
|
||||
sb.Clear();
|
||||
}
|
||||
sw.WriteLine("</code>\r\n");
|
||||
|
||||
sw.Write(template2);
|
||||
}
|
||||
|
||||
string cssFile = RuntimeDataAccess.GetPathName(HTML_EXPORT_CSS_FILE);
|
||||
string outputDir = Path.GetDirectoryName(pathName);
|
||||
string outputPath = Path.Combine(outputDir, HTML_EXPORT_CSS_FILE);
|
||||
if (File.Exists(cssFile) && (overwriteCss || !File.Exists(outputPath))) {
|
||||
Debug.WriteLine("Copying '" + cssFile + "' -> '" + outputPath + "'");
|
||||
try {
|
||||
File.Copy(cssFile, outputPath, true);
|
||||
} catch (Exception ex) {
|
||||
string msg = string.Format(Res.Strings.ERR_FILE_COPY_FAILED_FMT,
|
||||
cssFile, outputPath, ex.Message);
|
||||
MessageBox.Show(msg, Res.Strings.ERR_FILE_GENERIC_CAPTION,
|
||||
MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Generates a line of HTML output. The line will not have EOL markers added.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Currently just generating a line of pre-formatted text. We could also output
|
||||
/// every line as a table row, with HTML column definitions for each of our columns.
|
||||
/// </remarks>
|
||||
/// <param name="index">Index of line to output.</param>
|
||||
/// <param name="sb">String builder to append text to. Must be cleared before
|
||||
/// calling here. (This is a minor optimization.)</param>
|
||||
private bool GenerateHtmlLine(int index, StringBuilder sb) {
|
||||
Debug.Assert(sb.Length == 0);
|
||||
|
||||
// Width of "bytes" field, without '+' or trailing space.
|
||||
int bytesWidth = mColEnd[(int)Col.Bytes] - mColEnd[(int)Col.Address] - 2;
|
||||
|
||||
LineListGen.Line line = mCodeLineList[index];
|
||||
DisplayList.FormattedParts parts = mCodeLineList.GetFormattedParts(index);
|
||||
|
||||
// TODO: linkify label and operand fields
|
||||
|
||||
switch (line.LineType) {
|
||||
case LineListGen.Line.Type.Code:
|
||||
case LineListGen.Line.Type.Data:
|
||||
case LineListGen.Line.Type.EquDirective:
|
||||
case LineListGen.Line.Type.RegWidthDirective:
|
||||
case LineListGen.Line.Type.OrgDirective:
|
||||
case LineListGen.Line.Type.LocalVariableTable:
|
||||
if (parts.IsLongComment) {
|
||||
// This happens for long comments embedded in LV tables.
|
||||
if (mColEnd[(int)Col.Attr] != 0) {
|
||||
TextUtil.AppendPaddedString(sb, string.Empty, mColEnd[(int)Col.Attr]);
|
||||
}
|
||||
sb.Append(parts.Comment);
|
||||
break;
|
||||
}
|
||||
|
||||
if ((mLeftFlags & ActiveColumnFlags.Offset) != 0) {
|
||||
TextUtil.AppendPaddedString(sb, parts.Offset,
|
||||
mColEnd[(int)Col.Offset]);
|
||||
}
|
||||
if ((mLeftFlags & ActiveColumnFlags.Address) != 0) {
|
||||
string str;
|
||||
if (!string.IsNullOrEmpty(parts.Addr)) {
|
||||
str = parts.Addr + ":";
|
||||
} else {
|
||||
str = string.Empty;
|
||||
}
|
||||
TextUtil.AppendPaddedString(sb, str, mColEnd[(int)Col.Address]);
|
||||
}
|
||||
if ((mLeftFlags & ActiveColumnFlags.Bytes) != 0) {
|
||||
// Shorten the "...".
|
||||
string bytesStr = parts.Bytes;
|
||||
if (bytesStr != null && bytesStr.Length > bytesWidth) {
|
||||
bytesStr = bytesStr.Substring(0, bytesWidth) + "+";
|
||||
}
|
||||
TextUtil.AppendPaddedString(sb, bytesStr, mColEnd[(int)Col.Bytes]);
|
||||
}
|
||||
if ((mLeftFlags & ActiveColumnFlags.Flags) != 0) {
|
||||
TextUtil.AppendPaddedString(sb, parts.Flags, mColEnd[(int)Col.Flags]);
|
||||
}
|
||||
if ((mLeftFlags & ActiveColumnFlags.Attr) != 0) {
|
||||
TextUtil.AppendPaddedString(sb, parts.Attr, mColEnd[(int)Col.Attr]);
|
||||
}
|
||||
int labelOffset = sb.Length;
|
||||
TextUtil.AppendPaddedString(sb, parts.Label, mColEnd[(int)Col.Label]);
|
||||
TextUtil.AppendPaddedString(sb, parts.Opcode, mColEnd[(int)Col.Opcode]);
|
||||
int operandOffset = sb.Length;
|
||||
TextUtil.AppendPaddedString(sb, parts.Operand, mColEnd[(int)Col.Operand]);
|
||||
if (string.IsNullOrEmpty(parts.Comment)) {
|
||||
// Trim trailing spaces off opcode or operand. Would be more efficient
|
||||
// to just not generate the spaces, but this is simpler and we're not
|
||||
// in a hurry.
|
||||
TextUtil.TrimEnd(sb);
|
||||
} else {
|
||||
sb.Append(parts.Comment);
|
||||
}
|
||||
|
||||
// Replace label with anchor label. We do it this late because we need the
|
||||
// spacing to be properly set, and I don't feel like changing how all the
|
||||
// AppendPaddedString code works.
|
||||
if ((line.LineType == LineListGen.Line.Type.Code ||
|
||||
line.LineType == LineListGen.Line.Type.Data ||
|
||||
line.LineType == LineListGen.Line.Type.EquDirective) &&
|
||||
!string.IsNullOrEmpty(parts.Label)) {
|
||||
string linkLabel = "<a name=\"" + LABEL_LINK_PREFIX + parts.Label +
|
||||
"\">" + parts.Label + "</a>";
|
||||
sb.Remove(labelOffset, parts.Label.Length);
|
||||
sb.Insert(labelOffset, linkLabel);
|
||||
|
||||
// Adjust operand position.
|
||||
operandOffset += linkLabel.Length - parts.Label.Length;
|
||||
}
|
||||
|
||||
if ((line.LineType == LineListGen.Line.Type.Code ||
|
||||
line.LineType == LineListGen.Line.Type.Data) &&
|
||||
parts.Operand.Length > 0) {
|
||||
string linkOperand = GetLinkOperand(index, parts.Operand);
|
||||
if (!string.IsNullOrEmpty(linkOperand)) {
|
||||
sb.Remove(operandOffset, parts.Operand.Length);
|
||||
sb.Insert(operandOffset, linkOperand);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case LineListGen.Line.Type.LongComment:
|
||||
case LineListGen.Line.Type.Note:
|
||||
if (line.LineType == LineListGen.Line.Type.Note && !IncludeNotes) {
|
||||
return false;
|
||||
}
|
||||
if (mColEnd[(int)Col.Attr] != 0) {
|
||||
// Long comments aren't the left-most field, so pad it out.
|
||||
TextUtil.AppendPaddedString(sb, string.Empty, mColEnd[(int)Col.Attr]);
|
||||
}
|
||||
|
||||
// Notes have a background color. Use this to highlight the text. We
|
||||
// don't apply it to the padding on the left columns.
|
||||
int rgb = 0;
|
||||
if (parts.HasBackgroundColor) {
|
||||
SolidColorBrush b = parts.BackgroundBrush as SolidColorBrush;
|
||||
if (b != null) {
|
||||
rgb = (b.Color.R << 16) | (b.Color.G << 8) | (b.Color.B);
|
||||
}
|
||||
}
|
||||
if (rgb != 0) {
|
||||
sb.AppendFormat("<span style=\"background-color: #{0:x6}\">", rgb);
|
||||
sb.Append(parts.Comment);
|
||||
sb.Append("</span>");
|
||||
} else {
|
||||
sb.Append(parts.Comment);
|
||||
}
|
||||
break;
|
||||
case LineListGen.Line.Type.Blank:
|
||||
break;
|
||||
default:
|
||||
Debug.Assert(false);
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wraps the symbolic part of the operand with HTML link notation. If the operand
|
||||
/// doesn't have a linkable symbol, this return null.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// We're playing games with string substitution that feel a little flimsy, but this
|
||||
/// is much simpler than reformatting the operand from scratch.
|
||||
/// </remarks>
|
||||
/// <param name="index">Display line index.</param>
|
||||
private string GetLinkOperand(int index, string operand) {
|
||||
LineListGen.Line line = mCodeLineList[index];
|
||||
if (line.FileOffset < 0) {
|
||||
// EQU directive - shouldn't be here
|
||||
Debug.Assert(false);
|
||||
return null;
|
||||
}
|
||||
|
||||
// Check for a format descriptor with a symbol.
|
||||
Debug.Assert(line.LineType == LineListGen.Line.Type.Code ||
|
||||
line.LineType == LineListGen.Line.Type.Data);
|
||||
Anattrib attr = mProject.GetAnattrib(line.FileOffset);
|
||||
if (attr.DataDescriptor == null || !attr.DataDescriptor.HasSymbol) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Symbol refs are weak. If the symbol doesn't exist, the value will be
|
||||
// formatted in hex. We can't simply check to see if the formatted operand
|
||||
// contains the symbol, because we could false-positive on the use of symbols
|
||||
// whose label is a valid hex value, e.g. "ABCD = $ABCD".
|
||||
//
|
||||
// We also want to exclude references to local variables, since those aren't
|
||||
// unique. To handle local refs we could just create anchors by line number or
|
||||
// some other means of unique identification.
|
||||
if (!mProject.SymbolTable.TryGetNonVariableValue(attr.DataDescriptor.SymbolRef.Label,
|
||||
out Symbol sym)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
string linkified = "<a href=#" + LABEL_LINK_PREFIX + sym.Label + ">" +
|
||||
sym.Label + "</a>";
|
||||
return operand.Replace(sym.Label, linkified);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generates a table of global/exported symbols. If none exist, a "no symbols found"
|
||||
/// message is generated instead.
|
||||
/// </summary>
|
||||
private string GenerateHtmlSymbolTable() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
int count = 0;
|
||||
|
||||
foreach (Symbol sym in mProject.SymbolTable) {
|
||||
if (sym.SymbolType != Symbol.Type.GlobalAddrExport) {
|
||||
continue;
|
||||
}
|
||||
if (count == 0) {
|
||||
sb.Append("<table>\r\n");
|
||||
}
|
||||
sb.Append(" <tr>");
|
||||
sb.Append("<td><a href=#" + LABEL_LINK_PREFIX + sym.Label + ">" +
|
||||
sym.Label + "</a></td>");
|
||||
sb.Append("<td>" + mFormatter.FormatHexValue(sym.Value, 2) + "</td>");
|
||||
sb.Append("</tr>\r\n");
|
||||
count++;
|
||||
}
|
||||
|
||||
if (count == 0) {
|
||||
sb.AppendFormat("<p>{0}</p>\r\n", Res.Strings.NO_EXPORTED_SYMBOLS_FOUND);
|
||||
} else {
|
||||
sb.Append("</table>\r\n");
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
#endregion HTML
|
||||
}
|
||||
}
|
||||
|
@ -1314,6 +1314,9 @@ namespace SourceGen {
|
||||
Exporter eport = new Exporter(mProject, CodeLineList, mOutputFormatter,
|
||||
colFlags, rightWidths);
|
||||
eport.Selection = selection;
|
||||
|
||||
// Might want to set Mouse.OverrideCursor if the selection exceeds a few
|
||||
// hundred thousand lines.
|
||||
eport.SelectionToString(true, out string fullText, out string csvText);
|
||||
|
||||
DataObject dataObject = new DataObject();
|
||||
@ -2005,6 +2008,8 @@ namespace SourceGen {
|
||||
eport.Selection = selection;
|
||||
}
|
||||
|
||||
// This is generally fast enough that I don't feel the need to create a
|
||||
// progress window.
|
||||
try {
|
||||
Mouse.OverrideCursor = Cursors.Wait;
|
||||
|
||||
|
@ -49,9 +49,11 @@ limitations under the License.
|
||||
<system:String x:Key="str_ErrBadSymrefPart">Bad symbol reference part</system:String>
|
||||
<system:String x:Key="str_ErrBadTypeHint">Type hint not recognized</system:String>
|
||||
<system:String x:Key="str_ErrDuplicateLabelFmt">Removing duplicate label '{0}' (offset +{1:x6})</system:String>
|
||||
<system:String x:Key="str_ErrFileCopyFailedFmt">Failed copying {0} to {1}: {2}.</system:String>
|
||||
<system:String x:Key="str_ErrFileExistsNotDirFmt">The file {0} exists, but is not a directory.</system:String>
|
||||
<system:String x:Key="str_ErrFileGenericCaption">File Error</system:String>
|
||||
<system:String x:Key="str_ErrFileNotFoundFmt">File not found: {0}</system:String>
|
||||
<system:String x:Key="str_ErrFileReadFailedFmt">Failed reading {0}: {1}.</system:String>
|
||||
<system:String x:Key="str_ErrFileReadOnlyFmt">Cannot write to read-only file {0}.</system:String>
|
||||
<system:String x:Key="str_ErrInvalidIntValue">Could not convert value to integer</system:String>
|
||||
<system:String x:Key="str_ErrInvalidKeyValue">Key value is out of range</system:String>
|
||||
@ -91,6 +93,7 @@ limitations under the License.
|
||||
<system:String x:Key="str_LocalVariableTableClear">• Clear variables</system:String>
|
||||
<system:String x:Key="str_LocalVariableTableEmpty">• Empty variable table</system:String>
|
||||
<system:String x:Key="str_NoFilesAvailable">no files available</system:String>
|
||||
<system:String x:Key="str_NoExportedSymbolsFound">No exported symbols found.</system:String>
|
||||
<system:String x:Key="str_OpenDataDoesntExist">The file doesn't exist.</system:String>
|
||||
<system:String x:Key="str_OpenDataEmpty">File is empty</system:String>
|
||||
<system:String x:Key="str_OpenDataFailCaption">Unable to load data file</system:String>
|
||||
|
@ -79,12 +79,16 @@ namespace SourceGen.Res {
|
||||
(string)Application.Current.FindResource("str_ErrBadTypeHint");
|
||||
public static string ERR_DUPLICATE_LABEL_FMT =
|
||||
(string)Application.Current.FindResource("str_ErrDuplicateLabelFmt");
|
||||
public static string ERR_FILE_COPY_FAILED_FMT =
|
||||
(string)Application.Current.FindResource("str_ErrFileCopyFailedFmt");
|
||||
public static string ERR_FILE_EXISTS_NOT_DIR_FMT =
|
||||
(string)Application.Current.FindResource("str_ErrFileExistsNotDirFmt");
|
||||
public static string ERR_FILE_GENERIC_CAPTION =
|
||||
(string)Application.Current.FindResource("str_ErrFileGenericCaption");
|
||||
public static string ERR_FILE_NOT_FOUND_FMT =
|
||||
(string)Application.Current.FindResource("str_ErrFileNotFoundFmt");
|
||||
public static string ERR_FILE_READ_FAILED_FMT =
|
||||
(string)Application.Current.FindResource("str_ErrFileReadFailedFmt");
|
||||
public static string ERR_FILE_READ_ONLY_FMT =
|
||||
(string)Application.Current.FindResource("str_ErrFileReadOnlyFmt");
|
||||
public static string ERR_INVALID_INT_VALUE =
|
||||
@ -163,6 +167,8 @@ namespace SourceGen.Res {
|
||||
(string)Application.Current.FindResource("str_LocalVariableTableEmpty");
|
||||
public static string NO_FILES_AVAILABLE =
|
||||
(string)Application.Current.FindResource("str_NoFilesAvailable");
|
||||
public static string NO_EXPORTED_SYMBOLS_FOUND =
|
||||
(string)Application.Current.FindResource("str_NoExportedSymbolsFound");
|
||||
public static string OPEN_DATA_DOESNT_EXIST =
|
||||
(string)Application.Current.FindResource("str_OpenDataDoesntExist");
|
||||
public static string OPEN_DATA_EMPTY =
|
||||
|
29
SourceGen/RuntimeData/ExportTemplate.html
Normal file
29
SourceGen/RuntimeData/ExportTemplate.html
Normal file
@ -0,0 +1,29 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
|
||||
<head>
|
||||
<title>$ProjectName$ Disassembly</title>
|
||||
|
||||
<meta content="en-us" http-equiv="Content-Language" />
|
||||
<meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
|
||||
<meta name="description" content="SourceGen-generated disassembly of $ProjectName$" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
|
||||
<link href="SGStyle.css" rel="stylesheet" type="text/css" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>$ProjectName$ Disassembly</h1>
|
||||
|
||||
<div id="code-lines">
|
||||
$CodeLines$
|
||||
</div>
|
||||
|
||||
<h2>Symbol Table</h2>
|
||||
<div id="symbol-table">
|
||||
$SymbolTable$
|
||||
</div>
|
||||
</body>
|
||||
|
||||
<!-- generated by 6502bench SourceGen v$AppVersion$ - https://6502bench.com/ -->
|
||||
</html>
|
13
SourceGen/RuntimeData/SGStyle.css
Normal file
13
SourceGen/RuntimeData/SGStyle.css
Normal file
@ -0,0 +1,13 @@
|
||||
/*
|
||||
* 6502bench SourceGen disassembly output style.
|
||||
*/
|
||||
body {
|
||||
font-family: Arial, Helvetica, sans-serif;
|
||||
font-size: 14px; /* 16 recommended for mobile */
|
||||
padding: 0px;
|
||||
margin: 20px 10px 10px 10px; /* TRBL order */
|
||||
}
|
||||
table, th, td {
|
||||
border: 1px solid black;
|
||||
border-collapse: collapse;
|
||||
}
|
@ -36,7 +36,8 @@ limitations under the License.
|
||||
|
||||
<GroupBox Grid.Row="0" Header="General Options" Padding="2,4">
|
||||
<StackPanel>
|
||||
<CheckBox Content="Include notes" IsChecked="{Binding IncludeNotes}"/>
|
||||
<CheckBox Content="Include only selected lines" IsChecked="{Binding SelectionOnly}"/>
|
||||
<CheckBox Content="Include notes" Margin="0,2,0,0" IsChecked="{Binding IncludeNotes}"/>
|
||||
<CheckBox Content="Show Offset column" Margin="0,2,0,0" IsChecked="{Binding ShowOffset}"/>
|
||||
<CheckBox Content="Show Address column" Margin="0,2,0,0" IsChecked="{Binding ShowAddress}"/>
|
||||
<CheckBox Content="Show Bytes column" Margin="0,2,0,0" IsChecked="{Binding ShowBytes}"/>
|
||||
@ -86,9 +87,6 @@ limitations under the License.
|
||||
</TextBox.Text>
|
||||
</TextBox>
|
||||
</StackPanel>
|
||||
|
||||
<CheckBox Content="Include only selected lines" Margin="0,4,0,0" IsChecked="{Binding SelectionOnly}"/>
|
||||
|
||||
</StackPanel>
|
||||
</GroupBox>
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user