Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
[cdt-patch] HexEditor // Hex viewer patch

All,

  This is a patch which will provide a basic hd like hex
editor/dump.  I thought that it would be best rolled into
the CDT since it is something that C developers tend to use
a fair bit.  It is currently a rough work in progress but
it works well enough that it suits my needs.

Limitations:
- Read only currently
- Not the most intelligent drawing mechanism (too much flash)
- Requires you to select a fixed width font in the preferences.

Other than that it works well for me.  Would the CDT community
at large be interested?  I've attached a patch + zip file 
that would be my proposed changes.  The zip is of the entire
CDT.ui tree and includes new icons and the new source code.

Thanks,
 Thomas
-------------------------------------------------------------
Thomas (toe-mah) Fletcher       QNX Software Systems
thomasf@xxxxxxx                 OS Technology Developer
(613)-591-0931                  http://www.qnx.com/

Attachment: hexedit.zip
Description: Zip archive

? src/org/eclipse/cdt/internal/ui/editor/hex

? src/org/eclipse/cdt/internal/ui/editor/hex

? src/org/eclipse/cdt/internal/ui/editor/hex

? src/org/eclipse/cdt/internal/ui/editor/hex

Index: plugin.xml

===================================================================

RCS file: /home/tools/org.eclipse.cdt.ui/plugin.xml,v

retrieving revision 1.10

diff -u -r1.10 plugin.xml

--- plugin.xml	30 Sep 2002 13:30:58 -0000	1.10

+++ plugin.xml	23 Oct 2002 14:36:59 -0000

@@ -29,9 +29,9 @@

    <extension-point id="CCompletionContributor" name="%completionContributorName"/>

    <extension-point id="CElementFilters" name="%elementFiltersName"/>

 <!-- =========================================================================== -->

-<!-- Extension Implementation: must implement org.eclipse.jface.text.ITextHover  -->

-<!-- Purpose: Provide a perspective specific text hovering for CEditor files     -->

 <!-- Extension point: org.eclipse.cdt.ui.textHovers                        -->

+<!-- Purpose: Provide a perspective specific text hovering for CEditor files     -->

+<!-- Extension Implementation: must implement org.eclipse.jface.text.ITextHover  -->

 <!-- =========================================================================== -->

    <extension-point id="textHovers" name="%textHoversName"/>

 

@@ -132,8 +132,8 @@

             id="org.eclipse.cdt.ui.CView">

       </view>

    </extension>

-<!-- The wizards -->

 <!-- For C Wizards -->

+<!-- The wizards -->

    <extension

          point="org.eclipse.ui.newWizards">

       <category

@@ -233,6 +233,12 @@

             class="org.eclipse.cdt.internal.ui.editor.asm.AsmTextEditor"

             id="org.eclipse.cdt.ui.editor.asm.AsmEditor">

       </editor>

+      <editor

+            name="Hex Editor"

+            icon="icons/full/obj16/hex_file_obj.gif"

+            class="org.eclipse.cdt.internal.ui.editor.hex.HexEditor"

+            id="org.eclipse.cdt.ui.internal.editor.hex">

+      </editor>

    </extension>

    <extension

          point="org.eclipse.ui.preferencePages">

@@ -253,6 +259,11 @@

             class="org.eclipse.cdt.internal.ui.preferences.TemplatePreferencePage"

             id="org.eclipse.cdt.ui.preferences.TemplatePreferencePage">

       </page>

+      <page

+            name="Hex Editor"

+            class="org.eclipse.cdt.internal.ui.editor.hex.HexEditorPreferencePage"

+            id="org.eclipse.cdt.ui.internal.editor.hex.page">

+      </page>

    </extension>

    <extension

          point="org.eclipse.ui.propertyPages">

@@ -282,14 +293,6 @@

       </editorContribution>

    </extension>

 <!--

-   <page

-         objectClass="org.eclipse.core.resources.IFile"

-         name="%CLaunchingPropertyPage.executionArguments.name"

-         class="org.eclipse.cdt.internal.ui.preferences.CLaunchingPropertyPage"

-         id="org.eclipse.cdt.ui.preferences.CLaunchingPropertyPage">

-   </page>

--->

-<!--

 <extension

       point="org.eclipse.debug.core.launchers">

    <launcher

@@ -302,6 +305,14 @@

          id="org.eclipse.cdt.core.CApplicationLauncher">

    </launcher>

 </extension>

+-->

+<!--

+   <page

+         objectClass="org.eclipse.core.resources.IFile"

+         name="%CLaunchingPropertyPage.executionArguments.name"

+         class="org.eclipse.cdt.internal.ui.preferences.CLaunchingPropertyPage"

+         id="org.eclipse.cdt.ui.preferences.CLaunchingPropertyPage">

+   </page>

 -->

    <extension

          point="org.eclipse.ui.popupMenus">

Index: icons/full/obj16/hex_file_obj.gif

===================================================================

RCS file: icons/full/obj16/hex_file_obj.gif

diff -N icons/full/obj16/hex_file_obj.gif

Binary files /dev/null and hex_file_obj.gif differ

Index: src/org/eclipse/cdt/internal/ui/CPlugin.java

