Add IFF support to HexEditor

This commit is contained in:
peterdell 2019-09-23 00:14:35 +02:00
parent f2f1e5a598
commit e40d5bef75
19 changed files with 340 additions and 137 deletions

View File

@ -47,6 +47,8 @@ com.wudsn.ide.base.editor.hex.HexEditorFileContentMode.ATARI_MADS_FILE=Atari MAD
com.wudsn.ide.base.editor.hex.HexEditorFileContentMode.ATARI_SDX_FILE=Atari SpartaDOS X File
com.wudsn.ide.base.editor.hex.HexEditorFileContentMode.ATARI_SAP_FILE=Atari SAP File
com.wudsn.ide.base.editor.hex.HexEditorFileContentMode.C64_PRG_FILE=C64 PRG File
com.wudsn.ide.base.editor.hex.HexEditorFileContentMode.IFF_FILE=IFF File
com.wudsn.ide.base.editor.hex.HexEditorCharacterSet.ASCII=ASCII
com.wudsn.ide.base.editor.hex.HexEditorCharacterSet.ATARI_ATASCII=Atari ATASCII

View File

@ -47,6 +47,7 @@ com.wudsn.ide.base.editor.hex.HexEditorFileContentMode.ATARI_MADS_FILE=Atari MAD
com.wudsn.ide.base.editor.hex.HexEditorFileContentMode.ATARI_SAP_FILE=Atari SAP-Datei
com.wudsn.ide.base.editor.hex.HexEditorFileContentMode.ATARI_SDX_FILE=Atari SpartaDOS X-Datei
com.wudsn.ide.base.editor.hex.HexEditorFileContentMode.C64_PRG_FILE=C64 PRG-Datei
com.wudsn.ide.base.editor.hex.HexEditorFileContentMode.IFF_FILE=IFF-Datei
com.wudsn.ide.base.editor.hex.HexEditorCharacterSet.ASCII=ASCII
com.wudsn.ide.base.editor.hex.HexEditorCharacterSet.ATARI_ATASCII=Atari ATASCII

View File

