Now validating Applesoft import in user interface. #119

This commit is contained in:
Rob Greene 2023-10-21 16:59:15 -05:00
parent 643de4b4b1
commit 709ce6b47f
5 changed files with 137 additions and 114 deletions

View File

@ -33,6 +33,16 @@ public class ImportSpecification {
private String filetype;
private int address;
private boolean rawFileImport;
private byte[] fileData;
public ImportSpecification(ImportSpecification orig) {
this.sourceFilename = orig.sourceFilename;
this.targetFilename = orig.targetFilename;
this.filetype = orig.filetype;
this.address = orig.address;
this.rawFileImport = orig.rawFileImport;
this.fileData = orig.fileData;
}
/**
* Create the ImportSpecification with default values.
*/
@ -118,4 +128,22 @@ public class ImportSpecification {
public void setRawFileImport(boolean rawFileImport) {
this.rawFileImport = rawFileImport;
}
/**
* Set the binary file data (only done with validated file types).
*/
public void setFileData(byte[] fileData) {
this.fileData = fileData;
}
/**
* Get the binary file data (only done with validated file types).
*/
public byte[] getFileData() {
return fileData;
}
/**
* Answers true if this specification has file data attached.
*/
public boolean hasFileData() {
return fileData != null;
}
}

View File

@ -17,6 +17,7 @@ dependencies {
implementation project(':lib:ac-api')
implementation "net.sf.applecommander:applesingle-api:$asVersion"
implementation "net.sf.applecommander:bastools-api:$btVersion"
testImplementation "junit:junit:$junitVersion"
testImplementation "org.apache.commons:commons-lang3:$commonsLang3Version"

View File

@ -19,85 +19,14 @@
*/
package com.webcodepro.applecommander.ui.swt;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CTabFolder;
import org.eclipse.swt.custom.CTabItem;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.events.MenuAdapter;
import org.eclipse.swt.events.MenuEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.printing.PrintDialog;
import org.eclipse.swt.printing.Printer;
import org.eclipse.swt.printing.PrinterData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.MessageBox;
import org.eclipse.swt.widgets.ProgressBar;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.swt.widgets.ToolItem;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeItem;
import com.webcodepro.applecommander.compiler.ApplesoftCompiler;
import com.webcodepro.applecommander.storage.DirectoryEntry;
import com.webcodepro.applecommander.storage.Disk;
import com.webcodepro.applecommander.storage.DiskException;
import com.webcodepro.applecommander.storage.FileEntry;
import com.webcodepro.applecommander.storage.FileEntryComparator;
import com.webcodepro.applecommander.storage.FileFilter;
import com.webcodepro.applecommander.storage.FormattedDisk;
import com.webcodepro.applecommander.storage.*;
import com.webcodepro.applecommander.storage.FormattedDisk.FileColumnHeader;
import com.webcodepro.applecommander.storage.filters.AppleWorksDataBaseFileFilter;
import com.webcodepro.applecommander.storage.filters.AppleWorksSpreadSheetFileFilter;
import com.webcodepro.applecommander.storage.filters.AppleWorksWordProcessorFileFilter;
import com.webcodepro.applecommander.storage.filters.ApplesoftFileFilter;
import com.webcodepro.applecommander.storage.filters.AssemblySourceFileFilter;
import com.webcodepro.applecommander.storage.filters.BinaryFileFilter;
import com.webcodepro.applecommander.storage.filters.BusinessBASICFileFilter;
import com.webcodepro.applecommander.storage.filters.GraphicsFileFilter;
import com.webcodepro.applecommander.storage.filters.GutenbergFileFilter;
import com.webcodepro.applecommander.storage.filters.IntegerBasicFileFilter;
import com.webcodepro.applecommander.storage.filters.PascalTextFileFilter;
import com.webcodepro.applecommander.storage.filters.TextFileFilter;
import com.webcodepro.applecommander.storage.filters.*;
import com.webcodepro.applecommander.storage.os.prodos.ProdosDiskSizeDoesNotMatchException;
import com.webcodepro.applecommander.storage.os.prodos.ProdosFormatDisk;
import com.webcodepro.applecommander.storage.physical.ByteArrayImageLayout;
import com.webcodepro.applecommander.storage.physical.DosOrder;
import com.webcodepro.applecommander.storage.physical.ImageOrder;
import com.webcodepro.applecommander.storage.physical.NibbleOrder;
import com.webcodepro.applecommander.storage.physical.ProdosOrder;
import com.webcodepro.applecommander.storage.physical.*;
import com.webcodepro.applecommander.ui.ImportSpecification;
import com.webcodepro.applecommander.ui.UiBundle;
import com.webcodepro.applecommander.ui.UserPreferences;
@ -111,8 +40,28 @@ import com.webcodepro.applecommander.util.AppleUtil;
import com.webcodepro.applecommander.util.Host;
import com.webcodepro.applecommander.util.StreamUtil;
import com.webcodepro.applecommander.util.TextBundle;
import io.github.applecommander.applesingle.AppleSingle;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CTabFolder;
import org.eclipse.swt.custom.CTabItem;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.events.*;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.printing.PrintDialog;
import org.eclipse.swt.printing.Printer;
import org.eclipse.swt.printing.PrinterData;
import org.eclipse.swt.widgets.*;
import java.io.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.List;
import java.util.*;
/**
* Build the Disk File tab for the Disk Window.
@ -1193,10 +1142,15 @@ public class DiskExplorerTab {
i+1, specs.size()));
nameLabel.setText(spec.getSourceFilename());
progressBar.setSelection(i);
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
InputStream input = new FileInputStream(spec.getSourceFilename());
StreamUtil.copy(input, buffer);
byte[] fileData = buffer.toByteArray();
byte[] fileData = null;
if (spec.hasFileData()) {
fileData = spec.getFileData();
} else {
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
InputStream input = new FileInputStream(spec.getSourceFilename());
StreamUtil.copy(input, buffer);
fileData = buffer.toByteArray();
}
FileEntry fileEntry = directory.createFile();
fileEntry.setFilename(spec.getTargetFilename());
fileEntry.setFiletype(spec.getFiletype());

View File

@ -19,34 +19,6 @@
*/
package com.webcodepro.applecommander.ui.swt.wizard.importfile;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Iterator;
import java.util.Optional;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.layout.RowData;
import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.MessageBox;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.swt.widgets.Text;
import com.webcodepro.applecommander.storage.os.prodos.ProdosFormatDisk;
import com.webcodepro.applecommander.ui.ImportSpecification;
import com.webcodepro.applecommander.ui.UiBundle;
@ -55,11 +27,19 @@ import com.webcodepro.applecommander.ui.swt.util.SwtUtil;
import com.webcodepro.applecommander.ui.swt.wizard.WizardPane;
import com.webcodepro.applecommander.util.AppleUtil;
import com.webcodepro.applecommander.util.TextBundle;
import io.github.applecommander.applesingle.AppleSingle;
import io.github.applecommander.applesingle.AppleSingleReader;
import io.github.applecommander.applesingle.ProdosFileInfo;
import io.github.applecommander.applesingle.Utilities;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.*;
import org.eclipse.swt.widgets.*;
import java.io.*;
import java.util.Iterator;
import java.util.Optional;
/**
* Allow the used to choose the files to import into the disk image.
@ -362,6 +342,22 @@ public class ImportSelectFilesWizardPane extends WizardPane {
dialog.setDefaultButton(button);
button.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
try {
// Make an attempt at validating before accepting the change
ImportSpecification temp = new ImportSpecification(spec);
temp.setTargetFilename(getWizard().getDisk().
getSuggestedFilename(filenameText.getText()));
temp.setFiletype(filetypes.getItem(
filetypes.getSelectionIndex()));
temp.setAddress(AppleUtil.convertFormattedWord(
getAddressText().getText()));
temp.setRawFileImport(getRawCheckBox().getSelection());
wizard.validate(temp);
} catch (Throwable t) {
SwtUtil.showErrorDialog(wizard.getDialog(), "Error", t.getMessage());
return;
}
spec.setTargetFilename(getWizard().getDisk().
getSuggestedFilename(filenameText.getText()));
spec.setFiletype(filetypes.getItem(

View File

@ -19,17 +19,29 @@
*/
package com.webcodepro.applecommander.ui.swt.wizard.importfile;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.swt.widgets.Shell;
import com.webcodepro.applecommander.storage.FormattedDisk;
import com.webcodepro.applecommander.ui.ImportSpecification;
import com.webcodepro.applecommander.ui.UiBundle;
import com.webcodepro.applecommander.ui.swt.util.ImageManager;
import com.webcodepro.applecommander.ui.swt.wizard.Wizard;
import com.webcodepro.applecommander.ui.swt.wizard.WizardPane;
import com.webcodepro.applecommander.util.ApplesoftTokenizer;
import io.github.applecommander.bastools.api.Configuration;
import io.github.applecommander.bastools.api.Parser;
import io.github.applecommander.bastools.api.TokenReader;
import io.github.applecommander.bastools.api.Visitors;
import io.github.applecommander.bastools.api.model.Program;
import io.github.applecommander.bastools.api.model.Token;
import org.eclipse.swt.widgets.Shell;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.Queue;
import java.util.Set;
/**
* The Disk Import Wizard.
@ -38,6 +50,7 @@ import com.webcodepro.applecommander.ui.swt.wizard.WizardPane;
* @author Rob Greene
*/
public class ImportWizard extends Wizard {
private static Set<String> APPLESOFT_FILETYPES = Set.of("B", "BAS");
private FormattedDisk disk;
private List<ImportSpecification> importSpecifications;
/**
@ -58,9 +71,40 @@ public class ImportWizard extends Wizard {
/**
* Add an import specification.
*/
public void addImportSpecification(ImportSpecification importSpecification) {
public void addImportSpecification(ImportSpecification importSpecification) throws IOException {
validate(importSpecification);
getImportSpecifications().add(importSpecification);
}
/**
* Perform validation for some problematic file type imports.
*/
public void validate(ImportSpecification importSpecification) throws IOException {
if (APPLESOFT_FILETYPES.contains(importSpecification.getFiletype())) {
try {
// 1. Validate that this is a binary Applesoft file.
byte[] data = Files.readAllBytes(Path.of(importSpecification.getSourceFilename()));
ApplesoftTokenizer tokenizer = new ApplesoftTokenizer(data);
while (tokenizer.hasMoreTokens()) {
tokenizer.getNextToken(); // Make sure we can loop through entire program
}
importSpecification.setFileData(data);
} catch (Throwable ignored) {
try {
// 2. Make an attempt at tokenizing the file (assuming it's text).
File file = new File(importSpecification.getSourceFilename());
Configuration config = Configuration.builder().sourceFile(file).build();
Queue<Token> tokens = TokenReader.tokenize(config.sourceFile);
Parser parser = new Parser(tokens);
Program program = parser.parse();
byte[] data = Visitors.byteVisitor(config).dump(program);
importSpecification.setFileData(data);
} catch (Throwable ignored2) {
throw new IOException("File does not appear to be an Applesoft program");
}
}
}
}
/**
* Remove an import specification.
*/