===================================================================

RCS file: /home/tools/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CPlugin.java,v

retrieving revision 1.7

diff -u -r1.7 CPlugin.java

--- src/org/eclipse/cdt/internal/ui/CPlugin.java	16 Oct 2002 20:14:22 -0000	1.7

+++ src/org/eclipse/cdt/internal/ui/CPlugin.java	23 Oct 2002 14:37:00 -0000

@@ -17,6 +17,7 @@

 import org.eclipse.cdt.internal.ui.cview.CView;

 import org.eclipse.cdt.internal.ui.editor.CDocumentProvider;

 import org.eclipse.cdt.internal.ui.editor.asm.AsmTextTools;

+import org.eclipse.cdt.internal.ui.editor.hex.HexEditorPreferencePage;

 import org.eclipse.cdt.internal.ui.preferences.CEditorPreferencePage;

 import org.eclipse.cdt.internal.ui.preferences.CPluginPreferencePage;

 import org.eclipse.cdt.internal.ui.text.CTextTools;

@@ -317,6 +318,7 @@

 			public void run() {

 		CPluginPreferencePage.initDefaults(store);

 		CEditorPreferencePage.initDefaults(store);

+		HexEditorPreferencePage.initDefaults(store);

 		CView.initDefaults(store);

 	}

 		});

Index: src/org/eclipse/cdt/internal/ui/editor/HexEditor.java

===================================================================

RCS file: src/org/eclipse/cdt/internal/ui/editor/HexEditor.java

diff -N src/org/eclipse/cdt/internal/ui/editor/HexEditor.java

--- /dev/null	1 Jan 1970 00:00:00 -0000

+++ src/org/eclipse/cdt/internal/ui/editor/HexEditor.java	23 Oct 2002 14:37:02 -0000

@@ -0,0 +1,118 @@

+package org.eclipse.cdt.internal.ui.editor.hex;

+

+import java.io.FileNotFoundException;

+import java.io.IOException;

+

+import org.eclipse.swt.SWT;

+import org.eclipse.swt.widgets.Composite;

+import org.eclipse.core.runtime.IProgressMonitor;

+import org.eclipse.core.resources.IFile;

+import org.eclipse.core.resources.IMarker;

+import org.eclipse.ui.IEditorSite;

+import org.eclipse.ui.IEditorInput;

+import org.eclipse.ui.IFileEditorInput;

+import org.eclipse.ui.PartInitException;

+import org.eclipse.ui.part.EditorPart;

+

+/**

+ * Insert the type's description here.

+ * @see EditorPart

+ */

+public class HexEditor extends EditorPart {

+	IEditorSite 	fEdSite;

+	IEditorInput	fEdInput;	//This is really an IFileEditorInput

+	IFile			event_file;

+	HexTextDisplay fHexDisplay;

+	

+	/**

+	 * The constructor.

+	 */

+	public HexEditor() {

+	}

+

+	/**

+	 * Insert the method's description here.

+	 * @see EditorPart#createPartControl

+	 */

+	public void createPartControl(Composite parent)  {

+		fHexDisplay = new HexTextDisplay(parent, SWT.NONE);		

+

+		if(!(fEdInput instanceof IFileEditorInput)) {

+			return;

+		}

+		

+		IFile file = ((IFileEditorInput)fEdInput).getFile();

+		try {

+			fHexDisplay.setInput(file.getLocation().toOSString());

+		} catch (FileNotFoundException e) {

+		} catch (IOException e) {

+		}				

+	}

+

+	/**

+	 * Insert the method's description here.

+	 * @see EditorPart#setFocus

+	 */

+	public void setFocus()  {

+		fHexDisplay.setFocus();

+	}

+

+	/**

+	 * Insert the method's description here.

+	 * @see EditorPart#gotoMarker

+	 */

+	public void gotoMarker(IMarker marker)  {

+	}

+

+	/**

+	 * Insert the method's description here.

+	 * @see EditorPart#init

+	 */

+	public void init(IEditorSite site, IEditorInput input) throws PartInitException {

+		fEdSite = site;

+		fEdInput = input;

+		setSite(site);	

+		setTitle(input.getName() + " (Read only)");

+	}

+	

+	

+

+	/**

+	 * Insert the method's description here.

+	 * @see EditorPart#isDirty

+	 */

+	public boolean isDirty()  {

+		return false;

+	}

+

+	/**

+	 * Insert the method's description here.

+	 * @see EditorPart#isSaveAsAllowed

+	 */

+	public boolean isSaveAsAllowed()  {

+		return false;

+	}

+

+	/**

+	 * Insert the method's description here.

+	 * @see EditorPart#doSave

+	 */

+	public void doSave(IProgressMonitor monitor)  {

+	}

+

+	/**

+	 * Insert the method's description here.

+	 * @see EditorPart#doSaveAs

+	 */

+	public void doSaveAs()  {

+	}

+

+	/**

+	 * @see org.eclipse.ui.IWorkbenchPart#dispose()

+	 */

+	public void dispose() {

+		fHexDisplay.dispose();

+		super.dispose();

+	}

+

+}

