diff --git a/com.wudsn.ide.hex/META-INF/MANIFEST.MF b/com.wudsn.ide.hex/META-INF/MANIFEST.MF index 57e62ee6..8e06e2de 100644 --- a/com.wudsn.ide.hex/META-INF/MANIFEST.MF +++ b/com.wudsn.ide.hex/META-INF/MANIFEST.MF @@ -4,7 +4,6 @@ Bundle-Name: WUDSN IDE Hex Editor Plugin Bundle-SymbolicName: com.wudsn.ide.hex;singleton:=true Bundle-Version: 1.7.2.qualifier Bundle-Activator: com.wudsn.ide.hex.HexPlugin -Bundle-Localization: plugin Bundle-Vendor: Peter Dell Require-Bundle: org.eclipse.ui, org.eclipse.core.runtime, diff --git a/com.wudsn.ide.hex/build.properties b/com.wudsn.ide.hex/build.properties index 3ec7b4a9..491b2904 100644 --- a/com.wudsn.ide.hex/build.properties +++ b/com.wudsn.ide.hex/build.properties @@ -5,5 +5,7 @@ bin.includes = META-INF/,\ icons/,\ plugin.properties,\ plugin_de_DE.properties,\ - plugin.xml + plugin.xml,\ + OSGI-INF/,\ + bin/ diff --git a/com.wudsn.ide.hex/src/com/wudsn/ide/hex/HexEditor.java b/com.wudsn.ide.hex/src/com/wudsn/ide/hex/HexEditor.java index 8719c967..c92a3a3c 100644 --- a/com.wudsn.ide.hex/src/com/wudsn/ide/hex/HexEditor.java +++ b/com.wudsn.ide.hex/src/com/wudsn/ide/hex/HexEditor.java @@ -79,549 +79,547 @@ import com.wudsn.ide.base.hardware.HardwareCharacterSet; */ public final class HexEditor extends EditorPart implements ISelectionProvider, Application { - private static final String LABEL_SUFFIX = ": "; + private static final String LABEL_SUFFIX = ": "; - public final class MessageIds { + public final class MessageIds { - /** - * Creation is private. - */ - private MessageIds() { - } - - public static final int FILE_CONTENT_MODE = 1; - public static final int CHARACTER_SET = 2; - public static final int BYTES_PER_LINE = 3; - } - - public final class Actions { - - /** - * Creation is private. - */ - private Actions() { - } - - public static final int FILE_CONTENT_MODE_CHANGED = 1000; - public static final int CHARACTER_SET_TYPE_CHANGED = 1001; - public static final int BYTES_PER_ROW_CHANGED = 1002; - } - - public static final String ID = "com.wudsn.ide.hex.HexEditor"; - - private static final String CONTEXT_MENU_ID = "#HexEditorContext"; - private static final long MAX_FILE_SIZE = 8 * ByteArrayUtility.MB; - - private MessageManager messageManager; - private HexEditorParserComponent parserComponent; - - // Editor content outline page. - private HexEditorContentOutlinePage contentOutlinePage; - - // Editor header area. - private TextField fileContentSizeField; - private EnumField fileContentModeField; - private EnumField characterSetField; - private IntegerField bytesPerRowField; - - private StyledText textField; - private HexEditorSelection lastEditorSelection; - - // File source. - private IFile iFile; - private File ioFile; - - /** - * This main method is for testing the speed of the source file parser - * component only. - * - * @param args - * Not used, not null. - * @throws Exception - * If anything goes terribly wrong. - */ - public static void main(String[] args) throws Exception { - - System.out.print("Testing HexEditorParserComponent: Parsing took "); - // Initialize for stand alone usage. - new BasePlugin().start(null); - - HexEditorParserComponent parser = new HexEditorParserComponent(new MessageManager(new HexEditor())); - parser.setFileContent(new byte[100000]); - parser.determinePossibleFileContentModes(); - - long startTimeMillis = System.currentTimeMillis(); - parser.setFileContentMode(HexEditorFileContentMode.BINARY); - parser.parseFileContent(); - long duration = System.currentTimeMillis() - startTimeMillis; - System.out.println(duration+ " ms"); - System.exit(0); - - } - - /** - * Creation is public. Called by extension point - * "org.eclipse.ui.popupMenus". - */ - public HexEditor() { - super(); - - messageManager = new MessageManager(this); - - parserComponent = new HexEditorParserComponent(messageManager); - - } - - /** - * @see org.eclipse.ui.IEditorPart#init(IEditorSite, IEditorInput) - */ - @Override - public void init(IEditorSite site, IEditorInput input) throws PartInitException { - setSite(site); - setInput(input); - - try { - load(); - } catch (CoreException ex) { - BasePlugin.getInstance().showError(site.getShell(), ex.getMessage(), ex); - } - } - - /** - * @see org.eclipse.ui.IWorkbenchPart#createPartControl(Composite) - */ - @Override - public void createPartControl(Composite parent) { - - getSite().setSelectionProvider(this); - - GridLayout gridLayout = new GridLayout(1, true); - gridLayout.marginWidth = 0; - parent.setLayout(gridLayout); - GridData gd = new GridData(GridData.VERTICAL_ALIGN_BEGINNING); - gd.horizontalSpan = 1; - parent.setLayoutData(gd); - - Composite header = SWTFactory.createComposite(parent, 8, 1, GridData.FILL_HORIZONTAL); - FillLayout fillLayout = new FillLayout(SWT.HORIZONTAL); - fillLayout.marginWidth = 10; - header.setLayout(fillLayout); - - fileContentSizeField = new TextField(header, Texts.HEX_EDITOR_FILE_CONTENT_SIZE_FIELD_LABEL + LABEL_SUFFIX, - SWT.READ_ONLY); - fileContentSizeField.getLabel().setAlignment(SWT.RIGHT); - - fileContentModeField = new EnumField(header, - Texts.HEX_EDITOR_FILE_CONTENT_MODE_FIELD_LABEL + LABEL_SUFFIX, HexEditorFileContentMode.class, null); - fileContentModeField.getLabel().setAlignment(SWT.RIGHT); - - messageManager.registerField(fileContentModeField, MessageIds.FILE_CONTENT_MODE); - fileContentModeField.addSelectionAction(new Action(Actions.FILE_CONTENT_MODE_CHANGED, this)); - - characterSetField = new EnumField(header, - Texts.HEX_EDITOR_CHARACTER_SET_TYPE_FIELD_LABEL + LABEL_SUFFIX, HardwareCharacterSet.class, null); - characterSetField.getLabel().setAlignment(SWT.RIGHT); - messageManager.registerField(characterSetField, MessageIds.CHARACTER_SET); - characterSetField.addSelectionAction(new Action(Actions.CHARACTER_SET_TYPE_CHANGED, this)); - - bytesPerRowField = new IntegerField(header, Texts.HEX_EDITOR_BYTES_PER_ROW_FIELD_LABEL + LABEL_SUFFIX, null, - false, 1, SWT.NONE); - bytesPerRowField.getLabel().setAlignment(SWT.RIGHT); - messageManager.registerField(characterSetField, MessageIds.BYTES_PER_LINE); - bytesPerRowField.getControl().addKeyListener(new KeyListener() { - - @Override - public void keyReleased(KeyEvent e) { - if (e.keyCode == '\r') { - performAction(new Action(Actions.BYTES_PER_ROW_CHANGED, HexEditor.this)); + /** + * Creation is private. + */ + private MessageIds() { } - } - - @Override - public void keyPressed(KeyEvent e) { - - } - }); - bytesPerRowField.getControl().addFocusListener(new FocusListener() { - - @Override - public void focusLost(FocusEvent e) { - performAction(new Action(Actions.BYTES_PER_ROW_CHANGED, HexEditor.this)); - - } - - @Override - public void focusGained(FocusEvent e) { - } - }); - - // SWT.WRAP is very slow, so it's not used. - textField = new StyledText(parent, SWT.SCROLL_LINE | SWT.V_SCROLL | SWT.H_SCROLL | SWT.READ_ONLY); - gd = new GridData(GridData.FILL_VERTICAL | GridData.FILL_HORIZONTAL); - gd.horizontalIndent = 0; - textField.setLayoutData(gd); - textField.setIndent(10); - textField.setLineSpacing(0); - - // Create a menu manager for the context menu. - MenuManager manager = new MenuManager(CONTEXT_MENU_ID, CONTEXT_MENU_ID); - manager.setRemoveAllWhenShown(true); - - // Create menu and link to the field. - Menu textContextMenu = manager.createContextMenu(textField); - textField.setMenu(textContextMenu); - - getEditorSite().registerContextMenu(CONTEXT_MENU_ID, manager, this, false); - messageManager.clearMessages(); - dataToUi(); - } - - @SuppressWarnings("unchecked") - @Override - public T getAdapter(Class adapter) { - if (adapter != null && IContentOutlinePage.class.equals(adapter)) { - if (contentOutlinePage == null) { - - contentOutlinePage = new HexEditorContentOutlinePage(this); - contentOutlinePage.setInput(parserComponent.getOutlineBlocks()); - } - - return (T) contentOutlinePage; - } - return super.getAdapter(adapter); - } - - /** - * @see org.eclipse.ui.IWorkbenchPart#setFocus() - */ - @Override - public void setFocus() { - textField.setFocus(); - } - - private void load() throws CoreException { - - // Clear fields. - ioFile = null; - iFile = null; - - String fileName = ""; - IEditorInput input = getEditorInput(); - if (input instanceof IFileEditorInput) { - // Input file found in Eclipse Workspace. - iFile = ((IFileEditorInput) input).getFile(); - ioFile = iFile.getRawLocation().toFile(); - fileName = iFile.getName(); - } else if (input instanceof IPathEditorInput) { - // Input file is outside the Eclipse Workspace - IPathEditorInput pathEditorInput = (IPathEditorInput) input; - IPath path = pathEditorInput.getPath(); - ioFile = path.toFile(); - fileName = ioFile.getName(); - - } else { - // Not supported. + public static final int FILE_CONTENT_MODE = 1; + public static final int CHARACTER_SET = 2; + public static final int BYTES_PER_LINE = 3; } - byte[] fileContent; - Profiler profiler = new Profiler(this); - profiler.begin("readBytes", fileName); - if (ioFile != null) { - fileContent = FileUtility.readBytes(ioFile, MAX_FILE_SIZE, false); - } else if (iFile != null) { - fileContent = FileUtility.readBytes(iFile, MAX_FILE_SIZE, false); - } else { - fileContent = new byte[0]; - } - profiler.end("readBytes"); + public final class Actions { - // Set the content, determine the default file content mode and - // character set. - parserComponent.setFileContent(fileContent); - HexEditorFileContentMode defaultFileContentMode = parserComponent.determinePossibleFileContentModes(); - HardwareCharacterSet defaultCharacterSet = defaultFileContentMode.getDefaultCharacterSet(); - parserComponent.setFileContentMode(defaultFileContentMode); - parserComponent.setCharacterSet(defaultCharacterSet); - - setPartName(fileName); - - } - - public int getBytesPerRow() { - return parserComponent.getBytesPerRow(); - } - - @Override - public void addSelectionChangedListener(ISelectionChangedListener listener) { - // Nothing. - } - - @Override - public void removeSelectionChangedListener(ISelectionChangedListener listener) { - // Nothing. - } - - @Override - public HexEditorSelection getSelection() { - - Point textFieldSelection = textField.getSelection(); - String selectedText = textField.getText().substring(textFieldSelection.x, textFieldSelection.y); - - if (textFieldSelection.x == textFieldSelection.y) { - return null; - } - - - BasePlugin.getInstance().log("HexEditor selectedText=\"{0}\", selection.x={1}, selection.y={2}", new Object[] { - selectedText, String.valueOf(textFieldSelection.x), String.valueOf(textFieldSelection.y) }); - - lastEditorSelection = parserComponent.getSelection(textFieldSelection.x, textFieldSelection.y); - - return lastEditorSelection; - } - - @Override - public void setSelection(ISelection selection) { - // Single range selection? - if (selection instanceof HexEditorSelection) { - HexEditorSelection hexEditorSelection = (HexEditorSelection) selection; - long textStartOffset = parserComponent.getByteTextOffset(hexEditorSelection.getStartOffset()); - long textEndOffset = parserComponent.getByteTextOffset(hexEditorSelection.getEndOffset()); - setSelectionOffsets(textStartOffset, textEndOffset); - // Range of outline tree objects? - } else if (selection instanceof IStructuredSelection) { - IStructuredSelection structuredSelection = (IStructuredSelection) selection; - - if (structuredSelection.getFirstElement() instanceof HexEditorContentOutlineTreeObject) { - Iterator i = ((IStructuredSelection) selection).iterator(); - - long textStartOffset = Long.MAX_VALUE; - long textEndOffset = Long.MIN_VALUE; - while (i.hasNext()) { - HexEditorContentOutlineTreeObject treeObject = (HexEditorContentOutlineTreeObject) i.next(); - textStartOffset = Math.min(treeObject.getTextStartOffset(), textStartOffset); - textEndOffset = Math.max(treeObject.getTextEndOffset(), textEndOffset); + /** + * Creation is private. + */ + private Actions() { } - setSelectionOffsets(textStartOffset, textEndOffset); - } - } - setFocus(); - } - - private void setSelectionOffsets(long textStartOffset, long textEndOffset) { - if (textStartOffset < 0 || textEndOffset > Integer.MAX_VALUE) { - throw new IllegalArgumentException("Parameter textStartOffset=" + textStartOffset + " is out of range"); - } - if (textEndOffset < 0 || textEndOffset > Integer.MAX_VALUE) { - throw new IllegalArgumentException("Parameter textStartOffset=" + textStartOffset + " is out of range"); - } - try { - // Mark complete selection area. This also scrolls to - // the end of the area. - textField.setSelection(new Point((int) textStartOffset, (int) textEndOffset)); - lastEditorSelection = null; - - // - // // But we want to see start of the selection are, so - // // position explicitly. - textField.setTopIndex(textField.getContent().getLineAtOffset((int) textStartOffset)); - } catch (IllegalArgumentException x) { - // Ignore - } - } - - /** - * Gets the file path for saving the current selection. Called by - * {@link HexEditorSaveSelectionAsCommandHandler }. - * - * @return The file path, not null. - */ - public String getSelectionSaveFilePath() { - String result = "Selection"; - String extension = ".bin"; - if (parserComponent.getFileContentMode().equals(HexEditorFileContentMode.ATARI_DISK_IMAGE_K_FILE)) { - extension = ".xex"; + public static final int FILE_CONTENT_MODE_CHANGED = 1000; + public static final int CHARACTER_SET_TYPE_CHANGED = 1001; + public static final int BYTES_PER_ROW_CHANGED = 1002; } - if (ioFile != null) { - result = ioFile.getAbsolutePath(); - int index = result.lastIndexOf('.'); - if (index >= 0) { - result = result.substring(0, index); - } + public static final String ID = "com.wudsn.ide.hex.HexEditor"; + + private static final String CONTEXT_MENU_ID = "#HexEditorContext"; + private static final long MAX_FILE_SIZE = 8 * ByteArrayUtility.MB; + + private MessageManager messageManager; + private HexEditorParserComponent parserComponent; + + // Editor content outline page. + private HexEditorContentOutlinePage contentOutlinePage; + + // Editor header area. + private TextField fileContentSizeField; + private EnumField fileContentModeField; + private EnumField characterSetField; + private IntegerField bytesPerRowField; + + private StyledText textField; + private HexEditorSelection lastEditorSelection; + + // File source. + private IFile iFile; + private File ioFile; + + /** + * This main method is for testing the speed of the source file parser component + * only. + * + * @param args Not used, not null. + * @throws Exception If anything goes terribly wrong. + */ + public static void main(String[] args) throws Exception { + + System.out.print("Testing HexEditorParserComponent: Parsing took "); + // Initialize for stand alone usage. + new BasePlugin().start(null); + + HexEditorParserComponent parser = new HexEditorParserComponent(new MessageManager(new HexEditor())); + parser.setFileContent(new byte[100000]); + parser.determinePossibleFileContentModes(); + + long startTimeMillis = System.currentTimeMillis(); + parser.setFileContentMode(HexEditorFileContentMode.BINARY); + parser.parseFileContent(); + long duration = System.currentTimeMillis() - startTimeMillis; + System.out.println(duration + " ms"); + System.exit(0); + } - result += extension; + /** + * Creation is public. Called by extension point "org.eclipse.ui.popupMenus". + */ + public HexEditor() { + super(); - return result; - } + messageManager = new MessageManager(this); - @Override - public boolean isDirty() { - return false; - } + parserComponent = new HexEditorParserComponent(messageManager); - @Override - public void doSave(IProgressMonitor monitor) { - // Nothing. - - } - - @Override - public boolean isSaveAsAllowed() { - return false; - } - - @Override - public void doSaveAs() { - // Nothing. - } - - /** - * {@inheritDoc} - */ - @Override - public MessageManager getMessageManager() { - return messageManager; - } - - private void dataFromUi() { - messageManager.clearMessages(); - parserComponent.setFileContentMode(fileContentModeField.getValue()); - parserComponent.setCharacterSet(characterSetField.getValue()); - int bytesPerRow = bytesPerRowField.getValue(); - if (bytesPerRow < 1) { - bytesPerRow = 16; - } else if (bytesPerRow > 256) { - bytesPerRow = 256; - } - parserComponent.setBytesPerRow(bytesPerRow); - } - - private void dataToUi() { - - // File content size. - FileContent fileContent = parserComponent.getFileContent(); - long length = fileContent.getLength(); - String text = TextUtility.format(Texts.HEX_EDITOR_FILE_CONTENT_SIZE_FIELD_TEXT, - HexUtility.getLongValueHexString(length), NumberUtility.getLongValueDecimalString(length)); - fileContentSizeField.setValue(text); - - // File content mode. - fileContentModeField.setValue(parserComponent.getFileContentMode()); - - // Character set. - HardwareCharacterSet characterSet = parserComponent.getCharacterSet(); - characterSetField.setValue(characterSet); - if (!textField.getFont().equals(characterSet.getFont())) { - textField.setFont(characterSet.getFont()); } - // Bytes per Row - bytesPerRowField.setValue(parserComponent.getBytesPerRow()); + /** + * @see org.eclipse.ui.IEditorPart#init(IEditorSite, IEditorInput) + */ + @Override + public void init(IEditorSite site, IEditorInput input) throws PartInitException { + setSite(site); + setInput(input); - if (parserComponent.isParsingFileContentRequired()) { - StyledString styledString = parserComponent.parseFileContent(); - textField.setText(styledString.getString()); - lastEditorSelection = null; - textField.setStyleRanges(styledString.getStyleRanges()); - - if (contentOutlinePage != null) { - contentOutlinePage.setInput(parserComponent.getOutlineBlocks()); - } + try { + load(); + } catch (CoreException ex) { + BasePlugin.getInstance().showError(site.getShell(), ex.getMessage(), ex); + } } - messageManager.displayMessages(); - } + /** + * @see org.eclipse.ui.IWorkbenchPart#createPartControl(Composite) + */ + @Override + public void createPartControl(Composite parent) { - /** - * {@inheritDoc} - */ - @Override - public void performAction(Action action) { - try { + getSite().setSelectionProvider(this); - ISelection oldSelection = null; - dataFromUi(); + GridLayout gridLayout = new GridLayout(1, true); + gridLayout.marginWidth = 0; + parent.setLayout(gridLayout); + GridData gd = new GridData(GridData.VERTICAL_ALIGN_BEGINNING); + gd.horizontalSpan = 1; + parent.setLayoutData(gd); - switch (action.getId()) { - case Actions.FILE_CONTENT_MODE_CHANGED: - case Actions.CHARACTER_SET_TYPE_CHANGED: - case Actions.BYTES_PER_ROW_CHANGED: - oldSelection = getSelection(); - break; - } + Composite header = SWTFactory.createComposite(parent, 8, 1, GridData.FILL_HORIZONTAL); + FillLayout fillLayout = new FillLayout(SWT.HORIZONTAL); + fillLayout.marginWidth = 10; + header.setLayout(fillLayout); - dataToUi(); - if (oldSelection != null) { - setSelection(oldSelection); - } - } catch (Exception ex) { - BasePlugin.getInstance().showError(getSite().getShell(), "Error in update()", ex); + fileContentSizeField = new TextField(header, Texts.HEX_EDITOR_FILE_CONTENT_SIZE_FIELD_LABEL + LABEL_SUFFIX, + SWT.READ_ONLY); + fileContentSizeField.getLabel().setAlignment(SWT.RIGHT); + + fileContentModeField = new EnumField(header, + Texts.HEX_EDITOR_FILE_CONTENT_MODE_FIELD_LABEL + LABEL_SUFFIX, HexEditorFileContentMode.class, null); + fileContentModeField.getLabel().setAlignment(SWT.RIGHT); + + messageManager.registerField(fileContentModeField, MessageIds.FILE_CONTENT_MODE); + fileContentModeField.addSelectionAction(new Action(Actions.FILE_CONTENT_MODE_CHANGED, this)); + + characterSetField = new EnumField(header, + Texts.HEX_EDITOR_CHARACTER_SET_TYPE_FIELD_LABEL + LABEL_SUFFIX, HardwareCharacterSet.class, null); + characterSetField.getLabel().setAlignment(SWT.RIGHT); + messageManager.registerField(characterSetField, MessageIds.CHARACTER_SET); + characterSetField.addSelectionAction(new Action(Actions.CHARACTER_SET_TYPE_CHANGED, this)); + + bytesPerRowField = new IntegerField(header, Texts.HEX_EDITOR_BYTES_PER_ROW_FIELD_LABEL + LABEL_SUFFIX, null, + false, 1, SWT.NONE); + bytesPerRowField.getLabel().setAlignment(SWT.RIGHT); + messageManager.registerField(characterSetField, MessageIds.BYTES_PER_LINE); + bytesPerRowField.getControl().addKeyListener(new KeyListener() { + + @Override + public void keyReleased(KeyEvent e) { + if (e.keyCode == '\r') { + performAction(new Action(Actions.BYTES_PER_ROW_CHANGED, HexEditor.this)); + } + + } + + @Override + public void keyPressed(KeyEvent e) { + + } + }); + bytesPerRowField.getControl().addFocusListener(new FocusListener() { + + @Override + public void focusLost(FocusEvent e) { + performAction(new Action(Actions.BYTES_PER_ROW_CHANGED, HexEditor.this)); + + } + + @Override + public void focusGained(FocusEvent e) { + } + }); + + // SWT.WRAP is very slow, so it's not used. + textField = new StyledText(parent, SWT.SCROLL_LINE | SWT.V_SCROLL | SWT.H_SCROLL | SWT.READ_ONLY); + gd = new GridData(GridData.FILL_VERTICAL | GridData.FILL_HORIZONTAL); + gd.horizontalIndent = 0; + textField.setLayoutData(gd); + textField.setIndent(10); + textField.setLineSpacing(0); + + // Create a menu manager for the context menu. + MenuManager manager = new MenuManager(CONTEXT_MENU_ID, CONTEXT_MENU_ID); + manager.setRemoveAllWhenShown(true); + + // Create menu and link to the field. + Menu textContextMenu = manager.createContextMenu(textField); + textField.setMenu(textContextMenu); + + getEditorSite().registerContextMenu(CONTEXT_MENU_ID, manager, this, false); + messageManager.clearMessages(); + dataToUi(); } - } + @SuppressWarnings("unchecked") + @Override + public T getAdapter(Class adapter) { + if (adapter != null && IContentOutlinePage.class.equals(adapter)) { + if (contentOutlinePage == null) { - /** - * Called by {@link HexEditorClipboardCommandHandler}. - * - * @param bytes - * The byte array to be pasted, may be empty, not - * null. - * - * TODO Hex paste is not working yet - */ - final void pasteFromClipboard(byte[] bytes) { - if (bytes == null) { - throw new IllegalArgumentException("Parameter 'bytes' must not be null."); + contentOutlinePage = new HexEditorContentOutlinePage(this); + contentOutlinePage.setInput(parserComponent.getOutlineBlocks()); + } + + return (T) contentOutlinePage; + } + return super.getAdapter(adapter); } - HexEditorSelection selection = getSelection(); - // byte[] newFileContent; - // - // // If there is no end offset, we insert the new bytes. - // if (selection.getEndOffset() != - // HexEditorParserComponent.UNDEFINED_OFFSET) { - // int selectionStartOffset = (int) selection.getStartOffset(); - // int selectionEndOffset = (int) selection.getEndOffset(); - // - // int selectionLength = selectionEndOffset - selectionStartOffset + 1; - // int newFileContentLength = parserComponent.getFileContent().length - - // selectionLength + bytes.length; - // newFileContent = new byte[newFileContentLength]; - // System.arraycopy(parserComponent.getFileContent(), 0, newFileContent, - // 0, selectionStartOffset); - // System.arraycopy(bytes, 0, newFileContent, selectionStartOffset, - // bytes.length); - // int length = parserComponent.getFileContent().length - - // selectionEndOffset - 1; - // if (length > 0) { - // // TODO Hex paste is not working yet - // System.arraycopy(parserComponent.getFileContent(), - // selectionEndOffset, newFileContent, - // selectionStartOffset + bytes.length, length); - // } - // messageManager.sendMessage(0, IStatus.OK, - // "${0} ({1}) bytes pasted from clipboard to replace ${2} ({3}) bytes - // ", - // HexUtility.getLongValueHexString(bytes.length), - // NumberUtility.getLongValueDecimalString(bytes.length), - // HexUtility.getLongValueHexString(selectionLength), - // NumberUtility.getLongValueDecimalString(selectionLength)); - // } else { - // // If there is an end offset, we replace the selection with the new - // // bytes. - // newFileContent = parserComponent.getFileContent(); - // messageManager.sendMessage(0, IStatus.OK, "${0} ({1}) bytes inserted - // from clipboard", - // HexUtility.getLongValueHexString(bytes.length), - // NumberUtility.getLongValueDecimalString(bytes.length)); - // } - // - // parserComponent.setFileContent(newFileContent); - dataToUi(); - } + /** + * @see org.eclipse.ui.IWorkbenchPart#setFocus() + */ + @Override + public void setFocus() { + textField.setFocus(); + } + + private void load() throws CoreException { + + // Clear fields. + ioFile = null; + iFile = null; + + String fileName = ""; + IEditorInput input = getEditorInput(); + if (input instanceof IFileEditorInput) { + // Input file found in Eclipse Workspace. + iFile = ((IFileEditorInput) input).getFile(); + ioFile = iFile.getRawLocation().toFile(); + fileName = iFile.getName(); + } else if (input instanceof IPathEditorInput) { + // Input file is outside the Eclipse Workspace + IPathEditorInput pathEditorInput = (IPathEditorInput) input; + IPath path = pathEditorInput.getPath(); + ioFile = path.toFile(); + fileName = ioFile.getName(); + + } else { + // Not supported. + } + + byte[] fileContent; + Profiler profiler = new Profiler(this); + profiler.begin("readBytes", fileName); + if (ioFile != null) { + fileContent = FileUtility.readBytes(ioFile, MAX_FILE_SIZE, false); + } else if (iFile != null) { + fileContent = FileUtility.readBytes(iFile, MAX_FILE_SIZE, false); + } else { + fileContent = new byte[0]; + } + profiler.end("readBytes"); + + // Set the content, determine the default file content mode and + // character set. + parserComponent.setFileContent(fileContent); + HexEditorFileContentMode defaultFileContentMode = parserComponent.determinePossibleFileContentModes(); + HardwareCharacterSet defaultCharacterSet = defaultFileContentMode.getDefaultCharacterSet(); + parserComponent.setFileContentMode(defaultFileContentMode); + parserComponent.setCharacterSet(defaultCharacterSet); + + setPartName(fileName); + + } + + public int getBytesPerRow() { + return parserComponent.getBytesPerRow(); + } + + @Override + public void addSelectionChangedListener(ISelectionChangedListener listener) { + // Nothing. + } + + @Override + public void removeSelectionChangedListener(ISelectionChangedListener listener) { + // Nothing. + } + + @Override + public HexEditorSelection getSelection() { + + if (textField == null) { + return null; + } + Point textFieldSelection = textField.getSelection(); + String selectedText = textField.getText().substring(textFieldSelection.x, textFieldSelection.y); + + if (textFieldSelection.x == textFieldSelection.y) { + return null; + } + + BasePlugin.getInstance().log("HexEditor selectedText=\"{0}\", selection.x={1}, selection.y={2}", new Object[] { + selectedText, String.valueOf(textFieldSelection.x), String.valueOf(textFieldSelection.y) }); + + lastEditorSelection = parserComponent.getSelection(textFieldSelection.x, textFieldSelection.y); + + return lastEditorSelection; + } + + @Override + public void setSelection(ISelection selection) { + // Single range selection? + if (selection instanceof HexEditorSelection) { + HexEditorSelection hexEditorSelection = (HexEditorSelection) selection; + long textStartOffset = parserComponent.getByteTextOffset(hexEditorSelection.getStartOffset()); + long textEndOffset = parserComponent.getByteTextOffset(hexEditorSelection.getEndOffset()); + setSelectionOffsets(textStartOffset, textEndOffset); + // Range of outline tree objects? + } else if (selection instanceof IStructuredSelection) { + IStructuredSelection structuredSelection = (IStructuredSelection) selection; + + if (structuredSelection.getFirstElement() instanceof HexEditorContentOutlineTreeObject) { + Iterator i = ((IStructuredSelection) selection).iterator(); + + long textStartOffset = Long.MAX_VALUE; + long textEndOffset = Long.MIN_VALUE; + while (i.hasNext()) { + HexEditorContentOutlineTreeObject treeObject = (HexEditorContentOutlineTreeObject) i.next(); + textStartOffset = Math.min(treeObject.getTextStartOffset(), textStartOffset); + textEndOffset = Math.max(treeObject.getTextEndOffset(), textEndOffset); + } + setSelectionOffsets(textStartOffset, textEndOffset); + } + + } + setFocus(); + } + + private void setSelectionOffsets(long textStartOffset, long textEndOffset) { + if (textStartOffset < 0 || textEndOffset > Integer.MAX_VALUE) { + throw new IllegalArgumentException("Parameter textStartOffset=" + textStartOffset + " is out of range"); + } + if (textEndOffset < 0 || textEndOffset > Integer.MAX_VALUE) { + throw new IllegalArgumentException("Parameter textStartOffset=" + textStartOffset + " is out of range"); + } + try { + // Mark complete selection area. This also scrolls to + // the end of the area. + textField.setSelection(new Point((int) textStartOffset, (int) textEndOffset)); + lastEditorSelection = null; + + // + // // But we want to see start of the selection are, so + // // position explicitly. + textField.setTopIndex(textField.getContent().getLineAtOffset((int) textStartOffset)); + } catch (IllegalArgumentException x) { + // Ignore + } + } + + /** + * Gets the file path for saving the current selection. Called by + * {@link HexEditorSaveSelectionAsCommandHandler }. + * + * @return The file path, not null. + */ + public String getSelectionSaveFilePath() { + String result = "Selection"; + String extension = ".bin"; + if (parserComponent.getFileContentMode().equals(HexEditorFileContentMode.ATARI_DISK_IMAGE_K_FILE)) { + extension = ".xex"; + } + + if (ioFile != null) { + result = ioFile.getAbsolutePath(); + int index = result.lastIndexOf('.'); + if (index >= 0) { + result = result.substring(0, index); + } + } + + result += extension; + + return result; + } + + @Override + public boolean isDirty() { + return false; + } + + @Override + public void doSave(IProgressMonitor monitor) { + // Nothing. + + } + + @Override + public boolean isSaveAsAllowed() { + return false; + } + + @Override + public void doSaveAs() { + // Nothing. + } + + /** + * {@inheritDoc} + */ + @Override + public MessageManager getMessageManager() { + return messageManager; + } + + private void dataFromUi() { + messageManager.clearMessages(); + parserComponent.setFileContentMode(fileContentModeField.getValue()); + parserComponent.setCharacterSet(characterSetField.getValue()); + int bytesPerRow = bytesPerRowField.getValue(); + if (bytesPerRow < 1) { + bytesPerRow = 16; + } else if (bytesPerRow > 256) { + bytesPerRow = 256; + } + parserComponent.setBytesPerRow(bytesPerRow); + } + + private void dataToUi() { + + // File content size. + FileContent fileContent = parserComponent.getFileContent(); + long length = fileContent.getLength(); + String text = TextUtility.format(Texts.HEX_EDITOR_FILE_CONTENT_SIZE_FIELD_TEXT, + HexUtility.getLongValueHexString(length), NumberUtility.getLongValueDecimalString(length)); + fileContentSizeField.setValue(text); + + // File content mode. + fileContentModeField.setValue(parserComponent.getFileContentMode()); + + // Character set. + HardwareCharacterSet characterSet = parserComponent.getCharacterSet(); + characterSetField.setValue(characterSet); + if (!textField.getFont().equals(characterSet.getFont())) { + textField.setFont(characterSet.getFont()); + } + + // Bytes per Row + bytesPerRowField.setValue(parserComponent.getBytesPerRow()); + + if (parserComponent.isParsingFileContentRequired()) { + StyledString styledString = parserComponent.parseFileContent(); + textField.setText(styledString.getString()); + lastEditorSelection = null; + textField.setStyleRanges(styledString.getStyleRanges()); + + if (contentOutlinePage != null) { + contentOutlinePage.setInput(parserComponent.getOutlineBlocks()); + } + } + + messageManager.displayMessages(); + } + + /** + * {@inheritDoc} + */ + @Override + public void performAction(Action action) { + try { + + ISelection oldSelection = null; + dataFromUi(); + + switch (action.getId()) { + case Actions.FILE_CONTENT_MODE_CHANGED: + case Actions.CHARACTER_SET_TYPE_CHANGED: + case Actions.BYTES_PER_ROW_CHANGED: + oldSelection = getSelection(); + break; + } + + dataToUi(); + if (oldSelection != null) { + setSelection(oldSelection); + } + } catch (Exception ex) { + BasePlugin.getInstance().showError(getSite().getShell(), "Error in update()", ex); + } + + } + + /** + * Called by {@link HexEditorClipboardCommandHandler}. + * + * @param bytes The byte array to be pasted, may be empty, not + * null. + * + * TODO Hex paste is not working yet + */ + final void pasteFromClipboard(byte[] bytes) { + if (bytes == null) { + throw new IllegalArgumentException("Parameter 'bytes' must not be null."); + } + HexEditorSelection selection = getSelection(); + // byte[] newFileContent; + // + // // If there is no end offset, we insert the new bytes. + // if (selection.getEndOffset() != + // HexEditorParserComponent.UNDEFINED_OFFSET) { + // int selectionStartOffset = (int) selection.getStartOffset(); + // int selectionEndOffset = (int) selection.getEndOffset(); + // + // int selectionLength = selectionEndOffset - selectionStartOffset + 1; + // int newFileContentLength = parserComponent.getFileContent().length - + // selectionLength + bytes.length; + // newFileContent = new byte[newFileContentLength]; + // System.arraycopy(parserComponent.getFileContent(), 0, newFileContent, + // 0, selectionStartOffset); + // System.arraycopy(bytes, 0, newFileContent, selectionStartOffset, + // bytes.length); + // int length = parserComponent.getFileContent().length - + // selectionEndOffset - 1; + // if (length > 0) { + // // TODO Hex paste is not working yet + // System.arraycopy(parserComponent.getFileContent(), + // selectionEndOffset, newFileContent, + // selectionStartOffset + bytes.length, length); + // } + // messageManager.sendMessage(0, IStatus.OK, + // "${0} ({1}) bytes pasted from clipboard to replace ${2} ({3}) bytes + // ", + // HexUtility.getLongValueHexString(bytes.length), + // NumberUtility.getLongValueDecimalString(bytes.length), + // HexUtility.getLongValueHexString(selectionLength), + // NumberUtility.getLongValueDecimalString(selectionLength)); + // } else { + // // If there is an end offset, we replace the selection with the new + // // bytes. + // newFileContent = parserComponent.getFileContent(); + // messageManager.sendMessage(0, IStatus.OK, "${0} ({1}) bytes inserted + // from clipboard", + // HexUtility.getLongValueHexString(bytes.length), + // NumberUtility.getLongValueDecimalString(bytes.length)); + // } + // + // parserComponent.setFileContent(newFileContent); + dataToUi(); + + } } diff --git a/com.wudsn.ide.pas/OSGI-INF/l10n/bundle_de_DE.properties b/com.wudsn.ide.pas/OSGI-INF/l10n/bundle_de_DE.properties new file mode 100644 index 00000000..a9a7bd50 --- /dev/null +++ b/com.wudsn.ide.pas/OSGI-INF/l10n/bundle_de_DE.properties @@ -0,0 +1,2 @@ +#Properties file for com.wudsn.ide.pas +com.wudsn.ide.pas.compiler.PascalSourceFile.name = Pascal Quell-Datei \ No newline at end of file