diff --git a/core/org.eclipse.cdt.ui/plugin.properties b/core/org.eclipse.cdt.ui/plugin.properties
index e2d94044163..82ce43aff23 100644
--- a/core/org.eclipse.cdt.ui/plugin.properties
+++ b/core/org.eclipse.cdt.ui/plugin.properties
@@ -1,5 +1,5 @@
###############################################################################
-# Copyright (c) 2003, 2013 IBM Corporation, QNX Software Systems, and others.
+# Copyright (c) 2003, 2023 IBM Corporation, QNX Software Systems, and others.
#
# This program and the accompanying materials
# are made available under the terms of the Eclipse Public License 2.0
@@ -17,6 +17,7 @@
# Axel Mueller - [289339] Surround with
# Tomasz Wesolowski
# James Blackburn (Broadcom Corp.)
+# John Dallaway
###############################################################################
pluginName=C/C++ Development Tools UI
providerName=Eclipse CDT
@@ -226,7 +227,7 @@ markOccurrencesPreferencePage.name=Mark Occurrences
SaveActionsPreferencePage.name=Save Actions
ScalabilityPreferencePage.name=Scalability
-DefaultBinaryFileEditor.name = Default Binary File Editor
+DefaultBinaryFileEditor.name = Default Binary File Viewer
AsmEditor.name = Assembly Editor
# Task Action
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CEditorMessages.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CEditorMessages.java
index 9acec2140ea..29071473bdf 100644
--- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CEditorMessages.java
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CEditorMessages.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2014 QNX Software Systems and others.
+ * Copyright (c) 2000, 2023 QNX Software Systems and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
@@ -13,6 +13,7 @@
* Tomasz Wesolowski
* Alvaro Sanchez-Leon (Ericsson AB)
* Sergey Prigogin (Google)
+ * John Dallaway
*******************************************************************************/
package org.eclipse.cdt.internal.ui.editor;
@@ -63,6 +64,7 @@ public final class CEditorMessages extends NLS {
public static String OverrideIndicatorManager_overrides;
public static String OverrideIndicatorManager_shadows;
public static String OverrideIndicatorManager_via;
+ public static String DefaultBinaryFileEditor_TruncateHexDumpMessage;
public static String DefaultBinaryFileEditor_TruncateMessage;
public static String DefaultCEditorTextHover_html_name;
public static String DefaultCEditorTextHover_html_prototype;
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CEditorMessages.properties b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CEditorMessages.properties
index bc431524e22..debaf97733c 100644
--- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CEditorMessages.properties
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CEditorMessages.properties
@@ -1,5 +1,5 @@
#########################################
-# Copyright (c) 2005, 2013 IBM Corporation and others.
+# Copyright (c) 2005, 2023 IBM Corporation and others.
#
# This program and the accompanying materials
# are made available under the terms of the Eclipse Public License 2.0
@@ -17,6 +17,7 @@
# Tomasz Wesolowski
# Mathias Kunter
# Alvaro Sanchez-Leon (Ericsson)
+# John Dallaway
#########################################
AddInclude_label=Add Include
@@ -52,6 +53,7 @@ OverrideIndicatorManager_overrides=Overrides
OverrideIndicatorManager_shadows=Shadows
OverrideIndicatorManager_via=via
+DefaultBinaryFileEditor_TruncateHexDumpMessage=Truncated, result is too large, use command line xxd
DefaultBinaryFileEditor_TruncateMessage=Truncated, result is too large, use command line objdump
DefaultCEditorTextHover_html_name=Name:\u0020
DefaultCEditorTextHover_html_prototype=
Prototype:\u0020
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/DefaultBinaryFileEditor.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/DefaultBinaryFileEditor.java
index a8aec77db4a..7bb2cd57aee 100644
--- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/DefaultBinaryFileEditor.java
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/DefaultBinaryFileEditor.java
@@ -12,6 +12,7 @@
* Anton Leherbauer (Wind River Systems) - initial API and implementation
* John Dallaway - support both IArchive and IBinary as input (#413)
* John Dallaway - provide hex dump when no GNU tool factory (#416)
+ * John Dallaway - rework to use a FileDocumentProvider (#425)
*******************************************************************************/
package org.eclipse.cdt.internal.ui.editor;
@@ -24,156 +25,53 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
+import java.text.MessageFormat;
import org.apache.commons.io.HexDump;
-import org.eclipse.cdt.core.IBinaryParser;
+import org.eclipse.cdt.core.IBinaryParser.IBinaryFile;
import org.eclipse.cdt.core.model.CoreModel;
import org.eclipse.cdt.core.model.IArchive;
import org.eclipse.cdt.core.model.IBinary;
import org.eclipse.cdt.core.model.ICElement;
-import org.eclipse.cdt.core.resources.FileStorage;
-import org.eclipse.cdt.internal.ui.util.EditorUtility;
import org.eclipse.cdt.ui.CUIPlugin;
import org.eclipse.cdt.utils.IGnuToolFactory;
import org.eclipse.cdt.utils.Objdump;
import org.eclipse.core.resources.IFile;
-import org.eclipse.core.resources.IResourceChangeEvent;
-import org.eclipse.core.resources.IResourceChangeListener;
-import org.eclipse.core.resources.IResourceDelta;
-import org.eclipse.core.resources.IResourceDeltaVisitor;
-import org.eclipse.core.resources.IStorage;
-import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
-import org.eclipse.core.runtime.PlatformObject;
-import org.eclipse.core.runtime.content.IContentType;
-import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.core.runtime.Status;
import org.eclipse.jface.text.IDocument;
-import org.eclipse.jface.text.source.ISourceViewer;
-import org.eclipse.jface.text.source.IVerticalRuler;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.ui.IPersistableElement;
-import org.eclipse.ui.IStorageEditorInput;
-import org.eclipse.ui.PlatformUI;
-import org.eclipse.ui.editors.text.StorageDocumentProvider;
-import org.eclipse.ui.ide.IDE;
-import org.eclipse.ui.ide.ResourceUtil;
-import org.eclipse.ui.part.FileEditorInput;
-import org.eclipse.ui.texteditor.AbstractTextEditor;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IFileEditorInput;
+import org.eclipse.ui.editors.text.FileDocumentProvider;
+import org.eclipse.ui.editors.text.TextEditor;
/**
* A readonly editor to view binary files. This default implementation displays the GNU objdump output of the
* binary as plain text. If no objdump output can be obtained, a hex dump is displayed.
*/
-public class DefaultBinaryFileEditor extends AbstractTextEditor implements IResourceChangeListener {
+public class DefaultBinaryFileEditor extends TextEditor {
/**
- * A storage editor input for binary files.
+ * A file document provider for binary files.
*/
- public static class BinaryFileEditorInput extends PlatformObject implements IStorageEditorInput {
- private final ICElement fBinary;
- private IStorage fStorage;
+ public static class BinaryFileDocumentProvider extends FileDocumentProvider {
- /**
- * Create an editor input from the given binary.
- *
- * @param binary
- */
- public BinaryFileEditorInput(ICElement binary) {
- fBinary = binary;
- }
+ private static final String CONTENT_TRUNCATED_MESSAGE_FORMAT = "\n--- {0} ---\n"; //$NON-NLS-1$
- /*
- * @see org.eclipse.ui.IEditorInput#exists()
- */
- @Override
- public boolean exists() {
- return fBinary.exists();
- }
-
- /*
- * @see org.eclipse.ui.IEditorInput#getImageDescriptor()
- */
- @Override
- public ImageDescriptor getImageDescriptor() {
- IFile file = (IFile) fBinary.getResource();
- IContentType contentType = IDE.getContentType(file);
- return PlatformUI.getWorkbench().getEditorRegistry().getImageDescriptor(file.getName(), contentType);
- }
-
- /*
- * @see org.eclipse.ui.IEditorInput#getName()
- */
- @Override
- public String getName() {
- return fBinary.getElementName();
- }
-
- /*
- * @see org.eclipse.ui.IEditorInput#getPersistable()
- */
- @Override
- public IPersistableElement getPersistable() {
- return null;
- }
-
- /*
- * @see org.eclipse.ui.IEditorInput#getToolTipText()
- */
- @Override
- public String getToolTipText() {
- return fBinary.getResource().getFullPath().toString();
- }
-
- /*
- * @see org.eclipse.ui.IStorageEditorInput#getStorage()
- */
- @Override
- public IStorage getStorage() throws CoreException {
- if (fStorage == null) {
- IBinaryParser.IBinaryFile file = fBinary.getAdapter(IBinaryParser.IBinaryFile.class);
- if (file != null) {
- IPath filePath = file.getPath();
- IGnuToolFactory factory = file.getBinaryParser().getAdapter(IGnuToolFactory.class);
- if (factory != null) {
- Objdump objdump = factory.getObjdump(filePath);
- if (objdump != null) {
- try {
- // limit editor to X MB, if more - users should use objdump in command
- // this is UI blocking call, on 56M binary it takes more than 15 min
- // and generates at least 2.5G of assembly
- int limitBytes = 6 * 1024 * 1024; // this can run reasonably within seconds
- byte[] output = objdump.getOutput(limitBytes);
- if (output.length >= limitBytes) {
- // add a message for user
- String text = CEditorMessages.DefaultBinaryFileEditor_TruncateMessage;
- String message = "\n\n--- " + text + " ---\n" + objdump.toString(); //$NON-NLS-1$ //$NON-NLS-2$
- System.arraycopy(message.getBytes(), 0, output, limitBytes - message.length(),
- message.length());
- }
- fStorage = new FileStorage(new ByteArrayInputStream(output), filePath);
- } catch (IOException exc) {
- CUIPlugin.log(exc);
- }
- }
- } else { // provide a hex dump of the binary file in the absence of a GNU tool factory
- try {
- fStorage = new FileStorage(getHexDumpInputStream(filePath), filePath);
- } catch (IOException e) {
- CUIPlugin.log(e);
- }
- }
- }
- if (fStorage == null) {
- // backwards compatibility
- fStorage = EditorUtility.getStorage(fBinary);
- if (fStorage == null) {
- // fall back to binary content
- fStorage = (IFile) fBinary.getResource();
- }
- }
+ private InputStream getObjdumpInputStream(Objdump objdump) throws IOException {
+ // limit editor to X MB, if more - users should use objdump in command
+ // this is UI blocking call, on 56M binary it takes more than 15 min
+ // and generates at least 2.5G of assembly
+ int limitBytes = 6 * 1024 * 1024; // this can run reasonably within seconds
+ byte[] output = objdump.getOutput(limitBytes);
+ if (output.length >= limitBytes) {
+ // append a message for user
+ String message = "\n" + MessageFormat.format(CONTENT_TRUNCATED_MESSAGE_FORMAT, //$NON-NLS-1$
+ CEditorMessages.DefaultBinaryFileEditor_TruncateMessage) + objdump.toString();
+ System.arraycopy(message.getBytes(), 0, output, limitBytes - message.length(), message.length());
}
- return fStorage;
+ return new ByteArrayInputStream(output);
}
private InputStream getHexDumpInputStream(IPath filePath) throws IOException {
@@ -200,45 +98,60 @@ public class DefaultBinaryFileEditor extends AbstractTextEditor implements IReso
try (InputStream fileStream = new BufferedInputStream(new FileInputStream(filePath.toFile()))) {
int offset = 0;
while (true) {
- // read data for 64 complete lines of hex dump output (1 KiB buffer)
- final byte[] buffer = fileStream.readNBytes(BYTES_PER_LINE * 64);
+ // read data for 256 complete lines of hex dump output (4 KiB buffer)
+ final byte[] buffer = fileStream.readNBytes(BYTES_PER_LINE * 256);
if (0 == buffer.length) { // end of file stream
break;
}
+ // limit content to 16MiB data
+ if (offset >= 0x1000000) {
+ // append a message for user
+ String message = MessageFormat.format(CONTENT_TRUNCATED_MESSAGE_FORMAT,
+ CEditorMessages.DefaultBinaryFileEditor_TruncateHexDumpMessage);
+ outputStream.write(message.getBytes());
+ break;
+ }
HexDump.dump(buffer, offset, outputStream, 0);
offset += buffer.length;
}
}
}
- }
-
- /**
- * A storage document provider for binary files.
- */
- public static class BinaryFileDocumentProvider extends StorageDocumentProvider {
-
- /*
- * @see org.eclipse.ui.editors.text.StorageDocumentProvider#createDocument(java.lang.Object)
- */
- @Override
- protected IDocument createDocument(Object element) throws CoreException {
- IFile file = ResourceUtil.getFile(element);
- if (file != null) {
- ICElement cElement = CoreModel.getDefault().create(file);
- if (cElement instanceof IArchive || cElement instanceof IBinary) {
- element = new BinaryFileEditorInput(cElement);
+ private InputStream getBinaryFileContent(IBinaryFile binaryFile) throws CoreException {
+ try {
+ IPath filePath = binaryFile.getPath();
+ IGnuToolFactory factory = binaryFile.getBinaryParser().getAdapter(IGnuToolFactory.class);
+ if (factory != null) {
+ Objdump objdump = factory.getObjdump(filePath);
+ if (objdump != null) {
+ // use output from objdump tool
+ return getObjdumpInputStream(objdump);
+ }
}
+ // fall back to a hex dump if objdump tool not available
+ return getHexDumpInputStream(binaryFile.getPath());
+ } catch (IOException e) {
+ String message = (e.getMessage() != null ? e.getMessage() : ""); //$NON-NLS-1$
+ throw new CoreException(Status.error(message, e));
}
- return super.createDocument(element);
}
@Override
- public long getModificationStamp(Object element) {
- if (element instanceof FileEditorInput) {
- return ((FileEditorInput) element).getFile().getModificationStamp();
+ protected boolean setDocumentContent(IDocument document, IEditorInput editorInput, String encoding)
+ throws CoreException {
+ if (editorInput instanceof IFileEditorInput fileEditorInput) {
+ IFile file = fileEditorInput.getFile();
+ ICElement cElement = CoreModel.getDefault().create(file);
+ if (cElement instanceof IArchive || cElement instanceof IBinary) {
+ IBinaryFile binaryFile = cElement.getAdapter(IBinaryFile.class);
+ if (binaryFile != null) {
+ setDocumentContent(document, getBinaryFileContent(binaryFile), encoding);
+ return true;
+ }
+ return false;
+ }
}
- return 0;
+ return super.setDocumentContent(document, editorInput, encoding);
}
/*
@@ -262,53 +175,6 @@ public class DefaultBinaryFileEditor extends AbstractTextEditor implements IReso
public DefaultBinaryFileEditor() {
super();
setDocumentProvider(new BinaryFileDocumentProvider());
- ResourcesPlugin.getWorkspace().addResourceChangeListener(this, IResourceChangeEvent.POST_CHANGE);
}
- /*
- * @see
- * org.eclipse.ui.texteditor.AbstractDecoratedTextEditor#createSourceViewer(org.eclipse.swt.widgets.Composite
- * , org.eclipse.jface.text.source.IVerticalRuler, int)
- */
- @Override
- protected ISourceViewer createSourceViewer(Composite parent, IVerticalRuler ruler, int styles) {
- ISourceViewer sourceViewer = super.createSourceViewer(parent, ruler, styles);
- sourceViewer.setEditable(false);
- return sourceViewer;
- }
-
- @Override
- public void dispose() {
- ResourcesPlugin.getWorkspace().removeResourceChangeListener(this);
- }
-
- @Override
- public void resourceChanged(final IResourceChangeEvent event) {
- try {
- if (event.getType() == IResourceChangeEvent.POST_CHANGE) {
- event.getDelta().accept(new IResourceDeltaVisitor() {
- @Override
- public boolean visit(IResourceDelta delta) {
- if (delta.getResource().getName().equals(getEditorInput().getName())) {
- refresh();
- return false;
- }
- return true;
- }
- });
- }
- } catch (CoreException e) {
- CUIPlugin.log(e);
- }
- }
-
- protected void refresh() {
- PlatformUI.getWorkbench().getDisplay().asyncExec(() -> {
- try {
- doSetInput(getEditorInput());
- } catch (CoreException e) {
- CUIPlugin.log(e);
- }
- });
- }
}