Index: src/org/eclipse/cdt/internal/ui/editor/HexEditorPreferencePage.java

===================================================================

RCS file: src/org/eclipse/cdt/internal/ui/editor/HexEditorPreferencePage.java

diff -N src/org/eclipse/cdt/internal/ui/editor/HexEditorPreferencePage.java

--- /dev/null	1 Jan 1970 00:00:00 -0000

+++ src/org/eclipse/cdt/internal/ui/editor/HexEditorPreferencePage.java	23 Oct 2002 14:37:02 -0000

@@ -0,0 +1,110 @@

+package org.eclipse.cdt.internal.ui.editor.hex;

+

+import org.eclipse.ui.IWorkbench;

+import org.eclipse.swt.SWT;

+import org.eclipse.swt.graphics.FontData;

+import org.eclipse.swt.graphics.RGB;

+import org.eclipse.swt.layout.GridData;

+import org.eclipse.swt.layout.GridLayout;

+import org.eclipse.swt.widgets.Control;

+import org.eclipse.swt.widgets.Composite;

+import org.eclipse.swt.widgets.Label;

+import org.eclipse.cdt.internal.ui.CPlugin;

+import org.eclipse.jface.preference.ColorFieldEditor;

+import org.eclipse.jface.preference.FieldEditor;

+import org.eclipse.jface.preference.FontFieldEditor;

+import org.eclipse.jface.preference.IPreferenceStore;

+import org.eclipse.jface.preference.PreferenceConverter;

+import org.eclipse.jface.preference.PreferencePage;

+import org.eclipse.ui.IWorkbenchPreferencePage;

+

+/**

+ * Insert the type's description here.

+ * @see PreferencePage

+ */

+public class HexEditorPreferencePage extends PreferencePage implements IWorkbenchPreferencePage {

+	FontFieldEditor ffe;

+	ColorFieldEditor linefe;

+	ColorFieldEditor selfe;

+

+	/**

+	 * The constructor.

+	 */

+	public HexEditorPreferencePage() {

+	}

+

+	/**

+	 * Insert the method's description here.

+	 * @see PreferencePage#init

+	 */

+	public void init(IWorkbench workbench)  {

+		setPreferenceStore(CPlugin.getDefault().getPreferenceStore());

+	}

+

+	/**

+	 * Insert the method's description here.

+	 * @see PreferencePage#createContents

+	 */

+	protected Control createContents(Composite parent)  {

+		Composite control = new Composite(parent, SWT.NONE);

+		control.setLayout(new GridLayout(3, false));

+		control.setLayoutData(new GridData(GridData.FILL_HORIZONTAL | GridData.GRAB_HORIZONTAL));

+

+		linefe = new ColorFieldEditor(IHexEditorConstants.PREF_HEXEDIT_LINECOLOR,

+								  "Line Colour",

+								  control);

+		setFieldEditorSettings(linefe);

+		Label filler = new Label(control, SWT.NONE);

+		filler.setText("");

+		

+		selfe = new ColorFieldEditor(IHexEditorConstants.PREF_HEXEDIT_SELCOLOR,

+								  "Selection Colour",

+								  control);

+		setFieldEditorSettings(selfe);

+		filler = new Label(control, SWT.NONE);

+

+		ffe = new FontFieldEditor(IHexEditorConstants.PREF_HEXEDIT_FONT,

+								  "Editor font",

+								  control);

+		setFieldEditorSettings(ffe);

+	

+		return control;

+	}

+

+	private void setFieldEditorSettings(FieldEditor fe) {

+		fe.setPreferencePage(this);

+		fe.setPreferenceStore(getPreferenceStore());

+		fe.load();

+	}

+

+	/**

+	 * @see org.eclipse.jface.preference.PreferencePage#performDefaults()

+	 */

+	protected void performDefaults() {

+		ffe.loadDefault();

+		linefe.loadDefault();

+		selfe.loadDefault();		

+		super.performDefaults();

+	}

+

+	/**

+	 * @see org.eclipse.jface.preference.IPreferencePage#performOk()

+	 */

+	public boolean performOk() {

+		ffe.store();

+		linefe.store();

+		selfe.store();		

+		return super.performOk();

+	}

+

+	public static void initDefaults(IPreferenceStore store) {

+		FontData [] list = CPlugin.getActiveWorkbenchShell().getDisplay().getFontList("courier", true);

+		

+		if(list != null && list.length > 0) {

+			PreferenceConverter.setDefault(store, IHexEditorConstants.PREF_HEXEDIT_FONT, list);

+		}

+		

+		PreferenceConverter.setDefault(store, IHexEditorConstants.PREF_HEXEDIT_LINECOLOR, new RGB(225, 235, 224));

+		PreferenceConverter.setDefault(store, IHexEditorConstants.PREF_HEXEDIT_SELCOLOR, new RGB(125, 135, 124));

+	}

+}

Index: src/org/eclipse/cdt/internal/ui/editor/HexTextDisplay.java

===================================================================

RCS file: src/org/eclipse/cdt/internal/ui/editor/HexTextDisplay.java

diff -N src/org/eclipse/cdt/internal/ui/editor/HexTextDisplay.java