@ -73,6 +73,10 @@ public final class Texts extends NLS {
public static String HEX_EDITOR_C64_PRG_HEADER_PARAMETERS;
public static String HEX_EDITOR_C64_PRG_ERROR;
public static String HEX_EDITOR_IFF_CHUNK;
public static String HEX_EDITOR_IFF_FORM_CHUNK;
public static String HEX_EDITOR_IFF_FILE_ERROR;
public static String HEX_EDITOR_FILE_CONTENT_SIZE_FIELD_LABEL;
public static String HEX_EDITOR_FILE_CONTENT_SIZE_FIELD_TEXT;
public static String HEX_EDITOR_FILE_CONTENT_MODE_FIELD_LABEL;

View File

@ -34,6 +34,10 @@ HEX_EDITOR_C64_PRG_HEADER=Program
HEX_EDITOR_C64_PRG_HEADER_PARAMETERS={0}-{1} ({2})
HEX_EDITOR_C64_PRG_ERROR=PRG file structure error
HEX_EDITOR_IFF_CHUNK=Chunk {0} contains ${1} ({2}) bytes
HEX_EDITOR_IFF_FORM_CHUNK=Chunk {0} of type {1} contains ${2} ({3}) bytes
HEX_EDITOR_IFF_FILE_ERROR=IFF file structure error
HEX_EDITOR_FILE_CONTENT_SIZE_FIELD_LABEL=File Size
HEX_EDITOR_FILE_CONTENT_SIZE_FIELD_TEXT=${0} ({1}) bytes
HEX_EDITOR_FILE_CONTENT_MODE_FIELD_LABEL=File Mode

View File

@ -34,6 +34,10 @@ HEX_EDITOR_C64_PRG_HEADER=Programm
HEX_EDITOR_C64_PRG_HEADER_PARAMETERS={0}-{1} ({2})
HEX_EDITOR_C64_PRG_ERROR=PRG Dateistruktur defekt
HEX_EDITOR_IFF_CHUNK=Chunk
HEX_EDITOR_IFF_FORM_CHUNK=Chunk {0} vom Typ {1} enhl#t ${2} ({3}) Bytes
HEX_EDITOR_IFF_FILE_ERROR=IFF Dateistruktur defekt
HEX_EDITOR_FILE_CONTENT_SIZE_FIELD_LABEL=Dateigröße
HEX_EDITOR_FILE_CONTENT_SIZE_FIELD_TEXT=${0} ({1}) Bytes
HEX_EDITOR_FILE_CONTENT_MODE_FIELD_LABEL=Datei-Modus

View File

@ -281,12 +281,12 @@ public final class HexEditor extends EditorPart implements ISelectionProvider, A
public <T> T getAdapter(Class<T> adapter) {
if (adapter != null && IContentOutlinePage.class.equals(adapter)) {
if (contentOutlinePage == null) {
contentOutlinePage = new HexEditorContentOutlinePage(this);
contentOutlinePage.setInput(parserComponent.getOutlineBlocks());
}
return (T)contentOutlinePage;
return (T) contentOutlinePage;
}
return super.getAdapter(adapter);
}
@ -384,8 +384,8 @@ public final class HexEditor extends EditorPart implements ISelectionProvider, A
// Single range selection?
if (selection instanceof HexEditorSelection) {
HexEditorSelection hexEditorSelection = (HexEditorSelection) selection;
int textStartOffset = parserComponent.getByteTextOffset(hexEditorSelection.getStartOffset());
int textEndOffset = parserComponent.getByteTextOffset(hexEditorSelection.getEndOffset());
long textStartOffset = parserComponent.getByteTextOffset(hexEditorSelection.getStartOffset());
long textEndOffset = parserComponent.getByteTextOffset(hexEditorSelection.getEndOffset());
setSelectionOffsets(textStartOffset, textEndOffset);
// Range of outline tree objects?
} else if (selection instanceof IStructuredSelection) {
@ -394,8 +394,8 @@ public final class HexEditor extends EditorPart implements ISelectionProvider, A
if (structuredSelection.getFirstElement() instanceof HexEditorContentOutlineTreeObject) {
Iterator<?> i = ((IStructuredSelection) selection).iterator();
int textStartOffset = Integer.MAX_VALUE;
int textEndOffset = Integer.MIN_VALUE;
long textStartOffset = Long.MAX_VALUE;
long textEndOffset = Long.MIN_VALUE;
while (i.hasNext()) {
HexEditorContentOutlineTreeObject treeObject = (HexEditorContentOutlineTreeObject) i.next();
textStartOffset = Math.min(treeObject.getTextStartOffset(), textStartOffset);
@ -408,15 +408,21 @@ public final class HexEditor extends EditorPart implements ISelectionProvider, A
setFocus();
}
private void setSelectionOffsets(int textStartOffset, int textEndOffset) {
private void setSelectionOffsets(long textStartOffset, long textEndOffset) {
if (textStartOffset < 0 || textEndOffset > Integer.MAX_VALUE) {
throw new IllegalArgumentException("Parameter textStartOffset=" + textStartOffset + " is out of range");
}
if (textEndOffset < 0 || textEndOffset > Integer.MAX_VALUE) {
throw new IllegalArgumentException("Parameter textStartOffset=" + textStartOffset + " is out of range");
}
try {
// Mark complete selection area. This also scrolls to
// the end of the area.
textField.setSelection(new Point(textStartOffset, textEndOffset));
textField.setSelection(new Point((int) textStartOffset, (int) textEndOffset));
//
// // But we want to see start of the selection are, so
// // position explicitly.
textField.setTopIndex(textField.getContent().getLineAtOffset(textStartOffset));
textField.setTopIndex(textField.getContent().getLineAtOffset((int) textStartOffset));
} catch (IllegalArgumentException x) {
// Ignore
}
@ -570,16 +576,19 @@ public final class HexEditor extends EditorPart implements ISelectionProvider, A
// If there is no end offset, we insert the new bytes.
if (selection.getEndOffset() != HexEditorParserComponent.UNDEFINED_OFFSET) {
int selectionLength = selection.getEndOffset() - selection.getStartOffset() + 1;
newFileContent = new byte[parserComponent.getFileContent().length - selectionLength + bytes.length];
System.arraycopy(parserComponent.getFileContent(), 0, newFileContent, 0, selection.getStartOffset());
System.arraycopy(bytes, 0, newFileContent, selection.getStartOffset(), bytes.length);
int length = parserComponent.getFileContent().length - selection.getEndOffset() - 1;
int selectionStartOffset = (int) selection.getStartOffset();
int selectionEndOffset = (int) selection.getEndOffset();
int selectionLength = selectionEndOffset - selectionStartOffset + 1;
int newFileContentLength = parserComponent.getFileContent().length - selectionLength + bytes.length;
newFileContent = new byte[newFileContentLength];
System.arraycopy(parserComponent.getFileContent(), 0, newFileContent, 0, selectionStartOffset);
System.arraycopy(bytes, 0, newFileContent, selectionStartOffset, bytes.length);
int length = parserComponent.getFileContent().length - selectionEndOffset - 1;
if (length > 0) {
// TODO Hex paste is not working yet
System.arraycopy(parserComponent.getFileContent(), selection.getEndOffset(),
newFileContent, selection.getStartOffset() + bytes.length, length);
System.arraycopy(parserComponent.getFileContent(), selectionEndOffset, newFileContent,
selectionStartOffset + bytes.length, length);
}
messageManager.sendMessage(0, IStatus.OK,
"${0} ({1}) bytes pasted from clipboard to replace ${2} ({3}) bytes ",
@ -588,7 +597,7 @@ public final class HexEditor extends EditorPart implements ISelectionProvider, A
HexUtility.getLongValueHexString(selectionLength),
NumberUtility.getLongValueDecimalString(selectionLength));
} else {
// If there is and end offset, we replace the selection with the new
// If there is an end offset, we replace the selection with the new
// bytes.
newFileContent = parserComponent.getFileContent();
messageManager.sendMessage(0, IStatus.OK, "${0} ({1}) bytes inserted from clipboard",

View File

@ -29,10 +29,10 @@ import org.eclipse.jface.viewers.StyledString;
public final class HexEditorContentOutlineTreeObject {
private final StyledString styledString;
private int fileStartOffset;
private int textStartOffset;
private int fileEndOffset;
private int textEndOffset;
private long fileStartOffset;
private long textStartOffset;
private long fileEndOffset;
private long textEndOffset;
/**
* Create a new instance.
@ -62,7 +62,7 @@ public final class HexEditorContentOutlineTreeObject {
*
* @return The start offset, a non-negative integer.
*/
public int getFileStartOffset() {
public long getFileStartOffset() {
return fileStartOffset;
}
@ -73,7 +73,7 @@ public final class HexEditorContentOutlineTreeObject {
* The start offset, a non-negative integer or <code>-1</code> if
* the offset is not defined.
*/
public void setFileStartOffset(int fileOffset) {
public void setFileStartOffset(long fileOffset) {
this.fileStartOffset = fileOffset;
}
@ -84,7 +84,7 @@ public final class HexEditorContentOutlineTreeObject {
* @return The end offset, a non-negative integer or <code>-1</code> if the
* offset is not defined.
*/
public int getFileEndOffset() {
public long getFileEndOffset() {
return fileEndOffset;
}
@ -96,7 +96,7 @@ public final class HexEditorContentOutlineTreeObject {
* The end offset, a non-negative integer or <code>-1</code> if
* the offset is not defined.
*/
public void setFileEndOffset(int fileOffset) {
public void setFileEndOffset(long fileOffset) {
this.fileEndOffset = fileOffset;
}
@ -106,7 +106,7 @@ public final class HexEditorContentOutlineTreeObject {
*
* @return The offset, a non-negative integer.
*/
public int getTextStartOffset() {
public long getTextStartOffset() {
return textStartOffset;
}
@ -116,10 +116,10 @@ public final class HexEditorContentOutlineTreeObject {
* @param textOffset
* The offset, a non-negative integer.
*/
public void setTextStartOffset(int textOffset) {
public void setTextStartOffset(long textOffset) {
if (textOffset < 0) {
throw new IllegalArgumentException("Parameter 'textOffset' must not be negative. Specified value is "
+ textOffset + ".");
throw new IllegalArgumentException(
"Parameter 'textOffset' must not be negative. Specified value is " + textOffset + ".");
}
this.textStartOffset = textOffset;
}
@ -129,7 +129,7 @@ public final class HexEditorContentOutlineTreeObject {
*
* @return The offset, a non-negative integer.
*/
public int getTextEndOffset() {
public long getTextEndOffset() {
return textEndOffset;
}
@ -141,8 +141,8 @@ public final class HexEditorContentOutlineTreeObject {
*/
public void setTextEndOffset(int textOffset) {
if (textOffset < 0) {
throw new IllegalArgumentException("Parameter 'textOffset' must not be negative. Specified value is "
+ textOffset + ".");
throw new IllegalArgumentException(
"Parameter 'textOffset' must not be negative. Specified value is " + textOffset + ".");
}
this.textEndOffset = textOffset;
}

View File

@ -19,22 +19,45 @@
package com.wudsn.ide.base.editor.hex;
import com.wudsn.ide.base.editor.hex.parser.*;
enum HexEditorFileContentMode {
BINARY(Hardware.GENERIC), ATARI_COM_FILE(Hardware.ATARI8BIT), ATARI_DISK_IMAGE(Hardware.ATARI8BIT), ATARI_DISK_IMAGE_K_FILE(
Hardware.ATARI8BIT), ATARI_MADS_FILE(Hardware.ATARI8BIT), ATARI_SDX_FILE(Hardware.ATARI8BIT), ATARI_SAP_FILE(
Hardware.ATARI8BIT), C64_PRG_FILE(Hardware.C64);
BINARY(Hardware.GENERIC, BinaryParser.class), ATARI_COM_FILE(Hardware.ATARI8BIT,
AtariCOMParser.class), ATARI_DISK_IMAGE(Hardware.ATARI8BIT,
AtariDiskImageParser.class), ATARI_DISK_IMAGE_K_FILE(Hardware.ATARI8BIT,
AtariDiskImageKFileParser.class), ATARI_MADS_FILE(Hardware.ATARI8BIT,
AtariMADSParser.class), ATARI_SDX_FILE(Hardware.ATARI8BIT,
AtariSDXParser.class), ATARI_SAP_FILE(Hardware.ATARI8BIT,
AtariSAPParser.class), C64_PRG_FILE(Hardware.C64,
C64PRGParser.class), IFF_FILE(Hardware.GENERIC,
IFFParser.class);
private Hardware hardware;
private Class<? extends HexEditorParser> parserClass;
private HexEditorFileContentMode(Hardware hardware) {
private HexEditorFileContentMode(Hardware hardware, Class<? extends HexEditorParser> parserClass) {
if (hardware == null) {
throw new IllegalArgumentException("Parameter 'hardware' must not be null.");
}
if (parserClass == null) {
throw new IllegalArgumentException("Parameter 'parserClass' must not be null.");
}
this.hardware = hardware;
this.parserClass = parserClass;
}
public Hardware getHardware() {
return hardware;
}
public HexEditorParser createParser() {
try {
return parserClass.newInstance();
} catch (InstantiationException ex) {
throw new RuntimeException(ex);
} catch (IllegalAccessException ex) {
throw new RuntimeException(ex);
}
}
}

View File

@ -83,27 +83,38 @@ public abstract class HexEditorParser {
}
/**
* Gets a byte from the file content.
* Gets a byte (8-bit) from the file content.
*
* @param offset
* The offset, a non-negative integer.
* @return The byte from the file content.
*/
protected final int getFileContentByte(int offset) {
protected final int getFileContentByte(long offset) {
return owner.getFileContentByte(offset);
}
/**
* Gets a word from the file content.
* Gets a word (16 bit) in little endian format from the file content.
*
* @param offset
* The offset, a non-negative integer.
* @return The word from the file content.
*/
protected final int getFileContentWord(int offset) {
protected final int getFileContentWord(long offset) {
return owner.getFileContentWord(offset);
}
/**
* Gets a double word (32 bit) in big endian format from the file content.
*
* @param offset
* The offset, a non-negative integer.
* @return The word from the file content.
*/
protected final long getFileContentDoubleWordBigEndian(long offset) {
return owner.getFileContentDoubleWordBigEndian(offset);
}
/**
* Prints a block header in the context area and adds a block to the
* outline.
@ -128,13 +139,13 @@ public abstract class HexEditorParser {
* @return The tree object representing the block.
*/
protected final HexEditorContentOutlineTreeObject printBlockHeader(StyledString contentBuilder,
String blockHeaderText, int blockHeaderNumber, String blockHeaderParameterText, int offset,
int startAddress, int endAddress) {
String blockHeaderText, int blockHeaderNumber, String blockHeaderParameterText, long offset,
long startAddress, long endAddress) {
if (contentBuilder == null) {
throw new IllegalArgumentException("Parameter 'contentBuilder' must not be null.");
}
int blockLength = endAddress - startAddress + 1;
long blockLength = endAddress - startAddress + 1;
String blockHeaderNumberText;
if (blockHeaderNumber >= 0) {
blockHeaderNumberText = NumberUtility.getLongValueDecimalString(blockHeaderNumber);
@ -177,8 +188,7 @@ public abstract class HexEditorParser {
}
/**
* Prints a block header in the context area and adds a block to the
* outline.
* Adds a block to the outline.
*
* @param contentBuilder
* The content builder, not <code>null</code>.
@ -191,7 +201,7 @@ public abstract class HexEditorParser {
* @return The tree object representing the block.
*/
protected final HexEditorContentOutlineTreeObject printBlockHeader(StyledString contentBuilder,
StyledString headerStyledString, int offset) {
StyledString headerStyledString, long offset) {
return owner.printBlockHeader(contentBuilder, headerStyledString, offset);
}
@ -208,17 +218,17 @@ public abstract class HexEditorParser {
* @param offset
* The offset of the last block, a non-negative integer.
*/
protected final void printBlockWithError(StyledString contentBuilder, String errorText, int length, int offset) {
protected final void printBlockWithError(StyledString contentBuilder, String errorText, long length, long offset) {
owner.printBlockWithError(contentBuilder, errorText, length, offset);
}
protected final void skipByteTextIndex(int offset) {
protected final void skipByteTextIndex(long offset) {
owner.skipByteTextIndex(offset);
}
protected final int printBytes(HexEditorContentOutlineTreeObject treeObject, StyledString contentBuilder,
int offset, int maxOffset, boolean withStartAddress, int startAddress) {
protected final long printBytes(HexEditorContentOutlineTreeObject treeObject, StyledString contentBuilder,
long offset, long maxOffset, boolean withStartAddress, int startAddress) {
return owner.printBytes(treeObject, contentBuilder, offset, maxOffset, withStartAddress, startAddress);
}

View File

@ -35,20 +35,15 @@ import com.wudsn.ide.base.common.NumberUtility;
import com.wudsn.ide.base.common.Profiler;
import com.wudsn.ide.base.common.TextUtility;
import com.wudsn.ide.base.editor.hex.HexEditor.MessageIds;
import com.wudsn.ide.base.editor.hex.parser.AtariCOMParser;
import com.wudsn.ide.base.editor.hex.parser.AtariDiskImageKFileParser;
import com.wudsn.ide.base.editor.hex.parser.AtariDiskImageParser;
import com.wudsn.ide.base.editor.hex.parser.AtariMADSParser;
import com.wudsn.ide.base.editor.hex.parser.AtariParser;
import com.wudsn.ide.base.editor.hex.parser.AtariSAPParser;
import com.wudsn.ide.base.editor.hex.parser.AtariSDXParser;
import com.wudsn.ide.base.editor.hex.parser.BinaryParser;
import com.wudsn.ide.base.editor.hex.parser.C64PRGParser;
import com.wudsn.ide.base.gui.MessageManager;
final class HexEditorParserComponent {
public static final int UNDEFINED_OFFSET = -1;
public static final long UNDEFINED_OFFSET = -1;
private final static int BYTES_PER_ROW = 16;
private static final int INT_FF = 0xff;
@ -77,7 +72,7 @@ final class HexEditorParserComponent {
// Parsing state.
private List<HexEditorFileContentMode> possibleFileContentModes;
private List<HexEditorContentOutlineTreeObject> outlineBlocks;
private int[] byteTextOffsets;
private long[] byteTextOffsets;
private int byteTextIndex;
// Line buffers for binary to hex and char conversion.
@ -148,7 +143,7 @@ final class HexEditorParserComponent {
private void initByteTextOffsets() {
// Twice the space, because some format display the content twice, for
// example ATARI_DISK_IMAGE_K_FILE.
byteTextOffsets = new int[fileContent.length * 2];
byteTextOffsets = new long[fileContent.length * 2];
byteTextIndex = 0;
}
@ -266,6 +261,21 @@ final class HexEditorParserComponent {
result = HexEditorFileContentMode.C64_PRG_FILE;
}
}
// IFF files always have an even number of bytes
if (fileContent.length > 8 && (fileContent.length & 0x1) == 0) {
possibleFileContentModes.add(HexEditorFileContentMode.IFF_FILE);
char[] id = new char[4];
id[0] = (char) fileContent[0];
id[1] = (char) fileContent[1];
id[2] = (char) fileContent[2];
id[3] = (char) fileContent[3];
String chunk = String.copyValueOf(id);
boolean iff = chunk.equals("FORM") || chunk.equals("LIST") || chunk.equals("CAT ");
if (result.equals(HexEditorFileContentMode.BINARY) && iff) {
result = HexEditorFileContentMode.IFF_FILE;
}
}
return result;
}
@ -322,8 +332,8 @@ final class HexEditorParserComponent {
*/
public void setBytesPerRow(int bytesPerRow) {
if (bytesPerRow < 1) {
throw new IllegalArgumentException("Parameter 'bytesPerRow' must not be positive. Specified valie was "
+ bytesPerRow + ".");
throw new IllegalArgumentException(
"Parameter 'bytesPerRow' must not be positive. Specified valie was " + bytesPerRow + ".");
}
this.bytesPerRow = bytesPerRow;
}
@ -386,24 +396,7 @@ final class HexEditorParserComponent {
if (fileContent.length > 0) {
boolean error;
HexEditorParser parser;
if (fileContentMode.equals(HexEditorFileContentMode.ATARI_COM_FILE)) {
parser = new AtariCOMParser();
} else if (fileContentMode.equals(HexEditorFileContentMode.ATARI_DISK_IMAGE)) {
parser = new AtariDiskImageParser();
} else if (fileContentMode.equals(HexEditorFileContentMode.ATARI_DISK_IMAGE_K_FILE)) {
parser = new AtariDiskImageKFileParser();
} else if (fileContentMode.equals(HexEditorFileContentMode.ATARI_MADS_FILE)) {
parser = new AtariMADSParser();
} else if (fileContentMode.equals(HexEditorFileContentMode.ATARI_SDX_FILE)) {
parser = new AtariSDXParser();
} else if (fileContentMode.equals(HexEditorFileContentMode.ATARI_SAP_FILE)) {
parser = new AtariSAPParser();
} else if (fileContentMode.equals(HexEditorFileContentMode.C64_PRG_FILE)) {
parser = new C64PRGParser();
} else {
parser = new BinaryParser();
}
HexEditorParser parser = fileContentMode.createParser();
// Initialize the buffers for the hex and char conversion.
hexBuffer = new char[3 + bytesPerRow * 3 + 2];
@ -437,25 +430,54 @@ final class HexEditorParserComponent {
}
/**
* Gets a byte from the file content.
* Gets a byte (8 bit) from the file content.
*
* @param offset
* The offset, a non-negative integer.
* @return The byte from the file content.
*/
final int getFileContentByte(int offset) {
return fileContent[offset] & INT_FF;
final int getFileContentByte(long offset) {
if (offset < 0) {
throw new IllegalArgumentException("Parameter offset=" + offset + " must not be negative");
}
if (offset >= fileContent.length) {
throw new IllegalArgumentException(
"Parameter offset=" + offset + " must be less than the file content size " + fileContent.length);
}
return fileContent[(int) offset] & INT_FF;
}
/**
* Gets a word from the file content.
* Gets a word (16 bit) in little endian format from the file content.
*
* @param offset
* The offset, a non-negative integer.
* @return The word from the file content.
*/
final int getFileContentWord(int offset) {
return getFileContentByte(offset) + 256 * getFileContentByte(offset + 1);
final int getFileContentWord(long offset) {
return getFileContentByte(offset) + 0x100 * getFileContentByte(offset + 1);
}
/**
* Gets a word (16 bit) in big endian format from the file content.
*
* @param offset
* The offset, a non-negative integer.
* @return The word from the file content.
*/
final int getFileContentWordBigEndian(long offset) {
return getFileContentByte(offset + 1) + 0x100 * getFileContentByte(offset);
}
/**
* Gets a double word (32 bit) in big endian format from the file content.
*
* @param offset
* The offset, a non-negative integer.
* @return The word from the file content.
*/
final long getFileContentDoubleWordBigEndian(long offset) {
return getFileContentWordBigEndian(offset + 2) + 0x10000 * getFileContentWordBigEndian(offset);
}
/**
@ -473,7 +495,7 @@ final class HexEditorParserComponent {
* @return The tree object representing the block.
*/
final HexEditorContentOutlineTreeObject printBlockHeader(StyledString contentBuilder,
StyledString headerStyledString, int offset) {
StyledString headerStyledString, long offset) {
if (contentBuilder == null) {
throw new IllegalArgumentException("Parameter 'contentBuilder' must not be null.");
@ -503,7 +525,7 @@ final class HexEditorParserComponent {
* @param offset
* The offset of the last block, a non-negative integer.
*/
final void printBlockWithError(StyledString contentBuilder, String errorText, int length, int offset) {
final void printBlockWithError(StyledString contentBuilder, String errorText, long length, long offset) {
if (contentBuilder == null) {
throw new IllegalArgumentException("Parameter 'contentBuilder' must not be null.");
}
@ -525,22 +547,22 @@ final class HexEditorParserComponent {
offset = printBytes(treeObject, contentBuilder, offset, length - 1, true, 0);
}
final void skipByteTextIndex(int offset) {
final void skipByteTextIndex(long offset) {
byteTextIndex += offset;
}
final int printBytes(HexEditorContentOutlineTreeObject treeObject, StyledString contentBuilder, int offset,
int maxOffset, boolean withStartAddress, int startAddress) {
final long printBytes(HexEditorContentOutlineTreeObject treeObject, StyledString contentBuilder, long offset,
long maxOffset, boolean withStartAddress, int startAddress) {
if (offset < 0) {
throw new IllegalArgumentException("Parameter 'offset' must not be negative, specified value is " + offset
+ ".");
throw new IllegalArgumentException(
"Parameter 'offset' must not be negative, specified value is " + offset + ".");
}
if (maxOffset < 0) {
throw new IllegalArgumentException("Parameter 'offset' must not be negative, specified value is "
+ maxOffset + ".");
throw new IllegalArgumentException(
"Parameter 'offset' must not be negative, specified value is " + maxOffset + ".");
}
int length = Math.max(4, HexUtility.getLongValueHexLength(maxOffset));
int length = Math.max(4, HexUtility.getLongValueHexLength(fileContent.length));
char[] characterMapping = characterSet.getCharacterMapping();
while (offset <= maxOffset) {
int contentBuilderLineStartOffset = contentBuilder.length();
@ -609,11 +631,11 @@ final class HexEditorParserComponent {
*/
public HexEditorSelection getSelection(int x, int y) {
int startOffset = UNDEFINED_OFFSET;
int endOffset = UNDEFINED_OFFSET;
int textOffset = 0;
long startOffset = UNDEFINED_OFFSET;
long endOffset = UNDEFINED_OFFSET;
long textOffset = 0;
for (int i = 0; i < byteTextIndex && (startOffset == UNDEFINED_OFFSET || endOffset == UNDEFINED_OFFSET); i++) {
int nextTextOffset;
long nextTextOffset;
if (i < byteTextIndex - 1) {
nextTextOffset = byteTextOffsets[i + 1];
} else {
@ -633,23 +655,26 @@ final class HexEditorParserComponent {
if (startOffset == UNDEFINED_OFFSET) {
return null;
}
int length;
long length;
byte[] bytes;
length = endOffset - startOffset + 1;
// BasePlugin.getInstance().log("HexEditor.getSelection(): startOffset={0} endoffset={1} length={2}",
// BasePlugin.getInstance().log("HexEditor.getSelection():
// startOffset={0} endoffset={1} length={2}",
// new Object[] { String.valueOf(startOffset),
// String.valueOf(endOffset), String.valueOf(length) });
// Length not empty and selection does not cross file end boundary.
if (length > 0 && endOffset < fileContent.length) {
if (length > 0 && length < Integer.MAX_VALUE && startOffset < fileContent.length
&& endOffset < fileContent.length) {
// Reposition into first occurrence of in the file.
// This is relevant for the format that display the content more
// than once.
bytes = new byte[length];
bytes = new byte[(int) length];
// startOffset = startOffset % fileContent.length;
// endOffset = endOffset % fileContent.length;
// length = endOffset - startOffset + 1;
System.arraycopy(fileContent, startOffset, bytes, 0, length);
System.arraycopy(fileContent, (int) startOffset, bytes, 0, bytes.length);
// BasePlugin.getInstance().log(
// "HexEditor startOffset={0} endoffset={1} length={2}",
@ -672,9 +697,9 @@ final class HexEditorParserComponent {
* @return The text offset where the byte is represented or <code>-1</code>
* if there is no such text offset.
*/
public int getByteTextOffset(int byteOffset) {
public long getByteTextOffset(long byteOffset) {
if (byteOffset < byteTextOffsets.length) {
return byteTextOffsets[byteOffset];
return byteTextOffsets[(int) byteOffset];
}
return -1;
}

View File

@ -29,8 +29,8 @@ import org.eclipse.jface.viewers.ISelection;
*/
final class HexEditorSelection implements ISelection {
private int startOffset;
private int endOffset;
private long startOffset;
private long endOffset;
private byte[] bytes;
/**
@ -45,7 +45,7 @@ final class HexEditorSelection implements ISelection {
* The content of the selection, may be empty, not
* <code>null</code>.
*/
public HexEditorSelection(int startOffset, int endOffset, byte[] bytes) {
public HexEditorSelection(long startOffset, long endOffset, byte[] bytes) {
if (startOffset < 0) {
throw new IllegalArgumentException("Parameter 'startOffset' must not be negative, specified value is "
@ -74,7 +74,7 @@ final class HexEditorSelection implements ISelection {
* @return The start offset in the original array, a non-negative number.
*
*/
public int getStartOffset() {
public long getStartOffset() {
return startOffset;
}
@ -84,7 +84,7 @@ final class HexEditorSelection implements ISelection {
* @return The end offset in the original array, a non-negative number
* greater or equal to the start offset.
*/
public int getEndOffset() {
public long getEndOffset() {
return endOffset;
}

View File

@ -35,8 +35,8 @@ public final class HexEditorSelectionTransfer extends ByteArrayTransfer {
ByteArrayOutputStream out = new ByteArrayOutputStream();
DataOutputStream writeOut = new DataOutputStream(out);
byte[] bytes = hexEditorSelection.getBytes();
writeOut.writeInt(hexEditorSelection.getStartOffset());
writeOut.writeInt(hexEditorSelection.getEndOffset());
writeOut.writeLong(hexEditorSelection.getStartOffset());
writeOut.writeLong(hexEditorSelection.getEndOffset());
writeOut.writeInt(bytes.length);
writeOut.write(bytes);
@ -66,8 +66,8 @@ public final class HexEditorSelectionTransfer extends ByteArrayTransfer {
ByteArrayInputStream in = new ByteArrayInputStream(buffer);
DataInputStream readIn = new DataInputStream(in);
while (readIn.available() > 0) {
int startOffset = readIn.readInt();
int endOffset = readIn.readInt();
long startOffset = readIn.readLong();
long endOffset = readIn.readLong();
int size = readIn.readInt();
byte[] bytes = new byte[size];
readIn.read(bytes);

View File

@ -35,7 +35,7 @@ public class AtariDiskImageParser extends AtariParser {
boolean error = false;
int length = getFileContentLength();
int offset = 0;
long offset = 0;
HexEditorContentOutlineTreeObject treeObject;
treeObject = printBlockHeader(contentBuilder, Texts.HEX_EDITOR_ATARI_DISK_IMAGE_HEADER, -1, "", offset, offset,
@ -63,7 +63,8 @@ public class AtariDiskImageParser extends AtariParser {
while (blockMode && !error) {
treeObject = printBlockHeader(contentBuilder, Texts.HEX_EDITOR_ATARI_SECTOR_HEADER, sectorCount,
Texts.HEX_EDITOR_ATARI_SECTOR_HEADER_PARAMETERS, offset, startAddress, startAddress + sectorSize - 1);
Texts.HEX_EDITOR_ATARI_SECTOR_HEADER_PARAMETERS, offset, startAddress,
startAddress + sectorSize - 1);
offset = printBytes(treeObject, contentBuilder, offset, offset + sectorSize - 1, true, startAddress);
contentBuilder.append("\n");

View File

@ -48,7 +48,7 @@ public class AtariMADSParser extends HexEditorParser {
}
boolean error;
int offset = 0;
long offset = 0;
// Skip offset bytes in lookup array.
skipByteTextIndex(offset);
@ -82,7 +82,7 @@ public class AtariMADSParser extends HexEditorParser {
treeObject = printHeader(contentBuilder, offset, headerText);
offset = printBytes(treeObject, contentBuilder, offset, offset + 15, true, 0);
int blockEnd = offset + endAddress - startAddress;
long blockEnd = offset + endAddress - startAddress;
offset = printBytes(treeObject, contentBuilder, offset, blockEnd, true, startAddress);
@ -100,7 +100,7 @@ public class AtariMADSParser extends HexEditorParser {
// stored for each address (low byte of address being
// modified).
int dataSize = (type == '>' ? 3 : 2);
int blockEnd = offset + (dataLength * dataSize) - 1;
long blockEnd = offset + (dataLength * dataSize) - 1;
offset = printBytes(treeObject, contentBuilder, offset, blockEnd, false, 0);
@ -141,7 +141,7 @@ public class AtariMADSParser extends HexEditorParser {
int labelLength = getFileContentWord(offset + 2);
String labelName = getLabelName(offset + 4, labelLength);
int address = getFileContentWord(offset + 4 + labelLength);
int headerEnd = offset + 6 + labelLength - 1;
long headerEnd = offset + 6 + labelLength - 1;
switch (labelType) {
case 'P':
int procType = getFileContentByte(headerEnd + 1);
@ -194,7 +194,7 @@ public class AtariMADSParser extends HexEditorParser {
return error;
}
private HexEditorContentOutlineTreeObject printHeader(StyledString contentBuilder, int offset, String headerText) {
private HexEditorContentOutlineTreeObject printHeader(StyledString contentBuilder, long offset, String headerText) {
HexEditorContentOutlineTreeObject treeObject;
StyledString headerStyledString = new StyledString(headerText, offsetStyler);
contentBuilder.append(headerStyledString).append("\n");
@ -202,7 +202,7 @@ public class AtariMADSParser extends HexEditorParser {
return treeObject;
}
private HexEditorContentOutlineTreeObject printTypedHeader(StyledString contentBuilder, int offset, String text,
private HexEditorContentOutlineTreeObject printTypedHeader(StyledString contentBuilder, long offset, String text,
int type, int dataLength) {
HexEditorContentOutlineTreeObject treeObject;
String headerText = TextUtility.format(text, String.valueOf((char) type),
@ -211,7 +211,7 @@ public class AtariMADSParser extends HexEditorParser {
return treeObject;
}
private String getLabelName(int offset, int length) {
private String getLabelName(long offset, int length) {
StringBuffer buffer = new StringBuffer(8);
for (int i = 0; i < length; i++) {
buffer.append((char) getFileContentByte(offset + i));

View File

@ -29,7 +29,7 @@ public abstract class AtariParser extends HexEditorParser {
public final static int COM_HEADER = 0xffff;
protected final boolean parseAtariCOMFile(StyledString contentBuilder, int offset, int fileContentLength) {
protected final boolean parseAtariCOMFile(StyledString contentBuilder, long offset, int fileContentLength) {
if (contentBuilder == null) {
throw new IllegalArgumentException("Parameter 'contentBuilder' must not be null.");
}
@ -38,7 +38,7 @@ public abstract class AtariParser extends HexEditorParser {
int endAddress;
int blockCount;
int blockEnd;
long blockEnd;
// Skip offset bytes in lookup array.
skipByteTextIndex(offset);

View File

@ -31,7 +31,7 @@ public final class AtariSAPParser extends AtariParser {
if (contentBuilder == null) {
throw new IllegalArgumentException("Parameter 'contentBuilder' must not be null.");
}
int offset = 0;
long offset = 0;
int fileContentLenght = getFileContentLength();
int maxOffset = fileContentLenght - 2;
while (offset < maxOffset && getFileContentByte(offset) != 0xff && getFileContentByte(offset) != 0xff) {

View File

@ -43,7 +43,7 @@ public class AtariSDXParser extends HexEditorParser {
}
boolean error;
int offset = 0;
long offset = 0;
// Skip offset bytes in lookup array.
skipByteTextIndex(offset);
@ -74,7 +74,7 @@ public class AtariSDXParser extends HexEditorParser {
endAddress);
offset = printBytes(treeObject, contentBuilder, offset, offset + 5, true, 0);
int blockEnd = offset + endAddress - startAddress;
long blockEnd = offset + endAddress - startAddress;
offset = printBytes(treeObject, contentBuilder, offset, blockEnd, true, startAddress);
@ -94,7 +94,7 @@ public class AtariSDXParser extends HexEditorParser {
treeObject = printBlockHeader(contentBuilder, headerStyledString, offset);
offset = printBytes(treeObject, contentBuilder, offset, offset + 7, true, 0);
int blockEnd = offset + blockLength - 1;
long blockEnd = offset + blockLength - 1;
// Print bytes only of the block is not marked as EMPTY
if ((blockId & 0x80) != 0x80) {
@ -111,7 +111,7 @@ public class AtariSDXParser extends HexEditorParser {
contentBuilder.append(headerStyledString).append("\n");
treeObject = printBlockHeader(contentBuilder, headerStyledString, offset);
offset = printBytes(treeObject, contentBuilder, offset, offset + 4, true, 0);
int blockEnd = getBlockEnd(offset);
long blockEnd = getBlockEnd(offset);
offset = printBytes(treeObject, contentBuilder, offset, blockEnd, true, 0);
} else if (header == UPDATE_SYMBOLS_HEADER) {
String symbolName = getSymbolName(offset + 2);
@ -123,7 +123,7 @@ public class AtariSDXParser extends HexEditorParser {
contentBuilder.append(headerStyledString).append("\n");
treeObject = printBlockHeader(contentBuilder, headerStyledString, offset);
offset = printBytes(treeObject, contentBuilder, offset, offset + 11, true, 0);
int blockEnd = getBlockEnd(offset);
long blockEnd = getBlockEnd(offset);
offset = printBytes(treeObject, contentBuilder, offset, blockEnd, true, 0);
} else if (header == DEFINE_SYMBOLS_HEADER) {
int blockNumber = getFileContentByte(offset + 2);
@ -160,10 +160,10 @@ public class AtariSDXParser extends HexEditorParser {
* The start offset, a non-negative integer.
* @return The end offset, a non-negative integer.
*/
private int getBlockEnd(int offset) {
private long getBlockEnd(long offset) {
int fileContentLength = getFileContentLength();
int i = offset;
int blockEnd = -1;
long i = offset;
long blockEnd = -1;
while (blockEnd < 0 && i < fileContentLength) {
int location = getFileContentByte(i);
switch (location) {
@ -184,7 +184,7 @@ public class AtariSDXParser extends HexEditorParser {
return blockEnd;
}
private String getSymbolName(int offset) {
private String getSymbolName(long offset) {
StringBuffer buffer = new StringBuffer(8);
for (int i = 0; i < 8; i++) {
buffer.append((char) getFileContentByte(offset + i));

View File

@ -37,7 +37,7 @@ public class C64PRGParser extends HexEditorParser {
int endAddress;
int length = getFileContentLength();
int offset = 0;
long offset = 0;
error = (length < 2);
if (!error) {

View File

@ -0,0 +1,120 @@
/**
* Copyright (C) 2009 - 2019 <a href="https://www.wudsn.com" target="_top">Peter Dell</a>
*
* This file is part of WUDSN IDE.
*
* WUDSN IDE is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* WUDSN IDE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with WUDSN IDE. If not, see <http://www.gnu.org/licenses/>.
*/
package com.wudsn.ide.base.editor.hex.parser;
import org.eclipse.jface.viewers.StyledString;
import com.wudsn.ide.base.Texts;
import com.wudsn.ide.base.common.HexUtility;
import com.wudsn.ide.base.common.NumberUtility;
import com.wudsn.ide.base.common.TextUtility;
import com.wudsn.ide.base.editor.hex.HexEditorContentOutlineTreeObject;
import com.wudsn.ide.base.editor.hex.HexEditorParser;
public final class IFFParser extends HexEditorParser {
@Override
public final boolean parse(StyledString contentBuilder) {
if (contentBuilder == null) {
throw new IllegalArgumentException("Parameter 'contentBuilder' must not be null.");
}
boolean error;
long offset = 0;
long fileContentLength = getFileContentLength();
error = parse(contentBuilder, offset, fileContentLength, null);
return error;
}
private boolean parse(StyledString contentBuilder, long offset, long fileContentLength,
HexEditorContentOutlineTreeObject treeObject) {
boolean error;
error = (fileContentLength - offset) < 8;
if (!error) {
while ((fileContentLength - offset) >= 8 && !error) {
long headerLength = 8;
String chunkName = getChunkName(offset);
long chunkLength = getFileContentDoubleWordBigEndian(offset + 4);
String headerText;
String formTypeName = "";
boolean hasInnerChunks = false;
if (chunkName.equals("FORM")) {
if (chunkLength >= 4) {
formTypeName = getChunkName(offset + 8);
headerText = TextUtility.format(Texts.HEX_EDITOR_IFF_FORM_CHUNK, chunkName, formTypeName,
HexUtility.getLongValueHexString(chunkLength),
NumberUtility.getLongValueDecimalString(chunkLength));
headerLength += 4;
chunkLength -= 4;
// Ignore trailing parts in the file outside of the main chunk
fileContentLength = offset + chunkLength;
hasInnerChunks = true;
} else {
error = true;
headerText = null;
}
} else {
headerText = TextUtility.format(Texts.HEX_EDITOR_IFF_CHUNK, chunkName,
HexUtility.getLongValueHexString(chunkLength),
NumberUtility.getLongValueDecimalString(chunkLength));
}
if (!error) {
StyledString styledString = new StyledString(headerText, offsetStyler);
treeObject = printBlockHeader(contentBuilder, styledString, offset);
contentBuilder.append(styledString);
contentBuilder.append("\n");
offset = printBytes(treeObject, contentBuilder, offset, offset + headerLength - 1, false, 0);
if (hasInnerChunks) {
contentBuilder.append("\n");
parse(contentBuilder, offset, fileContentLength, treeObject);
offset += chunkLength;
} else {
offset = printBytes(treeObject, contentBuilder, offset, offset + chunkLength - 1, false, 0);
}
contentBuilder.append("\n");
// Skip padding byte
if ((offset & 0x1) == 1) {
offset++;
}
}
}
}
if (error) {
printBlockWithError(contentBuilder, Texts.HEX_EDITOR_IFF_FILE_ERROR, fileContentLength, offset);
}
return error;
}
private String getChunkName(long offset) {
char[] id = new char[4];
id[0] = (char) getFileContentByte(offset);
id[1] = (char) getFileContentByte(offset + 1);
id[2] = (char) getFileContentByte(offset + 2);
id[3] = (char) getFileContentByte(offset + 3);
return String.copyValueOf(id);
}
}