diff --git a/com.wudsn.ide.base/plugin.properties b/com.wudsn.ide.base/plugin.properties index 9ff12413..05828950 100644 --- a/com.wudsn.ide.base/plugin.properties +++ b/com.wudsn.ide.base/plugin.properties @@ -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 diff --git a/com.wudsn.ide.base/plugin_de_DE.properties b/com.wudsn.ide.base/plugin_de_DE.properties index 8e0503b7..30b5aab0 100644 --- a/com.wudsn.ide.base/plugin_de_DE.properties +++ b/com.wudsn.ide.base/plugin_de_DE.properties @@ -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 diff --git a/com.wudsn.ide.base/src/com/wudsn/ide/base/Texts.java b/com.wudsn.ide.base/src/com/wudsn/ide/base/Texts.java index 51a7f8a3..e269842e 100644 --- a/com.wudsn.ide.base/src/com/wudsn/ide/base/Texts.java +++ b/com.wudsn.ide.base/src/com/wudsn/ide/base/Texts.java @@ -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; diff --git a/com.wudsn.ide.base/src/com/wudsn/ide/base/Texts.properties b/com.wudsn.ide.base/src/com/wudsn/ide/base/Texts.properties index 3e48edc4..4a270fa2 100644 --- a/com.wudsn.ide.base/src/com/wudsn/ide/base/Texts.properties +++ b/com.wudsn.ide.base/src/com/wudsn/ide/base/Texts.properties @@ -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 diff --git a/com.wudsn.ide.base/src/com/wudsn/ide/base/Texts_de_DE.properties b/com.wudsn.ide.base/src/com/wudsn/ide/base/Texts_de_DE.properties index 9362106d..5ac1e8fc 100644 --- a/com.wudsn.ide.base/src/com/wudsn/ide/base/Texts_de_DE.properties +++ b/com.wudsn.ide.base/src/com/wudsn/ide/base/Texts_de_DE.properties @@ -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 diff --git a/com.wudsn.ide.base/src/com/wudsn/ide/base/editor/hex/HexEditor.java b/com.wudsn.ide.base/src/com/wudsn/ide/base/editor/hex/HexEditor.java index 76cb083d..db35130c 100644 --- a/com.wudsn.ide.base/src/com/wudsn/ide/base/editor/hex/HexEditor.java +++ b/com.wudsn.ide.base/src/com/wudsn/ide/base/editor/hex/HexEditor.java @@ -281,12 +281,12 @@ public final class HexEditor extends EditorPart implements ISelectionProvider, A public T getAdapter(Class 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", diff --git a/com.wudsn.ide.base/src/com/wudsn/ide/base/editor/hex/HexEditorContentOutlineTreeObject.java b/com.wudsn.ide.base/src/com/wudsn/ide/base/editor/hex/HexEditorContentOutlineTreeObject.java index 9c16dea2..c5f38ac5 100644 --- a/com.wudsn.ide.base/src/com/wudsn/ide/base/editor/hex/HexEditorContentOutlineTreeObject.java +++ b/com.wudsn.ide.base/src/com/wudsn/ide/base/editor/hex/HexEditorContentOutlineTreeObject.java @@ -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 -1 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 -1 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 -1 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; } diff --git a/com.wudsn.ide.base/src/com/wudsn/ide/base/editor/hex/HexEditorFileContentMode.java b/com.wudsn.ide.base/src/com/wudsn/ide/base/editor/hex/HexEditorFileContentMode.java index 1a914070..ff5bab0d 100644 --- a/com.wudsn.ide.base/src/com/wudsn/ide/base/editor/hex/HexEditorFileContentMode.java +++ b/com.wudsn.ide.base/src/com/wudsn/ide/base/editor/hex/HexEditorFileContentMode.java @@ -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 parserClass; - private HexEditorFileContentMode(Hardware hardware) { + private HexEditorFileContentMode(Hardware hardware, Class 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); + } + } } diff --git a/com.wudsn.ide.base/src/com/wudsn/ide/base/editor/hex/HexEditorParser.java b/com.wudsn.ide.base/src/com/wudsn/ide/base/editor/hex/HexEditorParser.java index 0b242228..22fdaa67 100644 --- a/com.wudsn.ide.base/src/com/wudsn/ide/base/editor/hex/HexEditorParser.java +++ b/com.wudsn.ide.base/src/com/wudsn/ide/base/editor/hex/HexEditorParser.java @@ -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 null. @@ -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); } diff --git a/com.wudsn.ide.base/src/com/wudsn/ide/base/editor/hex/HexEditorParserComponent.java b/com.wudsn.ide.base/src/com/wudsn/ide/base/editor/hex/HexEditorParserComponent.java index 60eb3dde..7d9d455c 100644 --- a/com.wudsn.ide.base/src/com/wudsn/ide/base/editor/hex/HexEditorParserComponent.java +++ b/com.wudsn.ide.base/src/com/wudsn/ide/base/editor/hex/HexEditorParserComponent.java @@ -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 possibleFileContentModes; private List 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 -1 * 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; } diff --git a/com.wudsn.ide.base/src/com/wudsn/ide/base/editor/hex/HexEditorSelection.java b/com.wudsn.ide.base/src/com/wudsn/ide/base/editor/hex/HexEditorSelection.java index 3096ec47..a91e0aaa 100644 --- a/com.wudsn.ide.base/src/com/wudsn/ide/base/editor/hex/HexEditorSelection.java +++ b/com.wudsn.ide.base/src/com/wudsn/ide/base/editor/hex/HexEditorSelection.java @@ -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 * null. */ - 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; } diff --git a/com.wudsn.ide.base/src/com/wudsn/ide/base/editor/hex/HexEditorSelectionTransfer.java b/com.wudsn.ide.base/src/com/wudsn/ide/base/editor/hex/HexEditorSelectionTransfer.java index c6da1cd8..1632785c 100644 --- a/com.wudsn.ide.base/src/com/wudsn/ide/base/editor/hex/HexEditorSelectionTransfer.java +++ b/com.wudsn.ide.base/src/com/wudsn/ide/base/editor/hex/HexEditorSelectionTransfer.java @@ -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); diff --git a/com.wudsn.ide.base/src/com/wudsn/ide/base/editor/hex/parser/AtariDiskImageParser.java b/com.wudsn.ide.base/src/com/wudsn/ide/base/editor/hex/parser/AtariDiskImageParser.java index 28c9ef6a..5e115930 100644 --- a/com.wudsn.ide.base/src/com/wudsn/ide/base/editor/hex/parser/AtariDiskImageParser.java +++ b/com.wudsn.ide.base/src/com/wudsn/ide/base/editor/hex/parser/AtariDiskImageParser.java @@ -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"); diff --git a/com.wudsn.ide.base/src/com/wudsn/ide/base/editor/hex/parser/AtariMADSParser.java b/com.wudsn.ide.base/src/com/wudsn/ide/base/editor/hex/parser/AtariMADSParser.java index 605085fc..68901698 100644 --- a/com.wudsn.ide.base/src/com/wudsn/ide/base/editor/hex/parser/AtariMADSParser.java +++ b/com.wudsn.ide.base/src/com/wudsn/ide/base/editor/hex/parser/AtariMADSParser.java @@ -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)); diff --git a/com.wudsn.ide.base/src/com/wudsn/ide/base/editor/hex/parser/AtariParser.java b/com.wudsn.ide.base/src/com/wudsn/ide/base/editor/hex/parser/AtariParser.java index 6f8eb059..4e095240 100644 --- a/com.wudsn.ide.base/src/com/wudsn/ide/base/editor/hex/parser/AtariParser.java +++ b/com.wudsn.ide.base/src/com/wudsn/ide/base/editor/hex/parser/AtariParser.java @@ -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); diff --git a/com.wudsn.ide.base/src/com/wudsn/ide/base/editor/hex/parser/AtariSAPParser.java b/com.wudsn.ide.base/src/com/wudsn/ide/base/editor/hex/parser/AtariSAPParser.java index 721cbe49..82addfcd 100644 --- a/com.wudsn.ide.base/src/com/wudsn/ide/base/editor/hex/parser/AtariSAPParser.java +++ b/com.wudsn.ide.base/src/com/wudsn/ide/base/editor/hex/parser/AtariSAPParser.java @@ -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) { diff --git a/com.wudsn.ide.base/src/com/wudsn/ide/base/editor/hex/parser/AtariSDXParser.java b/com.wudsn.ide.base/src/com/wudsn/ide/base/editor/hex/parser/AtariSDXParser.java index 0f4d9815..1d62c11b 100644 --- a/com.wudsn.ide.base/src/com/wudsn/ide/base/editor/hex/parser/AtariSDXParser.java +++ b/com.wudsn.ide.base/src/com/wudsn/ide/base/editor/hex/parser/AtariSDXParser.java @@ -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)); diff --git a/com.wudsn.ide.base/src/com/wudsn/ide/base/editor/hex/parser/C64PRGParser.java b/com.wudsn.ide.base/src/com/wudsn/ide/base/editor/hex/parser/C64PRGParser.java index 83ae4992..2584db7f 100644 --- a/com.wudsn.ide.base/src/com/wudsn/ide/base/editor/hex/parser/C64PRGParser.java +++ b/com.wudsn.ide.base/src/com/wudsn/ide/base/editor/hex/parser/C64PRGParser.java @@ -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) { diff --git a/com.wudsn.ide.base/src/com/wudsn/ide/base/editor/hex/parser/IFFParser.java b/com.wudsn.ide.base/src/com/wudsn/ide/base/editor/hex/parser/IFFParser.java new file mode 100644 index 00000000..8309cf38 --- /dev/null +++ b/com.wudsn.ide.base/src/com/wudsn/ide/base/editor/hex/parser/IFFParser.java @@ -0,0 +1,120 @@ +/** + * Copyright (C) 2009 - 2019 Peter Dell + * + * 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 . + */ + +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); + } + +}