--- /dev/null	1 Jan 1970 00:00:00 -0000

+++ src/org/eclipse/cdt/internal/ui/editor/HexTextDisplay.java	23 Oct 2002 14:37:02 -0000

@@ -0,0 +1,615 @@

+package org.eclipse.cdt.internal.ui.editor.hex;

+

+import java.io.FileNotFoundException;

+import java.io.IOException;

+import java.io.RandomAccessFile;

+import java.text.DecimalFormat;

+import java.util.Arrays;

+

+import org.eclipse.cdt.internal.ui.CPlugin;

+import org.eclipse.jface.preference.IPreferenceStore;

+import org.eclipse.jface.preference.PreferenceConverter;

+import org.eclipse.jface.util.IPropertyChangeListener;

+import org.eclipse.jface.util.PropertyChangeEvent;

+import org.eclipse.swt.*;

+//import org.eclipse.swt.custom.*;

+import org.eclipse.swt.events.*;

+//import org.eclipse.swt.layout.*;

+import org.eclipse.swt.widgets.*;

+import org.eclipse.swt.graphics.*;

+

+

+/**

+ * This is a custom widget put together for the sole purpose of being

+ * able to implement efficient drawing for the trace event data.

+ */

+public class HexTextDisplay extends Composite implements IPropertyChangeListener {

+	static final String TEST_LINE = "00000000  AB CD EF AB AB CD EF AB AB CD EF AB AB CD EF AB  1234567890123456"; 

+	static final String TEST_OFFSET = "00000000";

+	static final String TEST_HEXVAL = "AB CD EF AB AB CD EF AB AB CD EF AB AB CD EF AB";

+	static final String TEST_CHARVAL = "1234567890123456";

+	static final String FORMAT_OFFSET = "00000000";

+	static final int    VSPACER = 2;

+	static final int    LOWER_CHAR_DISPLAY_BOUND = 32;

+	static final int    UPPER_CHAR_DISPLAY_BOUND = 127;

+

+	static final int    MOUSE_DOWN = 1;

+	static final int    MOUSE_UP = 2;

+	static final int    KEY_UP = 1;

+	static final int    KEY_DOWN = 2;

+

+	long fDataLength;			//Length of data (in bytes)

+	long fVStartOffset;		//Visual start offset from start of stream (in bytes)

+	int  fVStartCharIndex;		//Visual start character

+	int  fBytesPerLine;		//Number of bytes per line

+

+	long  		fCursorHighlight;	//Cursor position (in bytes)

+	int		fCursorNibble;		//Top or lower nibble

+	boolean 	fHighlightHex;		//Highlight the hex values (else the chars)

+	

+	

+	RandomAccessFile 	fFile;	

+	IPreferenceStore 	fPrefStore;

+

+	//UI components

+	Canvas 			fCanvas;

+	Slider 			fVScroll;	

+	Slider 			fHScroll;

+	Image			fOffscreenImage;

+

+	//Driven by preferences

+	Font			fTextFont;

+	RGB				fLineRGB;

+	RGB				fSelRGB;

+	

+	/**

+	 * This is the layout class for the trace graph widget.

+	 */

+	class HexEditorLayout extends Layout {

+		int hpadding = 1;

+		int vpadding = 1;

+		int borderWidth = 1;

+

+		int scrollwh = 10;

+		

+		/**

+		* Computes the preferred size.

+		*/

+		public Point computeSize(Composite parent, int wHint, int hHint, boolean flushCache) {

+			Rectangle bounds = HexTextDisplay.this.getClientArea();

+			

+			Point pt = new Point(bounds.width, bounds.height);

+			return pt;

+		}

+

+		public void layout(Composite parent, boolean flushCache) {	

+			Rectangle bounds = HexTextDisplay.this.getClientArea();

+			

+			Point pt;

+			pt = fHScroll.computeSize(SWT.DEFAULT, SWT.DEFAULT);

+			scrollwh = pt.y;

+			//pt = fCanvas.computeSize(SWT.DEFAULT, SWT.DEFAULT);

+			

+			fCanvas.setBounds(bounds.x, bounds.y, bounds.width - scrollwh, bounds.height - scrollwh);

+			

+			fHScroll.setBounds(bounds.x, 

+							   bounds.y + bounds.height - scrollwh, 

+							   bounds.width - scrollwh, 

+							   scrollwh);

+			

+			fVScroll.setBounds(bounds.x + bounds.width - scrollwh, 

+							   bounds.y, 

+							   scrollwh,

+							   bounds.height - scrollwh);

+		}

+	}

+

+	/**

+	 * This is essentially everything we need to build a

+	 * trace graph.

+	 */	

+	public HexTextDisplay(Composite parent, int style) {

+		super(parent, 0);

+			

+		fCanvas= new Canvas(this, SWT.NONE);

+		fCanvas.setBackground(new Color(null, 255, 255, 255));

+		fCanvas.addPaintListener(new PaintListener() {

+			public void paintControl(PaintEvent e) {

+				HexTextDisplay.this.paintEditor(e);

+			}

+		});

+		fCanvas.addControlListener(new ControlAdapter() {

+			public void controlResized(ControlEvent e) {

+				HexTextDisplay.this.resizeEditor(e);

+			}

+		}); 

+		fCanvas.addMouseListener(new MouseAdapter() {

+			public void mouseDown(MouseEvent e) {

+				HexTextDisplay.this.mouseEvent(e, MOUSE_DOWN);

+			}

+			public void mouseUp(MouseEvent e) {

+				HexTextDisplay.this.mouseEvent(e, MOUSE_UP);

+			}

+		});

+		fCanvas.addMouseMoveListener(new MouseMoveListener() {

+			public void mouseMove(MouseEvent e) {

+				//TraceGraph.this.mouseGraph(e, MOUSE_MOVE);

+			}

+		});

+		fCanvas.addKeyListener(new KeyAdapter() {

+			public void keyReleased(KeyEvent e) {

+				//TraceGraph.this.keyReleased(e);

+			}

+			public void keyPressed(KeyEvent e) {

+				HexTextDisplay.this.keyEvent(e, KEY_DOWN);

+			}

+		});

+		fCanvas.addListener(SWT.MouseHover, new Listener() {

+			public void handleEvent(Event e) {

+			}

+		});

+				

+		fVScroll = new Slider(this, SWT.VERTICAL);

+		fVScroll.addSelectionListener(new SelectionAdapter() {

+			public void widgetSelected(SelectionEvent e) {

+				HexTextDisplay.this.scrollEditor(e);

+			}

+		});

+		fVScroll.setIncrement(1);

+

+		fHScroll = new Slider(this, SWT.HORIZONTAL);

+		fHScroll.addSelectionListener(new SelectionAdapter() {

+			public void widgetSelected(SelectionEvent e) {

+				HexTextDisplay.this.scrollEditor(e);

+			}

+		});

+		fHScroll.setIncrement(1);

+		

+		setLayout(new HexEditorLayout());

+			

+		//Suck the data from the preferences	

+		fPrefStore = CPlugin.getDefault().getPreferenceStore();

+		fPrefStore.addPropertyChangeListener(this);

+

+		//Fire a fake change to initialize ourselves

+		propertyChange(null);

+	}

+	

+	public void dispose() {

+		if(fFile != null) {

+			try {

+				fFile.close();

+			} catch(Exception ex) {

+				/* Ignore */

+			}

+		}

+		fPrefStore.removePropertyChangeListener(this);

+		super.dispose();

+	}

+

+	public void propertyChange(PropertyChangeEvent event) {

+		boolean redraw = false;

+		if(event == null || event.getProperty().equals(IHexEditorConstants.PREF_HEXEDIT_FONT)) {

+			fTextFont = new Font(null, PreferenceConverter.getFontData(fPrefStore, IHexEditorConstants.PREF_HEXEDIT_FONT));

+			fCanvas.setFont(fTextFont);

+			redraw = true;

+		}

+		if(event == null || event.getProperty().equals(IHexEditorConstants.PREF_HEXEDIT_LINECOLOR)) {

+			fLineRGB = PreferenceConverter.getColor(fPrefStore, IHexEditorConstants.PREF_HEXEDIT_LINECOLOR);

+			redraw = true;

+		}

+		if(event == null || event.getProperty().equals(IHexEditorConstants.PREF_HEXEDIT_SELCOLOR)) {

+			fSelRGB = PreferenceConverter.getColor(fPrefStore, IHexEditorConstants.PREF_HEXEDIT_SELCOLOR);

+			redraw = true;

+		}

+		

+		if(redraw) {

+			fCanvas.redraw();

+		}

+	}

+

+	

+	public void setInput(String filename) throws FileNotFoundException, IOException {

+		fFile = new RandomAccessFile(filename, "r");

+

+		fDataLength = fFile.length();		

+		fVStartOffset = 0;

+		fVStartCharIndex = 0;

+		fBytesPerLine = 16;

+		

+		fCanvas.redraw();

+	}

+	

+	/**

+	 * Retrieve the currently highlighted position.

+	 */

+	public long getCurrentOffset() {

+		return fCursorHighlight;

+	}

+

+	protected void scrollEditor(SelectionEvent ev) {

+		//Find the start line

+		int yscroll = fVScroll.getSelection();	

+		fVStartOffset = yscroll * fBytesPerLine;

+

+		//Find the y start character

+		int xscroll = fHScroll.getSelection();

+		fVStartCharIndex = xscroll;

+

+		fCanvas.redraw();

+	}

+

+	//@@@ TODO:

+	// In the future, we should only draw the background and then

+	// xor/overlay the currently selected position on top.  

+	protected void paintEditor(PaintEvent ev) {

+		if(fOffscreenImage != null) {

+			drawOffScreen();

+			ev.gc.drawImage(fOffscreenImage, 0, 0);

+		}

+	}

+

+	/**

+	 * This will clear the offscreen image and then draw the hex values on it.

+	 */

+	protected void drawOffScreen() {

+		GC gc = new GC(fOffscreenImage);

+		Color backclr = new Color(null, 255, 255, 255);

+		

+		gc.setBackground(backclr);

+		gc.fillRectangle(fOffscreenImage.getBounds());

+		backclr.dispose();

+

+		gc.setFont(fTextFont);

+		drawHexValues(gc);

+

+		gc.dispose();

+	}

+

+	/**

+	 * This is use to seperate out the "how" aspect of the drawing from the "where" 

+	 * so that we can choose to do this offscreen or on screen as we so desire. It

+	 * also gives us a point of seperation for later drawing things like markers

+	 * and user selections.

+	 * 

+	 * @@@ TODO Remove the reliance on a fixed width font.

+	 */

+	protected void drawHexValues(GC gc) {

+		Rectangle 	bounds = fCanvas.getClientArea();		

+

+		if(fFile == null) {

+			return;

+		}

+		

+		//@@@ Move much of these constants to the resize callback

+				

+		//Decide how many lines we can draw

+		Point pt = gc.stringExtent(TEST_LINE);

+		int fLineNum = bounds.height/(pt.y + VSPACER);

+		

+		//Calculate the positional offsets

+		int xstartoff = -1 * (fVStartCharIndex * gc.stringExtent(" ").x);

+		int offsetwidth = gc.stringExtent(TEST_OFFSET).x;

+		int hexvalwidth = gc.stringExtent(TEST_HEXVAL).x;

+

+//		int charvalwidth = gc.stringExtent(TEST_CHARVAL).x;

+		int spacerwidth = gc.stringExtent("  ").x;

+

+		Color clr = new Color(null, fLineRGB);

+		gc.setBackground(clr);

+		gc.fillRectangle(xstartoff, 0, offsetwidth, bounds.height);

+		clr.dispose();

+		

+		byte [] inputChars = new byte[fBytesPerLine];

+		StringBuffer outputLine = new StringBuffer();

+

+		DecimalFormat lineFmt = new DecimalFormat(FORMAT_OFFSET);

+	

+		//Draw those lines

+

+		int yOffset = 0;

+		long fileOffset = fVStartOffset; 

+		for(int i = 0; i < fLineNum; i++) {

+			fileOffset = fVStartOffset + (i*fBytesPerLine); 

+			if(fileOffset >= fDataLength) {

+				break;

+			}

+

+			//Determine which characters to highlight

+			if((fCursorHighlight >= fileOffset) && 

+			   (fCursorHighlight < (fileOffset + fBytesPerLine))) {

+			   	int hexCurOff, hexCurWidth;

+			   	int charCurOff, charCurWidth;

+			   	

+		   		hexCurWidth = gc.stringExtent("A").x;

+		   		hexCurOff = offsetwidth + spacerwidth;

+		   		hexCurOff += (fCursorHighlight - fileOffset) * (gc.stringExtent("AB ").x);

+

+			   	charCurWidth = gc.stringExtent(" ").x;

+		   		charCurOff = offsetwidth + hexvalwidth + (2 * spacerwidth);

+			    charCurOff += (fCursorHighlight - fileOffset) * charCurWidth;

+			   	

+				Color primary = new Color(null, fSelRGB);

+				Color secondary = new Color(null, fLineRGB);

+				

+				if(fHighlightHex) {

+					gc.setBackground(primary);	

+					gc.drawRectangle(xstartoff + hexCurOff, yOffset, 2 * hexCurWidth, pt.y);

+					if(fCursorNibble == 0) {

+						gc.fillRectangle(xstartoff + hexCurOff, yOffset, hexCurWidth, pt.y);

+					} else {

+						gc.fillRectangle(xstartoff + hexCurOff + hexCurWidth, yOffset, hexCurWidth, pt.y);

+					}

+				} else {

+					gc.setBackground(secondary);	

+					gc.fillRectangle(xstartoff + hexCurOff, yOffset, 2 * hexCurWidth, pt.y);

+				}

+						

+				gc.setBackground((fHighlightHex) ? secondary : primary);	

+				gc.fillRectangle(xstartoff + charCurOff, yOffset, charCurWidth, pt.y);

+				

+				primary.dispose();

+				secondary.dispose();

+			}

+

+			//Draw the rest of the string on top

+			int numBytes = 0;

+			try {

+				Arrays.fill(inputChars, (byte)0);

+				fFile.seek(fileOffset);

+				numBytes = fFile.read(inputChars);

+			} catch(Exception ex) {

+				System.out.println("Exception seeking/reading");

+				numBytes = -1;

+			}

+		

+			if(numBytes == -1) {

+				break;

+			}

+		

+			//Byte offset

+			outputLine.append(lineFmt.format(fileOffset));

+			outputLine.append("  ");

+			

+			//Hex values

+			for(int j = 0; j < inputChars.length; j++) {

+				if(j < numBytes) {

+					outputLine.append(makeHexByte(inputChars[j]));

+				} else {

+					outputLine.append("  ");

+				}

+				outputLine.append(" ");

+			}

+			

+			outputLine.append(" ");

+			

+			//Char values			

+			for(int j = 0; j < numBytes; j++) {

+				char ch = (char)(((char)inputChars[j]) & 0xff);

+				if(ch >= LOWER_CHAR_DISPLAY_BOUND && ch <= UPPER_CHAR_DISPLAY_BOUND) {

+					outputLine.append(ch);

+				} else {

+					outputLine.append(".");

+				}

+			}

+			

+			gc.drawText(outputLine.toString(), xstartoff, yOffset, true);

+			yOffset += pt.y + VSPACER;

+

+			outputLine.delete(0, outputLine.length());	

+		}

+	}

+

+	protected void resizeEditor(ControlEvent ev) {

+		Rectangle area = fCanvas.getClientArea();

+

+		GC gc = new GC(fCanvas);

+		int textWidth = gc.stringExtent(TEST_LINE).x;

+		int textHeight = gc.stringExtent(TEST_LINE).y + VSPACER;

+		int oneCharWidth = gc.stringExtent(" ").x;

+		gc.dispose();

+

+		//Set the horizontal scroll		

+		int numCharsTotal = TEST_LINE.length();

+		if(area.width >= textWidth) {

+			fHScroll.setSelection(0);

+			fHScroll.setEnabled(false);

+		} else {

+			fHScroll.setMinimum(0);

+			int max = numCharsTotal - (area.width / oneCharWidth);

+			fHScroll.setMaximum(max + fHScroll.getThumb());

+			fHScroll.setEnabled(true);

+		}

+

+		//Set the vertical scroll

+		int numLinesTotal = (int)(fDataLength / (long)fBytesPerLine) + 1;

+		int allLinesHeight = numLinesTotal * textHeight;

+		if(area.height >= allLinesHeight) {

+			fVScroll.setSelection(0);

+			fVScroll.setEnabled(false);

+		} else {

+			fVScroll.setMinimum(0);

+			int max = numLinesTotal - (area.height / textHeight);

+			fVScroll.setMaximum(max + fVScroll.getThumb());

+			fVScroll.setEnabled(true);

+		}

+

+		//Resize the offscreen image

+		if(fOffscreenImage != null) {

+			fOffscreenImage.dispose();

+			fOffscreenImage = null;

+		}

+		if(!isDisposed() && area.width > 0 && area.height > 0) {

+			fOffscreenImage = new Image(null, area);

+		}

+		

+		scrollEditor(null);

+	}

+

+	protected void mouseEvent(MouseEvent ev, int state) {

+		Rectangle bounds = fCanvas.getClientArea();

+		GC gc = new GC(fCanvas);

+

+		Point pt = gc.stringExtent(TEST_LINE);

+		int fLineNum = bounds.height/(pt.y + VSPACER);

+		

+		//Calculate the positional offsets

+		int xstartoff = -1 * (fVStartCharIndex * gc.stringExtent(" ").x);

+		int offsetwidth = gc.stringExtent(TEST_OFFSET).x;

+		int hexvalwidth = gc.stringExtent(TEST_HEXVAL).x;

+		int charvalwidth = gc.stringExtent(TEST_CHARVAL).x;

+		int spacerwidth = gc.stringExtent("  ").x;

+		gc.dispose();

+		

+		if(state == MOUSE_DOWN) {

+			fLineNum = ev.y / (pt.y + VSPACER);

+			

+			if(ev.x <= (xstartoff + offsetwidth + spacerwidth)) {

+				; //Ignore clicks in offset column

+			} else if (ev.x <= (xstartoff + offsetwidth + hexvalwidth + (2 * spacerwidth))) {

+				//Hex value selection

+				ev.x -= xstartoff + offsetwidth + spacerwidth;

+

+				fCursorHighlight = fVStartOffset;

+				fCursorHighlight += fLineNum * fBytesPerLine;

+				fCursorHighlight += (ev.x * fBytesPerLine) / hexvalwidth;

+				fCursorNibble = 0;

+				fHighlightHex = true;

+

+				fCanvas.redraw();

+			} else if (ev.x <= (xstartoff + offsetwidth + hexvalwidth + charvalwidth + (2 * spacerwidth))) {

+				//Character value selection;

+				ev.x -= xstartoff + offsetwidth + hexvalwidth + (2 * spacerwidth);

+

+				fCursorHighlight = fVStartOffset;

+				fCursorHighlight += fLineNum * fBytesPerLine;

+				fCursorHighlight += (ev.x * fBytesPerLine) / charvalwidth;

+				fHighlightHex = false;

+				

+				fCanvas.redraw();

+			}

+		}		

+

+	}

+

+	protected void keyEvent(KeyEvent ev, int state) {

+		long orgHighlight = fCursorHighlight;

+		int  orgNibble = fCursorNibble;

+		

+		if(ev.keyCode != 0) {		

+			switch(ev.keyCode) {

+			case SWT.ARROW_UP:

+				fCursorHighlight -= (fCursorHighlight >= fBytesPerLine) ? fBytesPerLine : 0;

+				break;

+			case SWT.ARROW_DOWN:

+				fCursorHighlight += (fCursorHighlight <= fDataLength - fBytesPerLine) ? fBytesPerLine : 0;

+				break;

+			case SWT.ARROW_LEFT:

+				if(fHighlightHex == false) {

+					fCursorHighlight -= (fCursorHighlight > 0) ? 1 : 0;

+				} else if(fCursorNibble == 0) {

+					fCursorNibble = 1;

+					fCursorHighlight -= (fCursorHighlight > 0) ? 1 : 0;

+				} else {

+					fCursorNibble = 0;

+				}

+				break;

+			case SWT.ARROW_RIGHT:

+				if(fHighlightHex == false) {

+					fCursorHighlight += (fCursorHighlight < fDataLength - 1) ? 1 : 0;

+				} else if(fCursorNibble == 1) {

+					fCursorHighlight += (fCursorHighlight < fDataLength - 1) ? 1 : 0;

+					fCursorNibble = 0;

+				} else {

+					fCursorNibble = 1;

+				}

+				break;

+			}

+		

+			if(orgHighlight != fCursorHighlight || orgNibble != fCursorNibble) {

+				ensureCursorVisible(false);

+				fCanvas.redraw();

+			}

+		} else {

+//TODO: Add editing capabilities

+//			//Edit the file limited by the entries we make

+//			if(fHighlightHex) {

+//				if((ev.character >= 'a' && ev.character <= 'z') ||

+//				   (ev.character >= '0' && ev.character <= '9') ||

+//				   (ev.character >= 'A' && ev.character <= 'Z')) {

+//				} else {

+//					getDisplay().beep();

+//				}

+//			} else {

+//				if(ev.character >= LOWER_CHAR_DISPLAY_BOUND && ev.character <= UPPER_CHAR_DISPLAY_BOUND) {

+//					try {

+//						fFile.seek(fCursorHighlight);

+//						fFile.write((byte)ev.character);

+//					} catch(Exception e) {

+//						/* Ignore */

+//					}

+//					fCanvas.redraw();

+//				} else {

+//					getDisplay().beep();

+//				}

+//			}

+		}

+		

+	}

+

+	/**

+	 * Recalculates the start/end indices based on making the highlighted 

+	 * cursor visible.  Does not cause a re-draw operation to occur.

+	 * @param center Setting center to true causes the display to center on the 

+	 * cursor position if it is not visible, otherwise it will appear as the first

+	 * or last line of the editor.

+	 * 

+	 * @@@ TODO: Support horizontal scrolling as well

+	 */

+	protected void ensureCursorVisible(boolean center) {	

+		GC gc = new GC(fCanvas);

+		Rectangle bounds = fCanvas.getClientArea();

+		Point pt = gc.stringExtent(TEST_LINE);

+		int fLineNum = bounds.height/(pt.y + VSPACER);

+		gc.dispose();

+		

+		long tempPosition = 0;

+		if(fCursorHighlight < fVStartOffset) {

+			if(center) {

+				tempPosition = (fCursorHighlight - ((fLineNum / 2) * fBytesPerLine));

+			} else {		

+				tempPosition = fCursorHighlight;

+			}

+		} else if(fCursorHighlight >= (fVStartOffset + (fLineNum * fBytesPerLine))) {

+			//Adjust for the fact that our current position consumes one line

+			if(center) {

+				tempPosition = (fCursorHighlight - (((fLineNum / 2) - 1) * fBytesPerLine));

+			} else {

+		   		tempPosition = (fCursorHighlight - ((fLineNum -1) * fBytesPerLine));

+			}

+		} else {

+			return;

+		}

+		

+		if(tempPosition <= 0) {

+			fVStartOffset = 0;

+		} else {

+			fVStartOffset = tempPosition - (tempPosition % fBytesPerLine);

+		}	

+	}

+

+	/**

+	 * This is used as a simple way to make a two char hex string value from a single byte.

+	 */

+	private String makeHexByte(byte b) {

+		int a = ((int)b) & 0xff;	

+		String s = Integer.toHexString(a);

+		

+		if(s.length() < 2) {

+			return "0" + s;

+		} else {

+			return s;

+		}

+	}

+}

+

Index: src/org/eclipse/cdt/internal/ui/editor/IHexEditorConstants.java

===================================================================

RCS file: src/org/eclipse/cdt/internal/ui/editor/IHexEditorConstants.java

diff -N src/org/eclipse/cdt/internal/ui/editor/IHexEditorConstants.java

--- /dev/null	1 Jan 1970 00:00:00 -0000

+++ src/org/eclipse/cdt/internal/ui/editor/IHexEditorConstants.java	23 Oct 2002 14:37:02 -0000

@@ -0,0 +1,12 @@

+package org.eclipse.cdt.internal.ui.editor.hex;

+

+/**

+ * Constants related to the hex editor

+ */

+public interface IHexEditorConstants {

+	static String HEX_EDITOR_BASE_ID = "org.eclipse.cdt.internal.ui.editor.hex";

+

+	public static String PREF_HEXEDIT_FONT = HEX_EDITOR_BASE_ID + ".EDITORFONT";

+	public static String PREF_HEXEDIT_LINECOLOR = HEX_EDITOR_BASE_ID + ".EDITORLINE";

+	public static String PREF_HEXEDIT_SELCOLOR = HEX_EDITOR_BASE_ID + ".EDITORSEL";

+}


Back to the top