diff --git a/com.wudsn.ide.asm/src/com/wudsn/ide/asm/compiler/CompilerRegistry.java b/com.wudsn.ide.asm/src/com/wudsn/ide/asm/compiler/CompilerRegistry.java index 166f8ad9..0850c3fd 100644 --- a/com.wudsn.ide.asm/src/com/wudsn/ide/asm/compiler/CompilerRegistry.java +++ b/com.wudsn.ide.asm/src/com/wudsn/ide/asm/compiler/CompilerRegistry.java @@ -45,174 +45,172 @@ import com.wudsn.ide.asm.compiler.syntax.CompilerSyntax; */ public final class CompilerRegistry { - /** - * The id of the extension point which provides the compilers. - */ - private static final String COMPILERS = "com.wudsn.ide.asm.compilers"; + /** + * The id of the extension point which provides the compilers. + */ + private static final String COMPILERS = "com.wudsn.ide.asm.compilers"; - /** - * The registered compiler definition. - */ - private List compilerDefinitionList; + /** + * The registered compiler definition. + */ + private List compilerDefinitionList; - /** - * The cached map of compiler instances. - */ - private Map compilerMap; + /** + * The cached map of compiler instances. + */ + private Map compilerMap; - /** - * Creation is public. - */ - public CompilerRegistry() { - compilerDefinitionList = Collections.emptyList(); - compilerMap = Collections.emptyMap(); + /** + * Creation is public. + */ + public CompilerRegistry() { + compilerDefinitionList = Collections.emptyList(); + compilerMap = Collections.emptyMap(); - } - - /** - * Initializes the list of available compilers. - */ - public void init() { - - compilerDefinitionList = new ArrayList(); - compilerMap = new TreeMap(); - - IExtensionRegistry extensionRegistry = Platform.getExtensionRegistry(); - IExtensionPoint extensionPoint = extensionRegistry.getExtensionPoint(COMPILERS); - if (extensionPoint == null) { - throw new IllegalStateException("Extension point '" + COMPILERS + "' is not defined."); } - IExtension[] extensions = extensionPoint.getExtensions(); + /** + * Initializes the list of available compilers. + */ + public void init() { - for (IExtension extension : extensions) { - IConfigurationElement[] configurationElements = extension.getConfigurationElements(); - for (IConfigurationElement configurationElement : configurationElements) { + compilerDefinitionList = new ArrayList(); + compilerMap = new TreeMap(); - try { - CompilerDefinition compilerDefinition; - compilerDefinition = new CompilerDefinition(); - compilerDefinition.setId(configurationElement.getAttribute("id")); - compilerDefinition.setName(configurationElement.getAttribute("name")); - compilerDefinition.setClassName(configurationElement.getAttribute("class")); - compilerDefinition.setHelpFilePaths(configurationElement.getAttribute("helpFilePaths")); - compilerDefinition.setHomePageURL(configurationElement.getAttribute("homePageURL")); - compilerDefinition.setDefaultParameters(configurationElement.getAttribute("defaultParameters")); - - configurationElement.getChildren("supportedCPU"); - IConfigurationElement[] supportedCPUArray; - supportedCPUArray = configurationElement.getChildren("supportedCPU"); - List supportedCPUs = new ArrayList(supportedCPUArray.length); - for (IConfigurationElement supportedCPU : supportedCPUArray) { - supportedCPUs.add(CPU.valueOf(supportedCPU.getAttribute("cpu"))); - } - supportedCPUs = Collections.unmodifiableList(supportedCPUs); - compilerDefinition.setSupportedCPUs(supportedCPUs); - compilerDefinition.setDefaultHardware(Hardware.valueOf(configurationElement - .getAttribute("defaultHardware"))); - - compilerDefinitionList.add(compilerDefinition); - - addCompiler(configurationElement, compilerDefinition); - } catch (RuntimeException ex) { - throw new RuntimeException("Error during registration of compiler '" - + configurationElement.getAttribute("id") + "'.", ex); + IExtensionRegistry extensionRegistry = Platform.getExtensionRegistry(); + IExtensionPoint extensionPoint = extensionRegistry.getExtensionPoint(COMPILERS); + if (extensionPoint == null) { + throw new IllegalStateException("Extension point '" + COMPILERS + "' is not defined."); } - } + + IExtension[] extensions = extensionPoint.getExtensions(); + + for (IExtension extension : extensions) { + IConfigurationElement[] configurationElements = extension.getConfigurationElements(); + for (IConfigurationElement configurationElement : configurationElements) { + + try { + CompilerDefinition compilerDefinition; + compilerDefinition = new CompilerDefinition(); + compilerDefinition.setId(configurationElement.getAttribute("id")); + compilerDefinition.setName(configurationElement.getAttribute("name")); + compilerDefinition.setClassName(configurationElement.getAttribute("class")); + compilerDefinition.setHelpFilePaths(configurationElement.getAttribute("helpFilePaths")); + compilerDefinition.setHomePageURL(configurationElement.getAttribute("homePageURL")); + compilerDefinition.setDefaultParameters(configurationElement.getAttribute("defaultParameters")); + + configurationElement.getChildren("supportedCPU"); + IConfigurationElement[] supportedCPUArray; + supportedCPUArray = configurationElement.getChildren("supportedCPU"); + List supportedCPUs = new ArrayList(supportedCPUArray.length); + for (IConfigurationElement supportedCPU : supportedCPUArray) { + supportedCPUs.add(CPU.valueOf(supportedCPU.getAttribute("cpu"))); + } + supportedCPUs = Collections.unmodifiableList(supportedCPUs); + compilerDefinition.setSupportedCPUs(supportedCPUs); + compilerDefinition + .setDefaultHardware(Hardware.valueOf(configurationElement.getAttribute("defaultHardware"))); + + compilerDefinitionList.add(compilerDefinition); + + addCompiler(configurationElement, compilerDefinition); + } catch (RuntimeException ex) { + throw new RuntimeException( + "Error during registration of compiler '" + configurationElement.getAttribute("id") + "'.", + ex); + } + } + } + + compilerDefinitionList = new ArrayList(compilerDefinitionList); + Collections.sort(compilerDefinitionList); + compilerDefinitionList = Collections.unmodifiableList(compilerDefinitionList); + compilerMap = Collections.unmodifiableMap(compilerMap); } - compilerDefinitionList = new ArrayList(compilerDefinitionList); - Collections.sort(compilerDefinitionList); - compilerDefinitionList = Collections.unmodifiableList(compilerDefinitionList); - compilerMap = Collections.unmodifiableMap(compilerMap); - } + /** + * Adds a new compiler. + * + * @param configurationElement The configuration element used as class instance + * factory, not null. + * + * @param compilerDefinition The compiler definition, not null. + */ + private void addCompiler(IConfigurationElement configurationElement, CompilerDefinition compilerDefinition) { + if (configurationElement == null) { + throw new IllegalArgumentException("Parameter 'configurationElement' must not be null."); + } + if (compilerDefinition == null) { + throw new IllegalArgumentException("Parameter 'compilerDefinition' must not be null."); + } + + String id = compilerDefinition.getId(); + Compiler compiler; + try { + // The class loading must be delegated to the framework. + compiler = (Compiler) configurationElement.createExecutableExtension("class"); + } catch (CoreException ex) { + throw new RuntimeException("Cannot create compiler instance for id '" + id + "'.", ex); + } + + // Build the list of common and specific syntax definition files. + List> compilerClasses = new ArrayList>(2); + compilerClasses.add(compiler.getClass()); + compilerClasses.add(Compiler.class); + + CompilerSyntax syntax; + syntax = new CompilerSyntax(id); + + syntax.loadXMLData(compilerClasses); + + compilerDefinition.setSyntax(syntax); + + compiler.setDefinition(compilerDefinition); + + compiler = compilerMap.put(id, compiler); + if (compiler != null) { + throw new RuntimeException( + "Compiler id '" + id + "' is already registered to class '" + compiler.getClass().getName() + "'."); + } - /** - * Adds a new compiler. - * - * @param configurationElement - * The configuration element used as class instance factory, not - * null. - * - * @param compilerDefinition - * The compiler definition, not null. - */ - private void addCompiler(IConfigurationElement configurationElement, CompilerDefinition compilerDefinition) { - if (configurationElement == null) { - throw new IllegalArgumentException("Parameter 'configurationElement' must not be null."); - } - if (compilerDefinition == null) { - throw new IllegalArgumentException("Parameter 'compilerDefinition' must not be null."); } - String id = compilerDefinition.getId(); - Compiler compiler; - try { - // The class loading must be delegated to the framework. - compiler = (Compiler) configurationElement.createExecutableExtension("class"); - } catch (CoreException ex) { - throw new RuntimeException("Cannot create compiler instance for id '" + id + "'.", ex); + /** + * Gets the unmodifiable list of compiler definitions, sorted by their id. + * + * + * @return The unmodifiable list of compiler definitions, sorted by their id, + * may be empty, not null + * + * @since 1.6.1 + */ + public List getCompilerDefinitions() { + return compilerDefinitionList; } - // Build the list of common and specific syntax definition files. - List> compilerClasses = new ArrayList>(2); - compilerClasses.add(compiler.getClass()); - compilerClasses.add(Compiler.class); + /** + * Gets the compiler for a given id. Instances of compiler are stateless + * singletons within the plugin. + * + * @param compilerId The compiler id, not null. + * + * @return The compiler, not null. + */ + public Compiler getCompiler(String compilerId) { + if (compilerId == null) { + throw new IllegalArgumentException("Parameter 'compilerId' must not be null."); + } + Compiler result; + synchronized (compilerMap) { - CompilerSyntax syntax; - syntax = new CompilerSyntax(id); + result = compilerMap.get(compilerId); + } + if (result == null) { - syntax.loadXMLData(compilerClasses); + throw new IllegalArgumentException("Unknown compiler id '" + compilerId + "'."); + } - compilerDefinition.setSyntax(syntax); - - compiler.setDefinition(compilerDefinition); - - compiler = compilerMap.put(id, compiler); - if (compiler != null) { - throw new RuntimeException("Compiler id '" + id + "' is already registered to class '" - + compiler.getClass().getName() + "'."); + return result; } - } - - /** - * Gets the unmodifiable list of compiler definitions, sorted by their id. - * - * - * @return The unmodifiable list of compiler definitions, sorted by their - * id, may be empty, not null - * - * @since 1.6.1 - */ - public List getCompilerDefinitions() { - return compilerDefinitionList; - } - - /** - * Gets the compiler for a given id. Instances of compiler are stateless - * singletons within the plugin. - * - * @param compilerId - * The compiler id, not null. - * - * @return The compiler, not null. - */ - public Compiler getCompiler(String compilerId) { - if (compilerId == null) { - throw new IllegalArgumentException("Parameter 'compilerId' must not be null."); - } - Compiler result; - synchronized (compilerMap) { - - result = compilerMap.get(compilerId); - } - if (result == null) { - - throw new IllegalArgumentException("Unknown compiler id '" + compilerId + "'."); - } - - return result; - } - } diff --git a/com.wudsn.ide.asm/src/com/wudsn/ide/asm/compiler/syntax/CompilerSyntaxUtility.java b/com.wudsn.ide.asm/src/com/wudsn/ide/asm/compiler/syntax/CompilerSyntaxUtility.java index f86b86a1..7f208a74 100644 --- a/com.wudsn.ide.asm/src/com/wudsn/ide/asm/compiler/syntax/CompilerSyntaxUtility.java +++ b/com.wudsn.ide.asm/src/com/wudsn/ide/asm/compiler/syntax/CompilerSyntaxUtility.java @@ -29,79 +29,77 @@ import com.wudsn.ide.asm.Texts; */ public final class CompilerSyntaxUtility { - /** - * Creation private. - */ - private CompilerSyntaxUtility() { - - } - - /** - * Gets the image path for an instruction type image. - * - * @param instruction - * The instruction, not null. - * @return The image path for the instruction type image, not empty and not - * null. - */ - public static String getTypeImagePath(Instruction instruction) { - if (instruction == null) { - throw new IllegalArgumentException("Parameter 'instruction' must not be null."); - } - String path; - - if (instruction instanceof Directive) { - path = "instruction-type-directive-16x16.gif"; - } else { - Opcode opcode = (Opcode) instruction; - switch (opcode.getType()) { - case InstructionType.LEGAL_OPCODE: - path = "instruction-type-legal-opcode-16x16.gif"; - break; - case InstructionType.ILLEGAL_OPCODE: - path = "instruction-type-illegal-opcode-16x16.gif"; - break; - case InstructionType.PSEUDO_OPCODE: - path = "instruction-type-pseudo-opcode-16x16.gif"; - break; - default: - throw new IllegalStateException("Unknown opcode type " + opcode.getType() + "."); - } + /** + * Creation private. + */ + private CompilerSyntaxUtility() { } - return path; - } - /** - * Gets the text for an instruction type. - * - * @param instruction - * The instruction, not null. - * @return The text for the instruction type image, may be empty, not - * null. - */ - public static String getTypeText(Instruction instruction) { - String text; + /** + * Gets the image path for an instruction type image. + * + * @param instruction The instruction, not null. + * @return The image path for the instruction type image, not empty and not + * null. + */ + public static String getTypeImagePath(Instruction instruction) { + if (instruction == null) { + throw new IllegalArgumentException("Parameter 'instruction' must not be null."); + } + String path; - if (instruction instanceof Directive) { - text = Texts.COMPILER_SYNTAX_INSTRUCTION_DIRECTIVE; - } else { - Opcode opcode = (Opcode) instruction; - switch (opcode.getType()) { - case InstructionType.LEGAL_OPCODE: - text = Texts.COMPILER_SYNTAX_LEGAL_OPCODE; - break; - case InstructionType.ILLEGAL_OPCODE: - text = Texts.COMPILER_SYNTAX_ILLEGAL_OPCODE; - break; - case InstructionType.PSEUDO_OPCODE: - text = Texts.COMPILER_SYNTAX_PSEUDO_OPCODE; - break; - default: - throw new IllegalStateException("Unknown opcode type " + opcode.getType() + "."); - } + if (instruction instanceof Directive) { + path = "instruction-type-directive-16x16.gif"; + } else { + Opcode opcode = (Opcode) instruction; + switch (opcode.getType()) { + case InstructionType.LEGAL_OPCODE: + path = "instruction-type-legal-opcode-16x16.gif"; + break; + case InstructionType.ILLEGAL_OPCODE: + path = "instruction-type-illegal-opcode-16x16.gif"; + break; + case InstructionType.PSEUDO_OPCODE: + path = "instruction-type-pseudo-opcode-16x16.gif"; + break; + default: + throw new IllegalStateException("Unknown opcode type " + opcode.getType() + "."); + } + } + return path; + } + + /** + * Gets the text for an instruction type. + * + * @param instruction The instruction, not null. + * @return The text for the instruction type image, may be empty, not + * null. + */ + public static String getTypeText(Instruction instruction) { + String text; + + if (instruction instanceof Directive) { + text = Texts.COMPILER_SYNTAX_INSTRUCTION_DIRECTIVE; + } else { + Opcode opcode = (Opcode) instruction; + switch (opcode.getType()) { + case InstructionType.LEGAL_OPCODE: + text = Texts.COMPILER_SYNTAX_LEGAL_OPCODE; + break; + case InstructionType.ILLEGAL_OPCODE: + text = Texts.COMPILER_SYNTAX_ILLEGAL_OPCODE; + break; + case InstructionType.PSEUDO_OPCODE: + text = Texts.COMPILER_SYNTAX_PSEUDO_OPCODE; + break; + default: + throw new IllegalStateException("Unknown opcode type " + opcode.getType() + "."); + } + + } + return text; } - return text; - } } diff --git a/com.wudsn.ide.asm/src/com/wudsn/ide/asm/compiler/writer/AppleFileWriter.java b/com.wudsn.ide.asm/src/com/wudsn/ide/asm/compiler/writer/AppleFileWriter.java index 7f28c993..b0007842 100644 --- a/com.wudsn.ide.asm/src/com/wudsn/ide/asm/compiler/writer/AppleFileWriter.java +++ b/com.wudsn.ide.asm/src/com/wudsn/ide/asm/compiler/writer/AppleFileWriter.java @@ -47,297 +47,297 @@ import com.wudsn.ide.base.common.StringUtility; */ public final class AppleFileWriter extends CompilerFileWriter { - private final static String HELLO_ENTRY_NAME = "HELLO"; - private final static String OUTPUT_IMAGE_ENTRY_NAME = "WORLD"; + private final static String HELLO_ENTRY_NAME = "HELLO"; + private final static String OUTPUT_IMAGE_ENTRY_NAME = "WORLD"; - private final class AppleSoftTokens { - public final static byte PRINT = (byte) 0xba; - public final static byte CHRS = (byte) 0xe7; - public final static byte CALL = (byte) 0x8c; + private final class AppleSoftTokens { + public final static byte PRINT = (byte) 0xba; + public final static byte CHRS = (byte) 0xe7; + public final static byte CALL = (byte) 0x8c; - // public String[] tokenNames = { "END", "FOR ", "NEXT ", "DATA ", - // "INPUT ", "DEL", "DIM ", "READ ", "GR", "TEXT", "PR#", "IN#", - // "CALL ", "PLOT", "HLIN ", "VLIN ", "HGR2", "HGR", "HCOLOR=", - // "HPLOT ", "DRAW ", "XDRAW ", "HTAB ", "HOME", "ROT=", "SCALE=", - // "SHLOAD", "TRACE", "NOTRACE", "NORMAL", "INVERSE", "FLASH", - // "COLOR=", "POP", "VTAB ", "HIMEM:", "LOMEM:", "ONERR ", - // "RESUME", "RECALL", "STORE", "SPEED=", "LET ", "GOTO ", "RUN", - // "IF ", "RESTORE", "& ", "GOSUB ", "RETURN", "REM ", "STOP", - // "ON ", "WAIT", "LOAD", "SAVE", "DEF", "POKE ", "PRINT ", - // "CONT", "LIST", "CLEAR", "GET ", "NEW", "TAB(", "TO ", "FN", - // "SPC(", "THEN ", "AT ", "NOT ", "STEP ", "+ ", "- ", "* ", - // "/ ", "^ ", "AND ", "OR ", "> ", "= ", "< ", "SGN", "INT", - // "ABS", "USR", "FRE", "SCRN(", "PDL", "POS ", "SQR", "RND", - // "LOG", "EXP", "COS", "SIN", "TAN", "ATN", "PEEK", "LEN", - // "STR$", "VAL", "ASC", "CHR$", "LEFT$", "RIGHT$", "MID$" }; + // public String[] tokenNames = { "END", "FOR ", "NEXT ", "DATA ", + // "INPUT ", "DEL", "DIM ", "READ ", "GR", "TEXT", "PR#", "IN#", + // "CALL ", "PLOT", "HLIN ", "VLIN ", "HGR2", "HGR", "HCOLOR=", + // "HPLOT ", "DRAW ", "XDRAW ", "HTAB ", "HOME", "ROT=", "SCALE=", + // "SHLOAD", "TRACE", "NOTRACE", "NORMAL", "INVERSE", "FLASH", + // "COLOR=", "POP", "VTAB ", "HIMEM:", "LOMEM:", "ONERR ", + // "RESUME", "RECALL", "STORE", "SPEED=", "LET ", "GOTO ", "RUN", + // "IF ", "RESTORE", "& ", "GOSUB ", "RETURN", "REM ", "STOP", + // "ON ", "WAIT", "LOAD", "SAVE", "DEF", "POKE ", "PRINT ", + // "CONT", "LIST", "CLEAR", "GET ", "NEW", "TAB(", "TO ", "FN", + // "SPC(", "THEN ", "AT ", "NOT ", "STEP ", "+ ", "- ", "* ", + // "/ ", "^ ", "AND ", "OR ", "> ", "= ", "< ", "SGN", "INT", + // "ABS", "USR", "FRE", "SCRN(", "PDL", "POS ", "SQR", "RND", + // "LOG", "EXP", "COS", "SIN", "TAN", "ATN", "PEEK", "LEN", + // "STR$", "VAL", "ASC", "CHR$", "LEFT$", "RIGHT$", "MID$" }; - // public int[] tokenAddresses = { 0xD870, 0xD766, 0xDCF9, 0xD995, - // 0xDBB2, - // 0xF331, 0xDFD9, 0xDBE2, 0xF390, 0xF399, 0xF1E5, 0xF1DE, 0xF1D5, - // 0xF225, 0xF232, 0xF241, 0xF3D8, 0xF3E2, 0xF6E9, 0xF6FE, 0xF769, - // 0xF76F, 0xF7E7, 0xFC58, 0xF721, 0xF727, 0xF775, 0xF26D, 0xF26F, - // 0xF273, 0xF277, 0xF280, 0xF24F, 0xD96B, 0xF256, 0xF286, 0xF2A6, - // 0xF2CB, 0xF318, 0xF3BC, 0xF39F, 0xF262, 0xDA46, 0xD93E, 0xD912, - // 0xD9C9, 0xD849, 0x03F5, 0xD921, 0xD96B, 0xD9DC, 0xD86E, 0xD9EC, - // 0xE784, 0xD8C9, 0xD8B0, 0xE313, 0xE77B, 0xFDAD5, 0xD896, - // 0xD6A5, 0xD66A, 0xDBA0, 0xD649, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - // 0, 0, 0, 0, 0, 0, 0, 0, 0xEB90, 0xEC23, 0xEBAF, 0x000A, 0xE2DE, - // 0xD412, 0xDFCD, 0xE2FF, 0xEE8D, 0xEFAE, 0xE941, 0xEF09, 0xEFEA, - // 0xEFF1, 0xF03A, 0xF09E, 0xE764, 0xE6D6, 0xE3C5, 0xE707, 0xE6E5, - // 0xE646, 0xE65A, 0xE686, 0xE691 }; - } + // public int[] tokenAddresses = { 0xD870, 0xD766, 0xDCF9, 0xD995, + // 0xDBB2, + // 0xF331, 0xDFD9, 0xDBE2, 0xF390, 0xF399, 0xF1E5, 0xF1DE, 0xF1D5, + // 0xF225, 0xF232, 0xF241, 0xF3D8, 0xF3E2, 0xF6E9, 0xF6FE, 0xF769, + // 0xF76F, 0xF7E7, 0xFC58, 0xF721, 0xF727, 0xF775, 0xF26D, 0xF26F, + // 0xF273, 0xF277, 0xF280, 0xF24F, 0xD96B, 0xF256, 0xF286, 0xF2A6, + // 0xF2CB, 0xF318, 0xF3BC, 0xF39F, 0xF262, 0xDA46, 0xD93E, 0xD912, + // 0xD9C9, 0xD849, 0x03F5, 0xD921, 0xD96B, 0xD9DC, 0xD86E, 0xD9EC, + // 0xE784, 0xD8C9, 0xD8B0, 0xE313, 0xE77B, 0xFDAD5, 0xD896, + // 0xD6A5, 0xD66A, 0xDBA0, 0xD649, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + // 0, 0, 0, 0, 0, 0, 0, 0, 0xEB90, 0xEC23, 0xEBAF, 0x000A, 0xE2DE, + // 0xD412, 0xDFCD, 0xE2FF, 0xEE8D, 0xEFAE, 0xE941, 0xEF09, 0xEFEA, + // 0xEFF1, 0xF03A, 0xF09E, 0xE764, 0xE6D6, 0xE3C5, 0xE707, 0xE6E5, + // 0xE646, 0xE65A, 0xE686, 0xE691 }; + } - @Override - public boolean createOrUpdateDiskImage(CompilerFiles files) { - String imageFilePath = files.outputFilePathWithoutExtension + ".dsk"; - String outputImageEntryName = OUTPUT_IMAGE_ENTRY_NAME; - String outputImageEntryTitle = "Loading " + files.outputFileNameWithoutExtension; - boolean autoCreate = true; + @Override + public boolean createOrUpdateDiskImage(CompilerFiles files) { + String imageFilePath = files.outputFilePathWithoutExtension + ".dsk"; + String outputImageEntryName = OUTPUT_IMAGE_ENTRY_NAME; + String outputImageEntryTitle = "Loading " + files.outputFileNameWithoutExtension; + boolean autoCreate = true; - if (StringUtility.isSpecified(imageFilePath)) { - File imageFile = new File(imageFilePath); - if (!imageFile.exists()) { + if (StringUtility.isSpecified(imageFilePath)) { + File imageFile = new File(imageFilePath); + if (!imageFile.exists()) { - // When auto creation is active, we copy a template file. - // This is the only way to get a disk image which is not only - // formatted but also has a boot loader which runs "HELLO". - if (autoCreate) { - String resource = "/lib/AppleDos.dsk"; - InputStream inputStream = Disk.class.getClassLoader().getResourceAsStream(resource); - if (inputStream == null) { - throw new RuntimeException("Cannot get input stream for '" + resource + "'"); - } - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - byte[] buffer = new byte[8192]; - int count; - do { - try { - count = inputStream.read(buffer); - } catch (IOException ex) { - throw new RuntimeException("Cannot read input stream for '" + resource + "'", ex); + // When auto creation is active, we copy a template file. + // This is the only way to get a disk image which is not only + // formatted but also has a boot loader which runs "HELLO". + if (autoCreate) { + String resource = "/lib/AppleDos.dsk"; + InputStream inputStream = Disk.class.getClassLoader().getResourceAsStream(resource); + if (inputStream == null) { + throw new RuntimeException("Cannot get input stream for '" + resource + "'"); + } + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + byte[] buffer = new byte[8192]; + int count; + do { + try { + count = inputStream.read(buffer); + } catch (IOException ex) { + throw new RuntimeException("Cannot read input stream for '" + resource + "'", ex); + } + + if (count > 0) { + bos.write(buffer, 0, count); + + } + } while (count > -1); + + try { + bos.close(); + } catch (IOException ex) { + throw new RuntimeException(ex); + } + + try { + FileUtility.writeBytes(imageFile, bos.toByteArray()); + } catch (CoreException ex) { + MarkerUtility.createMarker(files.mainSourceFile.iFile, 0, ex.getStatus().getSeverity(), "{0}", + ex.getStatus().getMessage()); + return false; + } + + } else { // no auto creation + + // ERROR: Disk image file '{0}' does not exist. Create a + // bootable disk image where the output file '{1}' can be + // stored. + MarkerUtility.createMarker(files.mainSourceFile.iFile, 0, IMarker.SEVERITY_ERROR, + Texts.MESSAGE_E132, imageFilePath, outputImageEntryName); + return false; + } } - - if (count > 0) { - bos.write(buffer, 0, count); - + if (!imageFile.canWrite()) { + // ERROR: Disk image file '{0}' is not writeable. Make the disk + // image file writeable, so the output file '{1}' can be stored. + MarkerUtility.createMarker(files.mainSourceFile.iFile, 0, IMarker.SEVERITY_ERROR, Texts.MESSAGE_E133, + imageFilePath, outputImageEntryName); + return false; } - } while (count > -1); - - try { - bos.close(); - } catch (IOException ex) { - throw new RuntimeException(ex); - } - - try { - FileUtility.writeBytes(imageFile, bos.toByteArray()); - } catch (CoreException ex) { - MarkerUtility.createMarker(files.mainSourceFile.iFile, 0, ex.getStatus().getSeverity(), "{0}", - ex.getStatus().getMessage()); + } + Disk disk; + try { + disk = new Disk(imageFilePath); + } catch (IOException ex) { + // ERROR: Disk image file '{0}' cannot be opened for reading. System + // error: {1} + MarkerUtility.createMarker(files.mainSourceFile.iFile, 0, IMarker.SEVERITY_ERROR, Texts.MESSAGE_E134, + imageFilePath, ex.getMessage()); return false; - } - - } else { // no auto creation - - // ERROR: Disk image file '{0}' does not exist. Create a - // bootable disk image where the output file '{1}' can be - // stored. - MarkerUtility.createMarker(files.mainSourceFile.iFile, 0, IMarker.SEVERITY_ERROR, - Texts.MESSAGE_E132, imageFilePath, outputImageEntryName); - return false; } - } - if (!imageFile.canWrite()) { - // ERROR: Disk image file '{0}' is not writeable. Make the disk - // image file writeable, so the output file '{1}' can be stored. - MarkerUtility.createMarker(files.mainSourceFile.iFile, 0, IMarker.SEVERITY_ERROR, Texts.MESSAGE_E133, - imageFilePath, outputImageEntryName); - return false; - } - } - Disk disk; - try { - disk = new Disk(imageFilePath); - } catch (IOException ex) { - // ERROR: Disk image file '{0}' cannot be opened for reading. System - // error: {1} - MarkerUtility.createMarker(files.mainSourceFile.iFile, 0, IMarker.SEVERITY_ERROR, Texts.MESSAGE_E134, - imageFilePath, ex.getMessage()); - return false; - } - FormattedDisk[] formattedDisks = disk.getFormattedDisks(); - if (formattedDisks == null || formattedDisks.length == 0) { - // ERROR: Disk image file '{0}' does not contain a valid file - // system. Make sure the disk image is properly formatted, so - // the output file '{1}' can be stored. - MarkerUtility.createMarker(files.mainSourceFile.iFile, 0, IMarker.SEVERITY_ERROR, Texts.MESSAGE_E135, - imageFilePath, outputImageEntryName); - return false; - } - - byte[] outputFileContent; - try { - outputFileContent = FileUtility.readBytes(files.outputFile, 65536, true); - } catch (CoreException ex) { - // ERROR: Cannot read output file. - MarkerUtility.createMarker(files.mainSourceFile.iFile, 0, ex.getStatus().getSeverity(), "{0}", ex - .getStatus().getMessage()); - return false; - } - - FormattedDisk formattedDisk; - try { - formattedDisk = formattedDisks[0]; - // Create HELLO with dummy address. - createHello(formattedDisk, outputImageEntryName, outputImageEntryTitle, 1234); - - FileEntry entry = formattedDisk.getFile(outputImageEntryName); - if (entry == null) { - entry = formattedDisk.createFile(); - // TODO This is required due to a BUG in AppleCommander - entry.setFilename(outputImageEntryName); - } - entry.setFiletype("B"); - - String fileName = files.outputFileName.toLowerCase(); - int length = outputFileContent.length; - byte[] content = outputFileContent; - if (entry.needsAddress()) { - int address; - if (fileName.endsWith(".b") && length > 4) { - // // AppleDos 3.3 binary file: - // start-lo,start-hi,length-lo,length-hi,data - address = getWord(outputFileContent, 0); - length = length - 4; - content = getData(outputFileContent, 4); - } else if (fileName.endsWith(".prg") && length > 2) { - // C64 program file - // start-lo,start-hi,data - address = getWord(outputFileContent, 0); - length = length - 2; - content = getData(outputFileContent, 2); - } else if (fileName.endsWith(".xex") && length > 6 - && ((getWord(outputFileContent, 0) & 0xffff) == 0xffff)) { - // AtariDOS 2.5 binary file: - // $ff,$ff,start-lo,start-hi,end-lo,end-hi,data - address = getWord(outputFileContent, 2); - length = length - 6; - content = getData(outputFileContent, 6); - } else { - // ERROR: Output file {0} has unknown executable file - // extension or content. File extensions ".b", ".prg" and - // ".xex" are allowed. - MarkerUtility.createMarker(files.mainSourceFile.iFile, 0, IMarker.SEVERITY_ERROR, - Texts.MESSAGE_E138, files.outputFilePath); - return false; + FormattedDisk[] formattedDisks = disk.getFormattedDisks(); + if (formattedDisks == null || formattedDisks.length == 0) { + // ERROR: Disk image file '{0}' does not contain a valid file + // system. Make sure the disk image is properly formatted, so + // the output file '{1}' can be stored. + MarkerUtility.createMarker(files.mainSourceFile.iFile, 0, IMarker.SEVERITY_ERROR, Texts.MESSAGE_E135, + imageFilePath, outputImageEntryName); + return false; } - // Method setAddress must be called after method setFileData! - entry.setFileData(content); - entry.setAddress(address); - // Update HELLO with acual start address. - createHello(formattedDisk, outputImageEntryName, outputImageEntryTitle, address); - } else { - entry.setFileData(outputFileContent); - } + byte[] outputFileContent; + try { + outputFileContent = FileUtility.readBytes(files.outputFile, 65536, true); + } catch (CoreException ex) { + // ERROR: Cannot read output file. + MarkerUtility.createMarker(files.mainSourceFile.iFile, 0, ex.getStatus().getSeverity(), "{0}", + ex.getStatus().getMessage()); + return false; + } - } catch (DiskFullException ex) { - // ERROR: Disk image file '{0}' is full. System - // error: {1} - MarkerUtility.createMarker(files.mainSourceFile.iFile, 0, IMarker.SEVERITY_ERROR, Texts.MESSAGE_E136, - imageFilePath, ex.getMessage()); - return false; + FormattedDisk formattedDisk; + try { + formattedDisk = formattedDisks[0]; + // Create HELLO with dummy address. + createHello(formattedDisk, outputImageEntryName, outputImageEntryTitle, 1234); + + FileEntry entry = formattedDisk.getFile(outputImageEntryName); + if (entry == null) { + entry = formattedDisk.createFile(); + // TODO This is required due to a BUG in AppleCommander + entry.setFilename(outputImageEntryName); + } + entry.setFiletype("B"); + + String fileName = files.outputFileName.toLowerCase(); + int length = outputFileContent.length; + byte[] content = outputFileContent; + if (entry.needsAddress()) { + int address; + if (fileName.endsWith(".b") && length > 4) { + // // AppleDos 3.3 binary file: + // start-lo,start-hi,length-lo,length-hi,data + address = getWord(outputFileContent, 0); + length = length - 4; + content = getData(outputFileContent, 4); + } else if (fileName.endsWith(".prg") && length > 2) { + // C64 program file + // start-lo,start-hi,data + address = getWord(outputFileContent, 0); + length = length - 2; + content = getData(outputFileContent, 2); + } else if (fileName.endsWith(".xex") && length > 6 + && ((getWord(outputFileContent, 0) & 0xffff) == 0xffff)) { + // AtariDOS 2.5 binary file: + // $ff,$ff,start-lo,start-hi,end-lo,end-hi,data + address = getWord(outputFileContent, 2); + length = length - 6; + content = getData(outputFileContent, 6); + } else { + // ERROR: Output file {0} has unknown executable file + // extension or content. File extensions ".b", ".prg" and + // ".xex" are allowed. + MarkerUtility.createMarker(files.mainSourceFile.iFile, 0, IMarker.SEVERITY_ERROR, + Texts.MESSAGE_E138, files.outputFilePath); + return false; + } + // Method setAddress must be called after method setFileData! + entry.setFileData(content); + entry.setAddress(address); + // Update HELLO with actual start address. + createHello(formattedDisk, outputImageEntryName, outputImageEntryTitle, address); + } else { + entry.setFileData(outputFileContent); + + } + + } catch (DiskFullException ex) { + // ERROR: Disk image file '{0}' is full. System + // error: {1} + MarkerUtility.createMarker(files.mainSourceFile.iFile, 0, IMarker.SEVERITY_ERROR, Texts.MESSAGE_E136, + imageFilePath, ex.getMessage()); + return false; + + } + + try { + formattedDisk.save(); + + } catch (IOException ex) { + + // ERROR: Disk image file '{0}' cannot be opened for writing. System + // error: {1} + MarkerUtility.createMarker(files.mainSourceFile.iFile, 0, IMarker.SEVERITY_ERROR, Texts.MESSAGE_E137, + imageFilePath, ex.getMessage()); + return false; + } + + return true; } - try { - formattedDisk.save(); + private static FileEntry createHello(FormattedDisk formattedDisk, String outputImageEntryName, + String outputImageEntryTitle, int runAddress) throws DiskFullException { + if (formattedDisk == null) { + throw new IllegalArgumentException("Parameter 'formattedDisk' must not be null."); + } + if (outputImageEntryName == null) { + throw new IllegalArgumentException("Parameter 'OUTPUT_IMAGE_ENTRY_NAME' must not be null."); + } + if (StringUtility.isEmpty(outputImageEntryName)) { + throw new IllegalArgumentException("Parameter 'OUTPUT_IMAGE_ENTRY_NAME' must not be empty."); + } + if (outputImageEntryTitle == null) { + throw new IllegalArgumentException("Parameter 'outputImageEntryTitle' must not be null."); + } + FileEntry entry; - } catch (IOException ex) { + entry = formattedDisk.getFile(HELLO_ENTRY_NAME); + if (entry == null) { + entry = formattedDisk.createFile(); + entry.setFilename(HELLO_ENTRY_NAME); + } + entry.setFiletype("A"); + byte[] program; + try { + // See "Beneath Apple DOS.pdf", 4-11/12 for the binary and AppleSoft + // file format. + // See http://www.textfiles.com/apple/ANATOMY/cmd.brun.bload.txt for + // the bug in the BRUN routine. Instead of BRUN now BLOAD is sent to + // DOS via PRINT CHR$(4) and the program is started via CALL. + // 10 PRINT "LOADING " : PRINT CHR$(4);"BRUN WORLD" : CALL + // <address> - // ERROR: Disk image file '{0}' cannot be opened for writing. System - // error: {1} - MarkerUtility.createMarker(files.mainSourceFile.iFile, 0, IMarker.SEVERITY_ERROR, Texts.MESSAGE_E137, - imageFilePath, ex.getMessage()); - return false; + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + bos.write(new byte[] { 0x00, 0x08, 0x0A, 0x00 }); + bos.write(new byte[] { AppleSoftTokens.PRINT, '"' }); + bos.write(outputImageEntryTitle.getBytes("US-ASCII")); + bos.write(new byte[] { '"', ':' }); + bos.write(new byte[] { AppleSoftTokens.PRINT, AppleSoftTokens.CHRS, '(', '4', ')', ';', '"', 'B', 'L', 'O', + 'A', 'D', ' ' }); + bos.write(outputImageEntryName.getBytes("US-ASCII")); + bos.write(new byte[] { '"', ':', AppleSoftTokens.CALL }); + bos.write(Integer.toString(runAddress).getBytes("US-ASCII")); + bos.write(new byte[] { 0, 0, 0 }); + program = bos.toByteArray(); + program[0] = (byte) (program.length); + } catch (UnsupportedEncodingException ex) { + throw new RuntimeException(ex); + } catch (IOException ex) { + throw new RuntimeException(ex); + } + + // Byte is the line length in bytes + entry.setFileData(program); + return entry; } - return true; + private static int getWord(byte[] bytes, int index) { + if (bytes == null) { + throw new IllegalArgumentException("Parameter 'bytes' must not be null."); + } - } - - private static FileEntry createHello(FormattedDisk formattedDisk, String outputImageEntryName, - String outputImageEntryTitle, int runAddress) throws DiskFullException { - if (formattedDisk == null) { - throw new IllegalArgumentException("Parameter 'formattedDisk' must not be null."); - } - if (outputImageEntryName == null) { - throw new IllegalArgumentException("Parameter 'OUTPUT_IMAGE_ENTRY_NAME' must not be null."); - } - if (StringUtility.isEmpty(outputImageEntryName)) { - throw new IllegalArgumentException("Parameter 'OUTPUT_IMAGE_ENTRY_NAME' must not be empty."); - } - if (outputImageEntryTitle == null) { - throw new IllegalArgumentException("Parameter 'outputImageEntryTitle' must not be null."); - } - FileEntry entry; - - entry = formattedDisk.getFile(HELLO_ENTRY_NAME); - if (entry == null) { - entry = formattedDisk.createFile(); - entry.setFilename(HELLO_ENTRY_NAME); - } - entry.setFiletype("A"); - byte[] program; - try { - // See "Beneath Apple DOS.pdf", 4-11/12 for the binary and AppleSoft - // file format. - // See http://www.textfiles.com/apple/ANATOMY/cmd.brun.bload.txt for - // the bug in the BRUN routine. Instead of BRUN now BLOAD is sent to - // DOS via PRINT CHR$(4) and the program is started via CALL. - // 10 PRINT "LOADING <title>" : PRINT CHR$(4);"BRUN WORLD" : CALL - // <address> - - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - bos.write(new byte[] { 0x00, 0x08, 0x0A, 0x00 }); - bos.write(new byte[] { AppleSoftTokens.PRINT, '"' }); - bos.write(outputImageEntryTitle.getBytes("US-ASCII")); - bos.write(new byte[] { '"', ':' }); - bos.write(new byte[] { AppleSoftTokens.PRINT, AppleSoftTokens.CHRS, '(', '4', ')', ';', '"', 'B', 'L', 'O', - 'A', 'D', ' ' }); - bos.write(outputImageEntryName.getBytes("US-ASCII")); - bos.write(new byte[] { '"', ':', AppleSoftTokens.CALL }); - bos.write(Integer.toString(runAddress).getBytes("US-ASCII")); - bos.write(new byte[] { 0, 0, 0 }); - program = bos.toByteArray(); - program[0] = (byte) (program.length); - } catch (UnsupportedEncodingException ex) { - throw new RuntimeException(ex); - } catch (IOException ex) { - throw new RuntimeException(ex); + return (0xff & bytes[index]) + 256 * (0xff & bytes[index + 1]); } - // Byte is the line length in bytes - entry.setFileData(program); - return entry; - } - - private static int getWord(byte[] bytes, int index) { - if (bytes == null) { - throw new IllegalArgumentException("Parameter 'bytes' must not be null."); + private static byte[] getData(byte[] bytes, int index) { + if (bytes == null) { + throw new IllegalArgumentException("Parameter 'bytes' must not be null."); + } + int length = bytes.length - index; + byte[] result = new byte[length]; + System.arraycopy(bytes, index, result, 0, length); + return result; } - - return (0xff & bytes[index]) + 256 * (0xff & bytes[index + 1]); - } - - private static byte[] getData(byte[] bytes, int index) { - if (bytes == null) { - throw new IllegalArgumentException("Parameter 'bytes' must not be null."); - } - int length = bytes.length - index; - byte[] result = new byte[length]; - System.arraycopy(bytes, index, result, 0, length); - return result; - } } diff --git a/com.wudsn.ide.asm/src/com/wudsn/ide/asm/editor/AssemblerEditor.java b/com.wudsn.ide.asm/src/com/wudsn/ide/asm/editor/AssemblerEditor.java index 04f9ad2c..dde24766 100644 --- a/com.wudsn.ide.asm/src/com/wudsn/ide/asm/editor/AssemblerEditor.java +++ b/com.wudsn.ide.asm/src/com/wudsn/ide/asm/editor/AssemblerEditor.java @@ -75,485 +75,478 @@ import com.wudsn.ide.base.common.Profiler; */ public abstract class AssemblerEditor extends TextEditor { - private AssemblerPlugin plugin; - private AssemblerEditorFilesLogic filesLogic; + private AssemblerPlugin plugin; + private AssemblerEditorFilesLogic filesLogic; - private Compiler compiler; + private Compiler compiler; - private AssemblerContentOutlinePage contentOutlinePage; - private ProjectionAnnotationModel annotationModel; + private AssemblerContentOutlinePage contentOutlinePage; + private ProjectionAnnotationModel annotationModel; - private Hardware hardware; + private Hardware hardware; - /** - * Creates a new instance. Constructor parameters are not useful, because - * the super constructor inverts the flow of control, so - * {@link #initializeEditor} is called before the code in this constructor - * is executed. - */ - protected AssemblerEditor() { - filesLogic = AssemblerEditorFilesLogic.createInstance(this); - } - - /** - * Gets the files logic associated with this editor. - * - * @return The files logic, not <code>null</code>. - */ - public AssemblerEditorFilesLogic getFilesLogic() { - return filesLogic; - } - - /** - * Gets the hardware for this editor. - * - * @return The hardware for this editor, not <code>null</code>. - * - * @since 1.6.1 - */ - protected final Hardware getHardware() { - if (hardware != null) { - return hardware; + /** + * Creates a new instance. Constructor parameters are not useful, because the + * super constructor inverts the flow of control, so {@link #initializeEditor} + * is called before the code in this constructor is executed. + */ + protected AssemblerEditor() { + filesLogic = AssemblerEditorFilesLogic.createInstance(this); } - return compiler.getDefinition().getDefaultHardware(); - } - /** - * Gets the compiler id for this editor. - * - * @return The compiler id for this editor, not empty and not - * <code>null</code>. - */ - protected abstract String getCompilerId(); - - @Override - protected final void initializeEditor() { - super.initializeEditor(); - - plugin = AssemblerPlugin.getInstance(); - compiler = plugin.getCompilerRegistry().getCompiler(getCompilerId()); - - setSourceViewerConfiguration(new AssemblerSourceViewerConfiguration(this, getPreferenceStore())); - - } - - /** - * Gets the plugin this compiler instance belongs to. - * - * @return The plugin this compiler instance belongs to, not - * <code>null</code>. - */ - public final AssemblerPlugin getPlugin() { - if (plugin == null) { - throw new IllegalStateException("Field 'plugin' must not be null."); + /** + * Gets the files logic associated with this editor. + * + * @return The files logic, not <code>null</code>. + */ + public AssemblerEditorFilesLogic getFilesLogic() { + return filesLogic; } - return plugin; - } - /** - * Gets the compiler preferences. - * - * @return The compiler preferences, not <code>null</code>. - */ - public final CompilerPreferences getCompilerPreferences() { - return plugin.getPreferences().getCompilerPreferences(getCompilerId(), getHardware()); - } - - /** - * Gets the compiler for this editor. - * - * @return The compiler for this editor, not <code>null</code>. - */ - public final Compiler getCompiler() { - if (compiler == null) { - throw new IllegalStateException("Field 'compiler' must not be null."); - } - return compiler; - } - - /** - * Gets the compiler definition for this editor. - * - * @return The compiler definition for this editor, not <code>null</code>. - * - * @sine 1.6.1 - */ - public final CompilerDefinition getCompilerDefinition() { - if (compiler == null) { - throw new IllegalStateException("Field 'compiler' must not be null."); - } - return compiler.getDefinition(); - } - - /** - * Gets the compiler source parser for this editor and the currently - * selected instruction set. - * - * @return The compiler source parser for this editor, not <code>null</code> - * . - */ - public final CompilerSourceParser createCompilerSourceParser() { - CPU cpu; - CompilerSourceParser result; - if (compiler == null) { - throw new IllegalStateException("Field 'compiler' must not be null."); - } - cpu = getCompilerPreferences().getCPU(); - result = compiler.createSourceParser(); - result.init(compiler.getDefinition().getSyntax().getInstructionSet(cpu)); - return result; - } - - /** - * This method is called whenever the input changes, i.e. after loading and - * after saving as new file. - * - * @param input - * The new input, may be <code>null</code> - */ - @Override - protected final void doSetInput(IEditorInput input) throws CoreException { - super.doSetInput(input); - - hardware = null; - if (input != null) { - IDocument document = getDocumentProvider().getDocument(getEditorInput()); - - CompilerSourcePartitionScanner partitionScanner = new CompilerSourcePartitionScanner(compiler - .getDefinition().getSyntax()); - partitionScanner.createDocumentPartitioner(document); - - AssemblerProperties properties = CompilerSourceParser.getDocumentProperties(document); - - IFile iFile = getCurrentIFile(); - if (iFile != null) { - try { - hardware = filesLogic.getHardware(iFile, properties); - } catch (InvalidAssemblerPropertyException ex) { - // Do not use MarkerUtility.gotoMarker to make sure this - // editor instance is used. - IDE.gotoMarker(this, ex.marker); - hardware = null; + /** + * Gets the hardware for this editor. + * + * @return The hardware for this editor, not <code>null</code>. + * + * @since 1.6.1 + */ + protected final Hardware getHardware() { + if (hardware != null) { + return hardware; } - } + return compiler.getDefinition().getDefaultHardware(); } - } + /** + * Gets the compiler id for this editor. + * + * @return The compiler id for this editor, not empty and not <code>null</code>. + */ + protected abstract String getCompilerId(); - @Override - protected final void createActions() { - super.createActions(); + @Override + protected final void initializeEditor() { + super.initializeEditor(); - ResourceBundle bundle = ResourceBundle.getBundle("com.wudsn.ide.asm.Actions", Locale.getDefault(), - AssemblerEditor.class.getClassLoader()); + plugin = AssemblerPlugin.getInstance(); + compiler = plugin.getCompilerRegistry().getCompiler(getCompilerId()); - String actionDefintionId; - String actionId; - actionDefintionId = ITextEditorActionDefinitionIds.CONTENT_ASSIST_PROPOSALS; - actionId = "com.wudsn.ide.asm.editor.ContentAssistProposal"; - IAction action = new TextOperationAction(bundle, actionId + ".", this, ISourceViewer.CONTENTASSIST_PROPOSALS); - action.setActionDefinitionId(actionDefintionId); - setAction(actionId, action); - markAsStateDependentAction(actionId, true); + setSourceViewerConfiguration(new AssemblerSourceViewerConfiguration(this, getPreferenceStore())); - SourceViewer sourceViewer = (SourceViewer) getSourceViewer(); - actionDefintionId = "com.wudsn.ide.asm.editor.AssemblerEditorToggleCommentCommand"; - actionId = actionDefintionId; - action = new AssemblerEditorToggleCommentAction(bundle, actionId + ".", this, sourceViewer); - action.setActionDefinitionId(actionId); - setAction(actionId, action); - markAsStateDependentAction(actionId, true); - - // Register rule double click. - ToggleBreakpointAction toggleBreakpointAction; - actionDefintionId = "org.eclipse.debug.ui.commands.ToggleBreakpoint"; - actionId = "RulerDoubleClick"; - action.setActionDefinitionId(actionId); - toggleBreakpointAction = new ToggleBreakpointAction(this, getDocumentProvider().getDocument(getEditorInput()), - getVerticalRuler()); - toggleBreakpointAction.setId(actionId); - setAction(actionId, toggleBreakpointAction); - markAsStateDependentAction(actionId, true); - toggleBreakpointAction.update(); - } - - final ISourceViewer getSourceViewerInternal() { - return getSourceViewer(); - } - - /** - * Refreshes the editor after changes to the text attributes or the text - * content. - * - * Called by {@link #updateIdentifiers(CompilerSourceFile)} and - * {@link AssemblerSourceViewerConfiguration#preferencesChanged(com.wudsn.ide.asm.preferences.AssemblerPreferences, java.util.Set)} - * . - */ - final void refreshSourceViewer() { - ISourceViewer isv = getSourceViewer(); - if (isv instanceof SourceViewer) { - ((SourceViewer) getSourceViewer()).invalidateTextPresentation(); - } - } - - @Override - public final void dispose() { - AssemblerSourceViewerConfiguration asvc; - asvc = (AssemblerSourceViewerConfiguration) getSourceViewerConfiguration(); - asvc.dispose(); - super.dispose(); - } - - @SuppressWarnings("unchecked") - @Override - public <T> T getAdapter(Class<T> adapter) { - if (IContentOutlinePage.class.equals(adapter)) { - if (contentOutlinePage == null) { - contentOutlinePage = new AssemblerContentOutlinePage(this); - // This causes double parsing upon starting with a new file - // currently. - updateContentOutlinePage(); - } - return (T)contentOutlinePage; - } - return super.getAdapter(adapter); - } - - /** - * Updates the content in view of the outline page. Called by - * {@link AssemblerReconcilingStategy#parse}. - */ - final void updateContentOutlinePage() { - if (contentOutlinePage != null) { - IEditorInput input = getEditorInput(); - - if (input != null) { - contentOutlinePage.setInput(input); - } - } - } - - /** - * Gets the compiler source file of the last parse process. - * - * @return The compiler source file of the last parse process or - * <code>null</code>. - */ - final CompilerSourceFile getCompilerSourceFile() { - CompilerSourceFile result; - if (contentOutlinePage != null) { - result = contentOutlinePage.getCompilerSourceFile(); - } else { - result = null; - } - return result; - } - - @Override - public final void createPartControl(Composite parent) { - if (parent == null) { - throw new IllegalArgumentException("Parameter 'parent' must not be null."); - } - super.createPartControl(parent); - ProjectionViewer viewer = (ProjectionViewer) getSourceViewer(); - - ProjectionSupport projectionSupport = new ProjectionSupport(viewer, getAnnotationAccess(), getSharedColors()); - projectionSupport.install(); - - // turn projection mode on - viewer.doOperation(ProjectionViewer.TOGGLE); - - annotationModel = viewer.getProjectionAnnotationModel(); - - } - - @Override - protected final ISourceViewer createSourceViewer(Composite parent, IVerticalRuler ruler, int styles) { - if (parent == null) { - throw new IllegalArgumentException("Parameter 'parent' must not be null."); - } - if (ruler == null) { - throw new IllegalArgumentException("Parameter 'ruler' must not be null."); - } - ISourceViewer viewer = new ProjectionViewer(parent, ruler, getOverviewRuler(), isOverviewRulerVisible(), styles); - - // Ensure decoration support has been created and configured. - getSourceViewerDecorationSupport(viewer); - - // The first single line comment delimiter is used as the default. - List<String> singleLineCommentDelimiters = compiler.getDefinition().getSyntax() - .getSingleLineCommentDelimiters(); - String[] array = singleLineCommentDelimiters.toArray(new String[singleLineCommentDelimiters.size()]); - viewer.setDefaultPrefixes(array, IDocument.DEFAULT_CONTENT_TYPE); - viewer.setDefaultPrefixes(array, CompilerSourcePartitionScanner.PARTITION_COMMENT_SINGLE); - - return viewer; - } - - /** - * Update the identifiers to be highlighted - * - * @param compilerSourceFile - * The compiler source file or <code>null</code>. - */ - final void updateIdentifiers(CompilerSourceFile compilerSourceFile) { - Profiler profiler = new Profiler(this.getClass()); - - AssemblerSourceViewerConfiguration asvc; - AssemblerSourceScanner ais; - asvc = (AssemblerSourceViewerConfiguration) getSourceViewerConfiguration(); - ais = asvc.getAssemblerInstructionScanner(); - - List<CompilerSourceParserTreeObject> newIdentifiers; - if (compilerSourceFile == null) { - newIdentifiers = Collections.emptyList(); - } else { - newIdentifiers = compilerSourceFile.getIdentifiers(); } - ais.setIdentifiers(newIdentifiers); - profiler.begin("refreshSourceViewer"); - // refreshSourceViewer(); - profiler.end("refreshSourceViewer"); - } - - /** - * Update the folding structure with a given list of foldingPositions. Used - * by the editor updater of {@link AssemblerReconcilingStategy}. - * - * @param foldingPositions - * The list of foldingPositions, may be empty, not - * <code>null</code>. - */ - final void updateFoldingStructure(List<Position> foldingPositions) { - if (foldingPositions == null) { - throw new IllegalArgumentException("Parameter 'foldingPositions' must not be null."); + /** + * Gets the plugin this compiler instance belongs to. + * + * @return The plugin this compiler instance belongs to, not <code>null</code>. + */ + public final AssemblerPlugin getPlugin() { + if (plugin == null) { + throw new IllegalStateException("Field 'plugin' must not be null."); + } + return plugin; } - // Create a working copy. - foldingPositions = new ArrayList<Position>(foldingPositions); - List<ProjectionAnnotation> deletions = new ArrayList<ProjectionAnnotation>(); - Object annotationObject = null; - ProjectionAnnotation annotation = null; - Position position = null; + /** + * Gets the compiler preferences. + * + * @return The compiler preferences, not <code>null</code>. + */ + public final CompilerPreferences getCompilerPreferences() { + return plugin.getPreferences().getCompilerPreferences(getCompilerId(), getHardware()); + } - // Access to the annotationModel is intentionally not synchronized, as - // otherwise deadlock would be the result. - for (@SuppressWarnings("rawtypes") - Iterator iter = annotationModel.getAnnotationIterator(); iter.hasNext();) { - annotationObject = iter.next(); + /** + * Gets the compiler for this editor. + * + * @return The compiler for this editor, not <code>null</code>. + */ + public final Compiler getCompiler() { + if (compiler == null) { + throw new IllegalStateException("Field 'compiler' must not be null."); + } + return compiler; + } - if (annotationObject instanceof ProjectionAnnotation) { - annotation = (ProjectionAnnotation) annotationObject; + /** + * Gets the compiler definition for this editor. + * + * @return The compiler definition for this editor, not <code>null</code>. + * + * @sine 1.6.1 + */ + public final CompilerDefinition getCompilerDefinition() { + if (compiler == null) { + throw new IllegalStateException("Field 'compiler' must not be null."); + } + return compiler.getDefinition(); + } - position = annotationModel.getPosition(annotation); + /** + * Gets the compiler source parser for this editor and the currently selected + * instruction set. + * + * @return The compiler source parser for this editor, not <code>null</code> . + */ + public final CompilerSourceParser createCompilerSourceParser() { + CPU cpu; + CompilerSourceParser result; + if (compiler == null) { + throw new IllegalStateException("Field 'compiler' must not be null."); + } + cpu = getCompilerPreferences().getCPU(); + result = compiler.createSourceParser(); + result.init(compiler.getDefinition().getSyntax().getInstructionSet(cpu)); + return result; + } - if (foldingPositions.contains(position)) { - foldingPositions.remove(position); + /** + * This method is called whenever the input changes, i.e. after loading and + * after saving as new file. + * + * @param input The new input, may be <code>null</code> + */ + @Override + protected final void doSetInput(IEditorInput input) throws CoreException { + super.doSetInput(input); + + hardware = null; + if (input != null) { + IDocument document = getDocumentProvider().getDocument(getEditorInput()); + + CompilerSourcePartitionScanner partitionScanner = new CompilerSourcePartitionScanner( + compiler.getDefinition().getSyntax()); + partitionScanner.createDocumentPartitioner(document); + + AssemblerProperties properties = CompilerSourceParser.getDocumentProperties(document); + + IFile iFile = getCurrentIFile(); + if (iFile != null) { + try { + hardware = filesLogic.getHardware(iFile, properties); + } catch (InvalidAssemblerPropertyException ex) { + // Do not use MarkerUtility.gotoMarker to make sure this + // editor instance is used. + IDE.gotoMarker(this, ex.marker); + hardware = null; + } + } + } + + } + + @Override + protected final void createActions() { + super.createActions(); + + ResourceBundle bundle = ResourceBundle.getBundle("com.wudsn.ide.asm.Actions", Locale.getDefault(), + AssemblerEditor.class.getClassLoader()); + + String actionDefintionId; + String actionId; + actionDefintionId = ITextEditorActionDefinitionIds.CONTENT_ASSIST_PROPOSALS; + actionId = "com.wudsn.ide.asm.editor.ContentAssistProposal"; + IAction action = new TextOperationAction(bundle, actionId + ".", this, ISourceViewer.CONTENTASSIST_PROPOSALS); + action.setActionDefinitionId(actionDefintionId); + setAction(actionId, action); + markAsStateDependentAction(actionId, true); + + SourceViewer sourceViewer = (SourceViewer) getSourceViewer(); + actionDefintionId = "com.wudsn.ide.asm.editor.AssemblerEditorToggleCommentCommand"; + actionId = actionDefintionId; + action = new AssemblerEditorToggleCommentAction(bundle, actionId + ".", this, sourceViewer); + action.setActionDefinitionId(actionId); + setAction(actionId, action); + markAsStateDependentAction(actionId, true); + + // Register rule double click. + ToggleBreakpointAction toggleBreakpointAction; + actionDefintionId = "org.eclipse.debug.ui.commands.ToggleBreakpoint"; + actionId = "RulerDoubleClick"; + action.setActionDefinitionId(actionId); + toggleBreakpointAction = new ToggleBreakpointAction(this, getDocumentProvider().getDocument(getEditorInput()), + getVerticalRuler()); + toggleBreakpointAction.setId(actionId); + setAction(actionId, toggleBreakpointAction); + markAsStateDependentAction(actionId, true); + toggleBreakpointAction.update(); + } + + final ISourceViewer getSourceViewerInternal() { + return getSourceViewer(); + } + + /** + * Refreshes the editor after changes to the text attributes or the text + * content. + * + * Called by {@link #updateIdentifiers(CompilerSourceFile)} and + * {@link AssemblerSourceViewerConfiguration#preferencesChanged(com.wudsn.ide.asm.preferences.AssemblerPreferences, java.util.Set)} + * . + */ + final void refreshSourceViewer() { + ISourceViewer isv = getSourceViewer(); + if (isv instanceof SourceViewer) { + ((SourceViewer) getSourceViewer()).invalidateTextPresentation(); + } + } + + @Override + public final void dispose() { + AssemblerSourceViewerConfiguration asvc; + asvc = (AssemblerSourceViewerConfiguration) getSourceViewerConfiguration(); + asvc.dispose(); + super.dispose(); + } + + @SuppressWarnings("unchecked") + @Override + public <T> T getAdapter(Class<T> adapter) { + if (IContentOutlinePage.class.equals(adapter)) { + if (contentOutlinePage == null) { + contentOutlinePage = new AssemblerContentOutlinePage(this); + // This causes double parsing upon starting with a new file + // currently. + updateContentOutlinePage(); + } + return (T) contentOutlinePage; + } + return super.getAdapter(adapter); + } + + /** + * Updates the content in view of the outline page. Called by + * {@link AssemblerReconcilingStategy#parse}. + */ + final void updateContentOutlinePage() { + if (contentOutlinePage != null) { + IEditorInput input = getEditorInput(); + + if (input != null) { + contentOutlinePage.setInput(input); + } + } + } + + /** + * Gets the compiler source file of the last parse process. + * + * @return The compiler source file of the last parse process or + * <code>null</code>. + */ + final CompilerSourceFile getCompilerSourceFile() { + CompilerSourceFile result; + if (contentOutlinePage != null) { + result = contentOutlinePage.getCompilerSourceFile(); } else { - deletions.add(annotation); + result = null; } - } + return result; + } + + @Override + public final void createPartControl(Composite parent) { + if (parent == null) { + throw new IllegalArgumentException("Parameter 'parent' must not be null."); + } + super.createPartControl(parent); + ProjectionViewer viewer = (ProjectionViewer) getSourceViewer(); + + ProjectionSupport projectionSupport = new ProjectionSupport(viewer, getAnnotationAccess(), getSharedColors()); + projectionSupport.install(); + + // turn projection mode on + viewer.doOperation(ProjectionViewer.TOGGLE); + + annotationModel = viewer.getProjectionAnnotationModel(); } - Annotation[] removeAnnotations = deletions.toArray(new Annotation[deletions.size()]); + @Override + protected final ISourceViewer createSourceViewer(Composite parent, IVerticalRuler ruler, int styles) { + if (parent == null) { + throw new IllegalArgumentException("Parameter 'parent' must not be null."); + } + if (ruler == null) { + throw new IllegalArgumentException("Parameter 'ruler' must not be null."); + } + ISourceViewer viewer = new ProjectionViewer(parent, ruler, getOverviewRuler(), isOverviewRulerVisible(), + styles); - // This will hold the new annotations along - // with their corresponding folding positions. - HashMap<ProjectionAnnotation, Position> newAnnotations = new HashMap<ProjectionAnnotation, Position>(); + // Ensure decoration support has been created and configured. + getSourceViewerDecorationSupport(viewer); - for (int i = 0; i < foldingPositions.size(); i++) { - annotation = new ProjectionAnnotation(); - newAnnotations.put(annotation, foldingPositions.get(i)); + // The first single line comment delimiter is used as the default. + List<String> singleLineCommentDelimiters = compiler.getDefinition().getSyntax() + .getSingleLineCommentDelimiters(); + String[] array = singleLineCommentDelimiters.toArray(new String[singleLineCommentDelimiters.size()]); + viewer.setDefaultPrefixes(array, IDocument.DEFAULT_CONTENT_TYPE); + viewer.setDefaultPrefixes(array, CompilerSourcePartitionScanner.PARTITION_COMMENT_SINGLE); + + return viewer; } - // Do not update anything if there is actual change to preserve the - // current cursor positioning. - if (removeAnnotations.length == 0 && newAnnotations.isEmpty()) { - return; + /** + * Update the identifiers to be highlighted + * + * @param compilerSourceFile The compiler source file or <code>null</code>. + */ + final void updateIdentifiers(CompilerSourceFile compilerSourceFile) { + Profiler profiler = new Profiler(this.getClass()); + + AssemblerSourceViewerConfiguration asvc; + AssemblerSourceScanner ais; + asvc = (AssemblerSourceViewerConfiguration) getSourceViewerConfiguration(); + ais = asvc.getAssemblerInstructionScanner(); + + List<CompilerSourceParserTreeObject> newIdentifiers; + if (compilerSourceFile == null) { + newIdentifiers = Collections.emptyList(); + } else { + newIdentifiers = compilerSourceFile.getIdentifiers(); + } + + ais.setIdentifiers(newIdentifiers); + profiler.begin("refreshSourceViewer"); + // refreshSourceViewer(); + profiler.end("refreshSourceViewer"); } - annotationModel.modifyAnnotations(removeAnnotations, newAnnotations, new Annotation[] {}); - } + /** + * Update the folding structure with a given list of foldingPositions. Used by + * the editor updater of {@link AssemblerReconcilingStategy}. + * + * @param foldingPositions The list of foldingPositions, may be empty, not + * <code>null</code>. + */ + final void updateFoldingStructure(List<Position> foldingPositions) { + if (foldingPositions == null) { + throw new IllegalArgumentException("Parameter 'foldingPositions' must not be null."); + } - /** - * Gets the directory of the current file. - * - * @return The directory of the current file or <code>null</code>. - */ - public final File getCurrentDirectory() { - File result; - result = getCurrentFile(); - if (result != null) { - result = result.getParentFile(); - } - return result; - } + // Create a working copy. + foldingPositions = new ArrayList<Position>(foldingPositions); + List<ProjectionAnnotation> deletions = new ArrayList<ProjectionAnnotation>(); + Object annotationObject = null; + ProjectionAnnotation annotation = null; + Position position = null; - /** - * Gets the the current file. - * - * @return The current file or <code>null</code>. - */ - public final File getCurrentFile() { - File result; - IEditorInput editorInput = getEditorInput(); - if (editorInput instanceof FileEditorInput) { - FileEditorInput fileEditorInput = (FileEditorInput) editorInput; - result = new File(fileEditorInput.getPath().toOSString()); - } else { - result = null; - } - return result; - } + // Access to the annotationModel is intentionally not synchronized, as + // otherwise deadlock would be the result. + for (@SuppressWarnings("rawtypes") + Iterator iter = annotationModel.getAnnotationIterator(); iter.hasNext();) { + annotationObject = iter.next(); - /** - * Gets the the current file. - * - * @return The current file or <code>null</code>. - */ - public final IFile getCurrentIFile() { - IFile result; - IEditorInput editorInput = getEditorInput(); - if (editorInput instanceof FileEditorInput) { - FileEditorInput fileEditorInput = (FileEditorInput) editorInput; - result = fileEditorInput.getFile(); + if (annotationObject instanceof ProjectionAnnotation) { + annotation = (ProjectionAnnotation) annotationObject; - } else { - result = null; - } - return result; - } + position = annotationModel.getPosition(annotation); - /** - * Position the cursor to the specified line in the document. - * - * @param line - * The line number, a positive integer. - * - * @return <code>true</code> if the positioning was successful. - */ - public final boolean gotoLine(int line) { - if (line < 1) { - throw new IllegalArgumentException("Parameter 'line' must be positive. Specified value is " + line + "."); + if (foldingPositions.contains(position)) { + foldingPositions.remove(position); + } else { + deletions.add(annotation); + } + } + + } + + Annotation[] removeAnnotations = deletions.toArray(new Annotation[deletions.size()]); + + // This will hold the new annotations along + // with their corresponding folding positions. + HashMap<ProjectionAnnotation, Position> newAnnotations = new HashMap<ProjectionAnnotation, Position>(); + + for (int i = 0; i < foldingPositions.size(); i++) { + annotation = new ProjectionAnnotation(); + newAnnotations.put(annotation, foldingPositions.get(i)); + } + + // Do not update anything if there is actual change to preserve the + // current cursor positioning. + if (removeAnnotations.length == 0 && newAnnotations.isEmpty()) { + return; + } + + annotationModel.modifyAnnotations(removeAnnotations, newAnnotations, new Annotation[] {}); } - IDocumentProvider provider = getDocumentProvider(); - IDocument document = provider.getDocument(getEditorInput()); - boolean result = false; - try { - int startOffset = document.getLineOffset(line - 1); - int lineLength = document.getLineLength(line - 1); - if (lineLength > 0) { - lineLength = lineLength - 1; - } - selectAndReveal(startOffset, lineLength); - result = true; - } catch (BadLocationException ex) { - plugin.logError("Cannot position to line {0}.", new Object[] { String.valueOf(line) }, ex); - result = false; + + /** + * Gets the directory of the current file. + * + * @return The directory of the current file or <code>null</code>. + */ + public final File getCurrentDirectory() { + File result; + result = getCurrentFile(); + if (result != null) { + result = result.getParentFile(); + } + return result; + } + + /** + * Gets the the current file. + * + * @return The current file or <code>null</code>. + */ + public final File getCurrentFile() { + File result; + IEditorInput editorInput = getEditorInput(); + if (editorInput instanceof FileEditorInput) { + FileEditorInput fileEditorInput = (FileEditorInput) editorInput; + result = new File(fileEditorInput.getPath().toOSString()); + } else { + result = null; + } + return result; + } + + /** + * Gets the the current file. + * + * @return The current file or <code>null</code>. + */ + public final IFile getCurrentIFile() { + IFile result; + IEditorInput editorInput = getEditorInput(); + if (editorInput instanceof FileEditorInput) { + FileEditorInput fileEditorInput = (FileEditorInput) editorInput; + result = fileEditorInput.getFile(); + + } else { + result = null; + } + return result; + } + + /** + * Position the cursor to the specified line in the document. + * + * @param line The line number, a positive integer. + * + * @return <code>true</code> if the positioning was successful. + */ + public final boolean gotoLine(int line) { + if (line < 1) { + throw new IllegalArgumentException("Parameter 'line' must be positive. Specified value is " + line + "."); + } + IDocumentProvider provider = getDocumentProvider(); + IDocument document = provider.getDocument(getEditorInput()); + boolean result = false; + try { + int startOffset = document.getLineOffset(line - 1); + int lineLength = document.getLineLength(line - 1); + if (lineLength > 0) { + lineLength = lineLength - 1; + } + selectAndReveal(startOffset, lineLength); + result = true; + } catch (BadLocationException ex) { + plugin.logError("Cannot position to line {0}.", new Object[] { String.valueOf(line) }, ex); + result = false; + } + return result; } - return result; - } } diff --git a/com.wudsn.ide.asm/src/com/wudsn/ide/asm/editor/AssemblerEditorFilesCommandHandler.java b/com.wudsn.ide.asm/src/com/wudsn/ide/asm/editor/AssemblerEditorFilesCommandHandler.java index 8afe7b85..f80e7686 100644 --- a/com.wudsn.ide.asm/src/com/wudsn/ide/asm/editor/AssemblerEditorFilesCommandHandler.java +++ b/com.wudsn.ide.asm/src/com/wudsn/ide/asm/editor/AssemblerEditorFilesCommandHandler.java @@ -39,55 +39,50 @@ import com.wudsn.ide.asm.compiler.CompilerFiles; */ public abstract class AssemblerEditorFilesCommandHandler extends AbstractHandler { - public AssemblerEditorFilesCommandHandler() { - super(); - } - - @Override - public Object execute(ExecutionEvent event) throws ExecutionException { - IEditorPart editor; - editor = HandlerUtil.getActiveEditorChecked(event); - if (!(editor instanceof AssemblerEditor)) { - return null; + public AssemblerEditorFilesCommandHandler() { + super(); } - AssemblerEditor assemblerEditor; - assemblerEditor = (AssemblerEditor) editor; + @Override + public Object execute(ExecutionEvent event) throws ExecutionException { + IEditorPart editor; + editor = HandlerUtil.getActiveEditorChecked(event); + if (!(editor instanceof AssemblerEditor)) { + return null; + } - CompilerFiles files; - files = AssemblerEditorFilesLogic.createInstance(assemblerEditor).createCompilerFiles(); + AssemblerEditor assemblerEditor; + assemblerEditor = (AssemblerEditor) editor; - if (files != null) { - execute(event, assemblerEditor, files); - } else { - try { - AssemblerPlugin.getInstance().showError( - assemblerEditor.getSite().getShell(), - "Operation '" + event.getCommand().getName() - + "' is not possible because the file in the editor is not located in the workspace.", - new Exception()); - } catch (NotDefinedException ignore) { - // Ignore - } + CompilerFiles files; + files = AssemblerEditorFilesLogic.createInstance(assemblerEditor).createCompilerFiles(); + + if (files != null) { + execute(event, assemblerEditor, files); + } else { + try { + AssemblerPlugin.getInstance().showError(assemblerEditor.getSite().getShell(), + "Operation '" + event.getCommand().getName() + + "' is not possible because the file in the editor is not located in the workspace.", + new Exception("Cannot resolve compiler files of " + assemblerEditor.getEditorInput())); + } catch (NotDefinedException ignore) { + // Ignore + } + } + return null; } - return null; - } - /** - * Perform the action on the current editor and file. - * - * @param event - * The event, not <code>null</code>. - * @param assemblerEditor - * The assembler editor, not <code>null</code> and with current - * files which are not <code>null</code>. - * @param files - * The current compiler files of the editor, not - * <code>null</code> . - * @throws ExecutionException - * if an exception occurred during execution. - */ - protected abstract void execute(ExecutionEvent event, AssemblerEditor assemblerEditor, CompilerFiles files) - throws ExecutionException; + /** + * Perform the action on the current editor and file. + * + * @param event The event, not <code>null</code>. + * @param assemblerEditor The assembler editor, not <code>null</code> and with + * current files which are not <code>null</code>. + * @param files The current compiler files of the editor, not + * <code>null</code> . + * @throws ExecutionException if an exception occurred during execution. + */ + protected abstract void execute(ExecutionEvent event, AssemblerEditor assemblerEditor, CompilerFiles files) + throws ExecutionException; } \ No newline at end of file diff --git a/com.wudsn.ide.asm/src/com/wudsn/ide/asm/editor/AssemblerEditorFilesLogic.java b/com.wudsn.ide.asm/src/com/wudsn/ide/asm/editor/AssemblerEditorFilesLogic.java index 20c1648c..2b41b9c2 100644 --- a/com.wudsn.ide.asm/src/com/wudsn/ide/asm/editor/AssemblerEditorFilesLogic.java +++ b/com.wudsn.ide.asm/src/com/wudsn/ide/asm/editor/AssemblerEditorFilesLogic.java @@ -55,318 +55,310 @@ import com.wudsn.ide.base.common.StringUtility; */ public final class AssemblerEditorFilesLogic { - private AssemblerEditor assemblerEditor; - - /** - * Create a new instance of the logic. - * - * @param assemblerEditor - * The assembler editor, not <code>null</code>. - * - * @return The new instance, not <code>null</code>. - */ - static AssemblerEditorFilesLogic createInstance(AssemblerEditor assemblerEditor) { - if (assemblerEditor == null) { - throw new IllegalArgumentException("Parameter 'assemblerEditor' must not be null."); - } - - AssemblerEditorFilesLogic result = new AssemblerEditorFilesLogic(); - result.assemblerEditor = assemblerEditor; - return result; - } - - /** - * Gets the container with all files related to the current files. - * - * @return The container with all files related to the current files or - * <code>null</code>. - */ - CompilerFiles createCompilerFiles() { - IFile sourceIFile; - CompilerFiles result; - sourceIFile = assemblerEditor.getCurrentIFile(); - if (sourceIFile != null) { - - IDocument document = assemblerEditor.getDocumentProvider().getDocument(assemblerEditor.getEditorInput()); - AssemblerProperties sourceFileProperties = CompilerSourceParser.getDocumentProperties(document); - - IFile mainSourceIFile; - AssemblerProperties mainSourceFileProperties; - - mainSourceIFile = sourceIFile; - mainSourceFileProperties = sourceFileProperties; - - AssemblerProperty property = sourceFileProperties.get(AssemblerProperties.MAIN_SOURCE_FILE); - if (property != null) { - if (StringUtility.isSpecified(property.value)) { - IPath mainSourceFileIPath; - mainSourceFileIPath = sourceIFile.getFullPath().removeLastSegments(1).append(property.value); - mainSourceIFile = ResourcesPlugin.getWorkspace().getRoot().getFile(mainSourceFileIPath); - File mainSourceFile = new File(mainSourceIFile.getLocation().toOSString()); - - try { - String mainSource; - - mainSource = FileUtility.readString(mainSourceFile, FileUtility.MAX_SIZE_UNLIMITED); - document = new Document(mainSource); - mainSourceFileProperties = CompilerSourceParser.getDocumentProperties(document); - } catch (CoreException ex) { - AssemblerPlugin plugin = AssemblerPlugin.getInstance(); - - plugin.logError("Cannot read main source file '{0'}", - new Object[] { mainSourceFile.getPath() }, ex); - mainSourceFileProperties = new AssemblerProperties(); - } + private AssemblerEditor assemblerEditor; + /** + * Create a new instance of the logic. + * + * @param assemblerEditor The assembler editor, not <code>null</code>. + * + * @return The new instance, not <code>null</code>. + */ + static AssemblerEditorFilesLogic createInstance(AssemblerEditor assemblerEditor) { + if (assemblerEditor == null) { + throw new IllegalArgumentException("Parameter 'assemblerEditor' must not be null."); } - } - result = new CompilerFiles(mainSourceIFile, mainSourceFileProperties, sourceIFile, sourceFileProperties, - assemblerEditor.getCompilerPreferences()); - } else { - result = null; - } - return result; - } - public boolean removeMarkers(CompilerFiles files) { - if (files == null) { - throw new IllegalArgumentException("Parameter 'files' must not be null."); + AssemblerEditorFilesLogic result = new AssemblerEditorFilesLogic(); + result.assemblerEditor = assemblerEditor; + return result; } - // Remove markers from the current file. - try { - files.sourceFile.iFile.deleteMarkers(IMarker.PROBLEM, true, IResource.DEPTH_INFINITE); - } catch (CoreException ex) { - assemblerEditor.getPlugin().logError("Cannot remove markers", null, ex); - } + /** + * Gets the container with all files related to the current files. + * + * @return The container with all files related to the current files or + * <code>null</code>. + */ + CompilerFiles createCompilerFiles() { + IFile sourceIFile; + CompilerFiles result; + sourceIFile = assemblerEditor.getCurrentIFile(); + if (sourceIFile != null) { - // If the main source file is not there, the error shall be related to - // the include source file. In all other cases, the main source file - // exists and is the main message target. - if (!files.mainSourceFile.iFile.exists()) { - int lineNumber = files.sourceFile.assemblerProperties.get(AssemblerProperties.MAIN_SOURCE_FILE).lineNumber; + IDocument document = assemblerEditor.getDocumentProvider().getDocument(assemblerEditor.getEditorInput()); + AssemblerProperties sourceFileProperties = CompilerSourceParser.getDocumentProperties(document); - // ERROR: Main source file '{0}' does not exist. - IMarker marker = MarkerUtility.createMarker(files.sourceFile.iFile, lineNumber, IMarker.SEVERITY_ERROR, - Texts.MESSAGE_E125, files.mainSourceFile.filePath); - MarkerUtility.gotoMarker(assemblerEditor, marker); - return false; - } + IFile mainSourceIFile; + AssemblerProperties mainSourceFileProperties; - // Remove markers from the other relevant files. - // TODO Use (only) include files parsed from main source file - try { - files.mainSourceFile.iFile.getParent().deleteMarkers(IMarker.PROBLEM, true, IResource.DEPTH_INFINITE); - } catch (CoreException ex) { - assemblerEditor.getPlugin().logError("Cannot remove markers", null, ex); - } - return true; - } + mainSourceIFile = sourceIFile; + mainSourceFileProperties = sourceFileProperties; - /** - * Determine the hardware defined by the property - * {@link AssemblerProperties#HARDWARE}. - * - * @param iFile - * The iFIle to which error message will be associated, not - * <code>null</code>. - * @param properties - * The assembler properties, not <code>null</code>. - * - * @return The hardware or <code>null</code> if is the not defined in the - * properties. - * @throws InvalidAssemblerPropertyException - * If the hardware is specified but invalid. Error message will - * be assigned to the iFile in this case. - * - * @since 1.6.1 - */ - Hardware getHardware(IFile iFile, AssemblerProperties properties) throws InvalidAssemblerPropertyException { - if (iFile == null) { - throw new IllegalArgumentException("Parameter 'iFile' must not be null."); - } - Hardware hardware = null; - AssemblerProperty hardwareProperty = properties.get(AssemblerProperties.HARDWARE); - if (hardwareProperty != null) { - Map<String, Hardware> allowedValues = new TreeMap<String, Hardware>(); - StringBuilder allowedValuesBuilder = new StringBuilder(); - for (Hardware value : Hardware.values()) { + AssemblerProperty property = sourceFileProperties.get(AssemblerProperties.MAIN_SOURCE_FILE); + if (property != null) { + if (StringUtility.isSpecified(property.value)) { + IPath mainSourceFileIPath; + mainSourceFileIPath = sourceIFile.getFullPath().removeLastSegments(1).append(property.value); + mainSourceIFile = ResourcesPlugin.getWorkspace().getRoot().getFile(mainSourceFileIPath); + File mainSourceFile = new File(mainSourceIFile.getLocation().toOSString()); - if (value != Hardware.GENERIC) { - if (allowedValuesBuilder.length() > 0) { - allowedValuesBuilder.append(","); - } - allowedValues.put(value.name(), value); - allowedValuesBuilder.append(value.name()); + try { + String mainSource; + + mainSource = FileUtility.readString(mainSourceFile, FileUtility.MAX_SIZE_UNLIMITED); + document = new Document(mainSource); + mainSourceFileProperties = CompilerSourceParser.getDocumentProperties(document); + } catch (CoreException ex) { + AssemblerPlugin plugin = AssemblerPlugin.getInstance(); + + plugin.logError("Cannot read main source file '{0'}", new Object[] { mainSourceFile.getPath() }, + ex); + mainSourceFileProperties = new AssemblerProperties(); + } + + } + } + result = new CompilerFiles(mainSourceIFile, mainSourceFileProperties, sourceIFile, sourceFileProperties, + assemblerEditor.getCompilerPreferences()); + } else { + result = null; } - } + return result; + } - String hardwarePropertyValue = hardwareProperty.value.toUpperCase(); - if (StringUtility.isEmpty(hardwarePropertyValue)) { + public boolean removeMarkers(CompilerFiles files) { + if (files == null) { + throw new IllegalArgumentException("Parameter 'files' must not be null."); + } + + // Remove markers from the current file. try { - iFile.deleteMarkers(IMarker.PROBLEM, true, IResource.DEPTH_ZERO); + files.sourceFile.iFile.deleteMarkers(IMarker.PROBLEM, true, IResource.DEPTH_INFINITE); } catch (CoreException ex) { - AssemblerPlugin.getInstance().logError("Cannot remove markers", null, ex); + assemblerEditor.getPlugin().logError("Cannot remove markers", null, ex); } - // ERROR: Hardware not specified. Specify one of the - // following valid values '{0}'. - IMarker marker = MarkerUtility.createMarker(iFile, hardwareProperty.lineNumber, IMarker.SEVERITY_ERROR, - Texts.MESSAGE_E128, new String[] { allowedValuesBuilder.toString() }); - throw new InvalidAssemblerPropertyException(hardwareProperty, marker); - } - hardware = allowedValues.get(hardwarePropertyValue); - if (hardware == null) { + // If the main source file is not there, the error shall be related to + // the include source file. In all other cases, the main source file + // exists and is the main message target. + if (!files.mainSourceFile.iFile.exists()) { + int lineNumber = files.sourceFile.assemblerProperties.get(AssemblerProperties.MAIN_SOURCE_FILE).lineNumber; + + // ERROR: Main source file '{0}' does not exist. + IMarker marker = MarkerUtility.createMarker(files.sourceFile.iFile, lineNumber, IMarker.SEVERITY_ERROR, + Texts.MESSAGE_E125, files.mainSourceFile.filePath); + MarkerUtility.gotoMarker(assemblerEditor, marker); + return false; + } + + // Remove markers from the other relevant files. + // TODO Use (only) include files parsed from main source file try { - iFile.deleteMarkers(IMarker.PROBLEM, true, IResource.DEPTH_ZERO); + files.mainSourceFile.iFile.getParent().deleteMarkers(IMarker.PROBLEM, true, IResource.DEPTH_INFINITE); } catch (CoreException ex) { - assemblerEditor.getPlugin().logError("Cannot remove markers", null, ex); + assemblerEditor.getPlugin().logError("Cannot remove markers", null, ex); } - // ERROR: Unknown hardware {0}. Specify one of the - // following valid values '{1}'. - IMarker marker = MarkerUtility.createMarker(iFile, hardwareProperty.lineNumber, IMarker.SEVERITY_ERROR, - Texts.MESSAGE_E124, new String[] { hardwarePropertyValue, allowedValuesBuilder.toString() }); - throw new InvalidAssemblerPropertyException(hardwareProperty, marker); - } - - } - return hardware; - } - - /** - * Determine the hardware of the main source file and makes sure that the - * include file uses the same hardware. - * - * @param files - * The compiler files, not <code>null</code>. - * @return The hardware to be used, or <code>null</code> if errors have - * occurred. - * - * @since 1.6.1 - */ - public Hardware getHardware(CompilerFiles files) { - if (files == null) { - throw new IllegalArgumentException("Parameter 'files' must not be null."); - } - Hardware mainSourceFileHardware; - Hardware sourceFileHardware; - try { - sourceFileHardware = getHardware(files.sourceFile.iFile, files.sourceFile.assemblerProperties); - } catch (InvalidAssemblerPropertyException ex) { - MarkerUtility.gotoMarker(assemblerEditor, ex.marker); - return null; - } - try { - mainSourceFileHardware = getHardware(files.mainSourceFile.iFile, files.mainSourceFile.assemblerProperties); - } catch (InvalidAssemblerPropertyException ex) { - MarkerUtility.gotoMarker(assemblerEditor, ex.marker); - return null; - } - Hardware defaultHardware = assemblerEditor.getCompilerDefinition().getDefaultHardware(); - int sourceFileLineNumber; - int mainSourceFileLineNumber; - if (sourceFileHardware == null) { - sourceFileHardware = defaultHardware; - sourceFileLineNumber = 0; - } else { - sourceFileLineNumber = files.sourceFile.assemblerProperties.get(AssemblerProperties.HARDWARE).lineNumber; - } - if (mainSourceFileHardware == null) { - mainSourceFileHardware = defaultHardware; - mainSourceFileLineNumber = 0; - } else { - mainSourceFileLineNumber = files.mainSourceFile.assemblerProperties.get(AssemblerProperties.HARDWARE).lineNumber; + return true; } - if (!sourceFileHardware.equals(mainSourceFileHardware)) { - // ERROR: Main source file specifies or defaults to hardware {0} - // while include file specifies or defaults to hardware '{1}'. - MarkerUtility.createMarker(files.mainSourceFile.iFile, mainSourceFileLineNumber, IMarker.SEVERITY_ERROR, - Texts.MESSAGE_E129, new String[] { mainSourceFileHardware.name(), sourceFileHardware.name() }); - MarkerUtility.createMarker(files.sourceFile.iFile, sourceFileLineNumber, IMarker.SEVERITY_ERROR, - Texts.MESSAGE_E129, new String[] { mainSourceFileHardware.name(), sourceFileHardware.name() }); - return null; - } - return mainSourceFileHardware; - } + /** + * Determine the hardware defined by the property + * {@link AssemblerProperties#HARDWARE}. + * + * @param iFile The iFIle to which error message will be associated, not + * <code>null</code>. + * @param properties The assembler properties, not <code>null</code>. + * + * @return The hardware or <code>null</code> if is the not defined in the + * properties. + * @throws InvalidAssemblerPropertyException If the hardware is specified but + * invalid. Error message will be + * assigned to the iFile in this case. + * + * @since 1.6.1 + */ + Hardware getHardware(IFile iFile, AssemblerProperties properties) throws InvalidAssemblerPropertyException { + if (iFile == null) { + throw new IllegalArgumentException("Parameter 'iFile' must not be null."); + } + Hardware hardware = null; + AssemblerProperty hardwareProperty = properties.get(AssemblerProperties.HARDWARE); + if (hardwareProperty != null) { + Map<String, Hardware> allowedValues = new TreeMap<String, Hardware>(); + StringBuilder allowedValuesBuilder = new StringBuilder(); + for (Hardware value : Hardware.values()) { - /** - * Validates the output file related settings of the compiler files. - * - * @param files - * The compiler files, not <code>null</code>. - * @return <code>true</code> if all settings are correct, <code>false</code> - * otherwise. - */ - public boolean validateOutputFile(CompilerFiles files) { - if (files == null) { - throw new IllegalArgumentException("Parameter 'files' must not be null."); - } - CompilerDefinition compilerDefinition = assemblerEditor.getCompilerDefinition(); - if (StringUtility.isEmpty(files.outputFileExtension)) { - // ERROR: Output file extension must be set in the preferences of - // compiler '{0}' or via the annotation '{1}'. - createMainSourceFileMessage(files, files.outputFileExtensionProperty, IMarker.SEVERITY_ERROR, - Texts.MESSAGE_E104, compilerDefinition.getName(), AssemblerProperties.OUTPUT_FILE_EXTENSION); + if (value != Hardware.GENERIC) { + if (allowedValuesBuilder.length() > 0) { + allowedValuesBuilder.append(","); + } + allowedValues.put(value.name(), value); + allowedValuesBuilder.append(value.name()); + } + } - return false; - } - if (!files.outputFileExtension.startsWith(".")) { - // ERROR: Output file extension {0} must start with ".". - createMainSourceFileMessage(files, files.outputFileExtensionProperty, IMarker.SEVERITY_ERROR, - Texts.MESSAGE_E139, files.outputFileExtension); - return false; + String hardwarePropertyValue = hardwareProperty.value.toUpperCase(); + if (StringUtility.isEmpty(hardwarePropertyValue)) { + try { + iFile.deleteMarkers(IMarker.PROBLEM, true, IResource.DEPTH_ZERO); + } catch (CoreException ex) { + AssemblerPlugin.getInstance().logError("Cannot remove markers", null, ex); + } + // ERROR: Hardware not specified. Specify one of the + // following valid values '{0}'. + IMarker marker = MarkerUtility.createMarker(iFile, hardwareProperty.lineNumber, IMarker.SEVERITY_ERROR, + Texts.MESSAGE_E128, new String[] { allowedValuesBuilder.toString() }); + throw new InvalidAssemblerPropertyException(hardwareProperty, marker); + } + hardware = allowedValues.get(hardwarePropertyValue); + + if (hardware == null) { + try { + iFile.deleteMarkers(IMarker.PROBLEM, true, IResource.DEPTH_ZERO); + } catch (CoreException ex) { + assemblerEditor.getPlugin().logError("Cannot remove markers", null, ex); + } + // ERROR: Unknown hardware {0}. Specify one of the + // following valid values '{1}'. + IMarker marker = MarkerUtility.createMarker(iFile, hardwareProperty.lineNumber, IMarker.SEVERITY_ERROR, + Texts.MESSAGE_E124, new String[] { hardwarePropertyValue, allowedValuesBuilder.toString() }); + throw new InvalidAssemblerPropertyException(hardwareProperty, marker); + } + + } + return hardware; } - if (StringUtility.isEmpty(files.outputFolderMode)) { - // ERROR: Output folder mode be set in the preferences of - // compiler '{0}' or via the annotation '{1}'. - createMainSourceFileMessage(files, files.outputFolderModeProperty, IMarker.SEVERITY_ERROR, - Texts.MESSAGE_E140, compilerDefinition.getName(), AssemblerProperties.OUTPUT_FOLDER_MODE); - - return false; - } - if (!CompilerOutputFolderMode.isDefined(files.outputFolderMode)) { - // ERROR: Unknown output folder mode {0}. Specify one of the - // following valid values '{1}'. - createMainSourceFileMessage(files, files.outputFolderModeProperty, IMarker.SEVERITY_ERROR, - Texts.MESSAGE_E141, files.outputFolderMode, CompilerOutputFolderMode.getAllowedValues()); - return false; + /** + * Determine the hardware of the main source file and makes sure that the + * include file uses the same hardware. + * + * @param files The compiler files, not <code>null</code>. + * @return The hardware to be used, or <code>null</code> if errors have + * occurred. + * + * @since 1.6.1 + */ + public Hardware getHardware(CompilerFiles files) { + if (files == null) { + throw new IllegalArgumentException("Parameter 'files' must not be null."); + } + Hardware mainSourceFileHardware; + Hardware sourceFileHardware; + try { + sourceFileHardware = getHardware(files.sourceFile.iFile, files.sourceFile.assemblerProperties); + } catch (InvalidAssemblerPropertyException ex) { + MarkerUtility.gotoMarker(assemblerEditor, ex.marker); + return null; + } + try { + mainSourceFileHardware = getHardware(files.mainSourceFile.iFile, files.mainSourceFile.assemblerProperties); + } catch (InvalidAssemblerPropertyException ex) { + MarkerUtility.gotoMarker(assemblerEditor, ex.marker); + return null; + } + Hardware defaultHardware = assemblerEditor.getCompilerDefinition().getDefaultHardware(); + int sourceFileLineNumber; + int mainSourceFileLineNumber; + if (sourceFileHardware == null) { + sourceFileHardware = defaultHardware; + sourceFileLineNumber = 0; + } else { + sourceFileLineNumber = files.sourceFile.assemblerProperties.get(AssemblerProperties.HARDWARE).lineNumber; + } + if (mainSourceFileHardware == null) { + mainSourceFileHardware = defaultHardware; + mainSourceFileLineNumber = 0; + } else { + mainSourceFileLineNumber = files.mainSourceFile.assemblerProperties + .get(AssemblerProperties.HARDWARE).lineNumber; + } + if (!sourceFileHardware.equals(mainSourceFileHardware)) { + // ERROR: Main source file specifies or defaults to hardware {0} + // while include file specifies or defaults to hardware '{1}'. + MarkerUtility.createMarker(files.mainSourceFile.iFile, mainSourceFileLineNumber, IMarker.SEVERITY_ERROR, + Texts.MESSAGE_E129, new String[] { mainSourceFileHardware.name(), sourceFileHardware.name() }); + MarkerUtility.createMarker(files.sourceFile.iFile, sourceFileLineNumber, IMarker.SEVERITY_ERROR, + Texts.MESSAGE_E129, new String[] { mainSourceFileHardware.name(), sourceFileHardware.name() }); + return null; + } + return mainSourceFileHardware; } - return true; - } + /** + * Validates the output file related settings of the compiler files. + * + * @param files The compiler files, not <code>null</code>. + * @return <code>true</code> if all settings are correct, <code>false</code> + * otherwise. + */ + public boolean validateOutputFile(CompilerFiles files) { + if (files == null) { + throw new IllegalArgumentException("Parameter 'files' must not be null."); + } + CompilerDefinition compilerDefinition = assemblerEditor.getCompilerDefinition(); + if (StringUtility.isEmpty(files.outputFileExtension)) { + // ERROR: Output file extension must be set in the preferences of + // compiler '{0}' or via the annotation '{1}'. + createMainSourceFileMessage(files, files.outputFileExtensionProperty, IMarker.SEVERITY_ERROR, + Texts.MESSAGE_E104, compilerDefinition.getName(), AssemblerProperties.OUTPUT_FILE_EXTENSION); - /** - * Creates a message associated with the main source file of an - * {@link AssemblerEditorFilesLogic} instance. The message is is bound to - * the line number number of the property (if available). Also the editor is - * position to the marker. - * - * @param files - * The {@link AssemblerEditorFilesLogic} not <code>null</code>. - * @param property - * The assembler editor property to which the message belongs or - * <code>null</code>. - * @param severity - * The message severity, see {@link IMarker#SEVERITY} - * @param message - * The message, may contain parameter "{0}" to "{9}". May be - * empty, not <code>null</code>. - * @param parameters - * The format parameters for the message, may be empty, not - * <code>null</code>. - */ - private void createMainSourceFileMessage(CompilerFiles files, AssemblerProperty property, int severity, - String message, String... parameters) { - if (files == null) { - throw new IllegalArgumentException("Parameter 'files' must not be null."); + return false; + } + if (!files.outputFileExtension.startsWith(".")) { + // ERROR: Output file extension {0} must start with ".". + createMainSourceFileMessage(files, files.outputFileExtensionProperty, IMarker.SEVERITY_ERROR, + Texts.MESSAGE_E139, files.outputFileExtension); + return false; + } + + if (StringUtility.isEmpty(files.outputFolderMode)) { + // ERROR: Output folder mode be set in the preferences of + // compiler '{0}' or via the annotation '{1}'. + createMainSourceFileMessage(files, files.outputFolderModeProperty, IMarker.SEVERITY_ERROR, + Texts.MESSAGE_E140, compilerDefinition.getName(), AssemblerProperties.OUTPUT_FOLDER_MODE); + + return false; + } + if (!CompilerOutputFolderMode.isDefined(files.outputFolderMode)) { + // ERROR: Unknown output folder mode {0}. Specify one of the + // following valid values '{1}'. + createMainSourceFileMessage(files, files.outputFolderModeProperty, IMarker.SEVERITY_ERROR, + Texts.MESSAGE_E141, files.outputFolderMode, CompilerOutputFolderMode.getAllowedValues()); + return false; + + } + + return true; } - IMarker marker = MarkerUtility.createMarker(files.mainSourceFile.iFile, (property == null ? 0 - : property.lineNumber), severity, message, parameters); - MarkerUtility.gotoMarker(assemblerEditor, marker); - } + /** + * Creates a message associated with the main source file of an + * {@link AssemblerEditorFilesLogic} instance. The message is is bound to the + * line number number of the property (if available). Also the editor is + * position to the marker. + * + * @param files The {@link AssemblerEditorFilesLogic} not + * <code>null</code>. + * @param property The assembler editor property to which the message belongs + * or <code>null</code>. + * @param severity The message severity, see {@link IMarker#SEVERITY} + * @param message The message, may contain parameter "{0}" to "{9}". May be + * empty, not <code>null</code>. + * @param parameters The format parameters for the message, may be empty, not + * <code>null</code>. + */ + private void createMainSourceFileMessage(CompilerFiles files, AssemblerProperty property, int severity, + String message, String... parameters) { + if (files == null) { + throw new IllegalArgumentException("Parameter 'files' must not be null."); + } + IMarker marker = MarkerUtility.createMarker(files.mainSourceFile.iFile, + (property == null ? 0 : property.lineNumber), severity, message, parameters); + MarkerUtility.gotoMarker(assemblerEditor, marker); + + } } \ No newline at end of file diff --git a/com.wudsn.ide.asm/src/com/wudsn/ide/asm/preferences/CompilerPreferences.java b/com.wudsn.ide.asm/src/com/wudsn/ide/asm/preferences/CompilerPreferences.java index d034e791..bd1b3829 100644 --- a/com.wudsn.ide.asm/src/com/wudsn/ide/asm/preferences/CompilerPreferences.java +++ b/com.wudsn.ide.asm/src/com/wudsn/ide/asm/preferences/CompilerPreferences.java @@ -33,214 +33,208 @@ import com.wudsn.ide.base.common.StringUtility; */ public final class CompilerPreferences { - private AssemblerPreferences assemblerPreferences; - private Hardware hardware; - private String compilerId; + private AssemblerPreferences assemblerPreferences; + private Hardware hardware; + private String compilerId; - CompilerPreferences(AssemblerPreferences assemblerPreferences, String compilerId, Hardware hardware) { - if (assemblerPreferences == null) { - throw new IllegalArgumentException("Parameter 'assemblerPreferences' must not be null."); + CompilerPreferences(AssemblerPreferences assemblerPreferences, String compilerId, Hardware hardware) { + if (assemblerPreferences == null) { + throw new IllegalArgumentException("Parameter 'assemblerPreferences' must not be null."); + } + if (compilerId == null) { + throw new IllegalArgumentException("Parameter 'compilerId' must not be null."); + } + if (StringUtility.isEmpty(compilerId)) { + throw new IllegalArgumentException("Parameter 'compilerId' must not be empty."); + } + if (hardware == null) { + throw new IllegalArgumentException("Parameter 'hardware' must not be null."); + } + this.assemblerPreferences = assemblerPreferences; + this.compilerId = compilerId; + this.hardware = hardware; } - if (compilerId == null) { - throw new IllegalArgumentException("Parameter 'compilerId' must not be null."); + /** + * Gets the compiler id of the compiler. + * + * @return The compiler id of the compiler, not empty and not <code>null</code>. + */ + public String getCompilerId() { + return compilerId; } - if (StringUtility.isEmpty(compilerId)) { - throw new IllegalArgumentException("Parameter 'compilerId' must not be empty."); + + /** + * Gets the hardware for which the compiler is invoked. + * + * @return The hardware, not <code>null</code>. + * + * @since 1.6.1 + */ + public Hardware getHardware() { + return hardware; } - if (hardware == null) { - throw new IllegalArgumentException("Parameter 'hardware' must not be null."); + + /** + * Gets the CPU for which the instructions shall be active. + * + * @return The CPU, not <code>null</code>. + * + * @since 1.6.1 + */ + public CPU getCPU() { + CPU result; + String cpuString = assemblerPreferences + .getString(AssemblerPreferencesConstants.getCompilerCPUName(compilerId, hardware)); + + if (StringUtility.isEmpty(cpuString)) { + result = CPU.MOS6502; + } else { + result = CPU.valueOf(cpuString); + } + return result; } - this.assemblerPreferences = assemblerPreferences; - this.compilerId = compilerId; - this.hardware = hardware; - } - /** - * Gets the compiler id of the compiler. - * - * @return The compiler id of the compiler, not empty and not - * <code>null</code>. - */ - public String getCompilerId() { - return compilerId; - } - - /** - * Gets the hardware for which the compiler is invoked. - * - * @return The hardware, not <code>null</code>. - * - * @since 1.6.1 - */ - public Hardware getHardware() { - return hardware; - } - - /** - * Gets the CPU for which the instructions shall be active. - * - * @return The CPU, not <code>null</code>. - * - * @since 1.6.1 - */ - public CPU getCPU() { - CPU result; - String cpuString = assemblerPreferences.getString(AssemblerPreferencesConstants.getCompilerCPUName(compilerId, - hardware)); - - if (StringUtility.isEmpty(cpuString)) { - result = CPU.MOS6502; - } else { - result = CPU.valueOf(cpuString); + /** + * Determines if illegal opcodes shall be highlighted and proposed. + * + * @return <code>true</code> if yet, <code>false</code> otherwise. + */ + @Deprecated + public boolean isIllegalOpcodesVisible() { + return getCPU() == CPU.MOS6502_ILLEGAL; } - return result; - } - /** - * Determines if illegal opcodes shall be highlighted and proposed. - * - * @return <code>true</code> if yet, <code>false</code> otherwise. - */ - @Deprecated - public boolean isIllegalOpcodesVisible() { - return getCPU() == CPU.MOS6502_ILLEGAL; - } - - /** - * Determines if W65816 opcodes shall be highlighted and proposed. - * - * @return <code>true</code> if yet, <code>false</code> otherwise. - */ - @Deprecated - public boolean isW65816OpcodesVisible() { - return getCPU() == CPU.MOS65816; - } - - /** - * Gets the parameters for the compiler. - * - * @return The parameters path for the compiler, may be empty, not - * <code>null</code>. - */ - public String getParameters() { - return assemblerPreferences.getString(AssemblerPreferencesConstants.getCompilerParametersName(compilerId, - hardware)); - } - - /** - * Gets the output folder mode for the compiler. - * - * @return The output folder mode for the compiler, see - * {@link CompilerOutputFolderMode}, may be empty, not - * <code>null</code>. - */ - public String getOutputFolderMode() { - - return assemblerPreferences.getString(AssemblerPreferencesConstants.getCompilerOutputFolderModeName(compilerId, - hardware)); - } - - /** - * Gets the output folder for the compiler in case the output folder mode is - * {@link CompilerOutputFolderMode#FIXED_FOLDER}. - * - * @return The output folder mode for the compiler, see - * {@link CompilerOutputFolderMode#FIXED_FOLDER}, may be empty, not - * <code>null</code>. - */ - public String getOutputFolderPath() { - - return assemblerPreferences.getString(AssemblerPreferencesConstants.getCompilerOutputFolderPathName(compilerId, - hardware)); - } - - /** - * Gets the output file extension for the compiler. - * - * @return The output file extension may be empty, not <code>null</code>. - */ - public String getOutputFileExtension() { - - return assemblerPreferences.getString(AssemblerPreferencesConstants.getCompilerOutputFileExtensionName( - compilerId, hardware)); - } - - /** - * Gets the id of the default runner to run the output file. - * - * @return The id of the runner to run the output file, not empty and not - * <code>null</code>. - */ - public String getRunnerId() { - String result = assemblerPreferences.getString(AssemblerPreferencesConstants.getCompilerRunnerIdName( - compilerId, hardware)); - if (StringUtility.isEmpty(result)) { - result = RunnerId.DEFAULT_APPLICATION; + /** + * Determines if W65816 opcodes shall be highlighted and proposed. + * + * @return <code>true</code> if yet, <code>false</code> otherwise. + */ + @Deprecated + public boolean isW65816OpcodesVisible() { + return getCPU() == CPU.MOS65816; } - return result; - } - /** - * Gets the executable path for the runner. - * - * @param runnerId - * The runner id, not empty and not <code>null</code>. - * - * @return The executable path for the runner, may be empty, not - * <code>null</code>. - */ - public String getRunnerExecutablePath(String runnerId) { - if (runnerId == null) { - throw new IllegalArgumentException("Parameter 'runnerId' must not be null."); + /** + * Gets the parameters for the compiler. + * + * @return The parameters path for the compiler, may be empty, not + * <code>null</code>. + */ + public String getParameters() { + return assemblerPreferences + .getString(AssemblerPreferencesConstants.getCompilerParametersName(compilerId, hardware)); } - if (StringUtility.isEmpty(runnerId)) { - throw new IllegalArgumentException("Parameter 'runnerId' must not be empty."); - } - return assemblerPreferences.getString(AssemblerPreferencesConstants.getCompilerRunnerExecutablePathName( - compilerId, hardware, runnerId)); - } - /** - * Gets the parameters for the runner. - * - * @param runnerId - * The runner id, not empty and not <code>null</code>. - * - * @return The parameters for the runner, may be empty, not - * <code>null</code>. - */ - public String getRunnerCommandLine(String runnerId) { - if (runnerId == null) { - throw new IllegalArgumentException("Parameter 'runnerId' must not be null."); - } - if (StringUtility.isEmpty(runnerId)) { - throw new IllegalArgumentException("Parameter 'runnerId' must not be empty."); - } - return assemblerPreferences.getString(AssemblerPreferencesConstants.getCompilerRunnerCommandLineName( - compilerId, hardware, runnerId)); - } + /** + * Gets the output folder mode for the compiler. + * + * @return The output folder mode for the compiler, see + * {@link CompilerOutputFolderMode}, may be empty, not + * <code>null</code>. + */ + public String getOutputFolderMode() { - /** - * Gets the wait for completion indicator for the runner. - * - * @param runnerId - * The runner id, not empty and not <code>null</code>. - * - * @return <code>true</code>if waiting for completion is requested, - * <code>false</code> otherwise. - * - * @since 1.6.1 - */ - public boolean isRunnerWaitForCompletion(String runnerId) { - if (runnerId == null) { - throw new IllegalArgumentException("Parameter 'runnerId' must not be null."); + return assemblerPreferences + .getString(AssemblerPreferencesConstants.getCompilerOutputFolderModeName(compilerId, hardware)); } - if (StringUtility.isEmpty(runnerId)) { - throw new IllegalArgumentException("Parameter 'runnerId' must not be empty."); + + /** + * Gets the output folder for the compiler in case the output folder mode is + * {@link CompilerOutputFolderMode#FIXED_FOLDER}. + * + * @return The output folder mode for the compiler, see + * {@link CompilerOutputFolderMode#FIXED_FOLDER}, may be empty, not + * <code>null</code>. + */ + public String getOutputFolderPath() { + + return assemblerPreferences + .getString(AssemblerPreferencesConstants.getCompilerOutputFolderPathName(compilerId, hardware)); + } + + /** + * Gets the output file extension for the compiler. + * + * @return The output file extension may be empty, not <code>null</code>. + */ + public String getOutputFileExtension() { + + return assemblerPreferences + .getString(AssemblerPreferencesConstants.getCompilerOutputFileExtensionName(compilerId, hardware)); + } + + /** + * Gets the id of the default runner to run the output file. + * + * @return The id of the runner to run the output file, not empty and not + * <code>null</code>. + */ + public String getRunnerId() { + String result = assemblerPreferences + .getString(AssemblerPreferencesConstants.getCompilerRunnerIdName(compilerId, hardware)); + if (StringUtility.isEmpty(result)) { + result = RunnerId.DEFAULT_APPLICATION; + } + return result; + } + + /** + * Gets the executable path for the runner. + * + * @param runnerId The runner id, not empty and not <code>null</code>. + * + * @return The executable path for the runner, may be empty, not + * <code>null</code>. + */ + public String getRunnerExecutablePath(String runnerId) { + if (runnerId == null) { + throw new IllegalArgumentException("Parameter 'runnerId' must not be null."); + } + if (StringUtility.isEmpty(runnerId)) { + throw new IllegalArgumentException("Parameter 'runnerId' must not be empty."); + } + return assemblerPreferences.getString( + AssemblerPreferencesConstants.getCompilerRunnerExecutablePathName(compilerId, hardware, runnerId)); + } + + /** + * Gets the parameters for the runner. + * + * @param runnerId The runner id, not empty and not <code>null</code>. + * + * @return The parameters for the runner, may be empty, not <code>null</code>. + */ + public String getRunnerCommandLine(String runnerId) { + if (runnerId == null) { + throw new IllegalArgumentException("Parameter 'runnerId' must not be null."); + } + if (StringUtility.isEmpty(runnerId)) { + throw new IllegalArgumentException("Parameter 'runnerId' must not be empty."); + } + return assemblerPreferences.getString( + AssemblerPreferencesConstants.getCompilerRunnerCommandLineName(compilerId, hardware, runnerId)); + } + + /** + * Gets the wait for completion indicator for the runner. + * + * @param runnerId The runner id, not empty and not <code>null</code>. + * + * @return <code>true</code>if waiting for completion is requested, + * <code>false</code> otherwise. + * + * @since 1.6.1 + */ + public boolean isRunnerWaitForCompletion(String runnerId) { + if (runnerId == null) { + throw new IllegalArgumentException("Parameter 'runnerId' must not be null."); + } + if (StringUtility.isEmpty(runnerId)) { + throw new IllegalArgumentException("Parameter 'runnerId' must not be empty."); + } + return assemblerPreferences.getBoolean( + AssemblerPreferencesConstants.getCompilerRunnerWaitForCompletionName(compilerId, hardware, runnerId)); } - return assemblerPreferences.getBoolean(AssemblerPreferencesConstants.getCompilerRunnerWaitForCompletionName( - compilerId, hardware, runnerId)); - } } diff --git a/com.wudsn.ide.hex/.classpath b/com.wudsn.ide.hex/.classpath index 0745e339..11e092e1 100644 --- a/com.wudsn.ide.hex/.classpath +++ b/com.wudsn.ide.hex/.classpath @@ -1,8 +1,11 @@ <?xml version="1.0" encoding="UTF-8"?> <classpath> - <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/> - <classpathentry kind="src" path="src"/> - <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/> - <classpathentry combineaccessrules="false" kind="src" path="/com.wudsn.ide.base"/> - <classpathentry kind="output" path="bin"/> + <classpathentry kind="con" + path="org.eclipse.pde.core.requiredPlugins" /> + <classpathentry kind="src" path="src" /> + <classpathentry kind="con" + path="org.eclipse.jdt.launching.JRE_CONTAINER" /> + <classpathentry combineaccessrules="false" kind="src" + path="/com.wudsn.ide.base" /> + <classpathentry kind="output" path="bin" /> </classpath> diff --git a/com.wudsn.ide.hex/src/com/wudsn/ide/hex/FileContent.java b/com.wudsn.ide.hex/src/com/wudsn/ide/hex/FileContent.java index 698e5e7a..e5bfca11 100644 --- a/com.wudsn.ide.hex/src/com/wudsn/ide/hex/FileContent.java +++ b/com.wudsn.ide.hex/src/com/wudsn/ide/hex/FileContent.java @@ -2,46 +2,42 @@ package com.wudsn.ide.hex; public interface FileContent { - /** - * Gets the length of the file content. - * - * @return The length of the file content, a non-negative integer. - */ - public int getLength(); + /** + * Gets the length of the file content. + * + * @return The length of the file content, a non-negative integer. + */ + public int getLength(); - /** - * Gets a byte (8 bit) from the file content. - * - * @param offset - * The offset, a non-negative integer. - * @return The byte from the file content. - */ - public int getByte(long offset); + /** + * Gets a byte (8 bit) from the file content. + * + * @param offset The offset, a non-negative integer. + * @return The byte from the file content. + */ + public int getByte(long offset); - /** - * 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. - */ - public int getWord(long offset); + /** + * 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. + */ + public int getWord(long offset); - /** - * 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. - */ - public int getWordBigEndian(long offset); + /** + * 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. + */ + public int getWordBigEndian(long 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. - */ - public long getDoubleWordBigEndian(long 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. + */ + public long getDoubleWordBigEndian(long offset); } diff --git a/com.wudsn.ide.hex/src/com/wudsn/ide/hex/FileContentImpl.java b/com.wudsn.ide.hex/src/com/wudsn/ide/hex/FileContentImpl.java index 31ba06a7..1cfe9c20 100644 --- a/com.wudsn.ide.hex/src/com/wudsn/ide/hex/FileContentImpl.java +++ b/com.wudsn.ide.hex/src/com/wudsn/ide/hex/FileContentImpl.java @@ -1,78 +1,74 @@ package com.wudsn.ide.hex; -public class FileContentImpl implements FileContent{ +public class FileContentImpl implements FileContent { - private byte[] fileContent; + private byte[] fileContent; - public FileContentImpl(byte[] fileContent) { - if (fileContent == null) { - throw new IllegalArgumentException("Parameter 'fileContent' must not be null."); + public FileContentImpl(byte[] fileContent) { + if (fileContent == null) { + throw new IllegalArgumentException("Parameter 'fileContent' must not be null."); + } + this.fileContent = fileContent; } - this.fileContent = fileContent; - } - /** - * Gets the length of the file content. - * - * @return The length of the file content, a non-negative integer. - */ - @Override - public int getLength() { - return fileContent.length; - } - - /** - * Gets a byte (8 bit) from the file content. - * - * @param offset - * The offset, a non-negative integer. - * @return The byte from the file content. - */ - @Override - public int getByte(long offset) { - if (offset < 0) { - throw new IllegalArgumentException("Parameter offset=" + offset + " must not be negative"); + /** + * Gets the length of the file content. + * + * @return The length of the file content, a non-negative integer. + */ + @Override + public int getLength() { + return fileContent.length; } - if (offset >= fileContent.length) { - throw new IllegalArgumentException( - "Parameter offset=" + offset + " must be less than the file content size " + fileContent.length); + + /** + * Gets a byte (8 bit) from the file content. + * + * @param offset The offset, a non-negative integer. + * @return The byte from the file content. + */ + @Override + public int getByte(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] & 0xff; } - return fileContent[(int) offset] & 0xff; - } - /** - * 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. - */ - @Override - public int getWord(long offset) { - return getByte(offset) + 0x100 * getByte(offset + 1); - } + /** + * 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. + */ + @Override + public int getWord(long offset) { + return getByte(offset) + 0x100 * getByte(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. - */ - @Override - public int getWordBigEndian(long offset) { - return getByte(offset + 1) + 0x100 * getByte(offset); - } + /** + * 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. + */ + @Override + public int getWordBigEndian(long offset) { + return getByte(offset + 1) + 0x100 * getByte(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. - */ - @Override - public long getDoubleWordBigEndian(long offset) { - return getWordBigEndian(offset + 2) + 0x10000 * getWordBigEndian(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. + */ + @Override + public long getDoubleWordBigEndian(long offset) { + return getWordBigEndian(offset + 2) + 0x10000 * getWordBigEndian(offset); + } } diff --git a/com.wudsn.ide.hex/src/com/wudsn/ide/hex/HexEditorClipboardCommandHandler.java b/com.wudsn.ide.hex/src/com/wudsn/ide/hex/HexEditorClipboardCommandHandler.java index b45bf29e..2f94c993 100644 --- a/com.wudsn.ide.hex/src/com/wudsn/ide/hex/HexEditorClipboardCommandHandler.java +++ b/com.wudsn.ide.hex/src/com/wudsn/ide/hex/HexEditorClipboardCommandHandler.java @@ -37,147 +37,147 @@ import com.wudsn.ide.base.common.NumberUtility; */ public final class HexEditorClipboardCommandHandler extends HexEditorSelectionCommandHandler { - public static final class CommandIds { + public static final class CommandIds { - private CommandIds() { - } - - public static final String COPY = "com.wudsn.ide.hex.HexEditorCopyToClipboardCommand"; - public static final String COPY_AS_HEX_VALUES = "com.wudsn.ide.hex.HexEditorCopyToClipboardAsHexValuesCommand"; - public static final String COPY_AS_DECIMAL_VALUES = "com.wudsn.ide.hex.HexEditorCopyToClipboardAsDecimalValuesCommand"; - public static final String COPY_AS_DECIMAL_VALUES_BLOCK = "com.wudsn.ide.hex.HexEditorCopyToClipboardAsDecimalValuesBlockCommand"; - public static final String COPY_AS_ASCII_STRING = "com.wudsn.ide.hex.HexEditorCopyToClipboardAsASCIIStringCommand"; - public static final String PASTE = "com.wudsn.ide.hex.HexEditorPasteFromClipboardCommand"; - } - - /** - * Creation is public. Called by extension point "org.eclipse.ui.handlers". - */ - public HexEditorClipboardCommandHandler() { - super(); - } - - @Override - protected void performAction() throws ExecutionException { - - byte[] bytes; - bytes = hexEditorSelection.getBytes(); - StringBuilder builder = new StringBuilder(5 * bytes.length); - String lineSeparator = System.getProperty("line.separator"); - - Object[] data; - Transfer[] transfers; - - int bytesPerRow = hexEditor.getBytesPerRow(); - if (commandId.equals(CommandIds.COPY) && !hexEditorSelection.isEmpty()) { - data = new Object[] { hexEditorSelection }; - transfers = new Transfer[] { HexEditorSelectionTransfer.getInstance() }; - copyToClipboard(bytes, data, transfers); - - } else if ((commandId.equals(CommandIds.COPY_AS_HEX_VALUES) - || commandId.equals(CommandIds.COPY_AS_DECIMAL_VALUES) - || commandId.equals(CommandIds.COPY_AS_DECIMAL_VALUES_BLOCK) - || commandId.equals(CommandIds.COPY_AS_ASCII_STRING)) && !hexEditorSelection.isEmpty()) { - if (commandId.equals(CommandIds.COPY_AS_HEX_VALUES)) { - builder.append(".byte "); - for (int i = 0; i < bytes.length; i++) { - builder.append("$"); - builder.append(HexUtility.getByteValueHexString(bytes[i] & 0xff)); - if ((i + 1) % bytesPerRow == 0) { - builder.append(lineSeparator); - if (i < bytes.length - 1) { - builder.append(".byte "); - } - } else { - if (i < bytes.length - 1) { - builder.append(','); - } - } + private CommandIds() { } - } else if (commandId.equals(CommandIds.COPY_AS_DECIMAL_VALUES) - || commandId.equals(CommandIds.COPY_AS_DECIMAL_VALUES_BLOCK)) { - // In block mode, decimals are aligned to 3 digits. - boolean block = commandId.equals(CommandIds.COPY_AS_DECIMAL_VALUES_BLOCK); - builder.append(".byte "); - for (int i = 0; i < bytes.length; i++) { - int b = bytes[i] & 0xff; - if (block) { - if (b < 10) { - builder.append(" "); - } else if (b < 100) { - builder.append(' '); + + public static final String COPY = "com.wudsn.ide.hex.HexEditorCopyToClipboardCommand"; + public static final String COPY_AS_HEX_VALUES = "com.wudsn.ide.hex.HexEditorCopyToClipboardAsHexValuesCommand"; + public static final String COPY_AS_DECIMAL_VALUES = "com.wudsn.ide.hex.HexEditorCopyToClipboardAsDecimalValuesCommand"; + public static final String COPY_AS_DECIMAL_VALUES_BLOCK = "com.wudsn.ide.hex.HexEditorCopyToClipboardAsDecimalValuesBlockCommand"; + public static final String COPY_AS_ASCII_STRING = "com.wudsn.ide.hex.HexEditorCopyToClipboardAsASCIIStringCommand"; + public static final String PASTE = "com.wudsn.ide.hex.HexEditorPasteFromClipboardCommand"; + } + + /** + * Creation is public. Called by extension point "org.eclipse.ui.handlers". + */ + public HexEditorClipboardCommandHandler() { + super(); + } + + @Override + protected void performAction() throws ExecutionException { + + byte[] bytes; + bytes = hexEditorSelection.getBytes(); + StringBuilder builder = new StringBuilder(5 * bytes.length); + String lineSeparator = System.getProperty("line.separator"); + + Object[] data; + Transfer[] transfers; + + int bytesPerRow = hexEditor.getBytesPerRow(); + if (commandId.equals(CommandIds.COPY) && !hexEditorSelection.isEmpty()) { + data = new Object[] { hexEditorSelection }; + transfers = new Transfer[] { HexEditorSelectionTransfer.getInstance() }; + copyToClipboard(bytes, data, transfers); + + } else if ((commandId.equals(CommandIds.COPY_AS_HEX_VALUES) + || commandId.equals(CommandIds.COPY_AS_DECIMAL_VALUES) + || commandId.equals(CommandIds.COPY_AS_DECIMAL_VALUES_BLOCK) + || commandId.equals(CommandIds.COPY_AS_ASCII_STRING)) && !hexEditorSelection.isEmpty()) { + if (commandId.equals(CommandIds.COPY_AS_HEX_VALUES)) { + builder.append(".byte "); + for (int i = 0; i < bytes.length; i++) { + builder.append("$"); + builder.append(HexUtility.getByteValueHexString(bytes[i] & 0xff)); + if ((i + 1) % bytesPerRow == 0) { + builder.append(lineSeparator); + if (i < bytes.length - 1) { + builder.append(".byte "); + } + } else { + if (i < bytes.length - 1) { + builder.append(','); + } + } + } + } else if (commandId.equals(CommandIds.COPY_AS_DECIMAL_VALUES) + || commandId.equals(CommandIds.COPY_AS_DECIMAL_VALUES_BLOCK)) { + // In block mode, decimals are aligned to 3 digits. + boolean block = commandId.equals(CommandIds.COPY_AS_DECIMAL_VALUES_BLOCK); + builder.append(".byte "); + for (int i = 0; i < bytes.length; i++) { + int b = bytes[i] & 0xff; + if (block) { + if (b < 10) { + builder.append(" "); + } else if (b < 100) { + builder.append(' '); + } + } + builder.append(Integer.toString(b)); + if ((i + 1) % bytesPerRow == 0) { + builder.append(lineSeparator); + if (i < bytes.length - 1) { + builder.append(".byte "); + } + } else { + if (i < bytes.length - 1) { + builder.append(','); + } + } + } + } else if (commandId.equals(CommandIds.COPY_AS_ASCII_STRING)) { + for (int i = 0; i < bytes.length; i++) { + char c = (char) (bytes[i] & 0xff); + builder.append(c); + } + } else { + throw new IllegalArgumentException("Unknown command '" + commandId + "'."); } - } - builder.append(Integer.toString(b)); - if ((i + 1) % bytesPerRow == 0) { - builder.append(lineSeparator); - if (i < bytes.length - 1) { - builder.append(".byte "); - } - } else { - if (i < bytes.length - 1) { - builder.append(','); - } - } + data = new Object[] { builder.toString(), hexEditorSelection }; + transfers = new Transfer[] { TextTransfer.getInstance(), HexEditorSelectionTransfer.getInstance() }; + copyToClipboard(bytes, data, transfers); + + } else if (commandId.equals(CommandIds.PASTE)) { + pasteFromClipboard(); } - } else if (commandId.equals(CommandIds.COPY_AS_ASCII_STRING)) { - for (int i = 0; i < bytes.length; i++) { - char c = (char) (bytes[i] & 0xff); - builder.append(c); + + } + + private void copyToClipboard(byte[] bytes, Object[] data, Transfer[] transfers) throws ExecutionException { + if (bytes == null) { + throw new IllegalArgumentException("Parameter 'bytes' must not be null."); } - } else { - throw new IllegalArgumentException("Unknown command '" + commandId + "'."); - } - data = new Object[] { builder.toString(), hexEditorSelection }; - transfers = new Transfer[] { TextTransfer.getInstance(), HexEditorSelectionTransfer.getInstance() }; - copyToClipboard(bytes, data, transfers); + if (data == null) { + throw new IllegalArgumentException("Parameter 'data' must not be null."); + } + if (transfers == null) { + throw new IllegalArgumentException("Parameter 'transfers' must not be null."); + } + IWorkbenchSite site = HandlerUtil.getActiveSiteChecked(event); + Clipboard clipboard = new Clipboard(site.getShell().getDisplay()); + try { - } else if (commandId.equals(CommandIds.PASTE)) { - pasteFromClipboard(); + clipboard.setContents(data, transfers); + + } finally { + clipboard.dispose(); + } + + // INFO: ${0} ({1}) bytes copied to clipboard. + messageManager.sendMessage(0, IStatus.OK, Texts.MESSAGE_I302, HexUtility.getLongValueHexString(bytes.length), + NumberUtility.getLongValueDecimalString(bytes.length)); } - } + private void pasteFromClipboard() throws ExecutionException { + + IWorkbenchSite site = HandlerUtil.getActiveSiteChecked(event); + Clipboard clipboard = new Clipboard(site.getShell().getDisplay()); + try { + + Object data = clipboard.getContents(HexEditorSelectionTransfer.getInstance()); + if (data != null) { + byte[] bytes = ((HexEditorSelection) data).getBytes(); + hexEditor.pasteFromClipboard(bytes); + + } + } finally { + clipboard.dispose(); + } - private void copyToClipboard(byte[] bytes, Object[] data, Transfer[] transfers) throws ExecutionException { - if (bytes == null) { - throw new IllegalArgumentException("Parameter 'bytes' must not be null."); } - if (data == null) { - throw new IllegalArgumentException("Parameter 'data' must not be null."); - } - if (transfers == null) { - throw new IllegalArgumentException("Parameter 'transfers' must not be null."); - } - IWorkbenchSite site = HandlerUtil.getActiveSiteChecked(event); - Clipboard clipboard = new Clipboard(site.getShell().getDisplay()); - try { - - clipboard.setContents(data, transfers); - - } finally { - clipboard.dispose(); - } - - // INFO: ${0} ({1}) bytes copied to clipboard. - messageManager.sendMessage(0, IStatus.OK, Texts.MESSAGE_I302, HexUtility.getLongValueHexString(bytes.length), - NumberUtility.getLongValueDecimalString(bytes.length)); - } - - private void pasteFromClipboard() throws ExecutionException { - - IWorkbenchSite site = HandlerUtil.getActiveSiteChecked(event); - Clipboard clipboard = new Clipboard(site.getShell().getDisplay()); - try { - - Object data = clipboard.getContents(HexEditorSelectionTransfer.getInstance()); - if (data != null) { - byte[] bytes = ((HexEditorSelection) data).getBytes(); - hexEditor.pasteFromClipboard(bytes); - - } - } finally { - clipboard.dispose(); - } - - } } diff --git a/com.wudsn.ide.hex/src/com/wudsn/ide/hex/HexEditorContentOutlineLabelProvider.java b/com.wudsn.ide.hex/src/com/wudsn/ide/hex/HexEditorContentOutlineLabelProvider.java index 72279c96..da55a554 100644 --- a/com.wudsn.ide.hex/src/com/wudsn/ide/hex/HexEditorContentOutlineLabelProvider.java +++ b/com.wudsn.ide.hex/src/com/wudsn/ide/hex/HexEditorContentOutlineLabelProvider.java @@ -31,50 +31,50 @@ import org.eclipse.swt.graphics.Image; */ final class HexEditorContentOutlineLabelProvider extends DelegatingStyledCellLabelProvider { - /** Outline segment image */ - private final Image segmentImage; + /** Outline segment image */ + private final Image segmentImage; - private static class HexEditorStyledLabelProvider extends LabelProvider implements IStyledLabelProvider { + private static class HexEditorStyledLabelProvider extends LabelProvider implements IStyledLabelProvider { + + /** + * Creation is local. + */ + HexEditorStyledLabelProvider() { + + } + + @Override + public StyledString getStyledText(Object element) { + if (element == null) { + throw new IllegalArgumentException("Parameter 'element' must not be null."); + } + HexEditorContentOutlineTreeObject treeObject; + treeObject = (HexEditorContentOutlineTreeObject) element; + return treeObject.getStyledString(); + } + } /** - * Creation is local. + * Creates a new instance. + * + * Called by + * {@link HexEditorContentOutlinePage#createControl(org.eclipse.swt.widgets.Composite)} + * . */ - HexEditorStyledLabelProvider() { - + HexEditorContentOutlineLabelProvider() { + super(new HexEditorStyledLabelProvider()); + HexPlugin plugin; + plugin = HexPlugin.getInstance(); + segmentImage = plugin.getImage("hex-editor-segment-16x16.gif"); } @Override - public StyledString getStyledText(Object element) { - if (element == null) { - throw new IllegalArgumentException("Parameter 'element' must not be null."); - } - HexEditorContentOutlineTreeObject treeObject; - treeObject = (HexEditorContentOutlineTreeObject) element; - return treeObject.getStyledString(); + public Image getImage(Object element) { + Image result; + + result = segmentImage; + + return result; } - } - - /** - * Creates a new instance. - * - * Called by - * {@link HexEditorContentOutlinePage#createControl(org.eclipse.swt.widgets.Composite)} - * . - */ - HexEditorContentOutlineLabelProvider() { - super(new HexEditorStyledLabelProvider()); - HexPlugin plugin; - plugin = HexPlugin.getInstance(); - segmentImage = plugin.getImage("hex-editor-segment-16x16.gif"); - } - - @Override - public Image getImage(Object element) { - Image result; - - result = segmentImage; - - return result; - } } diff --git a/com.wudsn.ide.hex/src/com/wudsn/ide/hex/HexEditorContentOutlinePage.java b/com.wudsn.ide.hex/src/com/wudsn/ide/hex/HexEditorContentOutlinePage.java index 14fbfb94..d155d6a7 100644 --- a/com.wudsn.ide.hex/src/com/wudsn/ide/hex/HexEditorContentOutlinePage.java +++ b/com.wudsn.ide.hex/src/com/wudsn/ide/hex/HexEditorContentOutlinePage.java @@ -34,52 +34,52 @@ import org.eclipse.ui.views.contentoutline.ContentOutlinePage; */ final class HexEditorContentOutlinePage extends ContentOutlinePage { - private HexEditor editor; - private Object input; + private HexEditor editor; + private Object input; + + HexEditorContentOutlinePage(HexEditor editor) { + if (editor == null) { + throw new IllegalArgumentException("Parameter 'editor' must not be null."); + } + this.editor = editor; - HexEditorContentOutlinePage(HexEditor editor) { - if (editor == null) { - throw new IllegalArgumentException("Parameter 'editor' must not be null."); } - this.editor = editor; - } + @Override + public void createControl(Composite parent) { + super.createControl(parent); - @Override - public void createControl(Composite parent) { - super.createControl(parent); + TreeViewer viewer = getTreeViewer(); + viewer.getControl().setFont(JFaceResources.getTextFont()); + viewer.setContentProvider(new HexEditorContentOutlineTreeContentProvider()); + viewer.setLabelProvider(new HexEditorContentOutlineLabelProvider()); + viewer.addSelectionChangedListener(this); + viewer.setAutoExpandLevel(AbstractTreeViewer.ALL_LEVELS); - TreeViewer viewer = getTreeViewer(); - viewer.getControl().setFont(JFaceResources.getTextFont()); - viewer.setContentProvider(new HexEditorContentOutlineTreeContentProvider()); - viewer.setLabelProvider(new HexEditorContentOutlineLabelProvider()); - viewer.addSelectionChangedListener(this); - viewer.setAutoExpandLevel(AbstractTreeViewer.ALL_LEVELS); - - updateTreeView(); - } - - @Override - public void selectionChanged(SelectionChangedEvent event) { - super.selectionChanged(event); - - ISelection selection = event.getSelection(); - editor.setSelection(selection); - } - - void setInput(Object input) { - if (input == null) { - throw new IllegalArgumentException("Parameter 'input' must not be null."); + updateTreeView(); } - this.input = input; - updateTreeView(); - } - private void updateTreeView() { - TreeViewer viewer = getTreeViewer(); - if (viewer != null) { - viewer.setInput(input); + @Override + public void selectionChanged(SelectionChangedEvent event) { + super.selectionChanged(event); + + ISelection selection = event.getSelection(); + editor.setSelection(selection); + } + + void setInput(Object input) { + if (input == null) { + throw new IllegalArgumentException("Parameter 'input' must not be null."); + } + this.input = input; + updateTreeView(); + } + + private void updateTreeView() { + TreeViewer viewer = getTreeViewer(); + if (viewer != null) { + viewer.setInput(input); + } } - } } diff --git a/com.wudsn.ide.hex/src/com/wudsn/ide/hex/HexEditorContentOutlineTreeContentProvider.java b/com.wudsn.ide.hex/src/com/wudsn/ide/hex/HexEditorContentOutlineTreeContentProvider.java index f016c8a4..3c3650b9 100644 --- a/com.wudsn.ide.hex/src/com/wudsn/ide/hex/HexEditorContentOutlineTreeContentProvider.java +++ b/com.wudsn.ide.hex/src/com/wudsn/ide/hex/HexEditorContentOutlineTreeContentProvider.java @@ -31,63 +31,63 @@ import org.eclipse.jface.viewers.Viewer; */ final class HexEditorContentOutlineTreeContentProvider implements ITreeContentProvider { - HexEditorContentOutlineTreeContentProvider() { - } - - /** - * {@inheritDoc} - */ - @Override - public Object[] getChildren(Object parentElement) { - return null; - } - - /** - * {@inheritDoc} - */ - @Override - public Object getParent(Object element) { - - return null; - } - - /** - * {@inheritDoc} - */ - @Override - public boolean hasChildren(Object element) { - return false; - } - - /** - * {@inheritDoc} - */ - @Override - public Object[] getElements(Object inputElement) { - Object[] result; - if (inputElement instanceof List<?>) { - result = ((List<?>) inputElement).toArray(); - } else { - result = null; + HexEditorContentOutlineTreeContentProvider() { } - return result; - } + /** + * {@inheritDoc} + */ + @Override + public Object[] getChildren(Object parentElement) { + return null; + } - /** - * {@inheritDoc} - */ - @Override - public void dispose() { + /** + * {@inheritDoc} + */ + @Override + public Object getParent(Object element) { - } + return null; + } - /** - * {@inheritDoc} - */ - @Override - public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + /** + * {@inheritDoc} + */ + @Override + public boolean hasChildren(Object element) { + return false; + } - } + /** + * {@inheritDoc} + */ + @Override + public Object[] getElements(Object inputElement) { + Object[] result; + if (inputElement instanceof List<?>) { + result = ((List<?>) inputElement).toArray(); + } else { + result = null; + } + + return result; + } + + /** + * {@inheritDoc} + */ + @Override + public void dispose() { + + } + + /** + * {@inheritDoc} + */ + @Override + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + + } } diff --git a/com.wudsn.ide.hex/src/com/wudsn/ide/hex/HexEditorContentOutlineTreeObject.java b/com.wudsn.ide.hex/src/com/wudsn/ide/hex/HexEditorContentOutlineTreeObject.java index aff4a6b3..13f966d3 100644 --- a/com.wudsn.ide.hex/src/com/wudsn/ide/hex/HexEditorContentOutlineTreeObject.java +++ b/com.wudsn.ide.hex/src/com/wudsn/ide/hex/HexEditorContentOutlineTreeObject.java @@ -28,122 +28,117 @@ import org.eclipse.jface.viewers.StyledString; */ public final class HexEditorContentOutlineTreeObject { - private final StyledString styledString; - private long fileStartOffset; - private long textStartOffset; - private long fileEndOffset; - private long textEndOffset; + private final StyledString styledString; + private long fileStartOffset; + private long textStartOffset; + private long fileEndOffset; + private long textEndOffset; - /** - * Create a new instance. - * - * @param styledString - * The styled string of the instance, may be empty not - * <code>null</code>. - */ - public HexEditorContentOutlineTreeObject(StyledString styledString) { - if (styledString == null) { - throw new IllegalArgumentException("Parameter 'styledString' must not be null."); + /** + * Create a new instance. + * + * @param styledString The styled string of the instance, may be empty not + * <code>null</code>. + */ + public HexEditorContentOutlineTreeObject(StyledString styledString) { + if (styledString == null) { + throw new IllegalArgumentException("Parameter 'styledString' must not be null."); + } + this.styledString = new StyledString().append(styledString); } - this.styledString = new StyledString().append(styledString); - } - /** - * Gets the styled string of the object. - * - * @return The styled string, not <code>null</code>. - */ - public StyledString getStyledString() { - return styledString; - } - - /** - * Gets the start offset of the tree object in the file. - * - * @return The start offset, a non-negative integer. - */ - public long getFileStartOffset() { - return fileStartOffset; - } - - /** - * Sets the start offset of the tree object in the file. - * - * @param fileOffset - * The start offset, a non-negative integer or <code>-1</code> if - * the offset is not defined. - */ - public void setFileStartOffset(long fileOffset) { - - this.fileStartOffset = fileOffset; - } - - /** - * Gets the end offset of the tree object in the file. - * - * @return The end offset, a non-negative integer or <code>-1</code> if the - * offset is not defined. - */ - public long getFileEndOffset() { - return fileEndOffset; - } - - /** - * Sets the end offset of the tree object in the file or <code>-1</code> if - * the offset is not defined. - * - * @param fileOffset - * The end offset, a non-negative integer or <code>-1</code> if - * the offset is not defined. - */ - public void setFileEndOffset(long fileOffset) { - - this.fileEndOffset = fileOffset; - } - - /** - * Gets the start offset of the tree object in the text. - * - * @return The offset, a non-negative integer. - */ - public long getTextStartOffset() { - return textStartOffset; - } - - /** - * Sets text start offset of the tree object in the text - * - * @param textOffset - * The offset, a non-negative integer. - */ - public void setTextStartOffset(long textOffset) { - if (textOffset < 0) { - throw new IllegalArgumentException( - "Parameter 'textOffset' must not be negative. Specified value is " + textOffset + "."); + /** + * Gets the styled string of the object. + * + * @return The styled string, not <code>null</code>. + */ + public StyledString getStyledString() { + return styledString; } - this.textStartOffset = textOffset; - } - /** - * Gets the end offset of the tree object in the text. - * - * @return The offset, a non-negative integer. - */ - public long getTextEndOffset() { - return textEndOffset; - } - - /** - * Sets text end offset of the tree object in the text - * - * @param textOffset - * The offset, a non-negative integer. - */ - public void setTextEndOffset(int textOffset) { - if (textOffset < 0) { - throw new IllegalArgumentException( - "Parameter 'textOffset' must not be negative. Specified value is " + textOffset + "."); + /** + * Gets the start offset of the tree object in the file. + * + * @return The start offset, a non-negative integer. + */ + public long getFileStartOffset() { + return fileStartOffset; + } + + /** + * Sets the start offset of the tree object in the file. + * + * @param fileOffset The start offset, a non-negative integer or <code>-1</code> + * if the offset is not defined. + */ + public void setFileStartOffset(long fileOffset) { + + this.fileStartOffset = fileOffset; + } + + /** + * Gets the end offset of the tree object in the file. + * + * @return The end offset, a non-negative integer or <code>-1</code> if the + * offset is not defined. + */ + public long getFileEndOffset() { + return fileEndOffset; + } + + /** + * Sets the end offset of the tree object in the file or <code>-1</code> if the + * offset is not defined. + * + * @param fileOffset The end offset, a non-negative integer or <code>-1</code> + * if the offset is not defined. + */ + public void setFileEndOffset(long fileOffset) { + + this.fileEndOffset = fileOffset; + } + + /** + * Gets the start offset of the tree object in the text. + * + * @return The offset, a non-negative integer. + */ + public long getTextStartOffset() { + return textStartOffset; + } + + /** + * Sets text start offset of the tree object in the text + * + * @param textOffset The offset, a non-negative integer. + */ + public void setTextStartOffset(long textOffset) { + if (textOffset < 0) { + throw new IllegalArgumentException( + "Parameter 'textOffset' must not be negative. Specified value is " + textOffset + "."); + } + this.textStartOffset = textOffset; + } + + /** + * Gets the end offset of the tree object in the text. + * + * @return The offset, a non-negative integer. + */ + public long getTextEndOffset() { + return textEndOffset; + } + + /** + * Sets text end offset of the tree object in the text + * + * @param textOffset The offset, a non-negative integer. + */ + public void setTextEndOffset(int textOffset) { + if (textOffset < 0) { + throw new IllegalArgumentException( + "Parameter 'textOffset' must not be negative. Specified value is " + textOffset + "."); + } + this.textEndOffset = textOffset; } - this.textEndOffset = textOffset; - } } diff --git a/com.wudsn.ide.hex/src/com/wudsn/ide/hex/HexEditorOpenCommandHandler.java b/com.wudsn.ide.hex/src/com/wudsn/ide/hex/HexEditorOpenCommandHandler.java index 3d5c910b..c483820e 100644 --- a/com.wudsn.ide.hex/src/com/wudsn/ide/hex/HexEditorOpenCommandHandler.java +++ b/com.wudsn.ide.hex/src/com/wudsn/ide/hex/HexEditorOpenCommandHandler.java @@ -28,10 +28,10 @@ import com.wudsn.ide.base.editor.CommonOpenEditorCommandHandler; */ public final class HexEditorOpenCommandHandler extends CommonOpenEditorCommandHandler { - /** - * Creation is public. Called by extension "org.eclipse.ui.popupMenus". - */ - public HexEditorOpenCommandHandler() { - super(HexEditor.ID); - } + /** + * Creation is public. Called by extension "org.eclipse.ui.popupMenus". + */ + public HexEditorOpenCommandHandler() { + super(HexEditor.ID); + } } diff --git a/com.wudsn.ide.hex/src/com/wudsn/ide/hex/HexEditorParser.java b/com.wudsn.ide.hex/src/com/wudsn/ide/hex/HexEditorParser.java index 137dd709..7ffeb75a 100644 --- a/com.wudsn.ide.hex/src/com/wudsn/ide/hex/HexEditorParser.java +++ b/com.wudsn.ide.hex/src/com/wudsn/ide/hex/HexEditorParser.java @@ -28,169 +28,150 @@ import com.wudsn.ide.base.common.TextUtility; public abstract class HexEditorParser { - private HexEditorParserComponent owner; - protected Styler offsetStyler; - protected Styler addressStyler; - protected FileContent fileContent; + private HexEditorParserComponent owner; + protected Styler offsetStyler; + protected Styler addressStyler; + protected FileContent fileContent; - /** - * Creation is protected. - */ - protected HexEditorParser() { - - } - - /** - * Initialized by owner. - * - * @param owner - * The owner, not <code>null</code>. - * @param offsetStyler - * The offset styler, not <code>null</code>. - * @param addressStyler - * The address styler, not <code>null</code>. - */ - void init(HexEditorParserComponent owner, Styler offsetStyler, Styler addressStyler) { - if (owner == null) { - throw new IllegalArgumentException("Parameter 'owner' must not be null."); - } - if (offsetStyler == null) { - throw new IllegalArgumentException("Parameter 'offsetStyler' must not be null."); - } - if (addressStyler == null) { - throw new IllegalArgumentException("Parameter 'offsetStyler' must not be null."); - } - this.owner = owner; - this.offsetStyler = offsetStyler; - this.addressStyler = addressStyler; - this.fileContent = owner.getFileContent(); - } - - /** - * Public API for parsing. - * - * @param contentBuilder - * The content builder, not <code>null</code>. - * @return <code>true</code> if parsing was OK, <code>false</code>otherwise. - */ - public abstract boolean parse(StyledString contentBuilder); - - /** - * Prints a block header in the context area and adds a block to the - * outline. - * - * @param contentBuilder - * The content builder, not <code>null</code>. - * @param blockHeaderText - * The header text for the block, may be empty, not - * <code>null</code>. - * @param blockHeaderNumber - * The block count or <code>-1</code> if count shall not be - * displayed. - * @param blockHeaderParameterText - * The pattern text of the form "{0}-{1} ({2})" - * @param offset - * The start offset, a non-negative integer. - * @param startAddress - * The start address, a non-negative integer. - * @param endAddress - * The end address, a non-negative integer. - * - * @return The tree object representing the block. - */ - protected final HexEditorContentOutlineTreeObject printBlockHeader(StyledString contentBuilder, - String blockHeaderText, int blockHeaderNumber, String blockHeaderParameterText, long offset, - long startAddress, long endAddress) { - - if (contentBuilder == null) { - throw new IllegalArgumentException("Parameter 'contentBuilder' must not be null."); - } - long blockLength = endAddress - startAddress + 1; - String blockHeaderNumberText; - if (blockHeaderNumber >= 0) { - blockHeaderNumberText = NumberUtility.getLongValueDecimalString(blockHeaderNumber); - } else { - blockHeaderNumberText = ""; - } - int length = Math.max(4, HexUtility.getLongValueHexLength(endAddress)); - String hexText = TextUtility.format(blockHeaderParameterText, - HexUtility.getLongValueHexString(startAddress, length), - HexUtility.getLongValueHexString(endAddress, length), - HexUtility.getLongValueHexString(blockLength, length)); - - String decimalText = TextUtility.format(blockHeaderParameterText, - NumberUtility.getLongValueDecimalString(startAddress), - NumberUtility.getLongValueDecimalString(endAddress), - NumberUtility.getLongValueDecimalString(blockLength)); - - StyledString styledString; - styledString = new StyledString(); - styledString.append(blockHeaderText, offsetStyler); - if (blockHeaderNumber >= 0) { - styledString.append(" "); - styledString.append(blockHeaderNumberText, offsetStyler); + /** + * Creation is protected. + */ + protected HexEditorParser() { } - if (StringUtility.isSpecified(blockHeaderParameterText)) { - styledString.append(" : "); - styledString.append(hexText, addressStyler); - styledString.append(" : "); - styledString.append(decimalText); + + /** + * Initialized by owner. + * + * @param owner The owner, not <code>null</code>. + * @param offsetStyler The offset styler, not <code>null</code>. + * @param addressStyler The address styler, not <code>null</code>. + */ + void init(HexEditorParserComponent owner, Styler offsetStyler, Styler addressStyler) { + if (owner == null) { + throw new IllegalArgumentException("Parameter 'owner' must not be null."); + } + if (offsetStyler == null) { + throw new IllegalArgumentException("Parameter 'offsetStyler' must not be null."); + } + if (addressStyler == null) { + throw new IllegalArgumentException("Parameter 'offsetStyler' must not be null."); + } + this.owner = owner; + this.offsetStyler = offsetStyler; + this.addressStyler = addressStyler; + this.fileContent = owner.getFileContent(); } - contentBuilder.append(blockHeaderText, offsetStyler); - if (blockHeaderNumber >= 0) { - contentBuilder.append(" "); - contentBuilder.append(blockHeaderNumberText, offsetStyler); + /** + * Public API for parsing. + * + * @param contentBuilder The content builder, not <code>null</code>. + * @return <code>true</code> if parsing was OK, <code>false</code>otherwise. + */ + public abstract boolean parse(StyledString contentBuilder); + + /** + * Prints a block header in the context area and adds a block to the outline. + * + * @param contentBuilder The content builder, not <code>null</code>. + * @param blockHeaderText The header text for the block, may be empty, + * not <code>null</code>. + * @param blockHeaderNumber The block count or <code>-1</code> if count + * shall not be displayed. + * @param blockHeaderParameterText The pattern text of the form "{0}-{1} ({2})" + * @param offset The start offset, a non-negative integer. + * @param startAddress The start address, a non-negative integer. + * @param endAddress The end address, a non-negative integer. + * + * @return The tree object representing the block. + */ + protected final HexEditorContentOutlineTreeObject printBlockHeader(StyledString contentBuilder, + String blockHeaderText, int blockHeaderNumber, String blockHeaderParameterText, long offset, + long startAddress, long endAddress) { + + if (contentBuilder == null) { + throw new IllegalArgumentException("Parameter 'contentBuilder' must not be null."); + } + long blockLength = endAddress - startAddress + 1; + String blockHeaderNumberText; + if (blockHeaderNumber >= 0) { + blockHeaderNumberText = NumberUtility.getLongValueDecimalString(blockHeaderNumber); + } else { + blockHeaderNumberText = ""; + } + int length = Math.max(4, HexUtility.getLongValueHexLength(endAddress)); + String hexText = TextUtility.format(blockHeaderParameterText, + HexUtility.getLongValueHexString(startAddress, length), + HexUtility.getLongValueHexString(endAddress, length), + HexUtility.getLongValueHexString(blockLength, length)); + + String decimalText = TextUtility.format(blockHeaderParameterText, + NumberUtility.getLongValueDecimalString(startAddress), + NumberUtility.getLongValueDecimalString(endAddress), + NumberUtility.getLongValueDecimalString(blockLength)); + + StyledString styledString; + styledString = new StyledString(); + styledString.append(blockHeaderText, offsetStyler); + if (blockHeaderNumber >= 0) { + styledString.append(" "); + styledString.append(blockHeaderNumberText, offsetStyler); + + } + if (StringUtility.isSpecified(blockHeaderParameterText)) { + styledString.append(" : "); + styledString.append(hexText, addressStyler); + styledString.append(" : "); + styledString.append(decimalText); + } + + contentBuilder.append(blockHeaderText, offsetStyler); + if (blockHeaderNumber >= 0) { + contentBuilder.append(" "); + contentBuilder.append(blockHeaderNumberText, offsetStyler); + } + contentBuilder.append("\n"); + return owner.printBlockHeader(contentBuilder, styledString, offset); } - contentBuilder.append("\n"); - return owner.printBlockHeader(contentBuilder, styledString, offset); - } - /** - * Adds a block to the outline. - * - * @param contentBuilder - * The content builder, not <code>null</code>. - * @param headerStyledString - * The style string for the block header in the outline, not - * <code>null</code>. - * @param offset - * The start offset, a non-negative integer. - * - * @return The tree object representing the block. - */ - protected final HexEditorContentOutlineTreeObject printBlockHeader(StyledString contentBuilder, - StyledString headerStyledString, long offset) { - return owner.printBlockHeader(contentBuilder, headerStyledString, offset); - } + /** + * Adds a block to the outline. + * + * @param contentBuilder The content builder, not <code>null</code>. + * @param headerStyledString The style string for the block header in the + * outline, not <code>null</code>. + * @param offset The start offset, a non-negative integer. + * + * @return The tree object representing the block. + */ + protected final HexEditorContentOutlineTreeObject printBlockHeader(StyledString contentBuilder, + StyledString headerStyledString, long offset) { + return owner.printBlockHeader(contentBuilder, headerStyledString, offset); + } - /** - * Prints the last block in case if contains an error like the wrong number - * of bytes. - * - * @param contentBuilder - * The content builder, not <code>null</code>. - * @param errorText - * The error text, not empty and not <code>null</code>. - * @param length - * The length of the last block, a non-negative integer. - * @param offset - * The offset of the last block, a non-negative integer. - */ - protected final void printBlockWithError(StyledString contentBuilder, String errorText, long length, long offset) { - owner.printBlockWithError(contentBuilder, errorText, length, offset); - } + /** + * Prints the last block in case if contains an error like the wrong number of + * bytes. + * + * @param contentBuilder The content builder, not <code>null</code>. + * @param errorText The error text, not empty and not <code>null</code>. + * @param length The length of the last block, a non-negative integer. + * @param offset The offset of the last block, a non-negative integer. + */ + protected final void printBlockWithError(StyledString contentBuilder, String errorText, long length, long offset) { + owner.printBlockWithError(contentBuilder, errorText, length, offset); + } - protected final void skipByteTextIndex(long offset) { - owner.skipByteTextIndex(offset); + protected final void skipByteTextIndex(long offset) { + owner.skipByteTextIndex(offset); - } + } - 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); + 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); - } + } } \ No newline at end of file diff --git a/com.wudsn.ide.hex/src/com/wudsn/ide/hex/HexEditorParserComponent.java b/com.wudsn.ide.hex/src/com/wudsn/ide/hex/HexEditorParserComponent.java index 72726a29..75d5ff3b 100644 --- a/com.wudsn.ide.hex/src/com/wudsn/ide/hex/HexEditorParserComponent.java +++ b/com.wudsn.ide.hex/src/com/wudsn/ide/hex/HexEditorParserComponent.java @@ -44,630 +44,614 @@ import com.wudsn.ide.hex.parser.AtariSDXParser; final class HexEditorParserComponent { - public static final long UNDEFINED_OFFSET = -1; - private final static int BYTES_PER_ROW = 16; + public static final long UNDEFINED_OFFSET = -1; + private final static int BYTES_PER_ROW = 16; - // Callback API. - private MessageManager messageManager; + // Callback API. + private MessageManager messageManager; - // Style components. - private Styler offsetStyler; - private Styler addressStyler; - private Styler charStyler; - private Styler errorStyler; + // Style components. + private Styler offsetStyler; + private Styler addressStyler; + private Styler charStyler; + private Styler errorStyler; - // File content and state. - private boolean fileContentParsed; - private HexEditorFileContentMode fileContentMode; - private byte[] fileContent; - private int bytesPerRow; - private HardwareCharacterSet characterSet; + // File content and state. + private boolean fileContentParsed; + private HexEditorFileContentMode fileContentMode; + private byte[] fileContent; + private int bytesPerRow; + private HardwareCharacterSet characterSet; - // Previous state with regards to parsing. - private HexEditorFileContentMode oldFileContentMode; - private byte[] oldFileContent; - private int oldBytesPerRow; - private HardwareCharacterSet oldCharacterSet; + // Previous state with regards to parsing. + private HexEditorFileContentMode oldFileContentMode; + private byte[] oldFileContent; + private int oldBytesPerRow; + private HardwareCharacterSet oldCharacterSet; - // Parsing state. - private List<HexEditorFileContentMode> possibleFileContentModes; - private List<HexEditorContentOutlineTreeObject> outlineBlocks; - private long[] byteTextOffsets; - private int byteTextIndex; + // Parsing state. + private List<HexEditorFileContentMode> possibleFileContentModes; + private List<HexEditorContentOutlineTreeObject> outlineBlocks; + private long[] byteTextOffsets; + private int byteTextIndex; - // Line buffers for binary to hex and char conversion. - private char[] hexChars; - private char[] hexBuffer; - private char[] charBuffer; + // Line buffers for binary to hex and char conversion. + private char[] hexChars; + private char[] hexBuffer; + private char[] charBuffer; - public HexEditorParserComponent(MessageManager messageManager) { - if (messageManager == null) { - throw new IllegalArgumentException("Parameter 'messageManager' must not be null."); - } - this.messageManager = messageManager; + public HexEditorParserComponent(MessageManager messageManager) { + if (messageManager == null) { + throw new IllegalArgumentException("Parameter 'messageManager' must not be null."); + } + this.messageManager = messageManager; - // Get static stylers for the styled string. - offsetStyler = StyledString.createColorRegistryStyler(JFacePreferences.COUNTER_COLOR, null); - addressStyler = StyledString.createColorRegistryStyler(JFacePreferences.QUALIFIER_COLOR, null); - charStyler = StyledString.createColorRegistryStyler(JFacePreferences.HYPERLINK_COLOR, null); + // Get static stylers for the styled string. + offsetStyler = StyledString.createColorRegistryStyler(JFacePreferences.COUNTER_COLOR, null); + addressStyler = StyledString.createColorRegistryStyler(JFacePreferences.QUALIFIER_COLOR, null); + charStyler = StyledString.createColorRegistryStyler(JFacePreferences.HYPERLINK_COLOR, null); - charStyler = new Styler() { + charStyler = new Styler() { - @Override - public void applyStyles(TextStyle textStyle) { - textStyle.font = null; + @Override + public void applyStyles(TextStyle textStyle) { + textStyle.font = null; - } - - }; - - errorStyler = StyledString.createColorRegistryStyler(JFacePreferences.ERROR_COLOR, null); - - // Initialize hex chars and normal character set type. - hexChars = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; - characterSet = HardwareCharacterSet.ASCII; - - clear(); - - } - - private void clear() { - // Initialize with empty file. - fileContentParsed = false; - fileContentMode = HexEditorFileContentMode.BINARY; - setFileContent(new byte[0]); - characterSet = HardwareCharacterSet.ASCII; - bytesPerRow = BYTES_PER_ROW; - - oldFileContentMode = null; - oldFileContent = null; - oldCharacterSet = null; - oldBytesPerRow = 0; - - possibleFileContentModes = new ArrayList<HexEditorFileContentMode>(); - outlineBlocks = new ArrayList<HexEditorContentOutlineTreeObject>(); - } - - public void setFileContent(byte[] fileContent) { - if (fileContent == null) { - throw new IllegalArgumentException("Parameter 'fileContent' must not be null."); - } - this.fileContent = fileContent; - initByteTextOffsets(); - } - - /** - * Reserve enough space for the lookup table that maps text offsets to file - * offsets. - */ - private void initByteTextOffsets() { - // Twice the space, because some formats display the content twice, for - // example ATARI_DISK_IMAGE_K_FILE. - byteTextOffsets = new long[fileContent.length * 2]; - Arrays.fill(byteTextOffsets, -1); - byteTextIndex = 0; - } - - /** - * Determines the possible file content modes based on the file content. - * - * @return The suggested default file content mode, not <code>null</code>. - */ - public HexEditorFileContentMode determinePossibleFileContentModes() { - - HexEditorFileContentMode result = HexEditorFileContentMode.BINARY; - possibleFileContentModes.clear(); - possibleFileContentModes.add(fileContentMode); - - HexEditorFileContentMode defaultMode = result; - FileContent fileContent = getFileContent(); - // COM header present? - if (fileContent.getLength() > 6) { - // AtariDOS COM file? - if (fileContent.getWord(0) == AtariParser.COM_HEADER) { - int startAddress = fileContent.getWord(2); - int endAddress = fileContent.getWord(4); - if (startAddress >= 0 && endAddress >= startAddress) { - defaultMode = HexEditorFileContentMode.ATARI_COM_FILE; - possibleFileContentModes.add(defaultMode); - - if (fileContent.getLength() > 16) { - if (fileContent.getWord(6) == AtariMADSParser.RELOC_HEADER) { - defaultMode = HexEditorFileContentMode.ATARI_MADS_FILE; - possibleFileContentModes.add(defaultMode); } - } - // New default? - if (result.equals(HexEditorFileContentMode.BINARY)) { - result = defaultMode; - } + + }; + + errorStyler = StyledString.createColorRegistryStyler(JFacePreferences.ERROR_COLOR, null); + + // Initialize hex chars and normal character set type. + hexChars = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; + characterSet = HardwareCharacterSet.ASCII; + + clear(); + + } + + private void clear() { + // Initialize with empty file. + fileContentParsed = false; + fileContentMode = HexEditorFileContentMode.BINARY; + setFileContent(new byte[0]); + characterSet = HardwareCharacterSet.ASCII; + bytesPerRow = BYTES_PER_ROW; + + oldFileContentMode = null; + oldFileContent = null; + oldCharacterSet = null; + oldBytesPerRow = 0; + + possibleFileContentModes = new ArrayList<HexEditorFileContentMode>(); + outlineBlocks = new ArrayList<HexEditorContentOutlineTreeObject>(); + } + + public void setFileContent(byte[] fileContent) { + if (fileContent == null) { + throw new IllegalArgumentException("Parameter 'fileContent' must not be null."); } - } // SpartaDOS X non relocatable file? - else if (fileContent.getWord(0) == AtariSDXParser.NON_RELOC_HEADER) { - int startAddress = fileContent.getWord(2); - int endAddress = fileContent.getWord(4); - if (startAddress > 0 && endAddress >= startAddress) { - defaultMode = HexEditorFileContentMode.ATARI_SDX_FILE; - possibleFileContentModes.add(defaultMode); - // New default? - if (result.equals(HexEditorFileContentMode.BINARY)) { - result = defaultMode; - } + this.fileContent = fileContent; + initByteTextOffsets(); + } + + /** + * Reserve enough space for the lookup table that maps text offsets to file + * offsets. + */ + private void initByteTextOffsets() { + // Twice the space, because some formats display the content twice, for + // example ATARI_DISK_IMAGE_K_FILE. + byteTextOffsets = new long[fileContent.length * 2]; + Arrays.fill(byteTextOffsets, -1); + byteTextIndex = 0; + } + + /** + * Determines the possible file content modes based on the file content. + * + * @return The suggested default file content mode, not <code>null</code>. + */ + public HexEditorFileContentMode determinePossibleFileContentModes() { + + HexEditorFileContentMode result = HexEditorFileContentMode.BINARY; + possibleFileContentModes.clear(); + possibleFileContentModes.add(fileContentMode); + + HexEditorFileContentMode defaultMode = result; + FileContent fileContent = getFileContent(); + // COM header present? + if (fileContent.getLength() > 6) { + // AtariDOS COM file? + if (fileContent.getWord(0) == AtariParser.COM_HEADER) { + int startAddress = fileContent.getWord(2); + int endAddress = fileContent.getWord(4); + if (startAddress >= 0 && endAddress >= startAddress) { + defaultMode = HexEditorFileContentMode.ATARI_COM_FILE; + possibleFileContentModes.add(defaultMode); + + if (fileContent.getLength() > 16) { + if (fileContent.getWord(6) == AtariMADSParser.RELOC_HEADER) { + defaultMode = HexEditorFileContentMode.ATARI_MADS_FILE; + possibleFileContentModes.add(defaultMode); + } + } + // New default? + if (result.equals(HexEditorFileContentMode.BINARY)) { + result = defaultMode; + } + } + } // SpartaDOS X non relocatable file? + else if (fileContent.getWord(0) == AtariSDXParser.NON_RELOC_HEADER) { + int startAddress = fileContent.getWord(2); + int endAddress = fileContent.getWord(4); + if (startAddress > 0 && endAddress >= startAddress) { + defaultMode = HexEditorFileContentMode.ATARI_SDX_FILE; + possibleFileContentModes.add(defaultMode); + // New default? + if (result.equals(HexEditorFileContentMode.BINARY)) { + result = defaultMode; + } + } + } // SpartaDOS X relocatable file? + else if (fileContent.getWord(0) == AtariSDXParser.RELOC_HEADER && fileContent.getLength() > 8) { + int blockNumber = fileContent.getByte(2); + if (blockNumber > 0) { + defaultMode = HexEditorFileContentMode.ATARI_SDX_FILE; + possibleFileContentModes.add(defaultMode); + // New default? + if (result.equals(HexEditorFileContentMode.BINARY)) { + result = defaultMode; + } + } + } } - } // SpartaDOS X relocatable file? - else if (fileContent.getWord(0) == AtariSDXParser.RELOC_HEADER && fileContent.getLength() > 8) { - int blockNumber = fileContent.getByte(2); - if (blockNumber > 0) { - defaultMode = HexEditorFileContentMode.ATARI_SDX_FILE; - possibleFileContentModes.add(defaultMode); - // New default? - if (result.equals(HexEditorFileContentMode.BINARY)) { - result = defaultMode; - } + + // ATR header present? + if ((fileContent.getLength() > 16 && fileContent.getByte(0) == 0x96 && fileContent.getByte(1) == 0x02)) { + defaultMode = HexEditorFileContentMode.ATARI_DISK_IMAGE; + possibleFileContentModes.add(defaultMode); + + // Special case of k-file (converted COM file) + int offset = AtariDiskImageKFileParser.ATARI_DISK_IMAGE_K_FILE_COM_FILE_OFFSET; + if (fileContent.getLength() > offset + 2 && fileContent.getWord(offset) == 0xffff) { + final int[] kFileBootHeader = new int[] { 0x00, 0x03, 0x00, 0x07, 0x14, 0x07, 0x4C, 0x14, 0x07 }; + boolean kFileBootHeaderFound = true; + for (int i = 0; i < kFileBootHeader.length; i++) { + if (fileContent.getByte(16 + i) != kFileBootHeader[i]) { + kFileBootHeaderFound = false; + } + } + if (kFileBootHeaderFound) { + defaultMode = HexEditorFileContentMode.ATARI_DISK_IMAGE_K_FILE; + possibleFileContentModes.add(defaultMode); + } + } + + // New default? + if (result.equals(HexEditorFileContentMode.BINARY)) { + result = defaultMode; + } } - } - } - // ATR header present? - if ((fileContent.getLength() > 16 && fileContent.getByte(0) == 0x96 && fileContent.getByte(1) == 0x02)) { - defaultMode = HexEditorFileContentMode.ATARI_DISK_IMAGE; - possibleFileContentModes.add(defaultMode); - - // Special case of k-file (converted COM file) - int offset = AtariDiskImageKFileParser.ATARI_DISK_IMAGE_K_FILE_COM_FILE_OFFSET; - if (fileContent.getLength() > offset + 2 && fileContent.getWord(offset) == 0xffff) { - final int[] kFileBootHeader = new int[] { 0x00, 0x03, 0x00, 0x07, 0x14, 0x07, 0x4C, 0x14, 0x07 }; - boolean kFileBootHeaderFound = true; - for (int i = 0; i < kFileBootHeader.length; i++) { - if (fileContent.getByte(16 + i) != kFileBootHeader[i]) { - kFileBootHeaderFound = false; - } + // SAP header present? + if ((fileContent.getLength() > 11 && fileContent.getByte(0) == 0x53 && fileContent.getByte(1) == 0x41) + && fileContent.getByte(2) == 0x50) { + possibleFileContentModes.add(HexEditorFileContentMode.ATARI_SAP_FILE); + // New default? + if (result.equals(HexEditorFileContentMode.BINARY)) { + result = HexEditorFileContentMode.ATARI_SAP_FILE; + } } - if (kFileBootHeaderFound) { - defaultMode = HexEditorFileContentMode.ATARI_DISK_IMAGE_K_FILE; - possibleFileContentModes.add(defaultMode); + + // PRG header present? + if ((fileContent.getLength() > 2 && fileContent.getWord(0) + fileContent.getLength() - 2 < 0x10000)) { + possibleFileContentModes.add(HexEditorFileContentMode.C64_PRG_FILE); + int loadAddress = fileContent.getWord(0); + if (result.equals(HexEditorFileContentMode.BINARY) && loadAddress >= 0x800 && loadAddress < 0x2000) { + result = HexEditorFileContentMode.C64_PRG_FILE; + } } - } - // New default? - if (result.equals(HexEditorFileContentMode.BINARY)) { - result = defaultMode; - } + // IFF files always have an even number of bytes + if (fileContent.getLength() > 8 && (fileContent.getLength() & 0x1) == 0) { + possibleFileContentModes.add(HexEditorFileContentMode.IFF_FILE); + char[] id = new char[4]; + id[0] = (char) fileContent.getByte(0); + id[1] = (char) fileContent.getByte(1); + id[2] = (char) fileContent.getByte(2); + id[3] = (char) fileContent.getByte(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; } - // SAP header present? - if ((fileContent.getLength() > 11 && fileContent.getByte(0) == 0x53 && fileContent.getByte(1) == 0x41) - && fileContent.getByte(2) == 0x50) { - possibleFileContentModes.add(HexEditorFileContentMode.ATARI_SAP_FILE); - // New default? - if (result.equals(HexEditorFileContentMode.BINARY)) { - result = HexEditorFileContentMode.ATARI_SAP_FILE; - } + /** + * Sets the file content for {@link #parseFileContent()}. + * + * @param fileContentMode The file content mode, not <code>null</code>. + */ + public void setFileContentMode(HexEditorFileContentMode fileContentMode) { + if (fileContentMode == null) { + throw new IllegalArgumentException("Parameter 'fileContentMode' must not be null."); + } + this.fileContentMode = fileContentMode; } - // PRG header present? - if ((fileContent.getLength() > 2 && fileContent.getWord(0) + fileContent.getLength() - 2 < 0x10000)) { - possibleFileContentModes.add(HexEditorFileContentMode.C64_PRG_FILE); - int loadAddress = fileContent.getWord(0); - if (result.equals(HexEditorFileContentMode.BINARY) && loadAddress >= 0x800 && loadAddress < 0x2000) { - result = HexEditorFileContentMode.C64_PRG_FILE; - } + /** + * Gets the file content for {@link #parseFileContent()}. + * + * @return fileContentMode The file content mode, not <code>null</code>. + */ + public HexEditorFileContentMode getFileContentMode() { + return fileContentMode; } - // IFF files always have an even number of bytes - if (fileContent.getLength() > 8 && (fileContent.getLength() & 0x1) == 0) { - possibleFileContentModes.add(HexEditorFileContentMode.IFF_FILE); - char[] id = new char[4]; - id[0] = (char) fileContent.getByte(0); - id[1] = (char) fileContent.getByte(1); - id[2] = (char) fileContent.getByte(2); - id[3] = (char) fileContent.getByte(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; - } + /** + * Sets the character set type. + * + * @param characterSet The character set type, not <code>null</code>. + */ + public void setCharacterSet(HardwareCharacterSet characterSet) { + if (characterSet == null) { + throw new IllegalArgumentException("Parameter 'characterSet' must not be null."); + } - /** - * Sets the file content for {@link #parseFileContent()}. - * - * @param fileContentMode - * The file content mode, not <code>null</code>. - */ - public void setFileContentMode(HexEditorFileContentMode fileContentMode) { - if (fileContentMode == null) { - throw new IllegalArgumentException("Parameter 'fileContentMode' must not be null."); - } - this.fileContentMode = fileContentMode; - } - - /** - * Gets the file content for {@link #parseFileContent()}. - * - * @return fileContentMode The file content mode, not <code>null</code>. - */ - public HexEditorFileContentMode getFileContentMode() { - return fileContentMode; - } - - /** - * Sets the character set type. - * - * @param characterSet - * The character set type, not <code>null</code>. - */ - public void setCharacterSet(HardwareCharacterSet characterSet) { - if (characterSet == null) { - throw new IllegalArgumentException("Parameter 'characterSet' must not be null."); + this.characterSet = characterSet; } - this.characterSet = characterSet; - } - - /** - * Gets the character set type. - * - * @return characterSet The character set type, not <code>null</code>. - */ - public HardwareCharacterSet getCharacterSet() { - return characterSet; - } - - /** - * Sets the number of bytes per row for {@link #parseFileContent()}. - * - * @param bytesPerRow - * The number of bytes per row, a positive integer. - */ - public void setBytesPerRow(int bytesPerRow) { - if (bytesPerRow < 1) { - throw new IllegalArgumentException( - "Parameter 'bytesPerRow' must not be positive. Specified valie was " + bytesPerRow + "."); - } - this.bytesPerRow = bytesPerRow; - } - - /** - * Gets the number of bytes per row for {@link #parseFileContent()}. - * - * @return The number of bytes per row, a positive integer. - */ - public int getBytesPerRow() { - return bytesPerRow; - } - - /** - * Determines if parsing is required. - * - * @return <code>true</code> if parsing is required, <code>false</code> - * otherwise. - */ - public boolean isParsingFileContentRequired() { - return !fileContentParsed || !Arrays.equals(fileContent, oldFileContent) - || !fileContentMode.equals(oldFileContentMode) || !characterSet.equals(oldCharacterSet) - || bytesPerRow != oldBytesPerRow; - } - - /** - * Parse the file content set with {@link #setFileContent(byte[])} according - * to the parameters set with - * {@link #setFileContentMode(HexEditorFileContentMode)}, - * {@link #setBytesPerRow(int)} and - * {@link #setCharacterSet(HardwareCharacterSet)}. - * - * @return The styles string representing the content. - */ - public StyledString parseFileContent() { - - Profiler profiler = new Profiler(this); - profiler.begin("parseFileContent", fileContent.length + " bytes"); - - outlineBlocks.clear(); - initByteTextOffsets(); - - StyledString contentBuilder = new StyledString(); - HexEditorContentOutlineTreeObject treeObject; - String text = TextUtility.format(Texts.HEX_EDITOR_FILE_SIZE, - HexUtility.getLongValueHexString(fileContent.length), - NumberUtility.getLongValueDecimalString(fileContent.length)); - contentBuilder.append(text); - treeObject = new HexEditorContentOutlineTreeObject(contentBuilder); - treeObject.setFileStartOffset(0); - treeObject.setTextStartOffset(contentBuilder.length()); - outlineBlocks.add(treeObject); - - contentBuilder = new StyledString(); - if (!possibleFileContentModes.contains(fileContentMode)) { - messageManager.sendMessage(MessageIds.FILE_CONTENT_MODE, IStatus.ERROR, Texts.MESSAGE_E300, - EnumUtility.getText(fileContentMode)); - return contentBuilder; + /** + * Gets the character set type. + * + * @return characterSet The character set type, not <code>null</code>. + */ + public HardwareCharacterSet getCharacterSet() { + return characterSet; } - if (fileContent.length > 0) { - boolean error; - HexEditorParser parser = fileContentMode.createParser(); - - // Initialize the buffers for the hex and char conversion. - hexBuffer = new char[3 + bytesPerRow * 3 + 2]; - for (int i = 0; i < hexBuffer.length; i++) { - hexBuffer[i] = ' '; - } - hexBuffer[1] = ':'; - hexBuffer[hexBuffer.length - 2] = '|'; - charBuffer = new char[bytesPerRow + 1]; - charBuffer[charBuffer.length - 1] = '\n'; - - parser.init(this, offsetStyler, addressStyler); - error = parser.parse(contentBuilder); - if (error) { - messageManager.sendMessage(MessageIds.FILE_CONTENT_MODE, IStatus.ERROR, Texts.MESSAGE_E301, - EnumUtility.getText(fileContentMode)); - } + /** + * Sets the number of bytes per row for {@link #parseFileContent()}. + * + * @param bytesPerRow The number of bytes per row, a positive integer. + */ + public void setBytesPerRow(int bytesPerRow) { + if (bytesPerRow < 1) { + throw new IllegalArgumentException( + "Parameter 'bytesPerRow' must not be positive. Specified valie was " + bytesPerRow + "."); + } + this.bytesPerRow = bytesPerRow; } - profiler.end("parseFileContent"); - - // Copy current state to state backup for change detection in {@link - // #isParsingFileContentRequired}, - fileContentParsed = true; - oldFileContentMode = fileContentMode; - oldFileContent = fileContent; - oldCharacterSet = characterSet; - oldBytesPerRow = bytesPerRow; - - return contentBuilder; - } - - /** - * Gets the file content. - * - * @return The file content, not <code>null</code>. - */ - final FileContent getFileContent() { - return new FileContentImpl(fileContent); // TODO Do not create newly - } - - /** - * Prints a block header in the context area and adds a block to the - * outline. - * - * @param contentBuilder - * The content builder, not <code>null</code>. - * @param headerStyledString - * The style string for the block header in the outline, not - * <code>null</code>. - * @param offset - * The start offset, a non-negative integer. - * - * @return The tree object representing the block. - */ - final HexEditorContentOutlineTreeObject printBlockHeader(StyledString contentBuilder, - StyledString headerStyledString, long offset) { - - if (contentBuilder == null) { - throw new IllegalArgumentException("Parameter 'contentBuilder' must not be null."); - } - if (headerStyledString == null) { - throw new IllegalArgumentException("Parameter 'styledString' must not be null."); - } - HexEditorContentOutlineTreeObject treeObject; - - treeObject = new HexEditorContentOutlineTreeObject(headerStyledString); - treeObject.setFileStartOffset(offset); - treeObject.setTextStartOffset(contentBuilder.length()); - outlineBlocks.add(treeObject); - return treeObject; - } - - /** - * Prints the last block in case if contains an error like the wrong number - * of bytes. - * - * @param contentBuilder - * The content builder, not <code>null</code>. - * @param errorText - * The error text, not empty and not <code>null</code>. - * @param length - * The length of the last block, a non-negative integer. - * @param offset - * The offset of the last block, a non-negative integer. - */ - final void printBlockWithError(StyledString contentBuilder, String errorText, long length, long offset) { - if (contentBuilder == null) { - throw new IllegalArgumentException("Parameter 'contentBuilder' must not be null."); + /** + * Gets the number of bytes per row for {@link #parseFileContent()}. + * + * @return The number of bytes per row, a positive integer. + */ + public int getBytesPerRow() { + return bytesPerRow; } - if (errorText == null) { - throw new IllegalArgumentException("Parameter 'errorText' must not be null."); + /** + * Determines if parsing is required. + * + * @return <code>true</code> if parsing is required, <code>false</code> + * otherwise. + */ + public boolean isParsingFileContentRequired() { + return !fileContentParsed || !Arrays.equals(fileContent, oldFileContent) + || !fileContentMode.equals(oldFileContentMode) || !characterSet.equals(oldCharacterSet) + || bytesPerRow != oldBytesPerRow; } - HexEditorContentOutlineTreeObject treeObject; - StyledString styledString = new StyledString(errorText, errorStyler); - treeObject = new HexEditorContentOutlineTreeObject(styledString); - treeObject.setFileStartOffset(UNDEFINED_OFFSET); - treeObject.setFileEndOffset(UNDEFINED_OFFSET); - treeObject.setTextStartOffset(contentBuilder.length()); - treeObject.setTextEndOffset(contentBuilder.length()); - outlineBlocks.add(treeObject); - contentBuilder.append(styledString); - contentBuilder.append("\n"); - offset = printBytes(treeObject, contentBuilder, offset, length - 1, true, 0); - } + /** + * Parse the file content set with {@link #setFileContent(byte[])} according to + * the parameters set with + * {@link #setFileContentMode(HexEditorFileContentMode)}, + * {@link #setBytesPerRow(int)} and + * {@link #setCharacterSet(HardwareCharacterSet)}. + * + * @return The styles string representing the content. + */ + public StyledString parseFileContent() { - final void skipByteTextIndex(long offset) { - byteTextIndex += offset; - } + Profiler profiler = new Profiler(this); + profiler.begin("parseFileContent", fileContent.length + " bytes"); - final long printBytes(HexEditorContentOutlineTreeObject treeObject, StyledString contentBuilder, long offset, - long maxOffset, boolean withStartAddress, int startAddress) { + outlineBlocks.clear(); + initByteTextOffsets(); - if (offset < 0) { - throw new IllegalArgumentException( - "Parameter 'offset' must not be negative, specified value is " + offset + "."); + StyledString contentBuilder = new StyledString(); + HexEditorContentOutlineTreeObject treeObject; + String text = TextUtility.format(Texts.HEX_EDITOR_FILE_SIZE, + HexUtility.getLongValueHexString(fileContent.length), + NumberUtility.getLongValueDecimalString(fileContent.length)); + contentBuilder.append(text); + treeObject = new HexEditorContentOutlineTreeObject(contentBuilder); + treeObject.setFileStartOffset(0); + treeObject.setTextStartOffset(contentBuilder.length()); + outlineBlocks.add(treeObject); + + contentBuilder = new StyledString(); + if (!possibleFileContentModes.contains(fileContentMode)) { + messageManager.sendMessage(MessageIds.FILE_CONTENT_MODE, IStatus.ERROR, Texts.MESSAGE_E300, + EnumUtility.getText(fileContentMode)); + return contentBuilder; + } + + if (fileContent.length > 0) { + boolean error; + HexEditorParser parser = fileContentMode.createParser(); + + // Initialize the buffers for the hex and char conversion. + hexBuffer = new char[3 + bytesPerRow * 3 + 2]; + for (int i = 0; i < hexBuffer.length; i++) { + hexBuffer[i] = ' '; + } + hexBuffer[1] = ':'; + hexBuffer[hexBuffer.length - 2] = '|'; + charBuffer = new char[bytesPerRow + 1]; + charBuffer[charBuffer.length - 1] = '\n'; + + parser.init(this, offsetStyler, addressStyler); + error = parser.parse(contentBuilder); + if (error) { + messageManager.sendMessage(MessageIds.FILE_CONTENT_MODE, IStatus.ERROR, Texts.MESSAGE_E301, + EnumUtility.getText(fileContentMode)); + } + } + + profiler.end("parseFileContent"); + + // Copy current state to state backup for change detection in {@link + // #isParsingFileContentRequired}, + fileContentParsed = true; + oldFileContentMode = fileContentMode; + oldFileContent = fileContent; + oldCharacterSet = characterSet; + oldBytesPerRow = bytesPerRow; + + return contentBuilder; } - if (maxOffset < 0) { - throw new IllegalArgumentException( - "Parameter 'offset' must not be negative, specified value is " + maxOffset + "."); + + /** + * Gets the file content. + * + * @return The file content, not <code>null</code>. + */ + final FileContent getFileContent() { + return new FileContentImpl(fileContent); // TODO Do not create newly } - int length = Math.max(4, HexUtility.getLongValueHexLength(fileContent.length)); - char[] characterMapping = characterSet.getCharacterMapping(); - while (offset <= maxOffset) { - int contentBuilderLineStartOffset = contentBuilder.length(); - contentBuilder.append(HexUtility.getLongValueHexString(offset, length), offsetStyler); + /** + * Prints a block header in the context area and adds a block to the outline. + * + * @param contentBuilder The content builder, not <code>null</code>. + * @param headerStyledString The style string for the block header in the + * outline, not <code>null</code>. + * @param offset The start offset, a non-negative integer. + * + * @return The tree object representing the block. + */ + final HexEditorContentOutlineTreeObject printBlockHeader(StyledString contentBuilder, + StyledString headerStyledString, long offset) { - if (withStartAddress) { - contentBuilder.append(" : "); - contentBuilder.append(HexUtility.getLongValueHexString(startAddress, length), addressStyler); + if (contentBuilder == null) { + throw new IllegalArgumentException("Parameter 'contentBuilder' must not be null."); + } + if (headerStyledString == null) { + throw new IllegalArgumentException("Parameter 'styledString' must not be null."); + } + HexEditorContentOutlineTreeObject treeObject; - } + treeObject = new HexEditorContentOutlineTreeObject(headerStyledString); + treeObject.setFileStartOffset(offset); + treeObject.setTextStartOffset(contentBuilder.length()); + outlineBlocks.add(treeObject); + return treeObject; + } - // Remember byte offset where the new line starts. - int contentBuilderStartOffset = contentBuilder.length(); - int h = 3; - for (int b = 0; b < bytesPerRow; b++) { - char highChar; - char lowChar; - char charValue; - if (offset > maxOffset) { - highChar = ' '; - lowChar = ' '; - charValue = ' '; + /** + * Prints the last block in case if contains an error like the wrong number of + * bytes. + * + * @param contentBuilder The content builder, not <code>null</code>. + * @param errorText The error text, not empty and not <code>null</code>. + * @param length The length of the last block, a non-negative integer. + * @param offset The offset of the last block, a non-negative integer. + */ + final void printBlockWithError(StyledString contentBuilder, String errorText, long length, long offset) { + if (contentBuilder == null) { + throw new IllegalArgumentException("Parameter 'contentBuilder' must not be null."); + } + + if (errorText == null) { + throw new IllegalArgumentException("Parameter 'errorText' must not be null."); + } + HexEditorContentOutlineTreeObject treeObject; + StyledString styledString = new StyledString(errorText, errorStyler); + treeObject = new HexEditorContentOutlineTreeObject(styledString); + treeObject.setFileStartOffset(UNDEFINED_OFFSET); + treeObject.setFileEndOffset(UNDEFINED_OFFSET); + treeObject.setTextStartOffset(contentBuilder.length()); + treeObject.setTextEndOffset(contentBuilder.length()); + + outlineBlocks.add(treeObject); + contentBuilder.append(styledString); + contentBuilder.append("\n"); + offset = printBytes(treeObject, contentBuilder, offset, length - 1, true, 0); + } + + final void skipByteTextIndex(long offset) { + byteTextIndex += offset; + } + + 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 + "."); + } + if (maxOffset < 0) { + throw new IllegalArgumentException( + "Parameter 'offset' must not be negative, specified value is " + maxOffset + "."); + } + int length = Math.max(4, HexUtility.getLongValueHexLength(fileContent.length)); + char[] characterMapping = characterSet.getCharacterMapping(); + while (offset <= maxOffset) { + int contentBuilderLineStartOffset = contentBuilder.length(); + + contentBuilder.append(HexUtility.getLongValueHexString(offset, length), offsetStyler); + + if (withStartAddress) { + contentBuilder.append(" : "); + contentBuilder.append(HexUtility.getLongValueHexString(startAddress, length), addressStyler); + + } + + // Remember byte offset where the new line starts. + int contentBuilderStartOffset = contentBuilder.length(); + int h = 3; + for (int b = 0; b < bytesPerRow; b++) { + char highChar; + char lowChar; + char charValue; + if (offset > maxOffset) { + highChar = ' '; + lowChar = ' '; + charValue = ' '; + } else { + int byteValue = getFileContent().getByte(offset); + highChar = hexChars[byteValue >> 4]; + lowChar = hexChars[byteValue & 0xf]; + charValue = characterMapping[byteValue]; + byteTextOffsets[byteTextIndex++] = (b == 0 ? contentBuilderLineStartOffset + : contentBuilderStartOffset + h); + offset++; + startAddress++; + } + hexBuffer[h++] = highChar; + hexBuffer[h++] = lowChar; + h++; + charBuffer[b] = charValue; + } + contentBuilder.append(hexBuffer); + contentBuilder.append(charBuffer, charStyler); + } + treeObject.setFileEndOffset(offset); + treeObject.setTextEndOffset(contentBuilder.length()); + return offset; + } + + /** + * Gets the list of outline blocks determined by {@link #parseFileContent()} . + * + * @return The list of outline blocks, may be empty, not <code>null</code>. + */ + public List<HexEditorContentOutlineTreeObject> getOutlineBlocks() { + return outlineBlocks; + } + + /** + * Gets the selection represented by the start and end offset in the text field. + * + * @param x is the offset of the first selected character + * @param y is the offset after the last selected character. + * @return The selection or <code>null</code>. + */ + public HexEditorSelection getSelection(int x, int y) { + + if (x > y) { + throw new IllegalArgumentException("x is greater than y"); + } + long startOffset = UNDEFINED_OFFSET; + for (long i = 0; i < byteTextIndex; i++) { + // BasePlugin.getInstance().log( + // "HexEditor.getSelection(): i={0} textOffset={1} + // nextTextOffset={2} startOffset={3} endOffset={4}", + // new Object[] { String.valueOf(i), String.valueOf(textOffset), + // String.valueOf(nextTextOffset), + // String.valueOf(startOffset), String.valueOf(endOffset) }); + if (getByteTextOffset(i) >= x) { + startOffset = i; + break; + } + } + + if (startOffset == UNDEFINED_OFFSET) { + return null; + } + + long endOffset = UNDEFINED_OFFSET; + for (long i = startOffset; i < byteTextIndex; i++) { + // BasePlugin.getInstance().log( + // "HexEditor.getSelection(): i={0} textOffset={1} + // nextTextOffset={2} startOffset={3} endOffset={4}", + // new Object[] { String.valueOf(i), String.valueOf(textOffset), + // String.valueOf(nextTextOffset), + // String.valueOf(startOffset), String.valueOf(endOffset) }); + + if (getByteTextOffset(i) >= y) { + endOffset = i; + break; + } + } + + if (endOffset == UNDEFINED_OFFSET) { + return null; + } + + long length; + byte[] bytes; + + length = endOffset - startOffset + 1; + BasePlugin.getInstance().log("HexEditor.getSelection(): startOffset={2} endoffset={3} length={4}", + new Object[] { String.valueOf(x), String.valueOf(y), String.valueOf(startOffset), + String.valueOf(endOffset), String.valueOf(length) }); + + // Length not empty or negative? + if (length > 0 && length < fileContent.length) { + // Reposition into first occurrence of in the file. + // This is relevant for the format that display the content more + // than once. + startOffset = startOffset % fileContent.length; + endOffset = endOffset % fileContent.length; + // Selection does not cross file end boundary? + if (startOffset <= endOffset) { + bytes = new byte[(int) length]; + System.arraycopy(fileContent, (int) startOffset, bytes, 0, bytes.length); + + } else { + + endOffset = startOffset; + bytes = new byte[0]; + + } } else { - int byteValue = getFileContent().getByte(offset); - highChar = hexChars[byteValue >> 4]; - lowChar = hexChars[byteValue & 0xf]; - charValue = characterMapping[byteValue]; - byteTextOffsets[byteTextIndex++] = (b == 0 ? contentBuilderLineStartOffset - : contentBuilderStartOffset + h); - offset++; - startAddress++; + endOffset = startOffset; + bytes = new byte[0]; } - hexBuffer[h++] = highChar; - hexBuffer[h++] = lowChar; - h++; - charBuffer[b] = charValue; - } - contentBuilder.append(hexBuffer); - contentBuilder.append(charBuffer, charStyler); - } - treeObject.setFileEndOffset(offset); - treeObject.setTextEndOffset(contentBuilder.length()); - return offset; - } - - /** - * Gets the list of outline blocks determined by {@link #parseFileContent()} - * . - * - * @return The list of outline blocks, may be empty, not <code>null</code>. - */ - public List<HexEditorContentOutlineTreeObject> getOutlineBlocks() { - return outlineBlocks; - } - - /** - * Gets the selection represented by the start and end offset in the text - * field. - * - * @param x - * is the offset of the first selected character - * @param y - * is the offset after the last selected character. - * @return The selection or <code>null</code>. - */ - public HexEditorSelection getSelection(int x, int y) { - - if (x > y) { - throw new IllegalArgumentException("x is greater than y"); - } - long startOffset = UNDEFINED_OFFSET; - for (long i = 0; i < byteTextIndex; i++) { - // BasePlugin.getInstance().log( - // "HexEditor.getSelection(): i={0} textOffset={1} - // nextTextOffset={2} startOffset={3} endOffset={4}", - // new Object[] { String.valueOf(i), String.valueOf(textOffset), - // String.valueOf(nextTextOffset), - // String.valueOf(startOffset), String.valueOf(endOffset) }); - if (getByteTextOffset(i) >= x) { - startOffset = i; - break; - } + HexEditorSelection hexEditorSelection = new HexEditorSelection(startOffset, endOffset, bytes); + return hexEditorSelection; } - if (startOffset == UNDEFINED_OFFSET) { - return null; + /** + * Gets the text offset for a byte offset. + * + * @param byteOffset The byte offset in the original byte array. + * @return The text offset where the byte is represented or + * <code>UNDEFINED_OFFSET</code> if there is no such text offset. + */ + public long getByteTextOffset(long byteOffset) { + if (byteOffset < byteTextOffsets.length) { + return byteTextOffsets[(int) byteOffset]; + } + return UNDEFINED_OFFSET; } - long endOffset = UNDEFINED_OFFSET; - for (long i = startOffset; i < byteTextIndex; i++) { - // BasePlugin.getInstance().log( - // "HexEditor.getSelection(): i={0} textOffset={1} - // nextTextOffset={2} startOffset={3} endOffset={4}", - // new Object[] { String.valueOf(i), String.valueOf(textOffset), - // String.valueOf(nextTextOffset), - // String.valueOf(startOffset), String.valueOf(endOffset) }); - - if (getByteTextOffset(i) >= y ) { - endOffset = i; - break; - } - } - - if (endOffset == UNDEFINED_OFFSET) { - return null; - } - - long length; - byte[] bytes; - - length = endOffset - startOffset + 1; - BasePlugin.getInstance().log("HexEditor.getSelection(): startOffset={2} endoffset={3} length={4}", - new Object[] { String.valueOf(x), String.valueOf(y), String.valueOf(startOffset), - String.valueOf(endOffset), String.valueOf(length) }); - - // Length not empty or negative? - if (length > 0 && length < fileContent.length) { - // Reposition into first occurrence of in the file. - // This is relevant for the format that display the content more - // than once. - startOffset = startOffset % fileContent.length; - endOffset = endOffset % fileContent.length; - // Selection does not cross file end boundary? - if (startOffset <= endOffset) { - bytes = new byte[(int) length]; - System.arraycopy(fileContent, (int) startOffset, bytes, 0, bytes.length); - - } else { - - endOffset = startOffset; - bytes = new byte[0]; - - } - } else { - endOffset = startOffset; - bytes = new byte[0]; - } - HexEditorSelection hexEditorSelection = new HexEditorSelection(startOffset, endOffset, bytes); - return hexEditorSelection; - } - - /** - * Gets the text offset for a byte offset. - * - * @param byteOffset - * The byte offset in the original byte array. - * @return The text offset where the byte is represented or - * <code>UNDEFINED_OFFSET</code> if there is no such text offset. - */ - public long getByteTextOffset(long byteOffset) { - if (byteOffset < byteTextOffsets.length) { - return byteTextOffsets[(int) byteOffset]; - } - return UNDEFINED_OFFSET; - } - } \ No newline at end of file diff --git a/com.wudsn.ide.hex/src/com/wudsn/ide/hex/HexEditorSaveSelectionAsCommandHandler.java b/com.wudsn.ide.hex/src/com/wudsn/ide/hex/HexEditorSaveSelectionAsCommandHandler.java index 63254c42..cb80ce5e 100644 --- a/com.wudsn.ide.hex/src/com/wudsn/ide/hex/HexEditorSaveSelectionAsCommandHandler.java +++ b/com.wudsn.ide.hex/src/com/wudsn/ide/hex/HexEditorSaveSelectionAsCommandHandler.java @@ -36,43 +36,43 @@ import com.wudsn.ide.base.common.TextUtility; public final class HexEditorSaveSelectionAsCommandHandler extends HexEditorSelectionCommandHandler { - public static final class CommandIds { + public static final class CommandIds { - private CommandIds() { - } - - public static final String SAVE_SELECTION_AS = "com.wudsn.ide.hex.HexEditorSaveSelectionAsCommand"; - } - - @Override - protected void performAction() throws ExecutionException { - if (commandId.equals(CommandIds.SAVE_SELECTION_AS) && !hexEditorSelection.isEmpty()) { - Shell shell = HandlerUtil.getActiveShell(event); - if (shell == null) { - return; - } - byte[] content = hexEditorSelection.getBytes(); - - FileDialog dialog = new FileDialog(shell, SWT.SAVE); - int length = content.length; - String hexLength = HexUtility.getLongValueHexString(length); - String decimalLength = NumberUtility.getLongValueDecimalString(length); - dialog.setText( - TextUtility.format(Texts.HEX_EDITOR_SAVE_SELECTION_AS_DIALOG_TITLE, hexLength, decimalLength)); - dialog.setFileName(hexEditor.getSelectionSaveFilePath()); - String filePath = dialog.open(); - if (filePath != null) { - try { - FileUtility.writeBytes(new File(filePath), content); - // INFO: ${0} ({1}) bytes saved as '{2}'. - hexEditor.getMessageManager().sendMessage(0, IStatus.OK, Texts.MESSAGE_I303, hexLength, - decimalLength, filePath); - } catch (CoreException ex) { - throw new ExecutionException(ex.getMessage()); + private CommandIds() { } - } + + public static final String SAVE_SELECTION_AS = "com.wudsn.ide.hex.HexEditorSaveSelectionAsCommand"; } - } + @Override + protected void performAction() throws ExecutionException { + if (commandId.equals(CommandIds.SAVE_SELECTION_AS) && !hexEditorSelection.isEmpty()) { + Shell shell = HandlerUtil.getActiveShell(event); + if (shell == null) { + return; + } + byte[] content = hexEditorSelection.getBytes(); + + FileDialog dialog = new FileDialog(shell, SWT.SAVE); + int length = content.length; + String hexLength = HexUtility.getLongValueHexString(length); + String decimalLength = NumberUtility.getLongValueDecimalString(length); + dialog.setText( + TextUtility.format(Texts.HEX_EDITOR_SAVE_SELECTION_AS_DIALOG_TITLE, hexLength, decimalLength)); + dialog.setFileName(hexEditor.getSelectionSaveFilePath()); + String filePath = dialog.open(); + if (filePath != null) { + try { + FileUtility.writeBytes(new File(filePath), content); + // INFO: ${0} ({1}) bytes saved as '{2}'. + hexEditor.getMessageManager().sendMessage(0, IStatus.OK, Texts.MESSAGE_I303, hexLength, + decimalLength, filePath); + } catch (CoreException ex) { + throw new ExecutionException(ex.getMessage()); + } + } + } + + } } diff --git a/com.wudsn.ide.hex/src/com/wudsn/ide/hex/HexEditorSelection.java b/com.wudsn.ide.hex/src/com/wudsn/ide/hex/HexEditorSelection.java index aa6e4141..ce9f0a7f 100644 --- a/com.wudsn.ide.hex/src/com/wudsn/ide/hex/HexEditorSelection.java +++ b/com.wudsn.ide.hex/src/com/wudsn/ide/hex/HexEditorSelection.java @@ -29,78 +29,75 @@ import org.eclipse.jface.viewers.ISelection; */ final class HexEditorSelection implements ISelection { - private long startOffset; - private long endOffset; - private byte[] bytes; + private long startOffset; + private long endOffset; + private byte[] bytes; - /** - * Creates a new selection. - * - * @param startOffset - * The start offset in the original array, a non-negative number. - * @param endOffset - * The end offset in the original array, a non-negative number - * greater or equal to the start offset. - * @param bytes - * The content of the selection, may be empty, not - * <code>null</code>. - */ - public HexEditorSelection(long startOffset, long endOffset, byte[] bytes) { + /** + * Creates a new selection. + * + * @param startOffset The start offset in the original array, a non-negative + * number. + * @param endOffset The end offset in the original array, a non-negative + * number greater or equal to the start offset. + * @param bytes The content of the selection, may be empty, not + * <code>null</code>. + */ + public HexEditorSelection(long startOffset, long endOffset, byte[] bytes) { - if (startOffset < 0) { - throw new IllegalArgumentException("Parameter 'startOffset' must not be negative, specified value is " - + startOffset + "."); + if (startOffset < 0) { + throw new IllegalArgumentException( + "Parameter 'startOffset' must not be negative, specified value is " + startOffset + "."); + } + if (endOffset < startOffset) { + throw new IllegalArgumentException("Parameter 'endOffset' must not be smaller than startOffset " + + startOffset + ", specified value is " + endOffset + "."); + } + if (bytes == null) { + throw new IllegalArgumentException("Parameter 'bytes' must not be null."); + } + this.startOffset = startOffset; + this.endOffset = endOffset; + this.bytes = bytes; } - if (endOffset < startOffset) { - throw new IllegalArgumentException("Parameter 'endOffset' must not be smaller than startOffset " - + startOffset + ", specified value is " + endOffset + "."); + + @Override + public boolean isEmpty() { + return bytes.length == 0; } - if (bytes == null) { - throw new IllegalArgumentException("Parameter 'bytes' must not be null."); + + /** + * Gets the start offset of the selection in the original array. + * + * @return The start offset in the original array, a non-negative number. + * + */ + public long getStartOffset() { + return startOffset; } - this.startOffset = startOffset; - this.endOffset = endOffset; - this.bytes = bytes; - } - @Override - public boolean isEmpty() { - return bytes.length == 0; - } + /** + * Gets the end offset in the original array. + * + * @return The end offset in the original array, a non-negative number greater + * or equal to the start offset. + */ + public long getEndOffset() { + return endOffset; + } - /** - * Gets the start offset of the selection in the original array. - * - * @return The start offset in the original array, a non-negative number. - * - */ - public long getStartOffset() { - return startOffset; - } + /** + * Gets the content of the selection. + * + * @return The content of the selection, may be empty, not <code>null</code> . + */ + public byte[] getBytes() { + return bytes; + } - /** - * Gets the end offset in the original array. - * - * @return The end offset in the original array, a non-negative number - * greater or equal to the start offset. - */ - public long getEndOffset() { - return endOffset; - } - - /** - * Gets the content of the selection. - * - * @return The content of the selection, may be empty, not <code>null</code> - * . - */ - public byte[] getBytes() { - return bytes; - } - - @Override - public String toString() { - return "HexEditorSelection from " + startOffset + " to " + endOffset + ": " + bytes.length + " bytes"; - } + @Override + public String toString() { + return "HexEditorSelection from " + startOffset + " to " + endOffset + ": " + bytes.length + " bytes"; + } } diff --git a/com.wudsn.ide.hex/src/com/wudsn/ide/hex/HexEditorSelectionCommandHandler.java b/com.wudsn.ide.hex/src/com/wudsn/ide/hex/HexEditorSelectionCommandHandler.java index a7eb19af..f75e4a4c 100644 --- a/com.wudsn.ide.hex/src/com/wudsn/ide/hex/HexEditorSelectionCommandHandler.java +++ b/com.wudsn.ide.hex/src/com/wudsn/ide/hex/HexEditorSelectionCommandHandler.java @@ -35,43 +35,43 @@ import com.wudsn.ide.base.gui.MessageManager; */ public abstract class HexEditorSelectionCommandHandler extends AbstractHandler { - protected ExecutionEvent event; - protected String commandId; - protected HexEditorSelection hexEditorSelection; - protected HexEditor hexEditor; - protected MessageManager messageManager; - - /** - * Creation is protected. - */ - protected HexEditorSelectionCommandHandler() { - super(); - } - - @Override - public final Object execute(ExecutionEvent event) throws ExecutionException { - IEditorPart editorPart; - ISelection menuEditorInputSelection; - editorPart = HandlerUtil.getActiveEditor(event); - menuEditorInputSelection = HandlerUtil.getActiveMenuSelection(event); - - if (editorPart instanceof HexEditor && menuEditorInputSelection instanceof HexEditorSelection) { - - this.event = event; - this.commandId = event.getCommand().getId(); - this.hexEditorSelection = (HexEditorSelection) menuEditorInputSelection; - this.hexEditor = ((HexEditor) editorPart); - this.messageManager = hexEditor.getMessageManager(); - messageManager.clearMessages(); - - performAction(); - - messageManager.displayMessages(); + protected ExecutionEvent event; + protected String commandId; + protected HexEditorSelection hexEditorSelection; + protected HexEditor hexEditor; + protected MessageManager messageManager; + /** + * Creation is protected. + */ + protected HexEditorSelectionCommandHandler() { + super(); } - return null; - } + @Override + public final Object execute(ExecutionEvent event) throws ExecutionException { + IEditorPart editorPart; + ISelection menuEditorInputSelection; + editorPart = HandlerUtil.getActiveEditor(event); + menuEditorInputSelection = HandlerUtil.getActiveMenuSelection(event); - protected abstract void performAction() throws ExecutionException; + if (editorPart instanceof HexEditor && menuEditorInputSelection instanceof HexEditorSelection) { + + this.event = event; + this.commandId = event.getCommand().getId(); + this.hexEditorSelection = (HexEditorSelection) menuEditorInputSelection; + this.hexEditor = ((HexEditor) editorPart); + this.messageManager = hexEditor.getMessageManager(); + messageManager.clearMessages(); + + performAction(); + + messageManager.displayMessages(); + + } + + return null; + } + + protected abstract void performAction() throws ExecutionException; } diff --git a/com.wudsn.ide.hex/src/com/wudsn/ide/hex/HexEditorSelectionTransfer.java b/com.wudsn.ide.hex/src/com/wudsn/ide/hex/HexEditorSelectionTransfer.java index 17709edf..369b830c 100644 --- a/com.wudsn.ide.hex/src/com/wudsn/ide/hex/HexEditorSelectionTransfer.java +++ b/com.wudsn.ide.hex/src/com/wudsn/ide/hex/HexEditorSelectionTransfer.java @@ -11,86 +11,86 @@ import org.eclipse.swt.dnd.TransferData; public final class HexEditorSelectionTransfer extends ByteArrayTransfer { - private static final String HEX_EDITOR_SELECTION_NAME = "HexEditorSelection"; - private static final int HEX_EDITOR_SELECTION_ID = registerType(HEX_EDITOR_SELECTION_NAME); - private static HexEditorSelectionTransfer instance = new HexEditorSelectionTransfer(); + private static final String HEX_EDITOR_SELECTION_NAME = "HexEditorSelection"; + private static final int HEX_EDITOR_SELECTION_ID = registerType(HEX_EDITOR_SELECTION_NAME); + private static HexEditorSelectionTransfer instance = new HexEditorSelectionTransfer(); - private HexEditorSelectionTransfer() { - } - - public static HexEditorSelectionTransfer getInstance() { - return instance; - } - - @Override - public void javaToNative(Object object, TransferData transferData) { - if (object == null || !(object instanceof HexEditorSelection)) - return; - - if (isSupportedType(transferData)) { - HexEditorSelection hexEditorSelection = (HexEditorSelection) object; - try { - // write data to a byte array and then ask super to convert to - // pMedium - ByteArrayOutputStream out = new ByteArrayOutputStream(); - DataOutputStream writeOut = new DataOutputStream(out); - byte[] bytes = hexEditorSelection.getBytes(); - writeOut.writeLong(hexEditorSelection.getStartOffset()); - writeOut.writeLong(hexEditorSelection.getEndOffset()); - writeOut.writeInt(bytes.length); - writeOut.write(bytes); - - byte[] buffer = out.toByteArray(); - writeOut.close(); - - super.javaToNative(buffer, transferData); - - } catch (IOException e) { - } + private HexEditorSelectionTransfer() { } - } - @Override - public Object nativeToJava(TransferData transferData) { + public static HexEditorSelectionTransfer getInstance() { + return instance; + } - if (isSupportedType(transferData)) { + @Override + public void javaToNative(Object object, TransferData transferData) { + if (object == null || !(object instanceof HexEditorSelection)) + return; - byte[] buffer = (byte[]) super.nativeToJava(transferData); - if (buffer == null) { - return null; - } + if (isSupportedType(transferData)) { + HexEditorSelection hexEditorSelection = (HexEditorSelection) object; + try { + // write data to a byte array and then ask super to convert to + // pMedium + ByteArrayOutputStream out = new ByteArrayOutputStream(); + DataOutputStream writeOut = new DataOutputStream(out); + byte[] bytes = hexEditorSelection.getBytes(); + writeOut.writeLong(hexEditorSelection.getStartOffset()); + writeOut.writeLong(hexEditorSelection.getEndOffset()); + writeOut.writeInt(bytes.length); + writeOut.write(bytes); - HexEditorSelection hexEditorSelection; - hexEditorSelection = null; - try { - ByteArrayInputStream in = new ByteArrayInputStream(buffer); - DataInputStream readIn = new DataInputStream(in); - while (readIn.available() > 0) { - long startOffset = readIn.readLong(); - long endOffset = readIn.readLong(); - int size = readIn.readInt(); - byte[] bytes = new byte[size]; - readIn.read(bytes); - hexEditorSelection = new HexEditorSelection(startOffset, endOffset, bytes); + byte[] buffer = out.toByteArray(); + writeOut.close(); + super.javaToNative(buffer, transferData); + + } catch (IOException e) { + } } - readIn.close(); - } catch (IOException ex) { - hexEditorSelection = null; - } - return hexEditorSelection; } - return null; - } + @Override + public Object nativeToJava(TransferData transferData) { - @Override - protected String[] getTypeNames() { - return new String[] { HEX_EDITOR_SELECTION_NAME }; - } + if (isSupportedType(transferData)) { - @Override - protected int[] getTypeIds() { - return new int[] { HEX_EDITOR_SELECTION_ID }; - } + byte[] buffer = (byte[]) super.nativeToJava(transferData); + if (buffer == null) { + return null; + } + + HexEditorSelection hexEditorSelection; + hexEditorSelection = null; + try { + ByteArrayInputStream in = new ByteArrayInputStream(buffer); + DataInputStream readIn = new DataInputStream(in); + while (readIn.available() > 0) { + long startOffset = readIn.readLong(); + long endOffset = readIn.readLong(); + int size = readIn.readInt(); + byte[] bytes = new byte[size]; + readIn.read(bytes); + hexEditorSelection = new HexEditorSelection(startOffset, endOffset, bytes); + + } + readIn.close(); + } catch (IOException ex) { + hexEditorSelection = null; + } + return hexEditorSelection; + } + + return null; + } + + @Override + protected String[] getTypeNames() { + return new String[] { HEX_EDITOR_SELECTION_NAME }; + } + + @Override + protected int[] getTypeIds() { + return new int[] { HEX_EDITOR_SELECTION_ID }; + } } diff --git a/com.wudsn.ide.hex/src/com/wudsn/ide/hex/HexPlugin.java b/com.wudsn.ide.hex/src/com/wudsn/ide/hex/HexPlugin.java index ca3923f6..421fb832 100644 --- a/com.wudsn.ide.hex/src/com/wudsn/ide/hex/HexPlugin.java +++ b/com.wudsn.ide.hex/src/com/wudsn/ide/hex/HexPlugin.java @@ -9,54 +9,54 @@ import com.wudsn.ide.base.common.AbstractIDEPlugin; */ public class HexPlugin extends AbstractIDEPlugin { - // The plug-in ID - public static final String ID = "com.wudsn.ide.hex"; //$NON-NLS-1$ + // The plug-in ID + public static final String ID = "com.wudsn.ide.hex"; //$NON-NLS-1$ - // The shared instance - private static HexPlugin plugin; + // The shared instance + private static HexPlugin plugin; - /** - * The constructor - */ - public HexPlugin() { - } - - /** - * {@inheritDoc} - */ - @Override - protected String getPluginId() { - return ID; - } - - /** - * {@inheritDoc} - */ - @Override - public void start(BundleContext context) throws Exception { - super.start(context); - plugin = this; - } - - /** - * {@inheritDoc} - */ - @Override - public void stop(BundleContext context) throws Exception { - plugin = null; - super.stop(context); - } - - /** - * Gets the shared plugin instance - * - * @return The plug-in, not <code>null</code>. - */ - public static HexPlugin getInstance() { - if (plugin == null) { - throw new IllegalStateException("Plugin not initialized or already stopped"); + /** + * The constructor + */ + public HexPlugin() { + } + + /** + * {@inheritDoc} + */ + @Override + protected String getPluginId() { + return ID; + } + + /** + * {@inheritDoc} + */ + @Override + public void start(BundleContext context) throws Exception { + super.start(context); + plugin = this; + } + + /** + * {@inheritDoc} + */ + @Override + public void stop(BundleContext context) throws Exception { + plugin = null; + super.stop(context); + } + + /** + * Gets the shared plugin instance + * + * @return The plug-in, not <code>null</code>. + */ + public static HexPlugin getInstance() { + if (plugin == null) { + throw new IllegalStateException("Plugin not initialized or already stopped"); + } + return plugin; } - return plugin; - } } diff --git a/com.wudsn.ide.hex/src/com/wudsn/ide/hex/Texts.java b/com.wudsn.ide.hex/src/com/wudsn/ide/hex/Texts.java index 5a9a6d9a..88f21445 100644 --- a/com.wudsn.ide.hex/src/com/wudsn/ide/hex/Texts.java +++ b/com.wudsn.ide.hex/src/com/wudsn/ide/hex/Texts.java @@ -28,65 +28,65 @@ import org.eclipse.osgi.util.NLS; */ public final class Texts extends NLS { - /** - * Hex editor - */ - public static String HEX_EDITOR_FILE_SIZE; + /** + * Hex editor + */ + public static String HEX_EDITOR_FILE_SIZE; - public static String HEX_EDITOR_ATARI_COM_BLOCK_HEADER; - public static String HEX_EDITOR_ATARI_COM_BLOCK_HEADER_PARAMETERS; - public static String HEX_EDITOR_ATARI_COM_BLOCK_ERROR; + public static String HEX_EDITOR_ATARI_COM_BLOCK_HEADER; + public static String HEX_EDITOR_ATARI_COM_BLOCK_HEADER_PARAMETERS; + public static String HEX_EDITOR_ATARI_COM_BLOCK_ERROR; - public static String HEX_EDITOR_ATARI_DISK_IMAGE_HEADER; - public static String HEX_EDITOR_ATARI_SECTOR_HEADER; - public static String HEX_EDITOR_ATARI_SECTOR_HEADER_PARAMETERS; - public static String HEX_EDITOR_ATARI_SECTOR_ERROR; + public static String HEX_EDITOR_ATARI_DISK_IMAGE_HEADER; + public static String HEX_EDITOR_ATARI_SECTOR_HEADER; + public static String HEX_EDITOR_ATARI_SECTOR_HEADER_PARAMETERS; + public static String HEX_EDITOR_ATARI_SECTOR_ERROR; - public static String HEX_EDITOR_ATARI_MADS_RELOC_BLOCK_HEADER; - public static String HEX_EDITOR_ATARI_MADS_UPDATE_RELOC_BLOCK_HEADER; - public static String HEX_EDITOR_ATARI_MADS_UPDATE_SYMBOLS_BLOCK_HEADER; - public static String HEX_EDITOR_ATARI_MADS_DEFINE_SYMBOLS_BLOCK_HEADER; - public static String HEX_EDITOR_ATARI_MADS_DEFINE_SYMBOL_HEADER; - public static String HEX_EDITOR_ATARI_MADS_BLOCK_ERROR; + public static String HEX_EDITOR_ATARI_MADS_RELOC_BLOCK_HEADER; + public static String HEX_EDITOR_ATARI_MADS_UPDATE_RELOC_BLOCK_HEADER; + public static String HEX_EDITOR_ATARI_MADS_UPDATE_SYMBOLS_BLOCK_HEADER; + public static String HEX_EDITOR_ATARI_MADS_DEFINE_SYMBOLS_BLOCK_HEADER; + public static String HEX_EDITOR_ATARI_MADS_DEFINE_SYMBOL_HEADER; + public static String HEX_EDITOR_ATARI_MADS_BLOCK_ERROR; - public static String HEX_EDITOR_ATARI_SAP_FILE_HEADER; + public static String HEX_EDITOR_ATARI_SAP_FILE_HEADER; - public static String HEX_EDITOR_ATARI_SDX_NON_RELOC_BLOCK_HEADER; - public static String HEX_EDITOR_ATARI_SDX_NON_RELOC_BLOCK_HEADER_PARAMETERS; - public static String HEX_EDITOR_ATARI_SDX_RELOC_BLOCK_HEADER; - public static String HEX_EDITOR_ATARI_SDX_UPDATE_RELOC_BLOCK_HEADER; - public static String HEX_EDITOR_ATARI_SDX_UPDATE_SYMBOLS_BLOCK_HEADER; - public static String HEX_EDITOR_ATARI_SDX_DEFINE_SYMBOLS_BLOCK_HEADER; - public static String HEX_EDITOR_ATARI_SDX_BLOCK_ERROR; + public static String HEX_EDITOR_ATARI_SDX_NON_RELOC_BLOCK_HEADER; + public static String HEX_EDITOR_ATARI_SDX_NON_RELOC_BLOCK_HEADER_PARAMETERS; + public static String HEX_EDITOR_ATARI_SDX_RELOC_BLOCK_HEADER; + public static String HEX_EDITOR_ATARI_SDX_UPDATE_RELOC_BLOCK_HEADER; + public static String HEX_EDITOR_ATARI_SDX_UPDATE_SYMBOLS_BLOCK_HEADER; + public static String HEX_EDITOR_ATARI_SDX_DEFINE_SYMBOLS_BLOCK_HEADER; + public static String HEX_EDITOR_ATARI_SDX_BLOCK_ERROR; - public static String HEX_EDITOR_C64_PRG_HEADER; - public static String HEX_EDITOR_C64_PRG_HEADER_PARAMETERS; - public static String HEX_EDITOR_C64_PRG_ERROR; + public static String HEX_EDITOR_C64_PRG_HEADER; + 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; - public static String HEX_EDITOR_CHARACTER_SET_TYPE_FIELD_LABEL; - public static String HEX_EDITOR_BYTES_PER_ROW_FIELD_LABEL; + 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_SAVE_SELECTION_AS_DIALOG_TITLE; + 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; + public static String HEX_EDITOR_CHARACTER_SET_TYPE_FIELD_LABEL; + public static String HEX_EDITOR_BYTES_PER_ROW_FIELD_LABEL; - /** - * Message for the {@link HexEditor} - */ - public static String MESSAGE_E300; - public static String MESSAGE_E301; - public static String MESSAGE_I302; - public static String MESSAGE_I303; + public static String HEX_EDITOR_SAVE_SELECTION_AS_DIALOG_TITLE; - /** - * Initializes the constants. - */ - static { - NLS.initializeMessages(Texts.class.getName(), Texts.class); - } + /** + * Message for the {@link HexEditor} + */ + public static String MESSAGE_E300; + public static String MESSAGE_E301; + public static String MESSAGE_I302; + public static String MESSAGE_I303; + + /** + * Initializes the constants. + */ + static { + NLS.initializeMessages(Texts.class.getName(), Texts.class); + } } diff --git a/com.wudsn.ide.hex/src/com/wudsn/ide/hex/parser/AtariCOMParser.java b/com.wudsn.ide.hex/src/com/wudsn/ide/hex/parser/AtariCOMParser.java index b1f97155..7ca23fcc 100644 --- a/com.wudsn.ide.hex/src/com/wudsn/ide/hex/parser/AtariCOMParser.java +++ b/com.wudsn.ide.hex/src/com/wudsn/ide/hex/parser/AtariCOMParser.java @@ -23,14 +23,14 @@ import org.eclipse.jface.viewers.StyledString; public final class AtariCOMParser extends AtariParser { - @Override - public boolean parse(StyledString contentBuilder) { - if (contentBuilder == null) { - throw new IllegalArgumentException("Parameter 'contentBuilder' must not be null."); + @Override + public boolean parse(StyledString contentBuilder) { + if (contentBuilder == null) { + throw new IllegalArgumentException("Parameter 'contentBuilder' must not be null."); + } + int offset = 0; + int fileContentLenght = fileContent.getLength(); + return parseAtariCOMFile(contentBuilder, offset, fileContentLenght); } - int offset = 0; - int fileContentLenght = fileContent.getLength(); - return parseAtariCOMFile(contentBuilder, offset, fileContentLenght); - } } diff --git a/com.wudsn.ide.hex/src/com/wudsn/ide/hex/parser/AtariDiskImageKFileParser.java b/com.wudsn.ide.hex/src/com/wudsn/ide/hex/parser/AtariDiskImageKFileParser.java index b78b7ab6..5b74f645 100644 --- a/com.wudsn.ide.hex/src/com/wudsn/ide/hex/parser/AtariDiskImageKFileParser.java +++ b/com.wudsn.ide.hex/src/com/wudsn/ide/hex/parser/AtariDiskImageKFileParser.java @@ -22,27 +22,27 @@ package com.wudsn.ide.hex.parser; import org.eclipse.jface.viewers.StyledString; public final class AtariDiskImageKFileParser extends AtariDiskImageParser { - // The offset where the COM file starts in an Atari Disk Image (k-file). - public static final int ATARI_DISK_IMAGE_K_FILE_COM_FILE_OFFSET = 16 + 3 * 128; + // The offset where the COM file starts in an Atari Disk Image (k-file). + public static final int ATARI_DISK_IMAGE_K_FILE_COM_FILE_OFFSET = 16 + 3 * 128; - @Override - public boolean parse(StyledString contentBuilder) { + @Override + public boolean parse(StyledString contentBuilder) { - if (contentBuilder == null) { - throw new IllegalArgumentException("Parameter 'contentBuilder' must not be null."); + if (contentBuilder == null) { + throw new IllegalArgumentException("Parameter 'contentBuilder' must not be null."); + } + + boolean error = super.parse(contentBuilder); + + // If the disk image is a k-file image, the contained COM file is parsed + // as well. + if (!error) { + // The length of the k-file is stored in $709/$70a. + int length = ATARI_DISK_IMAGE_K_FILE_COM_FILE_OFFSET + fileContent.getByte(0x19) + + 256 * fileContent.getByte(0x1a); + error = parseAtariCOMFile(contentBuilder, ATARI_DISK_IMAGE_K_FILE_COM_FILE_OFFSET, length); + } + return error; } - boolean error = super.parse(contentBuilder); - - // If the disk image is a k-file image, the contained COM file is parsed - // as well. - if (!error) { - // The length of the k-file is stored in $709/$70a. - int length = ATARI_DISK_IMAGE_K_FILE_COM_FILE_OFFSET + fileContent.getByte(0x19) + 256 - * fileContent.getByte(0x1a); - error = parseAtariCOMFile(contentBuilder, ATARI_DISK_IMAGE_K_FILE_COM_FILE_OFFSET, length); - } - return error; - } - } diff --git a/com.wudsn.ide.hex/src/com/wudsn/ide/hex/parser/AtariDiskImageParser.java b/com.wudsn.ide.hex/src/com/wudsn/ide/hex/parser/AtariDiskImageParser.java index 10e3ff85..6e63c11e 100644 --- a/com.wudsn.ide.hex/src/com/wudsn/ide/hex/parser/AtariDiskImageParser.java +++ b/com.wudsn.ide.hex/src/com/wudsn/ide/hex/parser/AtariDiskImageParser.java @@ -26,65 +26,65 @@ import com.wudsn.ide.hex.HexEditorContentOutlineTreeObject; public class AtariDiskImageParser extends AtariParser { - @Override - public boolean parse(StyledString contentBuilder) { + @Override + public boolean parse(StyledString contentBuilder) { - if (contentBuilder == null) { - throw new IllegalArgumentException("Parameter 'contentBuilder' must not be null."); - } + if (contentBuilder == null) { + throw new IllegalArgumentException("Parameter 'contentBuilder' must not be null."); + } - boolean error = false; - int length = fileContent.getLength(); - long offset = 0; + boolean error = false; + int length = fileContent.getLength(); + long offset = 0; - HexEditorContentOutlineTreeObject treeObject; - treeObject = printBlockHeader(contentBuilder, Texts.HEX_EDITOR_ATARI_DISK_IMAGE_HEADER, -1, "", offset, offset, - offset + 15); - offset = printBytes(treeObject, contentBuilder, offset, offset + 15, true, 0); - contentBuilder.append("\n"); - - boolean blockMode; - - blockMode = true; - - int mainSectorSize = fileContent.getByte(4) + 256 * fileContent.getByte(5); - int bootSectorSize = mainSectorSize; - - if (bootSectorSize == 256 && (length % 256) == 128 + 16) { - bootSectorSize = 128; - } - int startAddress = 0; - int sectorCount; - int sectorSize; - - sectorCount = 1; - sectorSize = bootSectorSize; - try { - 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); - offset = printBytes(treeObject, contentBuilder, offset, offset + sectorSize - 1, true, startAddress); + HexEditorContentOutlineTreeObject treeObject; + treeObject = printBlockHeader(contentBuilder, Texts.HEX_EDITOR_ATARI_DISK_IMAGE_HEADER, -1, "", offset, offset, + offset + 15); + offset = printBytes(treeObject, contentBuilder, offset, offset + 15, true, 0); contentBuilder.append("\n"); - if (offset >= length) { - blockMode = false; - } else if (length - offset < sectorSize) { - error = true; + boolean blockMode; + + blockMode = true; + + int mainSectorSize = fileContent.getByte(4) + 256 * fileContent.getByte(5); + int bootSectorSize = mainSectorSize; + + if (bootSectorSize == 256 && (length % 256) == 128 + 16) { + bootSectorSize = 128; } - sectorCount++; - if (sectorCount > 3) { - sectorSize = mainSectorSize; + int startAddress = 0; + int sectorCount; + int sectorSize; + + sectorCount = 1; + sectorSize = bootSectorSize; + try { + 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); + offset = printBytes(treeObject, contentBuilder, offset, offset + sectorSize - 1, true, startAddress); + contentBuilder.append("\n"); + + if (offset >= length) { + blockMode = false; + } else if (length - offset < sectorSize) { + error = true; + } + sectorCount++; + if (sectorCount > 3) { + sectorSize = mainSectorSize; + } + } + } catch (RuntimeException ex) { + contentBuilder.append(ex.toString()); } - } - } catch (RuntimeException ex) { - contentBuilder.append(ex.toString()); + if (error) { + printBlockWithError(contentBuilder, Texts.HEX_EDITOR_ATARI_SECTOR_ERROR, length, offset); + } + return error; } - if (error) { - printBlockWithError(contentBuilder, Texts.HEX_EDITOR_ATARI_SECTOR_ERROR, length, offset); - } - return error; - } } diff --git a/com.wudsn.ide.hex/src/com/wudsn/ide/hex/parser/AtariMADSParser.java b/com.wudsn.ide.hex/src/com/wudsn/ide/hex/parser/AtariMADSParser.java index e096fea9..4f7fd975 100644 --- a/com.wudsn.ide.hex/src/com/wudsn/ide/hex/parser/AtariMADSParser.java +++ b/com.wudsn.ide.hex/src/com/wudsn/ide/hex/parser/AtariMADSParser.java @@ -35,188 +35,188 @@ import com.wudsn.ide.hex.HexEditorParser; */ public class AtariMADSParser extends HexEditorParser { - public static final int COM_HEADER = 0xffff; - public static final int RELOC_HEADER = 0x524d; - public static final int UPDATE_RELOC_HEADER = 0xffef; - public static final int UPDATE_SYMBOLS_HEADER = 0xffee; - public static final int DEFINE_SYMBOLS_HEADER = 0xffed; + public static final int COM_HEADER = 0xffff; + public static final int RELOC_HEADER = 0x524d; + public static final int UPDATE_RELOC_HEADER = 0xffef; + public static final int UPDATE_SYMBOLS_HEADER = 0xffee; + public static final int DEFINE_SYMBOLS_HEADER = 0xffed; - @Override - public boolean parse(StyledString contentBuilder) { - if (contentBuilder == null) { - throw new IllegalArgumentException("Parameter 'contentBuilder' must not be null."); - } - - boolean error; - long offset = 0; - - // Skip offset bytes in lookup array. - skipByteTextIndex(offset); - - HexEditorContentOutlineTreeObject treeObject; - int fileContentLength = fileContent.getLength(); - - error = (fileContentLength - offset) < 17; - boolean first = true; - boolean more = true; - try { - while (more && !error) { - if (!first) { - contentBuilder.append("\n"); + @Override + public boolean parse(StyledString contentBuilder) { + if (contentBuilder == null) { + throw new IllegalArgumentException("Parameter 'contentBuilder' must not be null."); } - first = false; - if (offset == fileContentLength) { - more = false; - } else { - int header = fileContent.getWord(offset); - if (header == COM_HEADER && fileContent.getWord(offset + 6) == RELOC_HEADER) { - int startAddress = fileContent.getWord(offset + 2); - int endAddress = fileContent.getWord(offset + 4); - int config = fileContent.getByte(offset + 9); - String headerText = TextUtility.format(Texts.HEX_EDITOR_ATARI_MADS_RELOC_BLOCK_HEADER, - HexUtility.getLongValueHexString(startAddress, 4), - HexUtility.getLongValueHexString(endAddress, 4), - HexUtility.getByteValueHexString(config)); + boolean error; + long offset = 0; - treeObject = printHeader(contentBuilder, offset, headerText); - offset = printBytes(treeObject, contentBuilder, offset, offset + 15, true, 0); + // Skip offset bytes in lookup array. + skipByteTextIndex(offset); - long blockEnd = offset + endAddress - startAddress; + HexEditorContentOutlineTreeObject treeObject; + int fileContentLength = fileContent.getLength(); - offset = printBytes(treeObject, contentBuilder, offset, blockEnd, true, startAddress); - - } else if (header == UPDATE_RELOC_HEADER) { - - int type = fileContent.getByte(offset + 2); - int dataLength = fileContent.getWord(offset + 3); - - treeObject = printTypedHeader(contentBuilder, offset, - Texts.HEX_EDITOR_ATARI_MADS_UPDATE_RELOC_BLOCK_HEADER, type, dataLength); - offset = printBytes(treeObject, contentBuilder, offset, offset + 4, false, 0); - - // The exception is an update block for address high - // bytes ">", where for such a block an extra BYTE is - // stored for each address (low byte of address being - // modified). - int dataSize = (type == '>' ? 3 : 2); - long blockEnd = offset + (dataLength * dataSize) - 1; - - offset = printBytes(treeObject, contentBuilder, offset, blockEnd, false, 0); - - } else if (header == UPDATE_SYMBOLS_HEADER) { - /** - * <pre> - * HEADER WORD ($FFEE) - * TYPE CHAR (B-YTE, W-ORD, L-ONG, D-WORD, <, >) - * DATA_LENGTH WORD - * LABEL_LENGTH WORD - * LABEL_NAME ATASCII - * DATA WORD .. .. .. (DATA_LENGTH words) - * </pre> - */ - int type = fileContent.getByte(offset + 2); - int dataLength = fileContent.getWord(offset + 3); - int labelLength = fileContent.getWord(offset + 5); - - treeObject = printTypedHeader(contentBuilder, offset, - Texts.HEX_EDITOR_ATARI_MADS_UPDATE_SYMBOLS_BLOCK_HEADER, type, dataLength); - offset = printBytes(treeObject, contentBuilder, offset, offset + 6, false, 0); - offset = printBytes(treeObject, contentBuilder, offset, offset + labelLength - 1, false, 0); - offset = printBytes(treeObject, contentBuilder, offset, offset + dataLength * 2 - 1, false, 0); - - } else if (header == DEFINE_SYMBOLS_HEADER) { - - int length = fileContent.getWord(offset + 2); - String headerText = TextUtility.format(Texts.HEX_EDITOR_ATARI_MADS_DEFINE_SYMBOLS_BLOCK_HEADER, - HexUtility.getLongValueHexString(length, 4)); - StyledString headerStyledString = new StyledString(headerText, offsetStyler); - contentBuilder.append(headerStyledString).append("\n\n"); - treeObject = printBlockHeader(contentBuilder, headerStyledString, offset); - - offset += 4; - for (int i = 0; i < length; i++) { - int type = fileContent.getByte(offset); - int labelType = fileContent.getByte(offset + 1); - int labelLength = fileContent.getWord(offset + 2); - String labelName = getLabelName(offset + 4, labelLength); - int address = fileContent.getWord(offset + 4 + labelLength); - long headerEnd = offset + 6 + labelLength - 1; - switch (labelType) { - case 'P': - int procType = fileContent.getByte(headerEnd + 1); - int paramCount = fileContent.getWord(headerEnd + 2); - headerEnd += 4; - for (int j = 0; j < paramCount; j++) { - switch (procType) { - case 'D': - break; - case 'R': - headerEnd += 1; - break; - case 'V': - headerEnd += 1; - int paramLenght = fileContent.getWord(headerEnd); - headerEnd += 2 + paramLenght; - break; - } + error = (fileContentLength - offset) < 17; + boolean first = true; + boolean more = true; + try { + while (more && !error) { + if (!first) { + contentBuilder.append("\n"); } - break; - case 'A': - break; - case 'S': - break; - } + first = false; + if (offset == fileContentLength) { + more = false; + } else { + int header = fileContent.getWord(offset); + if (header == COM_HEADER && fileContent.getWord(offset + 6) == RELOC_HEADER) { + int startAddress = fileContent.getWord(offset + 2); + int endAddress = fileContent.getWord(offset + 4); + int config = fileContent.getByte(offset + 9); - headerText = TextUtility.format(Texts.HEX_EDITOR_ATARI_MADS_DEFINE_SYMBOL_HEADER, - String.valueOf((char) type), String.valueOf((char) labelType), labelName, - HexUtility.getLongValueHexString(address, 4)); - headerStyledString = new StyledString(headerText, offsetStyler); - contentBuilder.append(headerStyledString).append("\n"); - treeObject = printBlockHeader(contentBuilder, headerStyledString, offset); - offset = printBytes(treeObject, contentBuilder, offset, headerEnd, false, 0); + String headerText = TextUtility.format(Texts.HEX_EDITOR_ATARI_MADS_RELOC_BLOCK_HEADER, + HexUtility.getLongValueHexString(startAddress, 4), + HexUtility.getLongValueHexString(endAddress, 4), + HexUtility.getByteValueHexString(config)); + treeObject = printHeader(contentBuilder, offset, headerText); + offset = printBytes(treeObject, contentBuilder, offset, offset + 15, true, 0); + + long blockEnd = offset + endAddress - startAddress; + + offset = printBytes(treeObject, contentBuilder, offset, blockEnd, true, startAddress); + + } else if (header == UPDATE_RELOC_HEADER) { + + int type = fileContent.getByte(offset + 2); + int dataLength = fileContent.getWord(offset + 3); + + treeObject = printTypedHeader(contentBuilder, offset, + Texts.HEX_EDITOR_ATARI_MADS_UPDATE_RELOC_BLOCK_HEADER, type, dataLength); + offset = printBytes(treeObject, contentBuilder, offset, offset + 4, false, 0); + + // The exception is an update block for address high + // bytes ">", where for such a block an extra BYTE is + // stored for each address (low byte of address being + // modified). + int dataSize = (type == '>' ? 3 : 2); + long blockEnd = offset + (dataLength * dataSize) - 1; + + offset = printBytes(treeObject, contentBuilder, offset, blockEnd, false, 0); + + } else if (header == UPDATE_SYMBOLS_HEADER) { + /** + * <pre> + * HEADER WORD ($FFEE) + * TYPE CHAR (B-YTE, W-ORD, L-ONG, D-WORD, <, >) + * DATA_LENGTH WORD + * LABEL_LENGTH WORD + * LABEL_NAME ATASCII + * DATA WORD .. .. .. (DATA_LENGTH words) + * </pre> + */ + int type = fileContent.getByte(offset + 2); + int dataLength = fileContent.getWord(offset + 3); + int labelLength = fileContent.getWord(offset + 5); + + treeObject = printTypedHeader(contentBuilder, offset, + Texts.HEX_EDITOR_ATARI_MADS_UPDATE_SYMBOLS_BLOCK_HEADER, type, dataLength); + offset = printBytes(treeObject, contentBuilder, offset, offset + 6, false, 0); + offset = printBytes(treeObject, contentBuilder, offset, offset + labelLength - 1, false, 0); + offset = printBytes(treeObject, contentBuilder, offset, offset + dataLength * 2 - 1, false, 0); + + } else if (header == DEFINE_SYMBOLS_HEADER) { + + int length = fileContent.getWord(offset + 2); + String headerText = TextUtility.format(Texts.HEX_EDITOR_ATARI_MADS_DEFINE_SYMBOLS_BLOCK_HEADER, + HexUtility.getLongValueHexString(length, 4)); + StyledString headerStyledString = new StyledString(headerText, offsetStyler); + contentBuilder.append(headerStyledString).append("\n\n"); + treeObject = printBlockHeader(contentBuilder, headerStyledString, offset); + + offset += 4; + for (int i = 0; i < length; i++) { + int type = fileContent.getByte(offset); + int labelType = fileContent.getByte(offset + 1); + int labelLength = fileContent.getWord(offset + 2); + String labelName = getLabelName(offset + 4, labelLength); + int address = fileContent.getWord(offset + 4 + labelLength); + long headerEnd = offset + 6 + labelLength - 1; + switch (labelType) { + case 'P': + int procType = fileContent.getByte(headerEnd + 1); + int paramCount = fileContent.getWord(headerEnd + 2); + headerEnd += 4; + for (int j = 0; j < paramCount; j++) { + switch (procType) { + case 'D': + break; + case 'R': + headerEnd += 1; + break; + case 'V': + headerEnd += 1; + int paramLenght = fileContent.getWord(headerEnd); + headerEnd += 2 + paramLenght; + break; + } + } + break; + case 'A': + break; + case 'S': + break; + } + + headerText = TextUtility.format(Texts.HEX_EDITOR_ATARI_MADS_DEFINE_SYMBOL_HEADER, + String.valueOf((char) type), String.valueOf((char) labelType), labelName, + HexUtility.getLongValueHexString(address, 4)); + headerStyledString = new StyledString(headerText, offsetStyler); + contentBuilder.append(headerStyledString).append("\n"); + treeObject = printBlockHeader(contentBuilder, headerStyledString, offset); + offset = printBytes(treeObject, contentBuilder, offset, headerEnd, false, 0); + + } + + } else { + error = true; + } + } } - - } else { + } catch (RuntimeException ex) { + contentBuilder.append(ex.toString()); error = true; - } } - } - } catch (RuntimeException ex) { - contentBuilder.append(ex.toString()); - error = true; + + if (error) { + printBlockWithError(contentBuilder, Texts.HEX_EDITOR_ATARI_MADS_BLOCK_ERROR, fileContentLength, offset); + } + return error; } - if (error) { - printBlockWithError(contentBuilder, Texts.HEX_EDITOR_ATARI_MADS_BLOCK_ERROR, fileContentLength, offset); + private HexEditorContentOutlineTreeObject printHeader(StyledString contentBuilder, long offset, String headerText) { + HexEditorContentOutlineTreeObject treeObject; + StyledString headerStyledString = new StyledString(headerText, offsetStyler); + contentBuilder.append(headerStyledString).append("\n"); + treeObject = printBlockHeader(contentBuilder, headerStyledString, offset); + return treeObject; } - return error; - } - private HexEditorContentOutlineTreeObject printHeader(StyledString contentBuilder, long offset, String headerText) { - HexEditorContentOutlineTreeObject treeObject; - StyledString headerStyledString = new StyledString(headerText, offsetStyler); - contentBuilder.append(headerStyledString).append("\n"); - treeObject = printBlockHeader(contentBuilder, headerStyledString, offset); - return treeObject; - } - - private HexEditorContentOutlineTreeObject printTypedHeader(StyledString contentBuilder, long offset, String text, - int type, int dataLength) { - HexEditorContentOutlineTreeObject treeObject; - String headerText = TextUtility.format(text, String.valueOf((char) type), - HexUtility.getLongValueHexString(dataLength, 4)); - treeObject = printHeader(contentBuilder, offset, headerText); - return treeObject; - } - - private String getLabelName(long offset, int length) { - StringBuffer buffer = new StringBuffer(8); - for (int i = 0; i < length; i++) { - buffer.append((char) fileContent.getByte(offset + i)); + private HexEditorContentOutlineTreeObject printTypedHeader(StyledString contentBuilder, long offset, String text, + int type, int dataLength) { + HexEditorContentOutlineTreeObject treeObject; + String headerText = TextUtility.format(text, String.valueOf((char) type), + HexUtility.getLongValueHexString(dataLength, 4)); + treeObject = printHeader(contentBuilder, offset, headerText); + return treeObject; + } + + private String getLabelName(long offset, int length) { + StringBuffer buffer = new StringBuffer(8); + for (int i = 0; i < length; i++) { + buffer.append((char) fileContent.getByte(offset + i)); + } + return buffer.toString(); } - return buffer.toString(); - } } diff --git a/com.wudsn.ide.hex/src/com/wudsn/ide/hex/parser/AtariParser.java b/com.wudsn.ide.hex/src/com/wudsn/ide/hex/parser/AtariParser.java index a959f429..ba70d2da 100644 --- a/com.wudsn.ide.hex/src/com/wudsn/ide/hex/parser/AtariParser.java +++ b/com.wudsn.ide.hex/src/com/wudsn/ide/hex/parser/AtariParser.java @@ -27,101 +27,101 @@ import com.wudsn.ide.hex.HexEditorParser; public abstract class AtariParser extends HexEditorParser { - public final static int COM_HEADER = 0xffff; + public final static int COM_HEADER = 0xffff; - protected final boolean parseAtariCOMFile(StyledString contentBuilder, long offset, int fileContentLength) { - if (contentBuilder == null) { - throw new IllegalArgumentException("Parameter 'contentBuilder' must not be null."); - } - boolean error; - int startAddress; - int endAddress; - - int blockCount; - long blockEnd; - - // Skip offset bytes in lookup array. - skipByteTextIndex(offset); - - HexEditorContentOutlineTreeObject treeObject; - - error = (fileContentLength - offset) < 7; - if (!error) { - startAddress = fileContent.getWord(offset + 2); - endAddress = fileContent.getWord(offset + 4); - - blockCount = 1; - blockEnd = offset + endAddress - startAddress + 6; - treeObject = printBlockHeader(contentBuilder, Texts.HEX_EDITOR_ATARI_COM_BLOCK_HEADER, blockCount, - Texts.HEX_EDITOR_ATARI_COM_BLOCK_HEADER_PARAMETERS, offset, startAddress, endAddress); - offset = printBytes(treeObject, contentBuilder, offset, offset + 5, true, 0); - - boolean blockMode; - blockMode = true; - error = blockEnd >= fileContentLength; - try { - while (blockMode && !error) { - offset = printBytes(treeObject, contentBuilder, offset, blockEnd, true, startAddress); - - int headerLength = -1; - // No more bytes left? - if (offset == fileContentLength) { - blockMode = false; - } else - // At least 5 bytes available? (4 header bytes and 1 data - // byte) - if (fileContentLength - offset < 5) { - error = true; - } else { - boolean comHeader; - comHeader = fileContent.getWord(offset) == COM_HEADER; - if (comHeader) { - // At least 7 bytes available? (6 header bytes and 1 - // data byte) - if (fileContentLength - offset < 7) { - error = true; - } else { - // Inner COM header found - headerLength = 6; - startAddress = fileContent.getByte(offset + 2) + 256 * fileContent.getByte(offset + 3); - endAddress = fileContent.getByte(offset + 4) + 256 * fileContent.getByte(offset + 5); - } - } else { - // No inner COM header found - headerLength = 4; - startAddress = fileContent.getByte(offset + 0) + 256 * fileContent.getByte(offset + 1); - endAddress = fileContent.getByte(offset + 2) + 256 * fileContent.getByte(offset + 3); - } - error = endAddress < startAddress; - } - - if (blockMode) { - contentBuilder.append("\n"); - } - - if (blockMode && !error) { - blockCount++; - blockEnd = offset + endAddress - startAddress + headerLength; - if (blockEnd < fileContentLength) { - - treeObject = printBlockHeader(contentBuilder, Texts.HEX_EDITOR_ATARI_COM_BLOCK_HEADER, - blockCount, Texts.HEX_EDITOR_ATARI_COM_BLOCK_HEADER_PARAMETERS, offset, - startAddress, endAddress); - offset = printBytes(treeObject, contentBuilder, offset, offset + headerLength - 1, true, 0); - } else { - error = true; - } - } + protected final boolean parseAtariCOMFile(StyledString contentBuilder, long offset, int fileContentLength) { + if (contentBuilder == null) { + throw new IllegalArgumentException("Parameter 'contentBuilder' must not be null."); } - } catch (RuntimeException ex) { - contentBuilder.append(ex.toString()); - error = true; - } + boolean error; + int startAddress; + int endAddress; + + int blockCount; + long blockEnd; + + // Skip offset bytes in lookup array. + skipByteTextIndex(offset); + + HexEditorContentOutlineTreeObject treeObject; + + error = (fileContentLength - offset) < 7; + if (!error) { + startAddress = fileContent.getWord(offset + 2); + endAddress = fileContent.getWord(offset + 4); + + blockCount = 1; + blockEnd = offset + endAddress - startAddress + 6; + treeObject = printBlockHeader(contentBuilder, Texts.HEX_EDITOR_ATARI_COM_BLOCK_HEADER, blockCount, + Texts.HEX_EDITOR_ATARI_COM_BLOCK_HEADER_PARAMETERS, offset, startAddress, endAddress); + offset = printBytes(treeObject, contentBuilder, offset, offset + 5, true, 0); + + boolean blockMode; + blockMode = true; + error = blockEnd >= fileContentLength; + try { + while (blockMode && !error) { + offset = printBytes(treeObject, contentBuilder, offset, blockEnd, true, startAddress); + + int headerLength = -1; + // No more bytes left? + if (offset == fileContentLength) { + blockMode = false; + } else + // At least 5 bytes available? (4 header bytes and 1 data + // byte) + if (fileContentLength - offset < 5) { + error = true; + } else { + boolean comHeader; + comHeader = fileContent.getWord(offset) == COM_HEADER; + if (comHeader) { + // At least 7 bytes available? (6 header bytes and 1 + // data byte) + if (fileContentLength - offset < 7) { + error = true; + } else { + // Inner COM header found + headerLength = 6; + startAddress = fileContent.getByte(offset + 2) + 256 * fileContent.getByte(offset + 3); + endAddress = fileContent.getByte(offset + 4) + 256 * fileContent.getByte(offset + 5); + } + } else { + // No inner COM header found + headerLength = 4; + startAddress = fileContent.getByte(offset + 0) + 256 * fileContent.getByte(offset + 1); + endAddress = fileContent.getByte(offset + 2) + 256 * fileContent.getByte(offset + 3); + } + error = endAddress < startAddress; + } + + if (blockMode) { + contentBuilder.append("\n"); + } + + if (blockMode && !error) { + blockCount++; + blockEnd = offset + endAddress - startAddress + headerLength; + if (blockEnd < fileContentLength) { + + treeObject = printBlockHeader(contentBuilder, Texts.HEX_EDITOR_ATARI_COM_BLOCK_HEADER, + blockCount, Texts.HEX_EDITOR_ATARI_COM_BLOCK_HEADER_PARAMETERS, offset, + startAddress, endAddress); + offset = printBytes(treeObject, contentBuilder, offset, offset + headerLength - 1, true, 0); + } else { + error = true; + } + } + } + } catch (RuntimeException ex) { + contentBuilder.append(ex.toString()); + error = true; + } + } + if (error) { + printBlockWithError(contentBuilder, Texts.HEX_EDITOR_ATARI_COM_BLOCK_ERROR, fileContentLength, offset); + } + return error; } - if (error) { - printBlockWithError(contentBuilder, Texts.HEX_EDITOR_ATARI_COM_BLOCK_ERROR, fileContentLength, offset); - } - return error; - } } diff --git a/com.wudsn.ide.hex/src/com/wudsn/ide/hex/parser/AtariSAPParser.java b/com.wudsn.ide.hex/src/com/wudsn/ide/hex/parser/AtariSAPParser.java index 7e68802a..bfecdd1b 100644 --- a/com.wudsn.ide.hex/src/com/wudsn/ide/hex/parser/AtariSAPParser.java +++ b/com.wudsn.ide.hex/src/com/wudsn/ide/hex/parser/AtariSAPParser.java @@ -26,26 +26,26 @@ import com.wudsn.ide.hex.HexEditorContentOutlineTreeObject; public final class AtariSAPParser extends AtariParser { - @Override - public boolean parse(StyledString contentBuilder) { - if (contentBuilder == null) { - throw new IllegalArgumentException("Parameter 'contentBuilder' must not be null."); - } - long offset = 0; - int fileContentLenght = fileContent.getLength(); - int maxOffset = fileContentLenght - 2; - while (offset < maxOffset && fileContent.getByte(offset) != 0xff && fileContent.getByte(offset) != 0xff) { - offset++; - } - if (offset == maxOffset) { - return false; - } - HexEditorContentOutlineTreeObject treeObject = printBlockHeader(contentBuilder, - Texts.HEX_EDITOR_ATARI_SAP_FILE_HEADER, -1, "", 0, 0, 0); - printBytes(treeObject, contentBuilder, 0, offset - 1, false, 0); - contentBuilder.append("\n"); + @Override + public boolean parse(StyledString contentBuilder) { + if (contentBuilder == null) { + throw new IllegalArgumentException("Parameter 'contentBuilder' must not be null."); + } + long offset = 0; + int fileContentLenght = fileContent.getLength(); + int maxOffset = fileContentLenght - 2; + while (offset < maxOffset && fileContent.getByte(offset) != 0xff && fileContent.getByte(offset) != 0xff) { + offset++; + } + if (offset == maxOffset) { + return false; + } + HexEditorContentOutlineTreeObject treeObject = printBlockHeader(contentBuilder, + Texts.HEX_EDITOR_ATARI_SAP_FILE_HEADER, -1, "", 0, 0, 0); + printBytes(treeObject, contentBuilder, 0, offset - 1, false, 0); + contentBuilder.append("\n"); - return parseAtariCOMFile(contentBuilder, offset, fileContentLenght); - } + return parseAtariCOMFile(contentBuilder, offset, fileContentLenght); + } } diff --git a/com.wudsn.ide.hex/src/com/wudsn/ide/hex/parser/AtariSDXParser.java b/com.wudsn.ide.hex/src/com/wudsn/ide/hex/parser/AtariSDXParser.java index d1c3e0b4..26ce2709 100644 --- a/com.wudsn.ide.hex/src/com/wudsn/ide/hex/parser/AtariSDXParser.java +++ b/com.wudsn.ide.hex/src/com/wudsn/ide/hex/parser/AtariSDXParser.java @@ -30,165 +30,164 @@ import com.wudsn.ide.hex.Texts; public class AtariSDXParser extends HexEditorParser { - public static final int NON_RELOC_HEADER = 0xfffa; - public static final int RELOC_HEADER = 0xfffe; - public static final int UPDATE_RELOC_HEADER = 0xfffd; - public static final int UPDATE_SYMBOLS_HEADER = 0xfffb; - public static final int DEFINE_SYMBOLS_HEADER = 0xfffc; + public static final int NON_RELOC_HEADER = 0xfffa; + public static final int RELOC_HEADER = 0xfffe; + public static final int UPDATE_RELOC_HEADER = 0xfffd; + public static final int UPDATE_SYMBOLS_HEADER = 0xfffb; + public static final int DEFINE_SYMBOLS_HEADER = 0xfffc; - @Override - public boolean parse(StyledString contentBuilder) { - if (contentBuilder == null) { - throw new IllegalArgumentException("Parameter 'contentBuilder' must not be null."); - } - - boolean error; - long offset = 0; - - // Skip offset bytes in lookup array. - skipByteTextIndex(offset); - - HexEditorContentOutlineTreeObject treeObject; - int fileContentLength = fileContent.getLength(); - - error = (fileContentLength - offset) < 7; - boolean first = true; - boolean more = true; - try { - while (more && !error) { - if (!first) { - contentBuilder.append("\n"); + @Override + public boolean parse(StyledString contentBuilder) { + if (contentBuilder == null) { + throw new IllegalArgumentException("Parameter 'contentBuilder' must not be null."); } - first = false; - if (offset == fileContentLength) { - more = false; - } else { - int header = fileContent.getWord(offset); - if (header == NON_RELOC_HEADER) { - int startAddress = fileContent.getWord(offset + 2); - int endAddress = fileContent.getWord(offset + 4); - treeObject = printBlockHeader(contentBuilder, Texts.HEX_EDITOR_ATARI_SDX_NON_RELOC_BLOCK_HEADER, - -1, Texts.HEX_EDITOR_ATARI_SDX_NON_RELOC_BLOCK_HEADER_PARAMETERS, offset, startAddress, - endAddress); - offset = printBytes(treeObject, contentBuilder, offset, offset + 5, true, 0); + boolean error; + long offset = 0; - long blockEnd = offset + endAddress - startAddress; + // Skip offset bytes in lookup array. + skipByteTextIndex(offset); - offset = printBytes(treeObject, contentBuilder, offset, blockEnd, true, startAddress); + HexEditorContentOutlineTreeObject treeObject; + int fileContentLength = fileContent.getLength(); - } else if (header == RELOC_HEADER) { - int blockNumber = fileContent.getByte(offset + 2); - int blockId = fileContent.getByte(offset + 3); - int blockOffset = fileContent.getWord(offset + 4); - int blockLength = fileContent.getWord(offset + 6); + error = (fileContentLength - offset) < 7; + boolean first = true; + boolean more = true; + try { + while (more && !error) { + if (!first) { + contentBuilder.append("\n"); + } + first = false; + if (offset == fileContentLength) { + more = false; + } else { + int header = fileContent.getWord(offset); + if (header == NON_RELOC_HEADER) { + int startAddress = fileContent.getWord(offset + 2); + int endAddress = fileContent.getWord(offset + 4); - String headerText = TextUtility.format(Texts.HEX_EDITOR_ATARI_SDX_RELOC_BLOCK_HEADER, - NumberUtility.getLongValueDecimalString(blockNumber), - HexUtility.getByteValueHexString(blockId), - HexUtility.getLongValueHexString(blockOffset, 4), - HexUtility.getLongValueHexString(blockLength, 4)); - StyledString headerStyledString = new StyledString(headerText, offsetStyler); - contentBuilder.append(headerStyledString).append("\n"); - treeObject = printBlockHeader(contentBuilder, headerStyledString, offset); - offset = printBytes(treeObject, contentBuilder, offset, offset + 7, true, 0); + treeObject = printBlockHeader(contentBuilder, Texts.HEX_EDITOR_ATARI_SDX_NON_RELOC_BLOCK_HEADER, + -1, Texts.HEX_EDITOR_ATARI_SDX_NON_RELOC_BLOCK_HEADER_PARAMETERS, offset, startAddress, + endAddress); + offset = printBytes(treeObject, contentBuilder, offset, offset + 5, true, 0); - long blockEnd = offset + blockLength - 1; + long blockEnd = offset + endAddress - startAddress; - // Print bytes only of the block is not marked as EMPTY - if ((blockId & 0x80) != 0x80) { - offset = printBytes(treeObject, contentBuilder, offset, blockEnd, true, blockOffset); + offset = printBytes(treeObject, contentBuilder, offset, blockEnd, true, startAddress); + + } else if (header == RELOC_HEADER) { + int blockNumber = fileContent.getByte(offset + 2); + int blockId = fileContent.getByte(offset + 3); + int blockOffset = fileContent.getWord(offset + 4); + int blockLength = fileContent.getWord(offset + 6); + + String headerText = TextUtility.format(Texts.HEX_EDITOR_ATARI_SDX_RELOC_BLOCK_HEADER, + NumberUtility.getLongValueDecimalString(blockNumber), + HexUtility.getByteValueHexString(blockId), + HexUtility.getLongValueHexString(blockOffset, 4), + HexUtility.getLongValueHexString(blockLength, 4)); + StyledString headerStyledString = new StyledString(headerText, offsetStyler); + contentBuilder.append(headerStyledString).append("\n"); + treeObject = printBlockHeader(contentBuilder, headerStyledString, offset); + offset = printBytes(treeObject, contentBuilder, offset, offset + 7, true, 0); + + long blockEnd = offset + blockLength - 1; + + // Print bytes only of the block is not marked as EMPTY + if ((blockId & 0x80) != 0x80) { + offset = printBytes(treeObject, contentBuilder, offset, blockEnd, true, blockOffset); + } + } else if (header == UPDATE_RELOC_HEADER) { + int blockNumber = fileContent.getByte(offset + 2); + int blockLength = fileContent.getWord(offset + 3); + + String headerText = TextUtility.format(Texts.HEX_EDITOR_ATARI_SDX_UPDATE_RELOC_BLOCK_HEADER, + NumberUtility.getLongValueDecimalString(blockNumber), + HexUtility.getLongValueHexString(blockLength, 4)); + StyledString headerStyledString = new StyledString(headerText, offsetStyler); + contentBuilder.append(headerStyledString).append("\n"); + treeObject = printBlockHeader(contentBuilder, headerStyledString, offset); + offset = printBytes(treeObject, contentBuilder, offset, offset + 4, true, 0); + long blockEnd = getBlockEnd(offset); + offset = printBytes(treeObject, contentBuilder, offset, blockEnd, true, 0); + } else if (header == UPDATE_SYMBOLS_HEADER) { + String symbolName = getSymbolName(offset + 2); + int blockLength = fileContent.getWord(offset + 10); + + String headerText = TextUtility.format(Texts.HEX_EDITOR_ATARI_SDX_UPDATE_SYMBOLS_BLOCK_HEADER, + symbolName, HexUtility.getLongValueHexString(blockLength, 4)); + StyledString headerStyledString = new StyledString(headerText, offsetStyler); + contentBuilder.append(headerStyledString).append("\n"); + treeObject = printBlockHeader(contentBuilder, headerStyledString, offset); + offset = printBytes(treeObject, contentBuilder, offset, offset + 11, true, 0); + long blockEnd = getBlockEnd(offset); + offset = printBytes(treeObject, contentBuilder, offset, blockEnd, true, 0); + } else if (header == DEFINE_SYMBOLS_HEADER) { + int blockNumber = fileContent.getByte(offset + 2); + int blockOffset = fileContent.getWord(offset + 3); + String symbolName = getSymbolName(offset + 5); + + String headerText = TextUtility.format(Texts.HEX_EDITOR_ATARI_SDX_DEFINE_SYMBOLS_BLOCK_HEADER, + NumberUtility.getLongValueDecimalString(blockNumber), + HexUtility.getLongValueHexString(blockOffset), symbolName); + StyledString headerStyledString = new StyledString(headerText, offsetStyler); + contentBuilder.append(headerStyledString).append("\n"); + treeObject = printBlockHeader(contentBuilder, headerStyledString, offset); + offset = printBytes(treeObject, contentBuilder, offset, offset + 12, true, 0); + } else { + error = true; + } + } } - } else if (header == UPDATE_RELOC_HEADER) { - int blockNumber = fileContent.getByte(offset + 2); - int blockLength = fileContent.getWord(offset + 3); - - String headerText = TextUtility.format(Texts.HEX_EDITOR_ATARI_SDX_UPDATE_RELOC_BLOCK_HEADER, - NumberUtility.getLongValueDecimalString(blockNumber), - HexUtility.getLongValueHexString(blockLength, 4)); - StyledString headerStyledString = new StyledString(headerText, offsetStyler); - contentBuilder.append(headerStyledString).append("\n"); - treeObject = printBlockHeader(contentBuilder, headerStyledString, offset); - offset = printBytes(treeObject, contentBuilder, offset, offset + 4, true, 0); - long blockEnd = getBlockEnd(offset); - offset = printBytes(treeObject, contentBuilder, offset, blockEnd, true, 0); - } else if (header == UPDATE_SYMBOLS_HEADER) { - String symbolName = getSymbolName(offset + 2); - int blockLength = fileContent.getWord(offset + 10); - - String headerText = TextUtility.format(Texts.HEX_EDITOR_ATARI_SDX_UPDATE_SYMBOLS_BLOCK_HEADER, - symbolName, HexUtility.getLongValueHexString(blockLength, 4)); - StyledString headerStyledString = new StyledString(headerText, offsetStyler); - contentBuilder.append(headerStyledString).append("\n"); - treeObject = printBlockHeader(contentBuilder, headerStyledString, offset); - offset = printBytes(treeObject, contentBuilder, offset, offset + 11, true, 0); - long blockEnd = getBlockEnd(offset); - offset = printBytes(treeObject, contentBuilder, offset, blockEnd, true, 0); - } else if (header == DEFINE_SYMBOLS_HEADER) { - int blockNumber = fileContent.getByte(offset + 2); - int blockOffset = fileContent.getWord(offset + 3); - String symbolName = getSymbolName(offset + 5); - - String headerText = TextUtility.format(Texts.HEX_EDITOR_ATARI_SDX_DEFINE_SYMBOLS_BLOCK_HEADER, - NumberUtility.getLongValueDecimalString(blockNumber), - HexUtility.getLongValueHexString(blockOffset), symbolName); - StyledString headerStyledString = new StyledString(headerText, offsetStyler); - contentBuilder.append(headerStyledString).append("\n"); - treeObject = printBlockHeader(contentBuilder, headerStyledString, offset); - offset = printBytes(treeObject, contentBuilder, offset, offset + 12, true, 0); - } else { + } catch (RuntimeException ex) { + contentBuilder.append(ex.toString()); error = true; - } } - } - } catch (RuntimeException ex) { - contentBuilder.append(ex.toString()); - error = true; + + if (error) { + printBlockWithError(contentBuilder, Texts.HEX_EDITOR_ATARI_SDX_BLOCK_ERROR, fileContentLength, offset); + } + return error; } - if (error) { - printBlockWithError(contentBuilder, Texts.HEX_EDITOR_ATARI_SDX_BLOCK_ERROR, fileContentLength, offset); + /** + * Gets end offset for UPDATE_RELOC_HEADER and UPDATE_SYMBOLS_HEADER. + * + * @param offset The start offset, a non-negative integer. + * @return The end offset, a non-negative integer. + */ + private long getBlockEnd(long offset) { + int fileContentLength = fileContent.getLength(); + long i = offset; + long blockEnd = -1; + while (blockEnd < 0 && i < fileContentLength) { + int location = fileContent.getByte(i); + switch (location) { + case 0xfc: + blockEnd = i; + break; + case 0xfd: + i += 3; + break; + case 0xfe: + i += 3; + break; + default: + i++; + break; + } + } + return blockEnd; } - return error; - } - /** - * Gets end offset for UPDATE_RELOC_HEADER and UPDATE_SYMBOLS_HEADER. - * - * @param offset - * The start offset, a non-negative integer. - * @return The end offset, a non-negative integer. - */ - private long getBlockEnd(long offset) { - int fileContentLength = fileContent.getLength(); - long i = offset; - long blockEnd = -1; - while (blockEnd < 0 && i < fileContentLength) { - int location = fileContent.getByte(i); - switch (location) { - case 0xfc: - blockEnd = i; - break; - case 0xfd: - i += 3; - break; - case 0xfe: - i += 3; - break; - default: - i++; - break; - } + private String getSymbolName(long offset) { + StringBuffer buffer = new StringBuffer(8); + for (int i = 0; i < 8; i++) { + buffer.append((char) fileContent.getByte(offset + i)); + } + return buffer.toString(); } - return blockEnd; - } - - private String getSymbolName(long offset) { - StringBuffer buffer = new StringBuffer(8); - for (int i = 0; i < 8; i++) { - buffer.append((char) fileContent.getByte(offset + i)); - } - return buffer.toString(); - } } diff --git a/com.wudsn.ide.hex/src/com/wudsn/ide/hex/parser/BinaryParser.java b/com.wudsn.ide.hex/src/com/wudsn/ide/hex/parser/BinaryParser.java index 63739079..98b33aa7 100644 --- a/com.wudsn.ide.hex/src/com/wudsn/ide/hex/parser/BinaryParser.java +++ b/com.wudsn.ide.hex/src/com/wudsn/ide/hex/parser/BinaryParser.java @@ -26,14 +26,14 @@ import com.wudsn.ide.hex.HexEditorParser; public class BinaryParser extends HexEditorParser { - @Override - public boolean parse(StyledString contentBuilder) { - if (contentBuilder == null) { - throw new IllegalArgumentException("Parameter 'contentBuilder' must not be null."); + @Override + public boolean parse(StyledString contentBuilder) { + if (contentBuilder == null) { + throw new IllegalArgumentException("Parameter 'contentBuilder' must not be null."); + } + HexEditorContentOutlineTreeObject treeObject = new HexEditorContentOutlineTreeObject(contentBuilder); + printBytes(treeObject, contentBuilder, 0, fileContent.getLength() - 1, false, 0); + return false; } - HexEditorContentOutlineTreeObject treeObject = new HexEditorContentOutlineTreeObject(contentBuilder); - printBytes(treeObject, contentBuilder, 0, fileContent.getLength() - 1, false, 0); - return false; - } } diff --git a/com.wudsn.ide.hex/src/com/wudsn/ide/hex/parser/C64PRGParser.java b/com.wudsn.ide.hex/src/com/wudsn/ide/hex/parser/C64PRGParser.java index 13e6e33a..49d018a5 100644 --- a/com.wudsn.ide.hex/src/com/wudsn/ide/hex/parser/C64PRGParser.java +++ b/com.wudsn.ide.hex/src/com/wudsn/ide/hex/parser/C64PRGParser.java @@ -27,37 +27,37 @@ import com.wudsn.ide.hex.HexEditorParser; public class C64PRGParser extends HexEditorParser { - @Override - public boolean parse(StyledString contentBuilder) { - if (contentBuilder == null) { - throw new IllegalArgumentException("Parameter 'contentBuilder' must not be null."); + @Override + public boolean parse(StyledString contentBuilder) { + if (contentBuilder == null) { + throw new IllegalArgumentException("Parameter 'contentBuilder' must not be null."); + } + boolean error; + int startAddress; + int endAddress; + + int length = fileContent.getLength(); + long offset = 0; + + error = (length < 2); + if (!error) { + startAddress = fileContent.getByte(offset + 0) + 256 * fileContent.getByte(offset + 1); + endAddress = startAddress + length - 3; + + HexEditorContentOutlineTreeObject treeObject; + treeObject = printBlockHeader(contentBuilder, Texts.HEX_EDITOR_C64_PRG_HEADER, -1, + Texts.HEX_EDITOR_C64_PRG_HEADER_PARAMETERS, offset, startAddress, endAddress); + offset = printBytes(treeObject, contentBuilder, offset, offset + 1, true, 0); + + error = endAddress > 0xffff; + if (!error) { + printBytes(treeObject, contentBuilder, offset, length - 1, true, startAddress); + } + } + if (error) { + printBlockWithError(contentBuilder, Texts.HEX_EDITOR_C64_PRG_ERROR, length, offset); + } + return error; } - boolean error; - int startAddress; - int endAddress; - - int length = fileContent.getLength(); - long offset = 0; - - error = (length < 2); - if (!error) { - startAddress = fileContent.getByte(offset + 0) + 256 * fileContent.getByte(offset + 1); - endAddress = startAddress + length - 3; - - HexEditorContentOutlineTreeObject treeObject; - treeObject = printBlockHeader(contentBuilder, Texts.HEX_EDITOR_C64_PRG_HEADER, -1, - Texts.HEX_EDITOR_C64_PRG_HEADER_PARAMETERS, offset, startAddress, endAddress); - offset = printBytes(treeObject, contentBuilder, offset, offset + 1, true, 0); - - error = endAddress > 0xffff; - if (!error) { - printBytes(treeObject, contentBuilder, offset, length - 1, true, startAddress); - } - } - if (error) { - printBlockWithError(contentBuilder, Texts.HEX_EDITOR_C64_PRG_ERROR, length, offset); - } - return error; - } } diff --git a/com.wudsn.ide.hex/src/com/wudsn/ide/hex/parser/IFFParser.java b/com.wudsn.ide.hex/src/com/wudsn/ide/hex/parser/IFFParser.java index 1351974e..ce4d1b8e 100644 --- a/com.wudsn.ide.hex/src/com/wudsn/ide/hex/parser/IFFParser.java +++ b/com.wudsn.ide.hex/src/com/wudsn/ide/hex/parser/IFFParser.java @@ -30,92 +30,92 @@ import com.wudsn.ide.hex.Texts; 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 = fileContent.getLength(); - 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 = fileContent.getDoubleWordBigEndian(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)); + @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 = fileContent.getLength(); + 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) { - 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); + while ((fileContentLength - offset) >= 8 && !error) { + long headerLength = 8; + String chunkName = getChunkName(offset); + long chunkLength = fileContent.getDoubleWordBigEndian(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 (hasInnerChunks) { - contentBuilder.append("\n"); + 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); - parse(contentBuilder, offset, fileContentLength, treeObject); - offset += chunkLength; - } else { - offset = printBytes(treeObject, contentBuilder, offset, offset + chunkLength - 1, false, 0); - } - contentBuilder.append("\n"); + if (hasInnerChunks) { + contentBuilder.append("\n"); - // Skip padding byte - if ((offset & 0x1) == 1) { - offset++; - } + 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; } - 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) fileContent.getByte(offset); - id[1] = (char) fileContent.getByte(offset + 1); - id[2] = (char) fileContent.getByte(offset + 2); - id[3] = (char) fileContent.getByte(offset + 3); - return String.copyValueOf(id); - } + private String getChunkName(long offset) { + char[] id = new char[4]; + id[0] = (char) fileContent.getByte(offset); + id[1] = (char) fileContent.getByte(offset + 1); + id[2] = (char) fileContent.getByte(offset + 2); + id[3] = (char) fileContent.getByte(offset + 3); + return String.copyValueOf(id); + } }